Ответ
Данные в Google Docs c Google Analytics Core API Опции темы
Старый 22.07.2014, 16:13
  #1
Strike
 
Регистрация: 24.01.2014
Сообщений: 40

Данные в Google Docs c Google Analytics Core API
Как создать и автоматически обновлять панель данных на Google Docs с помощью Google Analytics Core API (БЕЗ ПРОГРАММИРОВАНИЯ)

Сегодня я снова проверял список текущих изменений разных показателей сайта. Сосредоточившись на Google Analytics, я задался вопросом, каким бы образом я мог бы автоматизировать отчетность разных ключевых показателей, и нашел интересный и действенный способ сделать это путем интеграции Google Drive и API Google Analytics.

После прочтения нескольких старых, но полезных статей, я обнаружил волшебный скрипт, который так и назывался "Magic Script", написанный Ником Михайловским. Коротко говоря, речь идет о скрипте, который позволил бы вам экспортировать данные из профиля Analytics в таблицы Google. Кроме того, в результате его работы появляется возможность настройки автоматических вызовов API, что обновляют данные в электронной таблице автоматически. Ну, разве это не отлично?!

Что ж, идея есть, надо ее реализовать, но проблема заключается в том, что в последнее время, компания Google изменила способ запуска сценариев на Google Drive. Вместо "script gallery" они сделали "add-ons", что делает интеграцию "магического скрипта" болезненным процессом.

Раньше вы могли бы просто выполнить поиск по галерее скриптов и найти нужный сценарий. В настоящее эта функция устарела.

Но, даже, несмотря на то, что дополнения Analytics Google, несомненно, очень полезны, я понял, что они не позволят автоматизировать запросы к API, и таким образом автоматически обновить панель.

Это меня дико взбесило, и я решил пошерстить Интернет в поиске решений. И, после некоторых копаний, я нашел довольно простой способ использовать магический скрипт без использования галереи сценариев:


Шаг 1 - Откройте новый лист данных Google и выберите "Tools" - "Script Editor"





Шаг 2 - Скопируйте и вставьте Magic Script в этот новый лист


/**

 * A script to automate requesting data from Google Analytics.
 *
 * @author [email protected] (Nick Mihailovski)
 */


/**
 * The name of the configration sheet.
 * And various parameters.
 */
var GA_CONFIG = 'gaconfig';
var NAME = 'query';
var VALUE = 'value';
var TYPE = 'type';
var SHEET_NAME = 'sheet-name';

var CORE_OPT_PARAM_NAMES = [
'dimensions',
'sort',
'filters',
'segment',
'start-index',
'max-results'];

var MCF_OPT_PARAM_NAMES = [
'dimensions',
'sort',
'filters',
'start-index',
'max-results'];

/**
 * The types of reports.
 */
var CORE_TYPE = 'core';
var MCF_TYPE = 'mcf';

/**
 * Create a Menu when the script loads. Adds a new gaconfig sheet if
 * one doesn't exist.
 */
function onOpen() {

var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();

// Add a menu.
activeSpreadsheet.addMenu(
"Google Analytics", [{
name: "Find Profile / ids", functionName: "findIds_"}, {
name: "Create Core Report", functionName: "createCoreReport"}, {
name: "Create MCF Report", functionName: "createMcfReport"}, {
name: "Get Data", functionName: "getData"
}]);

// Add a sheet called gaconfig if it doesn't already exist.
getOrCreateGaSheet_();
}

/**
 * Opens a UIService dialogue for users to select their Profile / ids
 * query parameter. This will traverse the Management API hierarchy
 * to populate various list boxes.
 */
function findIds_() {
var app = UiApp.createApplication()
.setTitle('Find Your Profile ID / ids Parameter')
.setWidth(700).setHeight(175);

var accountList = app.createListBox()
.setId('accountList').setName('accountList')
.setVisibleItemCount(1).setStyleAttribute('width', '100%');
var webpropertyList = app.createListBox()
.setId('webpropertyList').setName('webpropertyList')
.setVisibleItemCount(1).setStyleAttribute('width', '100%');
var profileList = app.createListBox()
.setId('profileList').setName('profileList')
.setVisibleItemCount(1).setStyleAttribute('width', '100%');;

// Grid for dropdowns.
var grid = app.createGrid(3, 2).setStyleAttribute(0, 0, 'width', '130px');
grid.setWidget(0, 0, app.createLabel('Select Account'));
grid.setWidget(0, 1, accountList);
grid.setWidget(1, 0, app.createLabel('Select Web Property'));
grid.setWidget(1, 1, webpropertyList);
grid.setWidget(2, 0, app.createLabel('Select Profile'));
grid.setWidget(2, 1, profileList);

grid.setStyleAttribute('border-bottom', '1px solid #999')
.setStyleAttribute('padding-bottom', '12px')
.setStyleAttribute('margin-bottom', '12px');

// Grid for id results.

//var profileLink = app.createLabel('add ids to sheet').addClickHandler();

var grid2 = app.createGrid(2, 3).setStyleAttribute(0, 0, 'width', '130px');
grid2.setWidget(0, 0, app.createLabel('Profile Id'));
grid2.setWidget(0, 1, app.createLabel().setId('profileId'));
grid2.setWidget(1, 0, app.createLabel('ids'));
grid2.setWidget(1, 1, app.createLabel().setId('ids'));
//grid2.setWidget(1, 2, profileLink);

var handler = app.createServerHandler('queryWebProperties_');
accountList.addChangeHandler(handler);

handler = app.createServerHandler('queryProfiles_');
webpropertyList.addChangeHandler(handler);

handler = app.createServerHandler('displayProfile_');
profileList.addChangeHandler(handler);

app.add(grid).add(grid2);

// Traverse the management hiearchy by default.
queryAccounts_();

// Show display.
var doc = SpreadsheetApp.getActiveSpreadsheet();
doc.show(app);
}

/**
 * Handler to query all the accounts for the user then update the
 * UI dialogue box.
 */
function queryAccounts_() {
var app = UiApp.getActiveApplication();
var accountList = app.getElementById('accountList');

// Query Accounts API
var accounts = Analytics.Management.Accounts.list();

if (accounts.getItems()) {
for (var i = 0, item; item = accounts.getItems()[i]; ++i) {
var name = item.getName();
var id = item.getId();
accountList.addItem(name, id);
}

var firstAccountId = accounts.getItems()[0].getId();
UserProperties.setProperty('accountId', firstAccountId);
queryWebProperties_();

} else {
accountList.addItem('No accounts for user.');
app.getElementById('webpropertyList').clear();
app.getElementById('profileList').clear();
displayProfile_('none');
}

return app;
}

/**
 * Handler to query all the webproperties.
 * @param {object} eventInfo Used retrieve the user's accountId.
 */
function queryWebProperties_(eventInfo) {
var app = UiApp.getActiveApplication();
var webpropertyList = app.getElementById('webpropertyList').clear();

// From saved id.
var accountId = UserProperties.getProperty('accountId');

// From server handler.
if (eventInfo && eventInfo.parameter && eventInfo.parameter.accountList) {
accountId = eventInfo.parameter.accountList;
UserProperties.setProperty('accountId', accountId);
}

var webproperties = Analytics.Management.Webproperties.list(accountId);
if (webproperties.getItems()) {
for (var i = 0, webproperty; webproperty = webproperties.getItems()[i]; ++i) {
var name = webproperty.getName();
var id = webproperty.getId();
webpropertyList.addItem(name, id);
}

var firstWebpropertyId = webproperties.getItems()[0].getId();
UserProperties.setProperty('webpropertyId', firstWebpropertyId);
queryProfiles_();

} else {
webpropertyList.addItem('No webproperties for user');
app.getElementById('profileList').clear();
displayProfile_('none');
}

return app;
}

/**
 * Handler to query all the profiles.
 * @param {Object} eventInfo Used retrieve the user's webpropertyId.
 */
function queryProfiles_(eventInfo) {
var app = UiApp.getActiveApplication();
var profileList = app.getElementById('profileList').clear();

var accountId = UserProperties.getProperty('accountId');
var webpropertyId = UserProperties.getProperty('webpropertyId');
if (eventInfo && eventInfo.parameter && eventInfo.parameter.webpropertyList) {
webpropertyId = eventInfo.parameter.webpropertyList;
}

var profiles = Analytics.Management.Profiles.list(accountId, webpropertyId);
if (profiles.getItems()) {
for (var i = 0, profile; profile = profiles.getItems()[i]; ++i) {
profileList.addItem(profile.getName(), profile.getId());
}

var firstProfileId = profiles.getItems()[0].getId();
UserProperties.setProperty('profileId', firstProfileId);
displayProfile_();

} else {
profileList.addItem('No profiles found.');
displayProfile_('none');
}
return app;
}

/**
 * Displays the user's profile on the spreadsheet.
 * @param {Objecty} eventInfo Used to retrieve the profile ID. 
 */
function displayProfile_(eventInfo) {
var app = UiApp.getActiveApplication();

var profileId = '';
var tableId = '';

if (eventInfo != 'none') {
var profileId = UserProperties.getProperty('profileId');
if (eventInfo && eventInfo.parameter && eventInfo.parameter.profileList) {
profileId = eventInfo.parameter.profileList;
}
var tableId = 'ga:' + profileId;
}

app.getElementById('profileId').setText(profileId);
app.getElementById('ids').setText(tableId);
return app;
}


/**
 * Returns the GA_CONFIG sheet. If it doesn't exist it is created.
 * @return {Sheet} The GA_CONFIG sheet.
 */
function getOrCreateGaSheet_() {
var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var gaConfig = activeSpreadsheet.getSheetByName(GA_CONFIG);
if (!gaConfig) {
gaConfig = activeSpreadsheet.insertSheet(GA_CONFIG, 0);
}
return gaConfig;
}


/**
 * Entry point for a user to create a new Core Report configuration.
 */
function createCoreReport() {
createGaReport_(CORE_TYPE);
}

/**
 * Entry point for a user to create a new MCF Report Configuration.
 */
function createMcfReport() {
createGaReport_(MCF_TYPE);
}

/**
 * Adds a GA Report configuration to the spreadsheet.
 * @param {String} The type of report configuration to add.
 *Should be either CORE_TYPE or MCF_TYPE.
 */
function createGaReport_(reportType) {
var sheet = getOrCreateGaSheet_();
var headerNumber = getLastNumber_(sheet);
var config = [
[NAME + headerNumber, VALUE + headerNumber],
[TYPE, reportType],
['ids', ''],
['start-date', ''],
['end-date', ''],
['last-n-days', ''],
['metrics', '']];

// Add API specific fields. Default to Core.
var paramNames = CORE_OPT_PARAM_NAMES;
if (reportType == MCF_TYPE) {
paramNames = MCF_OPT_PARAM_NAMES;
}
for (var i = 0, paramName; paramName = paramNames[i]; ++i) {
config.push([paramName, '']);
}

config.push([SHEET_NAME, '']);
sheet.getRange(1, sheet.getLastColumn() + 1, config.length, 2).setValues(config);
}

/**
 * Returns 1 greater than the largest trailing number in the header row.
 * @param {Object} sheet The sheet in which to find the last number.
 * @returns {Number} The next largest trailing number.
 */
function getLastNumber_(sheet) {
var maxNumber = 0;

var lastColIndex = sheet.getLastColumn();

if (lastColIndex > 0) {
var range = sheet.getRange(1, 1, 1, lastColIndex);

for (var colIndex = 1; colIndex < sheet.getLastColumn(); ++colIndex) {
var value = range.getCell(1, colIndex).getValue();
var headerNumber = getTrailingNumber_(value);
if (headerNumber) {
var number = parseInt(headerNumber, 10);
maxNumber = number > maxNumber ? number : maxNumber;
}
}
}
return maxNumber + 1;
}


/**
 * Main function to get data from the Analytics API. This reads the
 * configuration file, executes the queries, and displays the results.
 * @param {object} e Some undocumented parameter that is passed only
 * when the script is run from a trigger. Used to update
 * user on the status of the report.
 */
function getData(e) {
setupLog_();
var now = new Date();
log_('Running on: ' + now);

var sheet = getOrCreateGaSheet_();
var configs = getConfigs_(sheet);

if (!configs.length) {
log_('No report configurations found');

} else {
log_('Found ' + configs.length + ' report configurations.');

for (var i = 0, config; config = configs[i]; ++i) {
var configName = config[NAME];

try {
log_('Executing query: ' + configName);
var results = getResults_(config);

log_('Success. Writing results.');
displayResults_(results, config);

} catch (error) { 
log_('Error executing ' + configName + ': ' + error.message);
}
}
}
log_('Script done');

// Update the user about the status of the queries.
if( e === undefined ) {
displayLog_();
} 
}


/**
 * Returns an array of config objects. This reads the gaconfig sheet
 * and tries to extract adjacent column names that end with the same
 * number. For example Names1 : Values1. Then both columns are used
 * to define key-value pairs for the coniguration object. The first
 * column defines the keys, and the adjacent column values define
 * each keys values.
 * @param {Sheet} The GA_Config sheet from which to read configurations.
 * @returns {Array} An array of API query configuration object.
 */
function getConfigs_(sheet) {

var configs = [];
// There must be at least 2 columns.
if (sheet.getLastColumn() < 2) {
return configs;
}

var headerRange = sheet.getRange(1, 1, 1, sheet.getLastColumn());

// Test the name of each column to see if it has an adjacent column that ends
// in the same number. ie xxxx555 : yyyy555.
// Since we check 2 columns at a time, we don't need to check the last column,
// as there is no second column to also check. 
for (var colIndex = 1; colIndex <= headerRange.getNumColumns() - 1; ++colIndex) {
var firstColValue = headerRange.getCell(1, colIndex).getValue();
var firstColNum = getTrailingNumber_(firstColValue);

var secondColValue = headerRange.getCell(1, colIndex + 1).getValue();
var secondColNum = getTrailingNumber_(secondColValue);

if (firstColNum && secondColNum && firstColNum == secondColNum) {
configs.push(getConfigsStartingAtCol_(colIndex)); 
}
}

return configs;
}


/**
 * Returns the trailing number on a string. For example the
 * input: xxxx555 will return 555. Inputs with no trailing numbers
 * return undefined. Trailing whitespace is not ignored.
 * @param {string} input The input to parse.
 * @resturns {number} The trailing number on the input as a string.
 * undefined if no number was found.
 */
function getTrailingNumber_(input) {
// Match at one or more digits at the end of the string.
var pattern = /(\d+)$/;
var result = pattern.exec(input);
if (result) {
// Return the matched number.
return result[0];
}

return undefined;
}


/**
 * Returns the values from 2 columns from the GA_CONFIG sheet starting at
 * colIndex, as key-value pairs. Key-values are only returned if they do
 * not contain the empty string or have a boolean value of false.
 * If the key is start-date or end-date and the value is an instance of
 * the date object, the value will be converted to a string in yyyy-MM-dd.
 * If the key is start-index or max-results and the type of the value is
 * number, the value will be parsed into a string.
 * @param {number} colIndex The column index to return values from.
 * @return {object} The values starting in colIndex and the following column
 as key-value pairs.
 */
function getConfigsStartingAtCol_(colIndex) {
var config = {};

var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(GA_CONFIG);
var range = sheet.getRange(1, colIndex, sheet.getLastRow(), 2);

// The first cell of the first column becomes the name of the query.
config[NAME] = range.getCell(1,1).getValue();

for (var rowIndex = 2; rowIndex <= range.getLastRow(); ++rowIndex) {
var key = range.getCell(rowIndex, 1).getValue();
var value = range.getCell(rowIndex, 2).getValue();
if (value) {
if ((key == 'start-date' || key == 'end-date') && value instanceof Date) {
// Utilities.formatDate is too complicated since it requires a time zone
// which can be configured by account or per sheet.
value = formatGaDate_(value);

} else if ((key == 'start-index' || key == 'max-results') && typeof value == 'number') {
value = value.toString(); 
}
config[key] = value;
}
}

return config;
}


/**
 * Returns the dateInput object in yyyy-MM-dd.
 * @param {Date} dateInput The object to convert.
 * @returns {string} The date object as yyyy-MM-dd.
 */
function formatGaDate_(inputDate) {
var output = [];
var year = inputDate.getFullYear();

var month = inputDate.getMonth() + 1;
if (month < 10) {
month = '0' + month; 
}

var day = inputDate.getDate();
if (day < 10) {
day = '0' + day; 
}
return [year, month, day].join('-');
}


/**
 * Executes a Google Analytics API query and returns the results.
 * @param {object} config A configuration object with key-value
 * parameters representing various API query parameters.
 * @retuns {object} A JSON object with all the results from the API.
 */
function getResults_(config) {

// Translate last n days into the actual start and end dates.
// This value overrides any existing start or end dates.
if (config['last-n-days']) {
var lastNdays = parseInt(config['last-n-days'], 10);
config['start-date'] = getLastNdays_(lastNdays);
config['end-date'] = getLastNdays_(0);
}

var type = config[TYPE] || CORE_TYPE;// If no type, default to core type.
if (type == CORE_TYPE) {
var optParameters = getOptParamObject_(CORE_OPT_PARAM_NAMES, config);
var apiFunction = Analytics.Data.Ga.get;

} else if (type == MCF_TYPE) {
var optParameters = getOptParamObject_(MCF_OPT_PARAM_NAMES, config);
var apiFunction = Analytics.Data.Mcf.get
}

// Execute query and return the results.
// If any errors occur, they will be thrown and caught in a higher
// level of code.
var results = apiFunction(
config['ids'],
config['start-date'],
config['end-date'],
config['metrics'],
optParameters);

return results;
}

/**
 * Returns a date formatted as YYYY-MM-DD from the number of
 * days ago starting from today.
 * @param {number} nDays The number of days to request dats from today.
 * @returns {String} The YYY_MM_DD formatted date of the previous days.
 */
function getLastNdays_(nDays) {
var today = new Date();
var before = new Date();
before.setDate(today.getDate() - nDays);
return formatGaDate_(before);
}

/**
 * Returns all the valid optional parameters for a Reporting API Query.
 * This ensures non-valid parameters are not added to the query.
 * Parameters with empty values will not be added.
 * @param {array.<String>} optParamNames An array of all the valid param names.
 * @param {Object} config The configuration object.
 * @returns {object} An object with all the keys as param names and values as
 * param values.
 */
function getOptParamObject_(optParamNames, config) {
var optParameters = {};
for (var i = 0, paramName; paramName = optParamNames[i]; ++i) {
if (paramName in config && config[paramName]) {
optParameters[paramName] = config[paramName];
}
}
return optParameters;
}

/**
 * Displays all the API results of a sucessful query.
 * @param {object} results The data returned from the API.
 * @param {object} config An object that contains key value configuration
 * parameters.
 */
function displayResults_(results, config) {
// Use an object to force passing by reference.
var row = {};
row.count = 1;

var activeSheet = getOutputSheet_(config[SHEET_NAME]);
activeSheet.clear().setColumnWidth(1, 200);

outputResultInfo_(results, activeSheet, row, config[NAME]); 
outputTotalsForAllResults_(results, activeSheet, row)
outputHeaders_(results, activeSheet, row);

// Only output rows if they exist.
if (results.getRows()) {
var type = config[TYPE] || CORE_TYPE;// If no type, default to core type.
if (type == CORE_TYPE) {
outputCoreRows_(results, activeSheet, row);
} else if (type == MCF_TYPE) {
outputMcfRows_(results, activeSheet, row);
}
}
}


/**
 * Returns the sheet which should be used to output the results.
 * If no sheetName is used, a new sheet will be inserted.
 * If a sheetName is used, but doesn't yet exist, it will be inserted.
 * If a sheetName is used, and already exists, it will be returned.
 * @param {string} opt_sheetName The name of the sheet to return.
 * @returns {Sheet) a sheet object.
 */
function getOutputSheet_(opt_sheetName) {
var sheetName = opt_sheetName || false;
var activeSpreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet;
if (sheetName) {
activeSheet = activeSpreadSheet.getSheetByName(sheetName);
if (!activeSheet) {
activeSheet = activeSpreadSheet.insertSheet(sheetName);
}
} else {
activeSheet = activeSpreadSheet.insertSheet();
}
return activeSheet;
}


/**
 * Outputs whether the result contains sampled data.
 */
function outputResultInfo_(results, activeSheet, row, queryName) {
var now = Utilities.formatDate(new Date(), Session.getTimeZone(), "yyyy-MM-dd HH:mm:ss");

activeSheet.getRange(row.count, 1, 6, 2).setValues([
['Results for query', queryName],
['Date executed', now],
['Profile Name', results.getProfileInfo().getProfileName()],
['Total Results Found', results.getTotalResults()],
['Total Results Returned', results.getRows().length],
['Contains Sampled Data', results.getContainsSampledData()]
]);

// Merge 4 cells to make it look nice.
activeSheet.getRange(row.count + 1, 2, 1, 2).mergeAcross(); // For date / time.
activeSheet.getRange(row.count + 2, 2, 1, 4).mergeAcross(); // For profile name.
row.count += 7;
}


/**
 * Outpus the totals for all results. Goes through each header in one pass.
 * The number of dimensions are counted so that the range can be aligned with
 * the headers for all the rows. The metric names are put into an array in the
 * order they appear in the results. The totals for each metrics are also
 * looked up and put into an array in the same order as each name. Finally,
 * the name and totals are outputted into the sheet.
 */
function outputTotalsForAllResults_(results, activeSheet, row) {
activeSheet.getRange(row.count, 1).setValue('Totals For All Results');
++row.count;

var numDimensions = 0;
var metricNames = [];
var metricTotals = [];
for (var i = 0, header; header = results.getColumnHeaders()[i]; ++i) {
if (header.getColumnType() == 'DIMENSION') {
++numDimensions;
} else {
var metricName = header.getName();
metricNames.push(metricName);
var totalForMetric = results.getTotalsForAllResults()[metricName];
metricTotals.push(totalForMetric);
}
}

// Get a range that skips over the dimensions.
var range = activeSheet.getRange(row.count, numDimensions + 1, 2,
 results.getColumnHeaders().length - numDimensions);
range.setValues([metricNames, metricTotals]);
row.count += 3;
}


/**
 * Outputs the header values in the activeSheet.
 */
function outputHeaders_(results, activeSheet, row) {
var headerRange = activeSheet.getRange(row.count, 1, 1, results.getColumnHeaders().length);
var headerNames = [];
for (var i = 0; i < results.getColumnHeaders().length; ++i) {
headerNames.push(results.getColumnHeaders()[i].getName());
}
headerRange.setValues([headerNames]);

row.count += 1;
}


/**
 * Outputs the rows of data in the activeSheet. This also updates the first
 * occurance of the column that has date data to be in yyyy=MM-dd format.
 */
function outputCoreRows_(results, activeSheet, row) {
var rows = results.getRows();

// Update the ga:date columns to be in yyyy-MM-dd format.
var dateCols = getDateColumns_(results.getColumnHeaders());
if (dateCols.length) {

for (var rowIndex = 0; rowIndex < rows.length; ++rowIndex) {
for (var i = 0; i < dateCols.length; ++i) {
var dateColIndex = dateCols[i];
rows[rowIndex][dateColIndex] = convertToIsoDate_(rows[rowIndex][dateColIndex]);
}
}
}

activeSheet.getRange(row.count, 1,
 results.getRows().length,
 results.getColumnHeaders().length).setValues(rows);
}

/**
 * Outputs the rows of data in the active sheet. Each primitive dimension gets
 * it's own cell. Each primitiveValue gets it's own cell. The nodes of each
 * conversionPathValue get individual cells. Because the size of the resulting
 * table may vary, a counter keeps track of the final table.
 */
function outputMcfRows_(results, activeSheet, row) {
var maxCols = 1;
var outputTable = [];
for (var rowIndex = 0, resultRow; resultRow = results.getRows()[rowIndex]; ++rowIndex) {

var outputRow = [];
for (var colIndex = 0, cell; cell = resultRow[colIndex]; ++colIndex) {
var jsonCell = Utilities.jsonParse(cell);

if (jsonCell['primitiveValue']) {
outputRow.push(jsonCell['primitiveValue']);

} else if (jsonCell['conversionPathValue']) {
// All nodes become cells.
var nodeCell = [];
var nodes = jsonCell['conversionPathValue'];
for (var nodeIndex = 0, node; node = nodes[nodeIndex]; ++nodeIndex) {
nodeCell.push(node['nodeValue']);
}
outputRow.push(nodeCell.join(' > '));//TODO: should we auto-expand?
}
}
outputTable.push(outputRow);
if(outputRow.length > maxCols) {
maxCols = outputRow.length;
}
}

var range = activeSheet.getRange(row.count, 1,
 outputTable.length,
 maxCols);
range.setValues(outputTable);
}


/**
 * Returns an array with all the indicies of columns that contain the ga:date
 * dimension. The indicies start from 0.
 * @param {object} header The header object returned from the API.
 * @returns {Array.<number>} The 0-based indicies of the columns that contain
 */
function getDateColumns_(headers) {
var indicies = [];
for (var colIndex = 0; colIndex < headers.length; ++colIndex) {
var name = headers[colIndex].getName();
if (name == 'ga:date') {
indicies.push(colIndex);
}
}
return indicies;
}
 
/**
 * Converts a string in the format yyyyMMdd to the format yyyy-MM-dd.
 * @param {String} gaDate The string to convert.
 * @returns {String} The formatted string.
 */
function convertToIsoDate_(gaDate) {
var year = gaDate.substring(0, 4);
var month = gaDate.substring(4, 6);
var day = gaDate.substring(6, 8);
return [year, month, day].join('-');
}


/**
 * The output text that should be displayed in the log.
 * @private.
 */
var logArray_;


/**
 * Clears the in app log.
 * @private.
 */
function setupLog_() {
logArray_ = [];
}


/**
 * Appends a string as a new line to the log.
 * @param {String} value The value to add to the log.
 */
function log_(value) {
logArray_.push(value);

var app = UiApp.getActiveApplication();
var foo = app.getElementById('log');
foo.setText(getLog_());
}


/**
 * Returns the log as a string.
 * @returns {string} The log.
 */
function getLog_() {
return logArray_.join('\n'); 
}


/**
 * Displays the log in memory to the user.
 */
function displayLog_() {
var uiLog = UiApp.createApplication().setTitle('Report Status').setWidth(400).setHeight(500);
var panel = uiLog.createVerticalPanel();
uiLog.add(panel);

var txtOutput = uiLog.createTextArea().setId('log').setWidth('400').setHeight('500').setValue(getLog_());
panel.add(txtOutput);

SpreadsheetApp.getActiveSpreadsheet().show(uiLog); 
}
Или с источника





Шаг 3 - Включите API Google Analytics, перейдя в "Resources"- "Advanced Google Services". Примечание: вам может быть предложено ввести название сценария.





Шаг 4 – Перейдите к "Google Developers Console" и включите Analytics API





Шаг 5 - Обновите Google документ и, через несколько секунд, должна появиться вкладка "Google Analytics Tab". В выпадающем меню выберите "Create Core Report" (вы также можете создать мультиканальный отчет (Multi Channel Fund Report), и сохранить его).





Шаг 6 - Это создаст вам новую вкладку с именем "gaconfig" - Откройте ее.





Шаг 7 - Узнайте ID своего аккаунта, перейдя в Google Analytics и найдя Profile/ids и заполните параметр IDS

Шаг 8 - С помощью руководства пользователя, заполните остальные параметры (в данном случае я выбираю простой отчет о количестве посетителей, упорядоченные по дате)





Совет: Используйте Google Analytics query explorer, чтобы легче было заполнять параметры

Шаг 9 - Запустите сценарий, перейдя в "Google Analytics" - "GetData"





Данные будут загружаться в новой вкладке после параметра "sheet-name"





Если вы сделали ошибку, появится диалоговое окно, которое даст знать, что именно не так.

Шаг 10 - Настройте автоматический вызов повторяющихся API, возвратившись к своему сценарию и нажав на кнопку "Resources"- "Current Project triggers"





Шаг 11 - Добавление нового тригера. Выберите опцию "GetData" из выпадающего меню и выберите источник данных. Не забудьте сохранить.





Итак, что мы имеем? В результате нехитрых манипуляций, мы получили обновляемую GA панель, которой можно поделиться со своими коллегами. Вытащенные данные идут в отдельную вкладку, откуда, теперь, можно создавать классные графики и сложные формулы для мониторинга таких ключевых показателей, как уровень отказов и коэффициент вирусности для разных каналов.
Нравится 0   Не нравится 0
Пожаловаться на это сообщение 0  
Ответить с цитированием

Ответ
 
 

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Clicky Web Analytics лучше чем Google Analytics? Viper Аналитика 0 05.06.2014 15:55
Google Analytics будет проверять код на ошибки Midas Сервисы 1 17.04.2014 08:47
Обзор сервиса Google Analytics dangerous Сервисы 0 19.08.2013 03:21
«Перекрёстное опыление» в Google Analytics Alsu Статьи 0 20.05.2013 17:52
Простота в использовании Google Analytics API Alsu Сервисы 0 11.12.2012 13:33

Метки
google analytics, google docs, панель данных


Здесь присутствуют: 1 (пользователей: 0, гостей: 1)
 
Опции темы

Быстрый переход


Текущее время: 18:05. Часовой пояс GMT +3.