2016-12-07 5 views
0

Я пытаюсь импортировать свою аналитику YouTube в листы Google и следую за этим example, но не смог заставить ее работать. Я считаю, что я санкционировал все подходящие API и создал credentinal. Однако я столкнулся с ошибками, на которые я могу найти ответ.Автоматический импорт YouTube Analytics в Google Таблицы

Моя конечная цель - автоматически импортировать все мои данные YouTube (просмотров, продолжительность просмотра, доли, пол, возраст ...) в Google Таблицы с соответствующими заголовками и диаграммами.

Несколько ошибок я получаю:

Line 18 или мой файл .gs.

ReferenceError: "google" не определен. (строка 18, файл «Код») Отклонить

google.load ('visualization', '1.0', {'packages': ['corechart']});

Если удалить строку 18-26 я получаю ошибку на линии 324

TypeError: Не удается прочитать свойство «длина» от неопределенными. (строка 324, файл «Код») Отклонить

var numRows = analyticsResponse.rows.length;

Заранее благодарен!

function myFunction() { 
 
    // Retrieve your client ID from the {{ Google Cloud Console }} at 
 
    // {{ https://cloud.google.com/console }}. 
 
    var OAUTH2_CLIENT_ID = 'XXXXXXXX'; 
 
    var OAUTH2_SCOPES = [ 
 
    'https://www.googleapis.com/auth/yt-analytics.readonly', 
 
    'https://www.googleapis.com/auth/youtube.readonly' 
 
    ]; 
 

 
    var ONE_MONTH_IN_MILLISECONDS = 1000 * 60 * 60 * 24 * 30; 
 

 
    // Keep track of the currently authenticated user's YouTube channel ID. 
 
    var channelId; 
 

 

 
    // For information about the Google Chart Tools API, see: 
 
    // https://developers.google.com/chart/interactive/docs/quick_start 
 
    google.load('visualization', '1.0', {'packages': ['corechart']}); 
 

 
    // Upon loading, the Google APIs JS client automatically invokes this callback. 
 
    // See https://developers.google.com/api-client-library/javascript/features/authentication 
 
    window.onJSClientLoad = function() { 
 
    gapi.auth.init(function() { 
 
     window.setTimeout(checkAuth, 1); 
 
    }); 
 
    }; 
 

 
\t 
 
    // Attempt the immediate OAuth 2.0 client flow as soon as the page loads. 
 
    // If the currently logged-in Google Account has previously authorized 
 
    // the client specified as the OAUTH2_CLIENT_ID, then the authorization 
 
    // succeeds with no user intervention. Otherwise, it fails and the 
 
    // user interface that prompts for authorization needs to display. 
 
    function checkAuth() { 
 
    gapi.auth.authorize({ 
 
     client_id: OAUTH2_CLIENT_ID, 
 
     scope: OAUTH2_SCOPES, 
 
     immediate: true 
 
    }, handleAuthResult); 
 
    } 
 

 
    // Handle the result of a gapi.auth.authorize() call. 
 
    function handleAuthResult(authResult) { 
 
    if (authResult) { 
 
     // Authorization was successful. Hide authorization prompts and show 
 
     // content that should be visible after authorization succeeds. 
 
     $('.pre-auth').hide(); 
 
     $('.post-auth').show(); 
 

 
     loadAPIClientInterfaces(); 
 
    } else { 
 
     // Authorization was unsuccessful. Show content related to prompting for 
 
     // authorization and hide content that should be visible if authorization 
 
     // succeeds. 
 
     $('.post-auth').hide(); 
 
     $('.pre-auth').show(); 
 

 
     // Make the #login-link clickable. Attempt a non-immediate OAuth 2.0 
 
     // client flow. The current function is called when that flow completes. 
 
     $('#login-link').click(function() { 
 
     gapi.auth.authorize({ 
 
      client_id: OAUTH2_CLIENT_ID, 
 
      scope: OAUTH2_SCOPES, 
 
      immediate: false 
 
     }, handleAuthResult); 
 
     }); 
 
    } 
 
    } 
 

 
    // Load the client interfaces for the YouTube Analytics and Data APIs, which 
 
    // are required to use the Google APIs JS client. More info is available at 
 
    // https://developers.google.com/api-client-library/javascript/dev/dev_jscript#loading-the-client-library-and-the-api 
 
    function loadAPIClientInterfaces() { 
 
    gapi.client.load('youtube', 'v3', function() { 
 
     gapi.client.load('youtubeAnalytics', 'v1', function() { 
 
     // After both client interfaces load, use the Data API to request 
 
     // information about the authenticated user's channel. 
 
     getUserChannel(); 
 
     }); 
 
    }); 
 
    } 
 

 
    // Call the Data API to retrieve information about the currently 
 
    // authenticated user's YouTube channel. 
 
    function getUserChannel() { 
 
    // Also see: https://developers.google.com/youtube/v3/docs/channels/list 
 
    var request = gapi.client.youtube.channels.list({ 
 
     // Setting the "mine" request parameter's value to "true" indicates that 
 
     // you want to retrieve the currently authenticated user's channel. 
 
     mine: true, 
 
     part: 'id,contentDetails' 
 
    }); 
 

 
    request.execute(function(response) { 
 
     if ('error' in response) { 
 
     displayMessage(response.error.message); 
 
     } else { 
 
     // We need the channel's channel ID to make calls to the Analytics API. 
 
     // The channel ID value has the form "UCdLFeWKpkLhkguiMZUp8lWA". 
 
     channelId = response.items[0].id; 
 
     // Retrieve the playlist ID that uniquely identifies the playlist of 
 
     // videos uploaded to the authenticated user's channel. This value has 
 
     // the form "UUdLFeWKpkLhkguiMZUp8lWA". 
 
     var uploadsListId = response.items[0].contentDetails.relatedPlaylists.uploads; 
 
     // Use the playlist ID to retrieve the list of uploaded videos. 
 
     getPlaylistItems(uploadsListId); 
 
     } 
 
    }); 
 
    } 
 

 
    // Call the Data API to retrieve the items in a particular playlist. In this 
 
    // example, we are retrieving a playlist of the currently authenticated user's 
 
    // uploaded videos. By default, the list returns the most recent videos first. 
 
    function getPlaylistItems(listId) { 
 
    // See https://developers.google.com/youtube/v3/docs/playlistitems/list 
 
    var request = gapi.client.youtube.playlistItems.list({ 
 
     playlistId: listId, 
 
     part: 'snippet' 
 
    }); 
 

 
    request.execute(function(response) { 
 
     if ('error' in response) { 
 
     displayMessage(response.error.message); 
 
     } else { 
 
     if ('items' in response) { 
 
      // The jQuery.map() function iterates through all of the items in 
 
      // the response and creates a new array that only contains the 
 
      // specific property we're looking for: videoId. 
 
      var videoIds = $.map(response.items, function(item) { 
 
      return item.snippet.resourceId.videoId; 
 
      }); 
 

 
      // Now that we know the IDs of all the videos in the uploads list, 
 
      // we can retrieve information about each video. 
 
      getVideoMetadata(videoIds); 
 
     } else { 
 
      displayMessage('There are no videos in your channel.'); 
 
     } 
 
     } 
 
    }); 
 
    } 
 

 
    // Given an array of video IDs, this function obtains metadata about each 
 
    // video and then uses that metadata to display a list of videos. 
 
    function getVideoMetadata(videoIds) { 
 
    // https://developers.google.com/youtube/v3/docs/videos/list 
 
    var request = 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' in response) { 
 
     displayMessage(response.error.message); 
 
     } else { 
 
     // Get the jQuery wrapper for the #video-list element before starting 
 
     // the loop. 
 
     var videoList = $('#video-list'); 
 
     $.each(response.items, function() { 
 
      // Exclude videos that do not have any views, since those videos 
 
      // will not have any interesting viewcount Analytics data. 
 
      if (this.statistics.viewCount == 0) { 
 
      return; 
 
      } 
 

 
      var title = this.snippet.title; 
 
      var videoId = this.id; 
 

 
      // Create a new <li> element that contains an <a> element. 
 
      // Set the <a> element's text content to the video's title, and 
 
      // add a click handler that will display Analytics data when invoked. 
 
      var liElement = $('<li>'); 
 
      var aElement = $('<a>'); 
 
      // Setting the href value to '#' ensures that the browser renders the 
 
      // <a> element as a clickable link. 
 
      aElement.attr('href', '#'); 
 
      aElement.text(title); 
 
      aElement.click(function() { 
 
      displayVideoAnalytics(videoId); 
 
      }); 
 

 
      // Call the jQuery.append() method to add the new <a> element to 
 
      // the <li> element, and the <li> element to the parent 
 
      // list, which is identified by the 'videoList' variable. 
 
      liElement.append(aElement); 
 
      videoList.append(liElement); 
 
     }); 
 

 
     if (videoList.children().length == 0) { 
 
      // Display a message if the channel does not have any viewed videos. 
 
      displayMessage('Your channel does not have any videos that have been viewed.'); 
 
     } 
 
     } 
 
    }); 
 
    } 
 

 
    // This function requests YouTube Analytics data for a video and displays 
 
    // the results in a chart. 
 
    function displayVideoAnalytics(videoId) { 
 
    if (channelId) { 
 
     // To use a different date range, modify the ONE_MONTH_IN_MILLISECONDS 
 
     // variable to a different millisecond delta as desired. 
 
     var today = new Date(); 
 
     var lastMonth = new Date(today.getTime() - ONE_MONTH_IN_MILLISECONDS); 
 

 
     var request = gapi.client.youtubeAnalytics.reports.query({ 
 
     // The start-date and end-date parameters must be YYYY-MM-DD strings. 
 
     'start-date': formatDateString(lastMonth), 
 
     'end-date': formatDateString(today), 
 
     // At this time, you need to explicitly specify channel==channelId. 
 
     // See https://developers.google.com/youtube/analytics/v1/#ids 
 
     ids: 'channel==' + channelId, 
 
     dimensions: 'day', 
 
     sort: 'day', 
 
     // See https://developers.google.com/youtube/analytics/v1/available_reports 
 
     // for details about the different filters and metrics you can request 
 
     // if the "dimensions" parameter value is "day". 
 
     metrics: 'views', 
 
     filters: 'video==' + videoId 
 
     }); 
 

 
     request.execute(function(response) { 
 
     // This function is called regardless of whether the request succeeds. 
 
     // The response contains YouTube Analytics data or an error message. 
 
     if ('error' in response) { 
 
      displayMessage(response.error.message); 
 
     } else { 
 
      displayChart(videoId, response); 
 
     } 
 
     }); 
 
    } else { 
 
     // The currently authenticated user's channel ID is not available. 
 
     displayMessage('The YouTube channel ID for the current user is not available.'); 
 
    } 
 
    } 
 

 
    // This boilerplate code takes a Date object and returns a YYYY-MM-DD string. 
 
    function formatDateString(date) { 
 
    var yyyy = date.getFullYear().toString(); 
 
    var mm = padToTwoCharacters(date.getMonth() + 1); 
 
    var dd = padToTwoCharacters(date.getDate()); 
 

 
    return yyyy + '-' + mm + '-' + dd; 
 
    } 
 

 
    // If number is a single digit, prepend a '0'. Otherwise, return the number 
 
    // as a string. 
 
    function padToTwoCharacters(number) { 
 
    if (number < 10) { 
 
     return '0' + number; 
 
    } else { 
 
     return number.toString(); 
 
    } 
 
    } 
 

 
    // Call the Google Chart Tools API to generate a chart of Analytics data. 
 
    function displayChart(videoId, response) { 
 
    if ('rows' in response) { 
 
     hideMessage(); 
 

 
     // The columnHeaders property contains an array of objects representing 
 
     // each column'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" property and create a new array that only 
 
     // contains those values. 
 
     var columns = $.map(response.columnHeaders, function(item) { 
 
     return item.name; 
 
     }); 
 
     // The google.visualization.arrayToDataTable() function wants an array 
 
     // of arrays. The first element is an array of column titles, calculated 
 
     // above as "columns". The remaining elements are arrays that each 
 
     // represent a row of data. Fortunately, response.rows is already in 
 
     // this format, so it can just be concatenated. 
 
     // See https://developers.google.com/chart/interactive/docs/datatables_dataviews#arraytodatatable 
 
     var chartDataArray = [columns].concat(response.rows); 
 
     var chartDataTable = google.visualization.arrayToDataTable(chartDataArray); 
 

 
     var chart = new google.visualization.LineChart(document.getElementById('chart')); 
 
     chart.draw(chartDataTable, { 
 
     // Additional options can be set if desired as described at: 
 
     // https://developers.google.com/chart/interactive/docs/reference#visdraw 
 
     title: 'Views per Day of Video ' + videoId 
 
     }); 
 
    } else { 
 
     displayMessage('No data available for video ' + videoId); 
 
    } 
 
    } 
 

 
    // This helper method displays a message on the page. 
 
    function displayMessage(message) { 
 
    $('#message').text(message).show(); 
 
    } 
 

 
    // This helper method hides a previously displayed message on the page. 
 
    function hideMessage() { 
 
    $('#message').hide(); 
 
    } 
 

 

 
} 
 

 
function spreadsheetAnalytics() { 
 
    // Get the channel ID 
 
    var myChannels = YouTube.Channels.list('id', {mine: true}); 
 
    var channel = myChannels.items[0]; 
 
    var channelId = channel.id; 
 

 
    // Set the dates for our report 
 
    var today = new Date(); 
 
    var oneMonthAgo = new Date(); 
 
    oneMonthAgo.setMonth(today.getMonth() - 1); 
 
    var todayFormatted = Utilities.formatDate(today, 'UTC', 'yyyy-MM-dd') 
 
    var oneMonthAgoFormatted = Utilities.formatDate(oneMonthAgo, 'UTC', 'yyyy-MM-dd'); 
 

 
    // The YouTubeAnalytics.Reports.query() function has four required parameters and one optional 
 
    // parameter. The first parameter identifies the channel or content owner for which you are 
 
    // retrieving data. The second and third parameters specify the start and end dates for the 
 
    // report, respectively. The fourth parameter identifies the metrics that you are retrieving. 
 
    // The fifth parameter is an object that contains any additional optional parameters 
 
    // (dimensions, filters, sort, etc.) that you want to set. 
 
    var analyticsResponse = YouTubeAnalytics.Reports.query(
 
    'channel==' + channelId, 
 
    oneMonthAgoFormatted, 
 
    todayFormatted, 
 
    'views,likes,dislikes,shares', 
 
    { 
 
     dimensions: 'day', 
 
     sort: '-day' 
 
    }); 
 

 
    // Create a new Spreadsheet with rows and columns corresponding to our dates 
 
    var ssName = 'YouTube channel report ' + oneMonthAgoFormatted + ' - ' + todayFormatted; 
 
    var numRows = analyticsResponse.rows.length; 
 
    var numCols = analyticsResponse.columnHeaders.length; 
 
    
 
    // Add an extra row for column headers 
 
    var ssNew = SpreadsheetApp.create(ssName, numRows + 1, numCols); 
 

 
    // Get the first sheet 
 
    var sheet = ssNew.getSheets()[0]; 
 

 
    // Get the range for the title columns 
 
    // Remember, spreadsheets are 1-indexed, whereas arrays are 0-indexed 
 
    var headersRange = sheet.getRange(1, 1, 1, numCols); 
 
    var headers = []; 
 

 
    // These column headers will correspond with the metrics requested 
 
    // in the initial call: views, likes, dislikes, shares 
 
    for(var i in analyticsResponse.columnHeaders) { 
 
    var columnHeader = analyticsResponse.columnHeaders[i]; 
 
    var columnName = columnHeader.name; 
 
    headers[i] = columnName; 
 
    } 
 
    // This takes a 2 dimensional array 
 
    headersRange.setValues([headers]); 
 

 
    // Bold and freeze the column names 
 
    headersRange.setFontWeight('bold'); 
 
    sheet.setFrozenRows(1); 
 

 
    // Get the data range and set the values 
 
    var dataRange = sheet.getRange(2, 1, numRows, numCols); 
 
    dataRange.setValues(analyticsResponse.rows); 
 

 
    // Bold and freeze the dates 
 
    var dateHeaders = sheet.getRange(1, 1, numRows, 1); 
 
    dateHeaders.setFontWeight('bold'); 
 
    sheet.setFrozenColumns(1); 
 

 
    // Include the headers in our range. The headers are used 
 
    // to label the axes 
 
    var range = sheet.getRange(1, 1, numRows, numCols); 
 
    var chart = sheet.newChart() 
 
        .asColumnChart() 
 
        .setStacked() 
 
        .addRange(range) 
 
        .setPosition(4, 2, 10, 10) 
 
        .build(); 
 
    sheet.insertChart(chart); 
 

 
}

Я приложил скриншот моей текущей настройки и прилагается мой файл .gs.

ответ

0

Сценарий приложений - это язык программирования на стороне сервера. Вместо использования библиотеки JavaScript на стороне клиента он использует собственные встроенные службы для доступа к API Google. Он также имеет авторизацию и аутентификацию, испеченные в платформу через OAuth2. Взгляните на приведенный ниже пример аналитики. Когда запущен createReport, он получит аналитику для вашего канала youtube и сохранит их в новой таблице. Посмотрите на recents в драйвере для отчета.

Чтобы адаптировать это к вашим потребностям, взгляните на массив показателей.

/** 
* Creates a spreadsheet containing daily view counts, watch-time metrics, 
* and new-subscriber counts for a channel's videos. 
*/ 
function createReport() { 
    // Retrieve info about the user's YouTube channel. 
    var channels = YouTube.Channels.list('id,contentDetails', { 
    "mine":true 
    }); 
    var channelId = channels.items[0].id; 

    // Retrieve analytics report for the channel. 
    var oneMonthInMillis = 1000 * 60 * 60 * 24 * 30; 
    var today = new Date(); 
    var lastMonth = new Date(today.getTime() - oneMonthInMillis); 

    var metrics = [ 
    'views', 
    'estimatedMinutesWatched', 
    'averageViewDuration', 
    'averageViewPercentage', 
    'subscribersGained' 
    ]; 
    var options = { 
    dimensions: 'day', 
    sort: 'day' 
    }; 
    var result = YouTubeAnalytics.Reports.query('channel==' + channelId, 
     formatDateString(lastMonth), 
     formatDateString(today), 
     metrics.join(','), 
     options); 

    if (result.rows) { 
    var spreadsheet = SpreadsheetApp.create('YouTube Analytics Report'); 
    var sheet = spreadsheet.getActiveSheet(); 

    // Append the headers. 
    var headers = result.columnHeaders.map(function(columnHeader) { 
     return formatColumnName(columnHeader.name); 
    }); 
    sheet.appendRow(headers); 

    // Append the results. 
    sheet.getRange(2, 1, result.rows.length, headers.length) 
     .setValues(result.rows); 

    Logger.log('Report spreadsheet created: %s', 
     spreadsheet.getUrl()); 
    } else { 
    Logger.log('No rows returned.'); 
    } 
} 

/* 
* Converts a Date object into a YYYY-MM-DD string. 
*/ 
function formatDateString(date) { 
    return Utilities.formatDate(date, Session.getTimeZone(), 'yyyy-MM-dd'); 
} 

/* 
* Formats a column name into a more human-friendly name. For example 
* "averageViewPercentage" becomes "Average View Percentage". 
*/ 
function formatColumnName(columnName) { 
    var name = columnName.replace(/([a-z])([A-Z])/g, '$1 $2'); 
    name = name.slice(0, 1).toUpperCase() + name.slice(1); 
    return name; 
}