In this article we demonstrate the use case of intuitive knowledge articles. Unlike the text based knowledge article, we display YouTube videos searched based on the Subject of a sample Case. The demo also brings in data such as likes, dislikes and views of a particular video.
The Lightning Component is configurable such that it can be dragged and dropped on any objects (standard/custom) record page and it will fetch videos based on the text from the field whose API name is configured in a custom metadata created for this purpose. Below is a snapshot of some sample metadata records for few objects. Take a look at fieldName for Case object, configured with Subject field - hence the videos on Case record page will fetch videos based on the text in the Subject field.
Sample Custom Metadata records to configure YouTube Lightning Component for different objects
Snapshot of YouTube Lightning Component
Firstly, few things to setup in Google Cloud Platform
We need a Google Account to access the Google API Console, request an API key, and register our application.
After creating your project, make sure the YouTube Data API is one of the services that your application is registered to use:
API Console Search for "youtube api" and click YouTube Data API v3 Click Enable and in the following screen click under Credentials option click + CREATE CREDENTIALS The generated API key will be used in the callout code.
Below is a sample callout code using the YouTube Data API v3 and following is the response from the API.
HttpRequest request = new HttpRequest();
HttpResponse response = new HttpResponse();
Http http = new Http();
request.setEndpoint('https://www.googleapis.com/youtube/v3/search?maxResults=5&part=snippet&q='+searchResults.replaceAll(' ', '+')+'&type=video&key={YOUR_API_KEY}');
request.setMethod('GET');
try{
response = http.send(request);
System.debug(response.getBody());
}catch(System.CalloutException e) {
System.debug('Callout error: '+ e);
System.debug(response.toString());
}
Below is the JSON response for video search results based on the Subject of a sample case record.
{
"kind": "youtube#searchListResponse",
"etag": "\"xwzn9fn_LczrfK9QS3iZcGzqRGs/2ptDzqXXFWnBe5A1b1ypvIdH8NM\"",
"nextPageToken": "CAUQAA",
"regionCode": "US",
"pageInfo": {
"totalResults": 1000000,
"resultsPerPage": 5
},
"items": [
{
"kind": "youtube#searchResult",
"etag": "\"xwzn9fn_LczrfK9QS3iZcGzqRGs/XAQjwNlxoLq_epHnE2XFJB2G2sk\"",
"id": {
"kind": "youtube#video",
"videoId": "AHX6tHdQGiQ"
},
"snippet": {
"publishedAt": "2018-03-15T15:27:07.000Z",
"channelId": "UCbxQcz9k0NRRuy0ukgQTDQQ",
"title": "Ink Cartridges Are A Scam",
"description": "Printer companies are ripping us off, and it's high time we did something about it. Join me in starting the revolution.",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/AHX6tHdQGiQ/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/AHX6tHdQGiQ/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/AHX6tHdQGiQ/hqdefault.jpg",
"width": 480,
"height": 360
}
},
"channelTitle": "AustinMcConnell",
"liveBroadcastContent": "none"
}
},
{
"kind": "youtube#searchResult",
"etag": "\"xwzn9fn_LczrfK9QS3iZcGzqRGs/kZJUmeb5Su2YvYD_s8U0NOD7exs\"",
"id": {
"kind": "youtube#video",
"videoId": "wW6cw4ydn-o"
},
"snippet": {
"publishedAt": "2008-09-28T17:25:10.000Z",
"channelId": "UCQlGBspQdj17WOPBQMT1k9A",
"title": "Computer Upgrades & Repairs : How to Change Cartridges on an Inkjet Printer",
"description": "Change cartridges on an Inkjet printer by opening the printer door and lifting up on the flap to unlock the cartridge. Remove and replace an Inkjet printer ...",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/wW6cw4ydn-o/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/wW6cw4ydn-o/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/wW6cw4ydn-o/hqdefault.jpg",
"width": 480,
"height": 360
}
},
"channelTitle": "expertvillage",
"liveBroadcastContent": "none"
}
},
{
"kind": "youtube#searchResult",
"etag": "\"xwzn9fn_LczrfK9QS3iZcGzqRGs/NmUS9NDUZ8TYGWot_MqUes4sCSw\"",
"id": {
"kind": "youtube#video",
"videoId": "_S2lYXf-uu0"
},
"snippet": {
"publishedAt": "2019-08-10T15:00:04.000Z",
"channelId": "UCcyq283he07B7_KUX07mmtA",
"title": "Why Printer Ink Is So Expensive | So Expensive",
"description": "Printer ink can sometimes cost more than the printer itself. We talk with a former editor of the Recycler to find out why printer ink is so expensive. MORE SO ...",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/_S2lYXf-uu0/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/_S2lYXf-uu0/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/_S2lYXf-uu0/hqdefault.jpg",
"width": 480,
"height": 360
}
},
"channelTitle": "Business Insider",
"liveBroadcastContent": "none"
}
},
{
"kind": "youtube#searchResult",
"etag": "\"xwzn9fn_LczrfK9QS3iZcGzqRGs/ykbIv6fovakqi13OenCoJ0fO6ko\"",
"id": {
"kind": "youtube#video",
"videoId": "kaHHvDuuGV0"
},
"snippet": {
"publishedAt": "2008-09-28T17:15:59.000Z",
"channelId": "UCQlGBspQdj17WOPBQMT1k9A",
"title": "Computer Upgrades & Repairs : How to Change a Laser Printer Cartridge",
"description": "Change a laser printer cartridge by opening the printer door and detaching the cartridge from the system. Remove and replace a laser printer cartridge with tips ...",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/kaHHvDuuGV0/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/kaHHvDuuGV0/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/kaHHvDuuGV0/hqdefault.jpg",
"width": 480,
"height": 360
}
},
"channelTitle": "expertvillage",
"liveBroadcastContent": "none"
}
},
{
"kind": "youtube#searchResult",
"etag": "\"xwzn9fn_LczrfK9QS3iZcGzqRGs/0uDr-nCvxGVm4yx-KYXrJ0ioCaE\"",
"id": {
"kind": "youtube#video",
"videoId": "wqmA8jpJae4"
},
"snippet": {
"publishedAt": "2015-08-04T19:33:12.000Z",
"channelId": "UCgFb3rcjC_J7o97bM10cPqg",
"title": "How to get more out of your ink cartridge",
"description": "In this video, we show you how you can extend the life of an ink cartridge by resetting the memory of the cartridge. Follow the steps to reset the ink cartridge ...",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/wqmA8jpJae4/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/wqmA8jpJae4/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/wqmA8jpJae4/hqdefault.jpg",
"width": 480,
"height": 360
}
},
"channelTitle": "Inkjet Star, Inc.",
"liveBroadcastContent": "none"
}
}
]
}
We can get statistics based on video-Id
. Below is a sample callout code and following is the response structure. To fetch stats for multiple videos we need to pass comma separated string of video-Ids
HttpRequest request = new HttpRequest();
HttpResponse response = new HttpResponse();
Http http = new Http();
request.setEndpoint('https://www.googleapis.com/youtube/v3/videos?part=statistics&id='+searchkeyword+'&key={YOUR_API_KEY}');
request.setMethod('GET');
try{
response = http.send(request);
System.debug(response.getBody());
}catch(System.CalloutException e) {
System.debug('Callout error: '+ e);
System.debug(response.toString());
}
Below is JSON response for the statistics of videos that were fetched for a sample case record in the previous section.
{
"kind": "youtube#videoListResponse",
"etag": "\"xwzn9fnLczrfK9QS3iZcGzqRGs/4F-j0jHUNnpEF28bWSk1U5QR6yc\"",
"pageInfo": {
"totalResults": 5,
"resultsPerPage": 5
},
"items": [
{
"kind": "youtube#video",
"etag": "\"xwzn9fnLczrfK9QS3iZcGzqRGs/QI9T-hGUzWJ3O4obR6JVd89ub44\"",
"id": "wW6cw4ydn-o",
"statistics": {
"viewCount": "2253",
"likeCount": "3",
"dislikeCount": "1",
"favoriteCount": "0",
"commentCount": "1"
}
},
{
"kind": "youtube#video",
"etag": "\"xwzn9fnLczrfK9QS3iZcGzqRGs/d9JBVFPfaMPeRR5lnpStZUfr5J0\"",
"id": "AHX6tHdQGiQ",
"statistics": {
"viewCount": "6783848",
"likeCount": "409704",
"dislikeCount": "8360",
"favoriteCount": "0",
"commentCount": "33588"
}
},
{
"kind": "youtube#video",
"etag": "\"xwzn9fnLczrfK9QS3iZcGzqRGs/fpZ1NnnKDFBKSB44bRAXwp-ORRQ\"",
"id": "kaHHvDuuGV0",
"statistics": {
"viewCount": "3789",
"likeCount": "2",
"dislikeCount": "4",
"favoriteCount": "0",
"commentCount": "0"
}
},
{
"kind": "youtube#video",
"etag": "\"xwzn9fnLczrfK9QS3iZcGzqRGs/QgSbp0b85uXwldHjwTcDRwvbTY\"",
"id": "S2lYXf-uu0",
"statistics": {
"viewCount": "1544592",
"likeCount": "30921",
"dislikeCount": "634",
"favoriteCount": "0",
"commentCount": "2507"
}
},
{
"kind": "youtube#video",
"etag": "\"xwzn9fnLczrfK9QS3iZcGzqRGs/b5l8HC-8KjG-rCu5CNMzSzQBBM8\"",
"id": "q3n7YYkRhVU",
"statistics": {
"viewCount": "24293",
"likeCount": "202",
"dislikeCount": "18",
"favoriteCount": "0",
"commentCount": "59"
}
}
]
}
The callout code snippets goes into the controller associated to the component - Youtube_API_V3 here
<aura:component controller="Youtube_API_V3" implements="force:hasSObjectName,force:hasRecordId,force:lightningQuickAction,force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,forceCommunity:availableForAllPageTypes" access="global">
<aura:attribute name="recordId" type="String" />
<aura:attribute name="sObjectName" type="String" />
<aura:attribute name="videoIds" type="Map"/>
<aura:attribute name="videoIds1" type="Map"/>
<aura:attribute name="searchKeyword" type="String"/>
<aura:attribute name="Message" type="boolean" default="false"/>
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<lightning:spinner variant="brand" size="large" aura:id="Id_spinner" class="slds-hide" />
<article class="slds-post" style="padding-top: 20px;border-radius: 5px;border: 1px solid #ccc;">
<div class="slds-card__body">
<aura:iteration items="{!v.videoIds}" var="video">
<div class="slds-feed">
<ul class="slds-feed__list">
<li class="slds-feed__item">
<article class="slds-card">
<div class="slds-card__body slds-card__body_inner">
<div style="margin-bottom:10px">
<h3 style="color: rgb(0, 109, 204);font-weight: bold;font-size: 14px;"> <aura:unescapedHtml value="{!video.value}"/></h3>
</div>
<div class="slds-post__payload">
<a href="javascript:void(0);" class="slds-media slds-box slds-grow slds-text-link_reset">
<div class="slds-media__figure slds-medium-show">
<div class="slds-file slds-size_small">
<iframe frameborder="10" src="{!'https://www.youtube.com/embed/'+video.key}" width="150" height="100" style="border:0px solid #ccc;border-radius:5px;"></iframe>
</div>
</div>
<div class="slds-media__body">
<!--<h3 class="slds-text-heading_small">{!video.value}</h3>-->
<!--<p>{!video.value}</p>-->
<span class="slds-text-body_small" style="width: 183px;margin-left: -90px;display: block;">{!video.description}</span>
</div>
</a>
</div>
</div>
<footer class="slds-post__footer">
<ul class="slds-post__footer-actions-list slds-list_horizontal">
</ul>
<ul style="padding:0 20px 10px 0px" class="slds-post__footer-meta-list slds-list_horizontal slds-has-dividers_right slds-text-title">
<li class="slds-item" id="{!video.key+'-shares'}">{!video.viewCount} views</li>
<li class="slds-item">{!video.likeCount} likes</li>
<li class="slds-item">{!video.dislikeCount} dislikes</li>
</ul>
</footer>
</article>
</li>
</ul>
</div>
</aura:iteration>
</div>
</article>
</aura:component>
({
doInit:function(component, event, helper) {
var action1 = component.get('c.getResponse');
action1.setParams({
"RecordId": component.get("v.recordId"),
"sObjectName" : component.get("v.sObjectName")
});
action1.setCallback(this, function(response){
var state = response.getState();
if((state === 'SUCCESS')){
var custs = [];
var conts = response.getReturnValue();
for ( var key in conts ) {
var title = conts[key].split('!@#$')[0];
var description = conts[key].split('!@#$')[1];
var viewCount = conts[key].split('!@#$')[2];
var likeCount = conts[key].split('!@#$')[3];
var dislikeCount = conts[key].split('!@#$')[4];
custs.push({value:title,key:key,description:description,viewCount:viewCount,likeCount:likeCount,dislikeCount:dislikeCount});
}
component.set("v.videoIds", custs);
} else if( state === 'INCOMPLETE'){
console.log("User is offline, device doesn't support.");
} else if( state === 'ERROR'){
console.log('Problem , error: ' +
JSON.stringify(response.getError()));
} else{
console.log('Unknown problem, state: ' + state +
', error: ' + JSON.stringify(response.getError()));
}
});
$A.enqueueAction(action1);
},
})
YouTube statistics: https://www.oberlo.com/blog/youtube-statistics