Skip to content

Commit eec604e

Browse files
"Added sample: javascript/analytics_codelab.js"
1 parent 3cf79a5 commit eec604e

1 file changed

Lines changed: 297 additions & 0 deletions

File tree

javascript/analytics_codelab.js

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
(function() {
2+
// Retrieve your client ID from the {{ Google Cloud Console }} at
3+
// {{ https://cloud.google.com/console }}.
4+
var OAUTH2_CLIENT_ID = 'YOUR_CLIENT_ID';
5+
var OAUTH2_SCOPES = [
6+
'https://www.googleapis.com/auth/yt-analytics.readonly',
7+
'https://www.googleapis.com/auth/youtube.readonly'
8+
];
9+
10+
var ONE_MONTH_IN_MILLISECONDS = 1000 * 60 * 60 * 24 * 30;
11+
12+
// Keep track of the currently authenticated user's YouTube channel ID.
13+
var channelId;
14+
15+
// For information about the Google Chart Tools API, see:
16+
// https://developers.google.com/chart/interactive/docs/quick_start
17+
google.load('visualization', '1.0', {'packages': ['corechart']});
18+
19+
// Upon loading, the Google APIs JS client automatically invokes this callback.
20+
// See http://code.google.com/p/google-api-javascript-client/wiki/Authentication
21+
window.onJSClientLoad = function() {
22+
gapi.auth.init(function() {
23+
window.setTimeout(checkAuth, 1);
24+
});
25+
};
26+
27+
// Attempt the immediate OAuth 2.0 client flow as soon as the page loads.
28+
// If the currently logged-in Google Account has previously authorized
29+
// the client specified as the OAUTH2_CLIENT_ID, then the authorization
30+
// succeeds with no user intervention. Otherwise, it fails and the
31+
// user interface that prompts for authorization needs to display.
32+
function checkAuth() {
33+
gapi.auth.authorize({
34+
client_id: OAUTH2_CLIENT_ID,
35+
scope: OAUTH2_SCOPES,
36+
immediate: true
37+
}, handleAuthResult);
38+
}
39+
40+
// Handle the result of a gapi.auth.authorize() call.
41+
function handleAuthResult(authResult) {
42+
if (authResult) {
43+
// Authorization was successful. Hide authorization prompts and show
44+
// content that should be visible after authorization succeeds.
45+
$('.pre-auth').hide();
46+
$('.post-auth').show();
47+
48+
loadAPIClientInterfaces();
49+
} else {
50+
// Authorization was unsuccessful. Show content related to prompting for
51+
// authorization and hide content that should be visible if authorization
52+
// succeeds.
53+
$('.post-auth').hide();
54+
$('.pre-auth').show();
55+
56+
// Make the #login-link clickable. Attempt a non-immediate OAuth 2.0
57+
// client flow. The current function is called when that flow completes.
58+
$('#login-link').click(function() {
59+
gapi.auth.authorize({
60+
client_id: OAUTH2_CLIENT_ID,
61+
scope: OAUTH2_SCOPES,
62+
immediate: false
63+
}, handleAuthResult);
64+
});
65+
}
66+
}
67+
68+
// Load the client interfaces for the YouTube Analytics and Data APIs, which
69+
// are required to use the Google APIs JS client. More info is available at
70+
// http://code.google.com/p/google-api-javascript-client/wiki/GettingStarted#Loading_the_Client
71+
function loadAPIClientInterfaces() {
72+
gapi.client.load('youtube', 'v3', function() {
73+
gapi.client.load('youtubeAnalytics', 'v1', function() {
74+
// After both client interfaces load, use the Data API to request
75+
// information about the authenticated user's channel.
76+
getUserChannel();
77+
});
78+
});
79+
}
80+
81+
// Call the Data API to retrieve information about the currently
82+
// authenticated user's YouTube channel.
83+
function getUserChannel() {
84+
// Also see: https://developers.google.com/youtube/v3/docs/channels/list
85+
var request = gapi.client.youtube.channels.list({
86+
// Setting the "mine" request parameter's value to "true" indicates that
87+
// you want to retrieve the currently authenticated user's channel.
88+
mine: true,
89+
part: 'id,contentDetails'
90+
});
91+
92+
request.execute(function(response) {
93+
if ('error' in response) {
94+
displayMessage(response.error.message);
95+
} else {
96+
// We need the channel's channel ID to make calls to the Analytics API.
97+
// The channel ID value has the form "UCdLFeWKpkLhkguiMZUp8lWA".
98+
channelId = response.items[0].id;
99+
// Retrieve the playlist ID that uniquely identifies the playlist of
100+
// videos uploaded to the authenticated user's channel. This value has
101+
// the form "UUdLFeWKpkLhkguiMZUp8lWA".
102+
var uploadsListId = response.items[0].contentDetails.relatedPlaylists.uploads;
103+
// Use the playlist ID to retrieve the list of uploaded videos.
104+
getPlaylistItems(uploadsListId);
105+
}
106+
});
107+
}
108+
109+
// Call the Data API to retrieve the items in a particular playlist. In this
110+
// example, we are retrieving a playlist of the currently authenticated user's
111+
// uploaded videos. By default, the list returns the most recent videos first.
112+
function getPlaylistItems(listId) {
113+
// See https://developers.google.com/youtube/v3/docs/playlistitems/list
114+
var request = gapi.client.youtube.playlistItems.list({
115+
playlistId: listId,
116+
part: 'snippet'
117+
});
118+
119+
request.execute(function(response) {
120+
if ('error' in response) {
121+
displayMessage(response.error.message);
122+
} else {
123+
if ('items' in response) {
124+
// The jQuery.map() function iterates through all of the items in
125+
// the response and creates a new array that only contains the
126+
// specific property we're looking for: videoId.
127+
var videoIds = $.map(response.items, function(item) {
128+
return item.snippet.resourceId.videoId;
129+
});
130+
131+
// Now that we know the IDs of all the videos in the uploads list,
132+
// we can retrieve information about each video.
133+
getVideoMetadata(videoIds);
134+
} else {
135+
displayMessage('There are no videos in your channel.');
136+
}
137+
}
138+
});
139+
}
140+
141+
// Given an array of video IDs, this function obtains metadata about each
142+
// video and then uses that metadata to display a list of videos.
143+
function getVideoMetadata(videoIds) {
144+
// https://developers.google.com/youtube/v3/docs/videos/list
145+
var request = gapi.client.youtube.videos.list({
146+
// The 'id' property's value is a comma-separated string of video IDs.
147+
id: videoIds.join(','),
148+
part: 'id,snippet,statistics'
149+
});
150+
151+
request.execute(function(response) {
152+
if ('error' in response) {
153+
displayMessage(response.error.message);
154+
} else {
155+
// Get the jQuery wrapper for the #video-list element before starting
156+
// the loop.
157+
var videoList = $('#video-list');
158+
$.each(response.items, function() {
159+
// Exclude videos that do not have any views, since those videos
160+
// will not have any interesting viewcount Analytics data.
161+
if (this.statistics.viewCount == 0) {
162+
return;
163+
}
164+
165+
var title = this.snippet.title;
166+
var videoId = this.id;
167+
168+
// Create a new <li> element that contains an <a> element.
169+
// Set the <a> element's text content to the video's title, and
170+
// add a click handler that will display Analytics data when invoked.
171+
var liElement = $('<li>');
172+
var aElement = $('<a>');
173+
// Setting the href value to '#' ensures that the browser renders the
174+
// &lt;a&gt; element as a clickable link.
175+
aElement.attr('href', '#');
176+
aElement.text(title);
177+
aElement.click(function() {
178+
displayVideoAnalytics(videoId);
179+
});
180+
181+
// Call the jQuery.append() method to add the new &lt;a&gt; element to
182+
// the &lt;li&gt; element, and the &lt;li&gt; element to the parent
183+
// list, which is identified by the 'videoList' variable.
184+
liElement.append(aElement);
185+
videoList.append(liElement);
186+
});
187+
188+
if (videoList.children().length == 0) {
189+
// Display a message if the channel does not have any viewed videos.
190+
displayMessage('Your channel does not have any videos that have been viewed.');
191+
}
192+
}
193+
});
194+
}
195+
196+
// This function requests YouTube Analytics data for a video and displays
197+
// the results in a chart.
198+
function displayVideoAnalytics(videoId) {
199+
if (channelId) {
200+
// To use a different date range, modify the ONE_MONTH_IN_MILLISECONDS
201+
// variable to a different millisecond delta as desired.
202+
var today = new Date();
203+
var lastMonth = new Date(today.getTime() - ONE_MONTH_IN_MILLISECONDS);
204+
205+
var request = gapi.client.youtubeAnalytics.reports.query({
206+
// The start-date and end-date parameters must be YYYY-MM-DD strings.
207+
'start-date': formatDateString(lastMonth),
208+
'end-date': formatDateString(today),
209+
// At this time, you need to explicitly specify channel==channelId.
210+
// See https://developers.google.com/youtube/analytics/v1/#ids
211+
ids: 'channel==' + channelId,
212+
dimensions: 'day',
213+
sort: 'day',
214+
// See https://developers.google.com/youtube/analytics/v1/available_reports
215+
// for details about the different filters and metrics you can request
216+
// if the "dimensions" parameter value is "day".
217+
metrics: 'views',
218+
filters: 'video==' + videoId
219+
});
220+
221+
request.execute(function(response) {
222+
// This function is called regardless of whether the request succeeds.
223+
// The response contains YouTube Analytics data or an error message.
224+
if ('error' in response) {
225+
displayMessage(response.error.message);
226+
} else {
227+
displayChart(videoId, response);
228+
}
229+
});
230+
} else {
231+
// The currently authenticated user's channel ID is not available.
232+
displayMessage('The YouTube channel ID for the current user is not available.');
233+
}
234+
}
235+
236+
// This boilerplate code takes a Date object and returns a YYYY-MM-DD string.
237+
function formatDateString(date) {
238+
var yyyy = date.getFullYear().toString();
239+
var mm = padToTwoCharacters(date.getMonth() + 1);
240+
var dd = padToTwoCharacters(date.getDate());
241+
242+
return yyyy + '-' + mm + '-' + dd;
243+
}
244+
245+
// If number is a single digit, prepend a '0'. Otherwise, return the number
246+
// as a string.
247+
function padToTwoCharacters(number) {
248+
if (number < 10) {
249+
return '0' + number;
250+
} else {
251+
return number.toString();
252+
}
253+
}
254+
255+
// Call the Google Chart Tools API to generate a chart of Analytics data.
256+
function displayChart(videoId, response) {
257+
if ('rows' in response) {
258+
hideMessage();
259+
260+
// The columnHeaders property contains an array of objects representing
261+
// each column's title -- e.g.: [{name:"day"},{name:"views"}]
262+
// We need these column titles as a simple array, so we call jQuery.map()
263+
// to get each element's "name" property and create a new array that only
264+
// contains those values.
265+
var columns = $.map(response.columnHeaders, function(item) {
266+
return item.name;
267+
});
268+
// The google.visualization.arrayToDataTable() function wants an array
269+
// of arrays. The first element is an array of column titles, calculated
270+
// above as "columns". The remaining elements are arrays that each
271+
// represent a row of data. Fortunately, response.rows is already in
272+
// this format, so it can just be concatenated.
273+
// See https://developers.google.com/chart/interactive/docs/datatables_dataviews#arraytodatatable
274+
var chartDataArray = [columns].concat(response.rows);
275+
var chartDataTable = google.visualization.arrayToDataTable(chartDataArray);
276+
277+
var chart = new google.visualization.LineChart(document.getElementById('chart'));
278+
chart.draw(chartDataTable, {
279+
// Additional options can be set if desired as described at:
280+
// https://developers.google.com/chart/interactive/docs/reference#visdraw
281+
title: 'Views per Day of Video ' + videoId
282+
});
283+
} else {
284+
displayMessage('No data available for video ' + videoId);
285+
}
286+
}
287+
288+
// This helper method displays a message on the page.
289+
function displayMessage(message) {
290+
$('#message').text(message).show();
291+
}
292+
293+
// This helper method hides a previously displayed message on the page.
294+
function hideMessage() {
295+
$('#message').hide();
296+
}
297+
})();

0 commit comments

Comments
 (0)