Отчет эффективности объявлений — различия между версиями

Материал из Raskrutka
Перейти к: навигация, поиск
(Новая страница: «1. Создать пустую таблицу 2. Скопировать код»)
 
 
(не показана 1 промежуточная версия этого же участника)
Строка 1: Строка 1:
1. Создать пустую таблицу
+
1. Создать пустую таблицу Google Sheet
2. Скопировать код
+
 
 +
2. Скопировать код, приведенный ниже
 +
 
 +
3. '''Google Sheets URL''' - укажите ссылку на созданную таблицу (строка 16)
 +
 
 +
4. '''Date range''' - установите диапазон дат, который вы хотите проанализировать в формате ''год-месяц-день''. (строки 18 и 19)
 +
 
 +
5. '''Define campaigns to include or exclude''' -  определите, какие кампании нужно включить в отчет, либо исключить. По умолчанию включены все кампании. (строки 25 и 28)
 +
 
 +
6. '''Select your currency''' - установите валюту, используя символ, например "₴" или "$". (строка 30)
 +
 
 +
<pre>
 +
 
 +
/**********************
 +
*
 +
* AdWords script to pull ad data into a Google Sheet.
 +
*
 +
* Parameters include:
 +
* - Sheet URL
 +
* - Start and end dates
 +
* - Include/exclude paused ads
 +
* - Include/exclude ads with no conversions
 +
* - Lists of campaigns to include/exclude (or shows all)
 +
* - V1. Clicteq Limited
 +
*/
 +
function main() {
 +
  ///////////////////////// BEGIN USER EDIT AREA /////////////////////////////
 +
  //Enter the url of the sheet where you want the data to be added
 +
  var sheetURL = "Enter Google Sheets URL here";
 +
  //Enter start and end dates in this format:  2018-04-10
 +
  var startDate = "2018-04-01";
 +
  var endDate = "2018-04-14"
 +
  //Include paused ads?
 +
  var includePaused = false;
 +
  //Include ads with no conversions?
 +
  var includeNoConversions = true;
 +
  //List of campaign names to include (leave blank for all)
 +
  var includeCampaigns = [];// e.g. ["My campaign 1", "My campaign 2"];
 +
  //List of campaign names to exclude (leave blank for all,
 +
  //and do not exclude campaigns you have explicitly included)
 +
  var excludeCampaigns = [];// e.g. ["My campaign 1", "My campaign 2"];
 +
  //Enter here the currency used for the cost
 +
  var currency = "₴";
 +
  //List of outputs to display by
 +
  var pivots = ["HeadlinePart1","HeadlinePart2","Description","Path1","Path2"];
 +
  ///////////////////////// END USER EDIT AREA ///////////////////////////////
 +
  generateReports(sheetURL,pivots,startDate,endDate,includePaused,includeCampaigns,excludeCampaigns,includeNoConversions,currency)
 +
}
 +
//Put it all together and generate reports
 +
function generateReports(sheetURL,pivots,startDate,endDate,includePaused,includeCampaigns,excludeCampaigns,includeNoConversions,currency){
 +
  //Open the sheet provided by the user
 +
  var ss = SpreadsheetApp.openByUrl(sheetURL);
 +
  var start = convertPrettyDateToAQL(startDate);
 +
  var end = convertPrettyDateToAQL(endDate);
 +
  //Continue only if valid dates
 +
  if (start != undefined && end != undefined){
 +
    //Pivot by each of the five categories
 +
    for (var i=0;i<pivots.length;i++){
 +
      var pivot = pivots[i];
 +
      Logger.log("Retrieving Adwords data for " + pivot + "...");
 +
      addReportToSheetWithName(ss,pivot,start,end,includePaused,includeCampaigns,excludeCampaigns,includeNoConversions,currency);
 +
    }
 +
  }
 +
  else{
 +
    Logger.log("Dates entered not in correct format! Please make sure you enter them in the format specified: 2018-04-10 (YYYY-MM-DD)");
 +
  }
 +
}
 +
//Retrieve AdWords reporting data
 +
function generateAdWordsReport(pivot,start,end,paused,include,exclude,includeNoConversions){
 +
  var includes = "";
 +
  //If paused ads need to be shown, add it to the query, otherwise keep it as it is
 +
  var includePausedText = (paused ? "" : " Status = ENABLED ");
 +
  includes = addToQuery(includes,includePausedText);
 +
  //If include/exclude campaigns contain names, add them to the query, otherwise keep it as it is
 +
  var includeCampaignsText = include.length>0 ? (" CampaignName IN " + formatTextForQuerySet(include)) : "";
 +
  includes = addToQuery(includes,includeCampaignsText);
 +
  var excludeCampaignsText = exclude.length>0 ? (" CampaignName NOT_IN " + formatTextForQuerySet(exclude)) : "";
 +
  includes = addToQuery(includes,excludeCampaignsText);
 +
  if (!includeNoConversions){
 +
    includes = addToQuery(includes," Conversions > 0 ");
 +
  }
 +
  var query =  "SELECT " + pivot + ", Clicks, Impressions, Cost, Conversions, Ctr, ConversionRate, CostPerConversion " +
 +
          "FROM AD_PERFORMANCE_REPORT " +
 +
          includes +
 +
          "DURING " + start + "," + end;
 +
  var report = AdWordsApp.report(query);
 +
  return report;
 +
}
 +
//Generate report and fill sheet
 +
function addReportToSheetWithName(ss,pivot,start,end,paused,include,exclude,conversions,currency){
 +
  //Get or create the sheet with the pivot specified
 +
  var sheet = ss.getSheetByName(pivot);
 +
  if (sheet == undefined){
 +
      sheet = ss.insertSheet(pivot);
 +
  }
 +
  //Create the report
 +
  var report = generateAdWordsReport(pivot,start,end,paused,include,exclude,conversions);
 +
  //Add the data to the sheet. If the data exceeds the max sheet size,
 +
  //log it so the user knows
 +
  try{
 +
    Logger.log("Pivotting the data for " + pivot);
 +
    var data = getRowsAndAggregateToUnique(report,pivot);
 +
    var asArray = getObjectAsArray(data,pivot);
 +
    Logger.log("Writing data to the sheet\n");
 +
    if (asArray.length>0){
 +
      var range = sheet.getRange(1,1,asArray.length,asArray[0].length);
 +
      sheet.clear();
 +
      range.setValues(asArray);
 +
      sheet.setFrozenRows(1);
 +
      // Pct format
 +
      var column = sheet.getRange("F2:G");
 +
      column.setNumberFormat("#.##%")
 +
      // Currency format
 +
      column = sheet.getRange("H2:H");
 +
      column.setNumberFormat(currency + "#,##0.00");
 +
    }
 +
  }
 +
  catch(e){
 +
    Logger.log(e);
 +
  }
 +
}
 +
//Format array as AQL set
 +
function formatTextForQuerySet(array){
 +
  var awq = "[";
 +
  Logger.log(array);
 +
  for (var i=0;i<array.length;i++){
 +
    var item = "'" + array[i] + "'";
 +
    var isLast = (i==array.length-1);
 +
    awq += item + (isLast?"":",");
 +
    Logger.log(awq);
 +
  }
 +
  awq += "] ";
 +
  return awq;
 +
}
 +
//Add to query filter
 +
function addToQuery(queryBuilder,newQueryItem){
 +
  //no new queries to add
 +
  if (newQueryItem == ""){
 +
    return queryBuilder;
 +
  }
 +
  //add 'WHERE' or 'AND' depending on blank statement or existing statement
 +
  if (queryBuilder == ""){
 +
    queryBuilder +=  " WHERE " + newQueryItem;
 +
  }
 +
  else{
 +
    queryBuilder += " AND " + newQueryItem;
 +
  }
 +
  return queryBuilder;
 +
}
 +
//Retrieve rows for further processing and aggregation of data
 +
function getRowsAndAggregateToUnique(report,pivot){
 +
  var rows = report.rows();
 +
  var data = {};
 +
  while (rows.hasNext()){
 +
    var row = rows.next();
 +
    var dataRow = [];
 +
    var keys = Object.keys(row);
 +
    if (data[row[pivot]] == undefined){
 +
      data[row[pivot]] = {};
 +
    }
 +
    for (var i=0;i<keys.length;i++){
 +
      if (keys[i]!="Ctr" && keys[i]!="ConversionRate" && keys[i]!="CostPerConversion" && keys[i]!=pivot){
 +
        if (data[row[pivot]][keys[i]] == undefined){
 +
          data[row[pivot]][keys[i]] = 0;
 +
        }
 +
        var n = readNumber(row[keys[i]]);
 +
        var value = isNaN(n) ? 0 : n;
 +
        data[row[pivot]][keys[i]] += value*1;
 +
      }
 +
    }
 +
  }
 +
  //Now based on clicks, implessions, conversions and cost, calculare Ctr, ConversionRate and CostPerConversion
 +
  var pivotKeys = Object.keys(data);
 +
  for (var i=0;i<pivotKeys.length;i++){
 +
    var pivotKey = pivotKeys[i];
 +
    var value = ( isNaN(data[pivotKey]["Clicks"])
 +
                || (data[pivotKey]["Impressions"] == 0)
 +
                || isNaN(data[pivotKey]["Impressions"])
 +
                || isNaN(data[pivotKey]["Clicks"] / data[pivotKey]["Impressions"])
 +
                )? 0 : (data[pivotKey]["Clicks"] / data[pivotKey]["Impressions"]);
 +
    data[pivotKey]["Ctr"] = value;
 +
    value =    ( isNaN(data[pivotKey]["Conversions"])
 +
                || (data[pivotKey]["Clicks"] == 0)
 +
                || isNaN(data[pivotKey]["Clicks"])
 +
                || isNaN(data[pivotKey]["Conversions"] / data[pivotKey]["Clicks"])
 +
                )? 0 : (data[pivotKey]["Conversions"] / data[pivotKey]["Clicks"]);
 +
    data[pivotKey]["ConversionRate"] =  value;
 +
    value =    ( isNaN(data[pivotKey]["Cost"])
 +
                || (data[pivotKey]["Conversions"] == 0)
 +
                || isNaN(data[pivotKey]["Conversions"])
 +
                || isNaN(data[pivotKey]["Cost"] / data[pivotKey]["Conversions"])
 +
                )? 0 : (data[pivotKey]["Cost"]/ data[pivotKey]["Conversions"]);
 +
    data[pivotKey]["CostPerConversion"] = value;
 +
  }
 +
  return data;
 +
}
 +
//Convert the object to an array so it can be written to sheets
 +
function getObjectAsArray(obj,pivot){
 +
  var keys = Object.keys(obj);
 +
  //first add the headers
 +
  var rows = [[pivot,"Clicks","Impressions","Cost","Conversions","Ctr","ConversionRate","CostPerConversion"]];
 +
  //now add the data
 +
  for (var i=0;i<keys.length;i++){
 +
    var row = [keys[i] , obj[keys[i]]["Clicks"] , obj[keys[i]]["Impressions"] , obj[keys[i]]["Cost"]
 +
              , obj[keys[i]]["Conversions"] , obj[keys[i]]["Ctr"] , obj[keys[i]]["ConversionRate"]
 +
              ,obj[keys[i]]["CostPerConversion"]];
 +
    rows.push(row);
 +
  }
 +
  return rows;
 +
}
 +
//Fix the raw format returned by the report
 +
function readNumber(textNumber){
 +
  if (typeof textNumber == 'string'){
 +
    textNumber = textNumber.replace(',', '');
 +
    return parseFloat(textNumber);
 +
  }
 +
  return textNumber;
 +
}
 +
//Convert user input date into AQL format
 +
function convertPrettyDateToAQL(date){
 +
  var split = date.toString().split("-");
 +
  if (split.length == 3){
 +
    var year = split[0];
 +
    var month = split[1];
 +
    var day = split[2];
 +
    var checks = (year.length == 4) && (month <12) && (day <32);
 +
    if (checks){
 +
      var monthString = (month.toString().length == 1)?("0" + month.toString()):month.toString();
 +
      var dayString = (day.toString().length == 1)?("0" + day.toString()):day.toString();
 +
      var dateOut = year.toString() + monthString + dayString;
 +
      return dateOut;
 +
    }
 +
  }
 +
  //fallback
 +
  return undefined;
 +
}
 +
 
 +
</pre>

Текущая версия на 14:13, 24 апреля 2018

1. Создать пустую таблицу Google Sheet

2. Скопировать код, приведенный ниже

3. Google Sheets URL - укажите ссылку на созданную таблицу (строка 16)

4. Date range - установите диапазон дат, который вы хотите проанализировать в формате год-месяц-день. (строки 18 и 19)

5. Define campaigns to include or exclude - определите, какие кампании нужно включить в отчет, либо исключить. По умолчанию включены все кампании. (строки 25 и 28)

6. Select your currency - установите валюту, используя символ, например "₴" или "$". (строка 30)


/**********************
 *
 * AdWords script to pull ad data into a Google Sheet.
 *
 * Parameters include:
 * - Sheet URL
 * - Start and end dates
 * - Include/exclude paused ads
 * - Include/exclude ads with no conversions
 * - Lists of campaigns to include/exclude (or shows all)
 * - V1. Clicteq Limited
 */
function main() {
  ///////////////////////// BEGIN USER EDIT AREA /////////////////////////////
  //Enter the url of the sheet where you want the data to be added
  var sheetURL = "Enter Google Sheets URL here";
  //Enter start and end dates in this format:  2018-04-10
  var startDate = "2018-04-01";
  var endDate = "2018-04-14"
  //Include paused ads?
  var includePaused = false;
  //Include ads with no conversions?
  var includeNoConversions = true;
  //List of campaign names to include (leave blank for all)
  var includeCampaigns = [];// e.g. ["My campaign 1", "My campaign 2"];
  //List of campaign names to exclude (leave blank for all,
  //and do not exclude campaigns you have explicitly included)
  var excludeCampaigns = [];// e.g. ["My campaign 1", "My campaign 2"];
  //Enter here the currency used for the cost
  var currency = "₴";
  //List of outputs to display by
  var pivots = ["HeadlinePart1","HeadlinePart2","Description","Path1","Path2"];
  ///////////////////////// END USER EDIT AREA ///////////////////////////////
  generateReports(sheetURL,pivots,startDate,endDate,includePaused,includeCampaigns,excludeCampaigns,includeNoConversions,currency)
}
//Put it all together and generate reports
function generateReports(sheetURL,pivots,startDate,endDate,includePaused,includeCampaigns,excludeCampaigns,includeNoConversions,currency){
  //Open the sheet provided by the user
  var ss = SpreadsheetApp.openByUrl(sheetURL);
  var start = convertPrettyDateToAQL(startDate);
  var end = convertPrettyDateToAQL(endDate);
  //Continue only if valid dates
  if (start != undefined && end != undefined){
    //Pivot by each of the five categories
    for (var i=0;i<pivots.length;i++){
      var pivot = pivots[i];
      Logger.log("Retrieving Adwords data for " + pivot + "...");
      addReportToSheetWithName(ss,pivot,start,end,includePaused,includeCampaigns,excludeCampaigns,includeNoConversions,currency);
    }
  }
  else{
    Logger.log("Dates entered not in correct format! Please make sure you enter them in the format specified: 2018-04-10 (YYYY-MM-DD)");
  }
}
//Retrieve AdWords reporting data
function generateAdWordsReport(pivot,start,end,paused,include,exclude,includeNoConversions){
  var includes = "";
  //If paused ads need to be shown, add it to the query, otherwise keep it as it is
  var includePausedText = (paused ? "" : " Status = ENABLED ");
  includes = addToQuery(includes,includePausedText);
  //If include/exclude campaigns contain names, add them to the query, otherwise keep it as it is
  var includeCampaignsText = include.length>0 ? (" CampaignName IN " + formatTextForQuerySet(include)) : "";
  includes = addToQuery(includes,includeCampaignsText);
  var excludeCampaignsText = exclude.length>0 ? (" CampaignName NOT_IN " + formatTextForQuerySet(exclude)) : "";
  includes = addToQuery(includes,excludeCampaignsText);
  if (!includeNoConversions){
    includes = addToQuery(includes," Conversions > 0 ");
  }
  var query =   "SELECT " + pivot + ", Clicks, Impressions, Cost, Conversions, Ctr, ConversionRate, CostPerConversion " +
          "FROM AD_PERFORMANCE_REPORT " +
          includes +
          "DURING " + start + "," + end;
  var report = AdWordsApp.report(query);
  return report;
}
//Generate report and fill sheet
function addReportToSheetWithName(ss,pivot,start,end,paused,include,exclude,conversions,currency){
  //Get or create the sheet with the pivot specified
  var sheet = ss.getSheetByName(pivot);
  if (sheet == undefined){
      sheet = ss.insertSheet(pivot);
  }
  //Create the report
  var report = generateAdWordsReport(pivot,start,end,paused,include,exclude,conversions);
  //Add the data to the sheet. If the data exceeds the max sheet size,
  //log it so the user knows
  try{
    Logger.log("Pivotting the data for " + pivot);
    var data = getRowsAndAggregateToUnique(report,pivot);
    var asArray = getObjectAsArray(data,pivot);
    Logger.log("Writing data to the sheet\n");
    if (asArray.length>0){
      var range = sheet.getRange(1,1,asArray.length,asArray[0].length);
      sheet.clear();
      range.setValues(asArray);
      sheet.setFrozenRows(1);
      // Pct format
      var column = sheet.getRange("F2:G");
      column.setNumberFormat("#.##%")
      // Currency format
      column = sheet.getRange("H2:H");
      column.setNumberFormat(currency + "#,##0.00");
    }
  }
  catch(e){
    Logger.log(e);
  }
}
//Format array as AQL set
function formatTextForQuerySet(array){
  var awq = "[";
  Logger.log(array);
  for (var i=0;i<array.length;i++){
    var item = "'" + array[i] + "'";
    var isLast = (i==array.length-1);
    awq += item + (isLast?"":",");
    Logger.log(awq);
  }
  awq += "] ";
  return awq;
}
//Add to query filter
function addToQuery(queryBuilder,newQueryItem){
  //no new queries to add
  if (newQueryItem == ""){
    return queryBuilder;
  }
  //add 'WHERE' or 'AND' depending on blank statement or existing statement
  if (queryBuilder == ""){
    queryBuilder +=  " WHERE " + newQueryItem;
  }
  else{
    queryBuilder += " AND " + newQueryItem;
  }
  return queryBuilder;
}
//Retrieve rows for further processing and aggregation of data
function getRowsAndAggregateToUnique(report,pivot){
  var rows = report.rows();
  var data = {};
  while (rows.hasNext()){
    var row = rows.next();
    var dataRow = [];
    var keys = Object.keys(row);
    if (data[row[pivot]] == undefined){
      data[row[pivot]] = {};
    }
    for (var i=0;i<keys.length;i++){
      if (keys[i]!="Ctr" && keys[i]!="ConversionRate" && keys[i]!="CostPerConversion" && keys[i]!=pivot){
        if (data[row[pivot]][keys[i]] == undefined){
          data[row[pivot]][keys[i]] = 0;
        }
        var n = readNumber(row[keys[i]]);
        var value = isNaN(n) ? 0 : n;
        data[row[pivot]][keys[i]] += value*1;
      }
    }
  }
  //Now based on clicks, implessions, conversions and cost, calculare Ctr, ConversionRate and CostPerConversion
  var pivotKeys = Object.keys(data);
  for (var i=0;i<pivotKeys.length;i++){
    var pivotKey = pivotKeys[i];
    var value = ( isNaN(data[pivotKey]["Clicks"])
                 || (data[pivotKey]["Impressions"] == 0)
                 || isNaN(data[pivotKey]["Impressions"])
                 || isNaN(data[pivotKey]["Clicks"] / data[pivotKey]["Impressions"])
                )? 0 : (data[pivotKey]["Clicks"] / data[pivotKey]["Impressions"]);
    data[pivotKey]["Ctr"] = value;
    value =     ( isNaN(data[pivotKey]["Conversions"])
                 || (data[pivotKey]["Clicks"] == 0)
                 || isNaN(data[pivotKey]["Clicks"])
                 || isNaN(data[pivotKey]["Conversions"] / data[pivotKey]["Clicks"])
                )? 0 : (data[pivotKey]["Conversions"] / data[pivotKey]["Clicks"]);
    data[pivotKey]["ConversionRate"] =  value;
    value =     ( isNaN(data[pivotKey]["Cost"])
                 || (data[pivotKey]["Conversions"] == 0)
                 || isNaN(data[pivotKey]["Conversions"])
                 || isNaN(data[pivotKey]["Cost"] / data[pivotKey]["Conversions"])
                )? 0 : (data[pivotKey]["Cost"]/ data[pivotKey]["Conversions"]);
    data[pivotKey]["CostPerConversion"] = value;
  }
  return data;
}
//Convert the object to an array so it can be written to sheets
function getObjectAsArray(obj,pivot){
  var keys = Object.keys(obj);
  //first add the headers
  var rows = [[pivot,"Clicks","Impressions","Cost","Conversions","Ctr","ConversionRate","CostPerConversion"]];
  //now add the data
  for (var i=0;i<keys.length;i++){
    var row = [keys[i] , obj[keys[i]]["Clicks"] , obj[keys[i]]["Impressions"] , obj[keys[i]]["Cost"]
               , obj[keys[i]]["Conversions"] , obj[keys[i]]["Ctr"] , obj[keys[i]]["ConversionRate"]
               ,obj[keys[i]]["CostPerConversion"]];
    rows.push(row);
  }
  return rows;
}
//Fix the raw format returned by the report
function readNumber(textNumber){
  if (typeof textNumber == 'string'){
    textNumber = textNumber.replace(',', '');
    return parseFloat(textNumber);
  }
  return textNumber;
}
//Convert user input date into AQL format
function convertPrettyDateToAQL(date){
  var split = date.toString().split("-");
  if (split.length == 3){
    var year = split[0];
    var month = split[1];
    var day = split[2];
    var checks = (year.length == 4) && (month <12) && (day <32);
    if (checks){
      var monthString = (month.toString().length == 1)?("0" + month.toString()):month.toString();
      var dayString = (day.toString().length == 1)?("0" + day.toString()):day.toString();
      var dateOut = year.toString() + monthString + dayString;
      return dateOut;
    }
  }
  //fallback
  return undefined;
}