Build a Sample Application
Stay organized with collections
Save and categorize content based on your preferences.
AI-generated Key Takeaways
-
This web application utilizes the YouTube Data API to fetch a user's uploaded videos and the YouTube Analytics API to retrieve viewing statistics for those videos.
-
The application leverages OAuth 2.0 for secure user authentication, granting it read-only access to the user's YouTube data and analytics.
-
The Google Visualization API is employed to dynamically generate charts that visually represent the retrieved YouTube analytics data, such as daily views.
-
The application uses JavaScript, including jQuery for DOM manipulation, and the Google APIs Client Library to streamline interactions with Google's services.
-
The application filters out videos with zero views, and shows a message if the user channel has no viewed videos or the channel ID cannot be found.
This page walks you through the steps of building an application that uses several different APIs to chart viewing statistics for a user's YouTube videos. The application performs the following tasks:
- It uses the YouTube Data API to retrieve a list of the currently authenticated user's uploaded videos and then displays a list of video titles.
- When the user clicks on a particular video, the application calls the YouTube Analytics API to retrieve analytics data for that video.
- The application uses the Google Visualization API to chart the analytics data.
The following steps describe the process of building the application. In step 1, you create the application's HTML and CSS files. Steps 2 through 5 describe different parts of the JavaScript that the application uses. The complete sample code is also included at the end of the document.
- Step 1: Build your HTML page and CSS file
- Step 2: Enable OAuth 2.0 authentication
- Step 3: Retrieve data for the currently logged-in user
- Step 4: Request Analytics data for a video
- Step 5: Display Analytics data in a chart
Important: You need to register your application with Google to obtain an OAuth 2.0 client ID for your application.
Step 1: Build your HTML page and CSS file
In this step, you'll create an HTML page that loads the JavaScript libraries that the application will use. The HTML below shows the code for the page:
<!doctypehtml> <html> <head> <title>GoogleI/OYouTubeCodelab</title> <linktype="text/css"rel="stylesheet"href="index.css"> <scripttype="text/javascript"src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <scripttype="text/javascript"src="//www.google.com/jsapi"></script> <scripttype="text/javascript"src="index.js"></script> <scripttype="text/javascript"src="https://apis.google.com/js/client.js?onload=onJSClientLoad"></script> </head> <body> <divid="login-container"class="pre-auth">ThisapplicationrequiresaccesstoyourYouTubeaccount. Please<ahref="#"id="login-link">authorize</a>tocontinue. </div> <divclass="post-auth"> <divid="message"></div> <divid="chart"></div> <div>ChooseaVideo:</div> <ulid="video-list"></ul> </div> </body> </html>
As shown in the <head> tag of the sample page, the application uses the following libraries:
- jQuery provides helper methods to simplify HTML document traversing, event handling, animating and Ajax interactions.
- The Google API loader (
www.google.com/jsapi) lets you easily import one or more Google APIs. This sample application uses the API loader to load the Google Visualization API, which is used to chart the retrieved Analytics data. - The index.js library contains functions specific to the sample application. This tutorial walks you through the steps to create those functions.
- The Google APIs Client Library for JavaScript helps you to implement OAuth 2.0 authentication and to call the YouTube Analytics API.
The sample application also includes the index.css file. A sample CSS file, which you could save in the same directory as your HTML page, is shown below:
body {
font-family: Helvetica, sans-serif;
}
.pre-auth {
display: none;
}
.post-auth {
display: none;
}
#chart {
width: 500px;
height: 300px;
margin-bottom: 1em;
}
#video-list {
padding-left: 1em;
list-style-type: none;
}
#video-list > li {
cursor: pointer;
}
#video-list > li:hover {
color: blue;
}
Step 2: Enable OAuth 2.0 authentication
In this step, you'll start building the index.js file that's being called by your HTML page. With that in mind, create a file named index.js in the same directory as your HTML page and insert the following code in that file. Replace the string YOUR_CLIENT_ID with the client ID for your registered application.
(function(){ //RetrieveyourclientIDfromtheGoogleAPIConsoleat //https://console.cloud.google.com/. varOAUTH2_CLIENT_ID='YOUR_CLIENT_ID'; varOAUTH2_SCOPES=[ 'https://www.googleapis.com/auth/yt-analytics.readonly', 'https://www.googleapis.com/auth/youtube.readonly' ]; //Uponloading,theGoogleAPIsJSclientautomaticallyinvokesthiscallback. //Seehttps://developers.google.com/api-client-library/javascript/features/authentication window.onJSClientLoad=function(){ gapi.auth.init(function(){ window.setTimeout(checkAuth,1); }); }; //AttempttheimmediateOAuth2.0clientflowassoonasthepageloads. //Ifthecurrentlylogged-inGoogleAccounthaspreviouslyauthorized //theclientspecifiedastheOAUTH2_CLIENT_ID,thentheauthorization //succeedswithnouserintervention.Otherwise,itfailsandthe //userinterfacethatpromptsforauthorizationneedstodisplay. functioncheckAuth(){ gapi.auth.authorize({ client_id:OAUTH2_CLIENT_ID, scope:OAUTH2_SCOPES, immediate:true },handleAuthResult); } //Handletheresultofagapi.auth.authorize()call. functionhandleAuthResult(authResult){ if(authResult){ //Authorizationwassuccessful.Hideauthorizationpromptsandshow //contentthatshouldbevisibleafterauthorizationsucceeds. $('.pre-auth').hide(); $('.post-auth').show(); loadAPIClientInterfaces(); }else{ //Authorizationwasunsuccessful.Showcontentrelatedtopromptingfor //authorizationandhidecontentthatshouldbevisibleifauthorization //succeeds. $('.post-auth').hide(); $('.pre-auth').show(); //Makethe#login-link clickable. Attempt a non-immediate OAuth 2.0 //clientflow.Thecurrentfunctioniscalledwhenthatflowcompletes. $('#login-link').click(function(){ gapi.auth.authorize({ client_id:OAUTH2_CLIENT_ID, scope:OAUTH2_SCOPES, immediate:false },handleAuthResult); }); } } //Thishelpermethoddisplaysamessageonthepage. functiondisplayMessage(message){ $('#message').text(message).show(); } //Thishelpermethodhidesapreviouslydisplayedmessageonthepage. functionhideMessage(){ $('#message').hide(); } /*Inlatersteps,addadditionalfunctionsabovethisline.*/ })();
Step 3: Retrieve data for the currently logged-in user
In this step, you'll add a function to your index.js file that retrieves the currently logged-in user's uploaded videos feed using the YouTube Data API (v2.0). That feed will specify the user's YouTube channel ID, which you will need when calling the YouTube Analytics API. In addition, the sample app will list the user's uploaded videos so that the user can retrieve Analytics data for any individual video.
Make the following changes to your index.js file:
-
Add a function that loads the client interface for the YouTube Analytics and Data APIs. This is a prerequisite to using the Google APIs JavaScript client.
Once both API client interfaces are loaded, the function calls the
getUserChannelfunction.//LoadtheclientinterfacesfortheYouTubeAnalyticsandDataAPIs,which //arerequiredtousetheGoogleAPIsJSclient.Moreinfoisavailableat //https://developers.google.com/api-client-library/javascript/dev/dev_jscript#loading-the-client-library-and-the-api functionloadAPIClientInterfaces(){ gapi.client.load('youtube','v3',function(){ gapi.client.load('youtubeAnalytics','v1',function(){ //Afterbothclientinterfacesload,usetheDataAPItorequest //informationabouttheauthenticateduser's channel. getUserChannel(); }); }); }
-
Add the
channelIdvariable as well as thegetUserChannelfunction. The function calls the YouTube Data API (v3) and includes themineparameter, which indicates that the request is for the currently authenticated user's channel information. ThechannelIdwill be sent to the Analytics API to identify the channel for whom you are retrieving Analytics data.//Keeptrackofthecurrentlyauthenticateduser's YouTube channel ID. varchannelId; //CalltheDataAPItoretrieveinformationaboutthecurrently //authenticateduser's YouTube channel. functiongetUserChannel(){ //Alsosee:https://developers.google.com/youtube/v3/docs/channels/list varrequest=gapi.client.youtube.channels.list({ //Settingthe"mine"requestparameter's value to "true" indicates that //youwanttoretrievethecurrentlyauthenticateduser's channel. mine:true, part:'id,contentDetails' }); request.execute(function(response){ if('error'inresponse){ displayMessage(response.error.message); }else{ //Weneedthechannel's channel ID to make calls to the Analytics API. //ThechannelIDvaluehastheform"UCdLFeWKpkLhkguiMZUp8lWA". channelId=response.items[0].id; //RetrievetheplaylistIDthatuniquelyidentifiestheplaylistof //videosuploadedtotheauthenticateduser's channel. This value has //theform"UUdLFeWKpkLhkguiMZUp8lWA". varuploadsListId=response.items[0].contentDetails.relatedPlaylists.uploads; //UsetheplaylistIDtoretrievethelistofuploadedvideos. getPlaylistItems(uploadsListId); } }); }
-
Add the
getPlaylistItemsfunction, which retrieves the items in a specified playlist. In this case, the playlist lists the videos uploaded to the user's channel. (Note that the sample function below only retrieves the first 50 items in that feed, and you would need to implement pagination to fetch additional items.)After retrieving the list of playlist items, the function calls the
getVideoMetadata()function. That function then obtains metadata about each video in the list and adds each video to the list that the user sees.//CalltheDataAPItoretrievetheitemsinaparticularplaylist.Inthis //example,weareretrievingaplaylistofthecurrentlyauthenticateduser's //uploadedvideos.Bydefault,thelistreturnsthemostrecentvideosfirst. functiongetPlaylistItems(listId){ //Seehttps://developers.google.com/youtube/v3/docs/playlistitems/list varrequest=gapi.client.youtube.playlistItems.list({ playlistId:listId, part:'snippet' }); request.execute(function(response){ if('error'inresponse){ displayMessage(response.error.message); }else{ if('items'inresponse){ //ThejQuery.map()functioniteratesthroughalloftheitemsin //theresponseandcreatesanewarraythatonlycontainsthe //specificpropertywe're looking for: videoId. varvideoIds=$.map(response.items,function(item){ returnitem.snippet.resourceId.videoId; }); //NowthatweknowtheIDsofallthevideosintheuploadslist, //wecanretrieveinformationabouteachvideo. getVideoMetadata(videoIds); }else{ displayMessage('There are no videos in your channel.'); } } }); } //GivenanarrayofvideoIDs,thisfunctionobtainsmetadataabouteach //videoandthenusesthatmetadatatodisplayalistofvideos. functiongetVideoMetadata(videoIds){ //https://developers.google.com/youtube/v3/docs/videos/list varrequest=gapi.client.youtube.videos.list({ //The'id'property's value is a comma-separated string of video IDs. id:videoIds.join(','), part:'id,snippet,statistics' }); request.execute(function(response){ if('error'inresponse){ displayMessage(response.error.message); }else{ //GetthejQuerywrapperforthe#video-list element before starting //theloop. varvideoList=$('#video-list'); $.each(response.items,function(){ //Excludevideosthatdonothaveanyviews,sincethosevideos //willnothaveanyinterestingviewcountAnalyticsdata. if(this.statistics.viewCount==0){ return; } vartitle=this.snippet.title; varvideoId=this.id; //Createanew<li>elementthatcontainsan<a>element. //Setthe<a>element's text content to the video'stitle,and //addaclickhandlerthatwilldisplayAnalyticsdatawheninvoked. varliElement=$('<li>'); varaElement=$('<a>'); //Settingthehrefvalueto'#'ensuresthatthebrowserrendersthe //<a>elementasaclickablelink. aElement.attr('href','#'); aElement.text(title); aElement.click(function(){ displayVideoAnalytics(videoId); }); //CallthejQuery.append()methodtoaddthenew<a>elementto //the<li>element,andthe<li>elementtotheparent //list,whichisidentifiedbythe'videoList'variable. liElement.append(aElement); videoList.append(liElement); }); if(videoList.children().length==0){ //Displayamessageifthechanneldoesnothaveanyviewedvideos. displayMessage('Your channel does not have any videos that have been viewed.'); } } }); }
Step 4: Request Analytics data for a video
In this step, you'll modify the sample application so that when you click on a video's title, the application calls the YouTube Analytics API to retrieve Analytics data for that video. To do so, make the following changes to the sample application:
-
Add a variable that specifies the default date range for the retrieved Analytics report data.
varONE_MONTH_IN_MILLISECONDS=1000*60*60*24*30;
-
Add code that creates a
YYYY-MM-DDstring for a date object and that pads day and month numbers in dates to two digits://ThisboilerplatecodetakesaDateobjectandreturnsaYYYY-MM-DDstring. functionformatDateString(date){ varyyyy=date.getFullYear().toString(); varmm=padToTwoCharacters(date.getMonth()+1); vardd=padToTwoCharacters(date.getDate()); returnyyyy+'-'+mm+'-'+dd; } //Ifnumberisasingledigit,prependa'0'.Otherwise,returnthenumber //asastring. functionpadToTwoCharacters(number){ if(number < 10){ return'0'+number; }else{ returnnumber.toString(); } }
-
Define the
displayVideoAnalyticsfunction, which retrieves YouTube Analytics data for a video. This function will execute when the user clicks on a video in the list. ThegetVideoMetadatafunction, which prints the list of videos and was defined in step 3, defines the click event handler.//ThisfunctionrequestsYouTubeAnalyticsdataforavideoanddisplays //theresultsinachart. functiondisplayVideoAnalytics(videoId){ if(channelId){ //Touseadifferentdaterange,modifytheONE_MONTH_IN_MILLISECONDS //variabletoadifferentmilliseconddeltaasdesired. vartoday=newDate(); varlastMonth=newDate(today.getTime()-ONE_MONTH_IN_MILLISECONDS); varrequest=gapi.client.youtubeAnalytics.reports.query({ //Thestart-dateandend-dateparametersmustbeYYYY-MM-DDstrings. 'start-date':formatDateString(lastMonth), 'end-date':formatDateString(today), //Atthistime,youneedtoexplicitlyspecifychannel==channelId. //Seehttps://developers.google.com/youtube/analytics/v1/#ids ids:'channel=='+channelId, dimensions:'day', sort:'day', //Seehttps://developers.google.com/youtube/analytics/v1/available_reports //fordetailsaboutthedifferentfiltersandmetricsyoucanrequest //ifthe"dimensions"parametervalueis"day". metrics:'views', filters:'video=='+videoId }); request.execute(function(response){ //Thisfunctioniscalledregardlessofwhethertherequestsucceeds. //TheresponsecontainsYouTubeAnalyticsdataoranerrormessage. if('error'inresponse){ displayMessage(response.error.message); }else{ displayChart(videoId,response); } }); }else{ //Thecurrentlyauthenticateduser's channel ID is not available. displayMessage('The YouTube channel ID for the current user is not available.'); } }
See the API documentation's available reports page for more information about the data that could be retrieved and valid value combinations for the
metrics,dimensions, andfiltersparameters.
Step 5: Display Analytics data in a chart
In this step, you'll add the displayChart function, which sends the YouTube Analytics data to the Google Visualization API. That API then charts the information.
-
Load the Google Visualization API, which will display your data in a chart. See the Visualization API documentation for more details about charting options.
google.load('visualization','1.0',{'packages':['corechart']});
-
Define a new function named
displayChartthat uses the Google Visualization API to dynamically generate a chart showing the Analytics data.//CalltheGoogleChartToolsAPItogenerateachartofAnalyticsdata. functiondisplayChart(videoId,response){ if('rows'inresponse){ hideMessage(); //ThecolumnHeaderspropertycontainsanarrayofobjectsrepresenting //eachcolumn's title -- e.g.: [{name:"day"},{name:"views"}] // We need these column titles as a simple array, so we call jQuery.map() // to get each element's"name"propertyandcreateanewarraythatonly //containsthosevalues. varcolumns=$.map(response.columnHeaders,function(item){ returnitem.name; }); //Thegoogle.visualization.arrayToDataTable()functionwantsanarray //ofarrays.Thefirstelementisanarrayofcolumntitles,calculated //aboveas"columns".Theremainingelementsarearraysthateach //representarowofdata.Fortunately,response.rowsisalreadyin //thisformat,soitcanjustbeconcatenated. //Seehttps://developers.google.com/chart/interactive/docs/datatables_dataviews#arraytodatatable varchartDataArray=[columns].concat(response.rows); varchartDataTable=google.visualization.arrayToDataTable(chartDataArray); varchart=newgoogle.visualization.LineChart(document.getElementById('chart')); chart.draw(chartDataTable,{ //Additionaloptionscanbesetifdesiredasdescribedat: //https://developers.google.com/chart/interactive/docs/reference#visdraw title:'Views per Day of Video '+videoId }); }else{ displayMessage('No data available for video '+videoId); } }
See the complete index.js file
The index.js file below incorporates all of the changes from the steps shown above. Again, remember that you need to replace the string YOUR_CLIENT_ID with the client ID for your registered application.
(function(){ //RetrieveyourclientIDfromtheGoogleAPIConsoleat //https://console.cloud.google.com/. varOAUTH2_CLIENT_ID='YOUR_CLIENT_ID'; varOAUTH2_SCOPES=[ 'https://www.googleapis.com/auth/yt-analytics.readonly', 'https://www.googleapis.com/auth/youtube.readonly' ]; varONE_MONTH_IN_MILLISECONDS=1000*60*60*24*30; //Keeptrackofthecurrentlyauthenticateduser's YouTube channel ID. varchannelId; //ForinformationabouttheGoogleChartToolsAPI,see: //https://developers.google.com/chart/interactive/docs/quick_start google.load('visualization','1.0',{'packages':['corechart']}); //Uponloading,theGoogleAPIsJSclientautomaticallyinvokesthiscallback. //Seehttps://developers.google.com/api-client-library/javascript/features/authentication window.onJSClientLoad=function(){ gapi.auth.init(function(){ window.setTimeout(checkAuth,1); }); }; //AttempttheimmediateOAuth2.0clientflowassoonasthepageloads. //Ifthecurrentlylogged-inGoogleAccounthaspreviouslyauthorized //theclientspecifiedastheOAUTH2_CLIENT_ID,thentheauthorization //succeedswithnouserintervention.Otherwise,itfailsandthe //userinterfacethatpromptsforauthorizationneedstodisplay. functioncheckAuth(){ gapi.auth.authorize({ client_id:OAUTH2_CLIENT_ID, scope:OAUTH2_SCOPES, immediate:true },handleAuthResult); } //Handletheresultofagapi.auth.authorize()call. functionhandleAuthResult(authResult){ if(authResult){ //Authorizationwassuccessful.Hideauthorizationpromptsandshow //contentthatshouldbevisibleafterauthorizationsucceeds. $('.pre-auth').hide(); $('.post-auth').show(); loadAPIClientInterfaces(); }else{ //Authorizationwasunsuccessful.Showcontentrelatedtopromptingfor //authorizationandhidecontentthatshouldbevisibleifauthorization //succeeds. $('.post-auth').hide(); $('.pre-auth').show(); //Makethe#login-link clickable. Attempt a non-immediate OAuth 2.0 //clientflow.Thecurrentfunctioniscalledwhenthatflowcompletes. $('#login-link').click(function(){ gapi.auth.authorize({ client_id:OAUTH2_CLIENT_ID, scope:OAUTH2_SCOPES, immediate:false },handleAuthResult); }); } } //LoadtheclientinterfacesfortheYouTubeAnalyticsandDataAPIs,which //arerequiredtousetheGoogleAPIsJSclient.Moreinfoisavailableat //https://developers.google.com/api-client-library/javascript/dev/dev_jscript#loading-the-client-library-and-the-api functionloadAPIClientInterfaces(){ gapi.client.load('youtube','v3',function(){ gapi.client.load('youtubeAnalytics','v1',function(){ //Afterbothclientinterfacesload,usetheDataAPItorequest //informationabouttheauthenticateduser's channel. getUserChannel(); }); }); } //CalltheDataAPItoretrieveinformationaboutthecurrently //authenticateduser's YouTube channel. functiongetUserChannel(){ //Alsosee:https://developers.google.com/youtube/v3/docs/channels/list varrequest=gapi.client.youtube.channels.list({ //Settingthe"mine"requestparameter's value to "true" indicates that //youwanttoretrievethecurrentlyauthenticateduser's channel. mine:true, part:'id,contentDetails' }); request.execute(function(response){ if('error'inresponse){ displayMessage(response.error.message); }else{ //Weneedthechannel's channel ID to make calls to the Analytics API. //ThechannelIDvaluehastheform"UCdLFeWKpkLhkguiMZUp8lWA". channelId=response.items[0].id; //RetrievetheplaylistIDthatuniquelyidentifiestheplaylistof //videosuploadedtotheauthenticateduser's channel. This value has //theform"UUdLFeWKpkLhkguiMZUp8lWA". varuploadsListId=response.items[0].contentDetails.relatedPlaylists.uploads; //UsetheplaylistIDtoretrievethelistofuploadedvideos. getPlaylistItems(uploadsListId); } }); } //CalltheDataAPItoretrievetheitemsinaparticularplaylist.Inthis //example,weareretrievingaplaylistofthecurrentlyauthenticateduser's //uploadedvideos.Bydefault,thelistreturnsthemostrecentvideosfirst. functiongetPlaylistItems(listId){ //Seehttps://developers.google.com/youtube/v3/docs/playlistitems/list varrequest=gapi.client.youtube.playlistItems.list({ playlistId:listId, part:'snippet' }); request.execute(function(response){ if('error'inresponse){ displayMessage(response.error.message); }else{ if('items'inresponse){ //ThejQuery.map()functioniteratesthroughalloftheitemsin //theresponseandcreatesanewarraythatonlycontainsthe //specificpropertywe're looking for: videoId. varvideoIds=$.map(response.items,function(item){ returnitem.snippet.resourceId.videoId; }); //NowthatweknowtheIDsofallthevideosintheuploadslist, //wecanretrieveinformationabouteachvideo. getVideoMetadata(videoIds); }else{ displayMessage('There are no videos in your channel.'); } } }); } //GivenanarrayofvideoIDs,thisfunctionobtainsmetadataabouteach //videoandthenusesthatmetadatatodisplayalistofvideos. functiongetVideoMetadata(videoIds){ //https://developers.google.com/youtube/v3/docs/videos/list varrequest=gapi.client.youtube.videos.list({ //The'id'property's value is a comma-separated string of video IDs. id:videoIds.join(','), part:'id,snippet,statistics' }); request.execute(function(response){ if('error'inresponse){ displayMessage(response.error.message); }else{ //GetthejQuerywrapperforthe#video-list element before starting //theloop. varvideoList=$('#video-list'); $.each(response.items,function(){ //Excludevideosthatdonothaveanyviews,sincethosevideos //willnothaveanyinterestingviewcountAnalyticsdata. if(this.statistics.viewCount==0){ return; } vartitle=this.snippet.title; varvideoId=this.id; //Createanew<li>elementthatcontainsan<a>element. //Setthe<a>element's text content to the video'stitle,and //addaclickhandlerthatwilldisplayAnalyticsdatawheninvoked. varliElement=$('<li>'); varaElement=$('<a>'); //Settingthehrefvalueto'#'ensuresthatthebrowserrendersthe //<a>elementasaclickablelink. aElement.attr('href','#'); aElement.text(title); aElement.click(function(){ displayVideoAnalytics(videoId); }); //CallthejQuery.append()methodtoaddthenew<a>elementto //the<li>element,andthe<li>elementtotheparent //list,whichisidentifiedbythe'videoList'variable. liElement.append(aElement); videoList.append(liElement); }); if(videoList.children().length==0){ //Displayamessageifthechanneldoesnothaveanyviewedvideos. displayMessage('Your channel does not have any videos that have been viewed.'); } } }); } //ThisfunctionrequestsYouTubeAnalyticsdataforavideoanddisplays //theresultsinachart. functiondisplayVideoAnalytics(videoId){ if(channelId){ //Touseadifferentdaterange,modifytheONE_MONTH_IN_MILLISECONDS //variabletoadifferentmilliseconddeltaasdesired. vartoday=newDate(); varlastMonth=newDate(today.getTime()-ONE_MONTH_IN_MILLISECONDS); varrequest=gapi.client.youtubeAnalytics.reports.query({ //Thestart-dateandend-dateparametersmustbeYYYY-MM-DDstrings. 'start-date':formatDateString(lastMonth), 'end-date':formatDateString(today), //Atthistime,youneedtoexplicitlyspecifychannel==channelId. //Seehttps://developers.google.com/youtube/analytics/v1/#ids ids:'channel=='+channelId, dimensions:'day', sort:'day', //Seehttps://developers.google.com/youtube/analytics/v1/available_reports //fordetailsaboutthedifferentfiltersandmetricsyoucanrequest //ifthe"dimensions"parametervalueis"day". metrics:'views', filters:'video=='+videoId }); request.execute(function(response){ //Thisfunctioniscalledregardlessofwhethertherequestsucceeds. //TheresponsecontainsYouTubeAnalyticsdataoranerrormessage. if('error'inresponse){ displayMessage(response.error.message); }else{ displayChart(videoId,response); } }); }else{ //Thecurrentlyauthenticateduser's channel ID is not available. displayMessage('The YouTube channel ID for the current user is not available.'); } } //ThisboilerplatecodetakesaDateobjectandreturnsaYYYY-MM-DDstring. functionformatDateString(date){ varyyyy=date.getFullYear().toString(); varmm=padToTwoCharacters(date.getMonth()+1); vardd=padToTwoCharacters(date.getDate()); returnyyyy+'-'+mm+'-'+dd; } //Ifnumberisasingledigit,prependa'0'.Otherwise,returnthenumber //asastring. functionpadToTwoCharacters(number){ if(number < 10){ return'0'+number; }else{ returnnumber.toString(); } } //CalltheGoogleChartToolsAPItogenerateachartofAnalyticsdata. functiondisplayChart(videoId,response){ if('rows'inresponse){ hideMessage(); //ThecolumnHeaderspropertycontainsanarrayofobjectsrepresenting //eachcolumn's title -- e.g.: [{name:"day"},{name:"views"}] //Weneedthesecolumntitlesasasimplearray,sowecalljQuery.map() //togeteachelement's "name" property and create a new array that only //containsthosevalues. varcolumns=$.map(response.columnHeaders,function(item){ returnitem.name; }); //Thegoogle.visualization.arrayToDataTable()functionwantsanarray //ofarrays.Thefirstelementisanarrayofcolumntitles,calculated //aboveas"columns".Theremainingelementsarearraysthateach //representarowofdata.Fortunately,response.rowsisalreadyin //thisformat,soitcanjustbeconcatenated. //Seehttps://developers.google.com/chart/interactive/docs/datatables_dataviews#arraytodatatable varchartDataArray=[columns].concat(response.rows); varchartDataTable=google.visualization.arrayToDataTable(chartDataArray); varchart=newgoogle.visualization.LineChart(document.getElementById('chart')); chart.draw(chartDataTable,{ //Additionaloptionscanbesetifdesiredasdescribedat: //https://developers.google.com/chart/interactive/docs/reference#visdraw title:'Views per Day of Video '+videoId }); }else{ displayMessage('No data available for video '+videoId); } } //Thishelpermethoddisplaysamessageonthepage. functiondisplayMessage(message){ $('#message').text(message).show(); } //Thishelpermethodhidesapreviouslydisplayedmessageonthepage. functionhideMessage(){ $('#message').hide(); } })();