In this post, you will learn how to build a custom function that imports into a sheet the comments of a YouTube video given the video URL.

This is what the end result looks like:

This function can be useful for building a custom YouTube analytics dashboard or conducting research.

1. Get the template

Click the button below to copy the template sheet with the custom function ready for use. Once you get your copy, all you need to do is follow the short video tutorial to initialize the script.

G

In the following lines, I’ll explain how I developed this function. So, stick with me if you’re interested in more details.

2. Creating the core function

The first thing we need to do is enable the YouTube Data API. This advanced service provides us with broad access to YouTube’s public data. It allows us to fetch details about videos. To enable it, open your Google Script editor, then go to Resources > Advanced Google Services > YouTube Data API > Enable.

Next, let’s create a core function that takes as input a video URL and the number of comments (N) and it will retrieve the N most recent comments on this video.

function getCommentsData(videoLink, numberOfComments, getReplies) {
  var videoID = videoLink.split('v=')[1];

  // Don't run on empty
  if(!videoID){return null}

  var comments = [];
  var pageToken = "";
  var response = YouTube.CommentThreads.list('id, replies, snippet', {videoId: videoID, pageToken: pageToken, maxResults: numberOfComments});
  
  for(var i in response.items) {
    var item = response.items[i];

    var authorName = item.snippet.topLevelComment.snippet.authorDisplayName
    var comment = item.snippet.topLevelComment.snippet.textDisplay.replace("'", "'")
    var likeCount = item.snippet.topLevelComment.snippet.likeCount
    var authorProfileImageUrl = item.snippet.topLevelComment.snippet.authorProfileImageUrl
    var authorChannelUrl = item.snippet.topLevelComment.snippet.authorChannelUrl
    var publishDate = new Date(item.snippet.topLevelComment.snippet.publishedAt);
    var formattedDate = publishDate.toLocaleDateString("en-US", { month: "2-digit", day: "2-digit", year: "numeric" });
    var formattedTime = publishDate.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" });
    var formattedDateTime = formattedDate + " " + formattedTime;

    var row = [authorName, comment, likeCount, authorProfileImageUrl, authorChannelUrl, formattedDateTime]
    comments.push(row);

  }

  comments = comments.slice(0, numberOfComments);
  
  var result= { data: comments };
  console.log(result)

  return result;
}

3. Creating the custom function

If we try to call getCommentsData(), we will get an error indicating that the call to the YouTube Data API has failed. The reason is that custom functions in Google Sheets run with limited authorization and are unable to call advanced services that require user authorization, such as the YouTube Data API.

So we need to find a way to grant our custom function the necessary permissions to run. As a solution, we will first deploy the script as a web app, which will grant the necessary permissions for the function to access the YouTube Data API. Then, we’ll use the URL of the web app to make HTTPS requests to the core function getCommentsData().

For this reason, we need to add a few functions to the code:

  • IMPORTCOMMENTS(videoLink, numberOfComments):
    We will create a wrapper function IMPORTCOMMENTS that will finally become the actual custom function. Whenever this custom function is called from the sheet, instead of trying to call the core function directly (which would fail due to insufficient permissions), a request will be made to the web app we deployed. The web app, with its sufficient permissions, will then call the getCommentsData() function and return the results. This way, we can successfully access the YouTube Data API.
  • makeRequestToWebApp(parameters):
    This function is responsible for making a request to the web app. It uses the UrlFetchApp.fetch method to make the HTTP request. The response from the web app is then parsed and returned. 
  • doGet(e) 
    This function is automatically executed when a GET request is made to the URL of the web app. In this script, the doGet function checks the request_type parameter of the request. If the request_type is “importcomments”, it calls the getCommentsData() function with the videoLink parameter from the request. The result of the getVideoData function is then turned into a string and returned.

Here is the updated script:

/**
 * CUSTOM FUNCTION TO IMPORT YOUTUBE CHANNEL VIDEOS
 * 
 * Written with ❤️ by Joseph Asinyo
 */



// IMPORTANT NOTE: Deploy the script as a web app and insert the url below
var WEB_APP_URL = "INSERT_THE_WEB_APP_URL_HERE";



/**
 * Fetches comment information from YouTube API based on a video link.
 *
 * @param {string} videoLink The link of the YouTube video.
 * @param {number} numberOfComments The number of comments to return.
 * @return {Object} The comment information.
 * @customfunction
 */
function IMPORTCOMMENTS(videoLink, numberOfComments) {
  numberOfComments = numberOfComments || 50;
  var parameters = {
    "request_type": "importcomments",
    "videoLink": videoLink,
    "numberOfComments": numberOfComments
  }

  var result = makeRequestToWebApp(parameters)
  return result;
}



function makeRequestToWebApp(parameters) {
  var url = WEB_APP_URL+"?";

  for (const key of Object.keys(parameters)) {
    url += key+"="+parameters[key]+"&";
  }
  url = url.slice(0, -1); // Remove the last "&" character

  console.log(url)

  var response = UrlFetchApp.fetch(url).getContentText();
  var result = JSON.parse(response).data;

  return result;
}



// Web Apps using as the wrapper.
function doGet(e) {
  var request_type = e.parameter.request_type
  if(request_type == "importcomments"){
    var res = getCommentsData(e.parameter.videoLink, e.parameter.numberOfComments, e.parameter.getReplies)
  } 

  return ContentService.createTextOutput(JSON.stringify(res));
}



function getCommentsData(videoLink, numberOfComments, getReplies) {
  var videoID = videoLink.split('v=')[1];

  // Don't run on empty
  if(!videoID){return null}

  var comments = [];
  var pageToken = "";
  var response = YouTube.CommentThreads.list('id, replies, snippet', {videoId: videoID, pageToken: pageToken, maxResults: numberOfComments});
  
  for(var i in response.items) {
    var item = response.items[i];

    var authorName = item.snippet.topLevelComment.snippet.authorDisplayName
    var comment = item.snippet.topLevelComment.snippet.textDisplay.replace("'", "'")
    var likeCount = item.snippet.topLevelComment.snippet.likeCount
    var authorProfileImageUrl = item.snippet.topLevelComment.snippet.authorProfileImageUrl
    var authorChannelUrl = item.snippet.topLevelComment.snippet.authorChannelUrl
    var publishDate = new Date(item.snippet.topLevelComment.snippet.publishedAt);
    var formattedDate = publishDate.toLocaleDateString("en-US", { month: "2-digit", day: "2-digit", year: "numeric" });
    var formattedTime = publishDate.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" });
    var formattedDateTime = formattedDate + " " + formattedTime;

    var row = [authorName, comment, likeCount, authorProfileImageUrl, authorChannelUrl, formattedDateTime]
    comments.push(row);

  }

  comments = comments.slice(0, numberOfComments);
  
  var result= { data: comments };
  console.log(result)

  return result;
}

3. Usage capacity of IMPORTCOMMENTS

The number of daily requests that can be made with the function depends on the YouTube Data API’s daily quota. The default quota allocation for the YouTube Data API is 10,000 units per day.

Each API request incurs a quota cost. The CommentThreads.list method, used in the getCommentsData function has a quota cost of 1 unit.

This cost is incurred irrespective of the number of comments that are fetched in a single call. So numberOfComments does not affect the quota cost. This means that each call to the custom function costs 1 unit from your daily quota.

Therefore, with the default quota allocation, you can make up to 10,000 requests per day to IMPORTCOMMENTS.

This is under the assumption that no other requests are being made on the same project that consumes the quota.

It’s important to note that the daily quota resets at midnight Pacific Time. If you reach the quota limit, you can request additional quota by completing the Quota extension request form for YouTube API Services.

Useful links:

Shares:

Leave a Reply

Your email address will not be published. Required fields are marked *