DEV Community

Rick Viscomi
Rick Viscomi

Posted on • Updated on

Using Sheets and the YouTube API to track video analytics

I host a biweekly video series on YouTube called The State of the Web and being the data nerd that I am, I wanted a way to monitor the public stats about each video to see how they're performing: number of views, likes, dislikes, comments, etc. In this post I walk you through how to set up your own dashboard to monitor the videos you care about.

the finished spreadsheet

You can see my finished product in this sheet. If you'd like, you can just make a copy of that sheet and plug in your own videos, but keep in mind that you may still need to follow some of these steps to get things like the YouTube API enabled.

Getting started

You'll need a blank Google Sheet to get started. Rename the default sheet to "Video Stats" so there's an identifiable name for it in the script.

Row 1 will be the headings for the table of stats:

  • Video Title
  • Video ID
  • Views
  • Likes
  • Dislikes
  • Comments
  • Duration

The only input needed by you is the title and ID for each video in columns A and B. Optionally, you can add the following columns for more stats:

  • Likes per View
  • Dislikes per View
  • Percent Likes
  • Percent Dislikes
  • Comments per View

These are calculated locally from the API results using simple Sheets formulas. For example, calculating the percent of likes uses this formula: =IFERROR(D2/(D2+E2), ""). One trick to apply the same formula to all cells in the column is to select the cell with the formula already applied, press Cmd+Shift+Down to select all following cells in the column, and press Cmd+D to apply the formula. The IFERROR function prevents division by zero errors for empty rows.

You can also format the columns to prettify their respective values. For example, the duration looks best in MM:SS format, while the calculated fields look best as percents.

Next, create a "Named Range" for the Video ID values by going to Data > Named Ranges... and adding a new range called "IDs" for range 'Video Stats'!B2:B1000. This allows the script to more easily scan the list of video IDs.

The brains of the analytics

To make the dashboard work, we need to talk to YouTube and get stats about each video. That's possible with a bit of Apps Script, which you can write by going to Tools > Script Editor.

In the newly opened editor, name your project "YouTube Analytics" and paste this script:

// This is "Sheet1" by default. Keep it in sync after any renames.
var SHEET_NAME = 'Video Stats';

// This is the named range containing all video IDs.
var VIDEO_ID_RANGE_NAME = 'IDs';

// Update these values after adding/removing columns.
var Column = {
  VIEWS: 'C',
  LIKES: 'D',
  DISLIKES: 'E',
  COMMENTS: 'F',
  DURATION: 'G'
};

// Adds a "YouTube" context menu to manually update stats.
function onOpen() {
  var spreadsheet = SpreadsheetApp.getActive();
  var entries = [{name: "Update Stats", functionName: "updateStats"}];

  spreadsheet.addMenu("YouTube", entries);
};

function updateStats() {
  var spreadsheet = SpreadsheetApp.getActive();
  var videoIds = getVideoIds();
  var stats = getStats(videoIds.join(','));
  writeStats(stats);
}

// Gets all video IDs from the range and ignores empty values.
function getVideoIds() {
  var spreadsheet = SpreadsheetApp.getActive();
  var range = spreadsheet.getRangeByName(VIDEO_ID_RANGE_NAME);
  var values = range.getValues();
  var videoIds = [];
  for (var i = 0; i < values.length; i++) {
    var value = values[i][0];
    if (!value) {
      return videoIds;
    }
    videoIds.push(value);
  }
  return videoIds;
}

// Queries the YouTube API to get stats for all videos.
function getStats(videoIds) {
  return YouTube.Videos.list('contentDetails,statistics', {'id': videoIds}).items;
}

// Converts the API results to cells in the sheet.
function writeStats(stats) {
  var spreadsheet = SpreadsheetApp.getActive();
  var sheet = spreadsheet.getSheetByName(SHEET_NAME);
  var durationPattern = new RegExp(/PT((\d+)M)?(\d+)S/);
  for (var i = 0; i < stats.length; i++) {
    var cell = sheet.setActiveCell(Column.VIEWS + (2+i));
    cell.setValue(stats[i].statistics.viewCount);
    cell = sheet.setActiveCell(Column.LIKES + (2+i));
    cell.setValue(stats[i].statistics.likeCount);
    cell = sheet.setActiveCell(Column.DISLIKES + (2+i));
    cell.setValue(stats[i].statistics.dislikeCount);
    cell = sheet.setActiveCell(Column.COMMENTS + (2+i));
    cell.setValue(stats[i].statistics.commentCount);
    cell = sheet.setActiveCell(Column.DURATION + (2+i));
    var duration = stats[i].contentDetails.duration;
    var result = durationPattern.exec(duration);
    var min = result && result[2] || '00';
    var sec = result && result[3] || '00';
    cell.setValue('00:' + min + ':' + sec);
  }
}

Refer to the comments in the code for a description of what each function does.

There are a couple more things left to do in the script editor to make everything work:

  1. Enable the API
  2. Set up triggers so that the stats are updated automatically

enable the YT API

To enable the API, go to Resources > Advanced Google Services... and scroll down to and enable the YouTube Data API. You must also click the "Google Cloud Platform API Dashboard" link and search for "YouTube Data API v3" to enable it for your project.

setting up triggers

To set up triggers, go to Edit > Current project's triggers and configure it as seen in the screenshot above. It does two things:

  • updates the stats every 15 minutes, so you can leave the sheet open and get the latest data
  • updates the stats as soon as you open the sheet

YT menu

There is also a "YouTube" menu added to the sheet if you want to manually trigger an update.

Wrapping up

That's all there is to it. My sheet also has some examples of secondary sheets that summarize the stats with other tables and charts, but you can customize your dashboard any way you like.

If you own the YouTube channel on which the videos are uploaded, you may also have access to private stats like watchtime and subscription data. But the great thing about this script is that you can monitor any YouTube videos regardless of ownership β€” it's all public info!

Latest comments (34)

Collapse
 
_lobeira_today profile image
A Lobeira today

Hi, my name is Fran. Is it possible to use this way to track channel subs instead video statistics? Thanks in advance.

Collapse
 
olekstomek profile image
olekstomek

Hi, thanks for showing us the use of Google Apps Script. ;)
I use your code and spreadsheet and adapted it in my solution which allows you to check the statistics of videos in the given YouTube playlist. This is the link to the repository: github.com/olekstomek/gscript-trac...

Collapse
 
bhagiradh1993 profile image
bhagiradh akuthota

I'm facing this particular issue. Can anyone please help me

*GoogleJsonResponseException: API call to youtube.videos.list failed with error: The request specifies an invalid filter parameter.
*

Collapse
 
jonesadamd profile image
Adam J.

Hi Rick,
Great article and example of tracking YouTube video's with the API, but any chance you can update it to include pagetokens for more than 50 lines.

Or can we create code to split the getVideoIds() and writeStats(stats) for a maximum of 50 then continue down the range?

Thank you

Collapse
 
max_alexander_ profile image
MaxπŸ”₯Alexander

Awesome awesome awesome! Thank you! How do I capture A 24 hour snapshot and a 7 day snapshot of a video?

Collapse
 
dickeytyler profile image
Tyler Dickey

Hey Rick! I'm having some issues setting up the triggers for this sheet. Once I set the trigger up as shown in your article I get caught in this endless loop of having to log into my google account and give the script permission to get data from YouTube. Any tips?

Collapse
 
chan_kuris profile image
KurisC

Hello Rick, when hitting 50 videos, the script no longer works, is there any way around this?

Collapse
 
chan_kuris profile image
KurisC

docs.google.com/spreadsheets/d/1ui...

If you check through the videos yourself, you will notice that at "Our Summer" and below, the views are aligned with the wrong video ID, but I am not sure what is causing this?

Thank You :D

Collapse
 
pixelgroove profile image
Udi Sabach

Hi. I had this working, and now getting an error "API call to youtube.videos.list failed with error: The request specifies an invalid filter parameter. (line 49, file "Code")".

Any how to fix this?

Collapse
 
pixelgroove profile image
Udi Sabach

I noticed the issue is that i was hitting the 50 video limit. Once i reduced the list, it worked.

Collapse
 
wrldwzrd89 profile image
Eric Ahnell

This looks real interesting - will give this a try and see how it goes!

Collapse
 
f97c621c553743a profile image
Shiva Kumar

Hey I am trying to track my youtube usage across the computer and phone. Given this approach is awesome and works well, it is very cumbersome to manually input the video titles and the Vid IDs. I do have the YouTube history enabled, I want only a suggestion from you about the approach I can take to be able to log the Videos I have watched and also on which dates based on my history.

Thank you

Collapse
 
dakotageek profile image
DakotaGeek

Hi Rick, I'm following your instructions and although everything appears correct, I'm getting the following error when running the script.
"API call to youtube.videos.list failed with error: No filter selected. Expected one of: chart, id, myRated, idParam (line 49, file "Code")"

Line 49 in the script is an exact copy-paste from your article as follows:
"return YouTube.Videos.list('contentDetails,statistics', {'id': videoIds}).items;"

Any thoughts on why this error would occur?

Collapse
 
dakotageek profile image
DakotaGeek

Some of the other posts here answered my question. This is an example of hitting the limit of 50 requests to the API.

Since the Named Range is 999 entries long, perhaps Rick could update his script to iterate through 999 entries in chunks of 50?

Collapse
 
ms86uk profile image
Marco Scarpa

Rick, since yesterday I'm receiving this error:

  1. That’s an error.

Error: disabled_client

The OAuth client was disabled.

Collapse
 
pranay profile image
pranay

Hi Rick,

thank you for this article. However, I'm experiencing a problem with the code and I'm utterly new to coding. When I'm trying to run the code, it is not happening and an error message pops up TypeError: Cannot call method "getValues" of null.

Please tell me where I could have gone wrong and also how to rectify it. Thanks a ton.

Pranay

Collapse
 
aakankshadp profile image
aakanksha-dp

I am facing the same issue. Did you fix this? If yes, please help me on how to fix it.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.