YouTube video integration is the process of embedding YouTube videos or the YouTube API into various apps, websites, or software systems. This integration enables users to access, view, and interact with YouTube videos immediately inside the context of the integrated platform. In this post, we will integrate YouTube Video API in Salesforce Lightning.
Common use cases of YouTube video integration
1. Content Enrichment
Incorporating YouTube videos into a website, blog, or application can enhance the content by adding visual and multimedia aspects that captivate consumers.
2. Marketing & Promotion
To engage customers and increase sales, businesses might integrate promotional videos, adverts, or product demos within their websites or applications.
3. Statistics and Tracking
Access to YouTube statistics is frequently included in integration, allowing content creators to track video performance, view counts, and user interaction. Users can quickly share integrated YouTube videos on social networking networks, increasing the reach of the content.
4. Email marketing
Marketers frequently incorporate YouTube video integration into email marketing. While email clients may not always support direct video embedding, marketers can include video thumbnails linked to YouTube, encouraging readers to click and watch the video.
Let us integrate YouTube videos into the Salesforce Lightning Web Component.
Steps for YouTube Video Integration
- Create a Project on Google
- Get YouTube Video API Key
- Create Apex Class to Integrate YouTube Video API
- Create LWC to show Videos
- Test Functionality
1. Create a Project in Google
Follow the steps mentioned in the section Create a user in Google Console from post Integrate Google API with Salesforce. In step 3 of this section, use YouTube Data API v3 to enable YouTube Video API. Rest of the steps will be similar to this section.
2. Get YouTube Video API Key
Once API is enabled, let us get the API key to use in Apex Code. You can get the API Key from the Credential Tab.

Get the API Key from the opened dialogue.

2. Create Apex Class to Integrate YouTube Video API
Create an apex class YouTubeVideoService to integrate YouTube API in Salesforce. I have used basic code for integration. You can use your API Integration framework for integration. If you don’t have any integration framework, then you can start with Generic Apex class for Calling External System
API Url – https://www.googleapis.com/youtube/v3/search
public class CalloutException extends Exception { | |
} |
public class YouTubeVideoService { | |
private static final String SEARCH_URL = 'https://www.googleapis.com/youtube/v3/search'; | |
private static final String API_KEY = 'AIzaSyBMfB1eG0w32r3SHXvzoF5k4FcgRduM-bM'; // Put Your API_KEY Here | |
public static List<VideoWrapper> getYTVideos(string searchKey, string pageToken){ | |
try | |
{ | |
searchKey = (searchKey == null) ? 'salesforce' : searchKey; | |
// YouTube API Callouts | |
Http http = new Http(); | |
HttpRequest req = new HttpRequest(); | |
Httpresponse res = null; | |
//maxResults - No of Video Need to return | |
//type - playlist, channel, video | |
String endpoint = SEARCH_URL + '?part=snippet' + '&maxResults=20&type=video' + | |
'&q=' + EncodingUtil.urlEncode(searchKey, 'UTF-8') + | |
'&key=' + API_KEY; | |
if(string.isNotBlank(pageToken)) | |
{ | |
endpoint+='&pageToken='+pageToken; | |
} | |
System.debug('endpoint '+endpoint); | |
req.setEndPoint(endpoint); | |
req.setMethod('GET'); | |
res = http.send(req); | |
// Deserializing json data | |
YouTubeData response = (YouTubeData)JSON.deserialize(res.getBody(), YouTubeData.class); | |
System.debug('response '+response); | |
List<YouTubeData.Item> items = response.items; | |
// Filling Wrapper Data for lightning component | |
List<VideoWrapper> videoList = new List<VideoWrapper>(); | |
if(response==null || response.items==null) return null; | |
VideoWrapper videoWrap=null; | |
for (YouTubeData.Item itemObj : response.items) { | |
videoWrap = new VideoWrapper(); | |
videoWrap.nextPageToken=response.nextPageToken; | |
videoWrap.prevPageToken=response.prevPageToken; | |
videoWrap.videoId = itemObj.id.videoId; | |
videoWrap.description = itemObj.Snippet.description; | |
videoWrap.thumbnails = itemObj.Snippet.thumbnails.medium.url; | |
videoWrap.title = itemObj.Snippet.title; | |
videoWrap.channelTitle = itemObj.Snippet.channelTitle; | |
videoList.add(videoWrap); | |
} | |
return videoList; | |
} | |
catch(Exception ex) | |
{ | |
throw new CalloutException(ex.getStackTraceString()); | |
} | |
} | |
} |
Wrapper Classes
Wrapper classes for the above integration are below. You can remove some of the properties which you don’t need.
public class VideoWrapper | |
{ | |
@AuraEnabled | |
public string videoId {get;set;} | |
@AuraEnabled | |
public string description {get;set;} | |
@AuraEnabled | |
public String thumbnails {get;set;} | |
@AuraEnabled | |
public String title {get;set;} | |
@AuraEnabled | |
public String channelTitle {get;set;} | |
@AuraEnabled | |
public String publishedAt {get;set;} | |
@AuraEnabled | |
public String nextPageToken {get;set;} | |
@AuraEnabled | |
public String prevPageToken {get;set;} | |
} |
public class YouTubeData | |
{ | |
public List<YouTubeData.Item> items { get; set; } | |
public String kind { get; set; } | |
public String etag { get; set; } | |
public String nextPageToken { get; set; } | |
public String prevPageToken { get; set; } | |
public YouTubeData.PageInfo pageInfo { get; set; } | |
public class PageInfo { | |
public Integer totalResults { get; set; } | |
public Integer resultsPerPage { get; set; } | |
} | |
public class Item { | |
public String kind { get; set; } | |
public String etag { get; set; } | |
public YouTubeData.Id id { get; set; } | |
public YouTubeData.Snippet snippet { get; set; } | |
} | |
public class Id { | |
public String kind { get; set; } | |
public String videoId { get; set; } | |
} | |
public class Snippet { | |
public Datetime publishedAt { get; set; } | |
public String channelId { get; set; } | |
public String title { get; set; } | |
public String description { get; set; } | |
public YouTubeData.Thumbnails thumbnails { get; set; } | |
public String channelTitle { get; set; } | |
public String liveBroadcastContent { get; set; } | |
} | |
public class Thumbnails { | |
public YouTubeData.Thumbnail medium { get; set; } | |
public YouTubeData.Thumbnail high { get; set; } | |
} | |
public class Thumbnail { | |
public String url { get; set; } | |
} | |
} |
YouTube Controller Class
Create a YouTube video controller class which will be called from Lightning Web Components.
public class VideoController { | |
@AuraEnabled | |
public static List<VideoWrapper> getVideos(string searchText,string page) | |
{ | |
if(string.isNotBlank(searchText)) | |
{ | |
return YouTubeVideoService.getYTVideos(searchText, page); | |
} | |
return null; | |
} | |
} |
4. Create LWC to show Videos
Create a Lightning Web Component to show videos using the apex class VideoController. Based on search criteria, we can get many records so we can add buttons to get the next/previous 20 (pagination size) records from API.
<template> | |
<lightning-card title="Video Explorer"> | |
<lightning-layout pull-to-boundary="medium"> | |
<lightning-layout-item flexibility="auto" padding="horizontal-medium"> | |
| |
</lightning-layout-item> | |
<lightning-layout-item flexibility="auto" padding="horizontal-medium"> | |
<lightning-input data-name="image" | |
name="enter-search" | |
label="Video Search Criteria" | |
type="search" | |
placeholder="Search Keyword" | |
></lightning-input> | |
</lightning-layout-item> | |
<lightning-layout-item flexibility="auto" padding="horizontal-medium"> | |
<lightning-button label="Get Videos" onclick={getVideos} style="padding-top:20px;margin-top:20px"></lightning-button> | |
</lightning-layout-item> | |
<lightning-layout-item flexibility="auto" padding="horizontal-medium"> | |
| |
</lightning-layout-item> | |
</lightning-layout> | |
<div class="slds-grid slds-wrap tilepart slds-scrollable_y slds-m-left_small"> | |
<template for:each={videoList} for:item="v"> | |
<div class="slds-has-dividers_around-space slds-box slds-m-around_xxx-small" | |
key={v.title} style="max-width: 300;;min-width: 300"> | |
<article class="slds-tile slds-tile_board"> | |
<iframe height="auto" src={v.url} frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> | |
<div style="width:250px"> | |
<h3 class="slds-tile__title" style="text-align: center;word-wrap: break-word;"> | |
{v.title} | |
</h3> | |
</div> | |
</article> | |
</div> | |
</template> | |
</div> | |
<template if:true={showPagination}> | |
<!-- Pagination Buttons Start --> | |
<div class="slds-align_absolute-center"> | |
<lightning-button label="Previous" icon-name="utility:chevronleft" onclick={previousHandler} | |
disabled={isPreviousDisable}> | |
</lightning-button> | |
<lightning-button label="Next" icon-name="utility:chevronright" icon-position="right" onclick={nextHandler} | |
disabled={isNextDisable}> | |
</lightning-button> | |
</div> | |
<!-- Pagination Buttons End --> | |
<!-- Datatable with Pagination End --> | |
</template> | |
</lightning-card> | |
</template> |
import { LightningElement,track } from 'lwc'; | |
import getVideos from '@salesforce/apex/VideoController.getVideos'; | |
export default class YoutubeVideoExplorer extends LightningElement { | |
@track videoList; | |
@track nextToken; | |
@track prevToken; | |
error; | |
isNextDisable=false; | |
isPreviousDisable=false; | |
showPagination=false; | |
getVideos(e) | |
{ | |
this.getYTVideos(''); | |
} | |
getYTVideos(token) | |
{ | |
console.log('Token-'+token); | |
var elm=this.template.querySelector('[data-name=image]').value; | |
getVideos({searchText: elm,page:token}) | |
.then((data,error) => { | |
if (data) { | |
data.forEach(function (element) { | |
element.url = 'https://www.youtube.com/embed/'+element.videoId; | |
}); | |
this.videoList=data; | |
if(data!==undefined) | |
{ | |
this.nextToken=data[0].nextPageToken; | |
this.prevToken=data[0].prevPageToken; | |
} | |
this.isPreviousDisable=(this.prevToken===undefined); | |
this.isNextDisableDisable=(this.nextToken===undefined); | |
this.showPagination=(this.isPreviousDisable||this.showPagination); | |
} else if (error) { | |
console.log('Error:'+ JSON.stringify(error)); | |
this.error = error; | |
} | |
}); | |
} | |
previousHandler(e) | |
{ | |
this.getYTVideos(this.prevToken); | |
this.isPreviousDisable=(this.prevToken==undefined); | |
} | |
nextHandler(e) | |
{ | |
this.getYTVideos(this.nextToken); | |
this.isNextDisable=(this.nextToken==undefined); | |
} | |
} |
<?xml version="1.0" encoding="UTF-8"?> | |
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> | |
<apiVersion>58.0</apiVersion> | |
<isExposed>true</isExposed> | |
<targets> | |
<target>lightningCommunity__Page</target> | |
<target>lightningCommunity__Default</target> | |
<target>lightning__RecordPage</target> | |
<target>lightning__AppPage</target> | |
<target>lightning__HomePage</target> | |
</targets> | |
</LightningComponentBundle> |
5. Test Functionality
Based on the above code integration it will show searched videos. Check out this video for a demo.
Reference
Integrate Google API with Salesforce
Related Posts
Object Identification using Google Cloud Vision in Salesforce
Logo Recognition using Google Cloud Vision in Salesforce
Extract Text From Image using Google Cloud Vision
2 Comments
The Return type of the VideoController return YouTubeVideoService.getYTVideos(searchText, ’20’); should be String format but in the blog it is been passed as a Number which is throwing an error
Hello Raj,
Code is updated. Please check and confirm.
Thank You,
Dhanik