显示带有标签的帖子 谷歌文档. 显示所有帖子
显示带有标签的帖子 谷歌文档. 显示所有帖子

2013年7月1日,星期一

广告系列和关键字效果报告

老板要求您汇总的许多每日或每周报告任务都可以使用AdWords脚本自动执行。我的一位读者通过了以下要求脚本的请求,该脚本可以节省他每天的时间,并将其一些绩效报告汇总在一起。也许它也可以节省您一些时间。

以下脚本将构建具有五个标签的Google Spreadsheet:
  1. 过去7天的广告系列效果摘要
  2. 迄今为止的广告系列效果月份
  3. 上个月的广告系列效果
  4. 过去7天的关键字效果摘要
  5. 过去7天的每日关键字效果

您需要做的就是创建一个 新的Google电子表格 并将网址粘贴到脚本中。然后,您可以安排此脚本每天运行,并在早上开始工作时,将刷新所有数据。

谢谢,
拉斯

/************************************
* Campaign and Keyword Summary Report
* Version: 1.2
* Changelog v1.2 - Fixed INVALID_PREDICATE_ENUM_VALUE
* ChangeLog v1.1 - Removed apiVersion from 报告 呼叫
* Created By: 拉斯 Savage
* FreeAdWordsScripts.com
************************************/
var SPREADSHEET_URL = "PASTE GOOGLE SPREADSHEET URL HERE";

function main() {
  //These names are important. change them with caution
  var tabs = ['camp_perf_7_days','camp_perf_mtd','camp_perf_last_month','keyword_perf_7_days','keyword_perf_7_days_daily'];
  for(var i in tabs) {
    var results = runQuery(tabs[i]);
    writeToSpreadsheet(tabs[i],results);
  }
}

//Helper function to get or 创造 the 电子表格
function getSheet(tab) {
  var s_sheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
  var sheet;
  try {
    sheet = s_sheet.getSheetByName(tab);
    if(!sheet) {
      sheet = s_sheet.insertSheet(tab, 0);
    }
  } catch(e) {
    sheet = s_sheet.insertSheet(tab, 0);
  }
  return sheet
}

//Function to write the rows of the report to the sheet
function writeToSpreadsheet(tab,rows) {
  var to_write = 兑换RowsToSpreadsheetRows(tab,rows);
  var s_sheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
  var sheet = getSheet(tab);
  sheet.clear();
  
  var numRows = sheet.getMaxRows();
  if(numRows < to_write.length) {
    sheet.insertRows(1,to_write.length-numRows); 
  }
  var range = sheet.getRange(1,1,to_write.length,to_write[0].length);
  range.setValues(to_write);
}

//A generic function used to build and run the report query
function runQuery(tab) {
  var API_VERSION = { includeZeroImpressions : false };
  var cols = getColumns(tab);
  var report = getReport(tab);
  var date_range = getDateRange(tab);
  var where = getWhereClause(tab);
  var query = ['select',cols.join(','),'from',report,where,'during',date_range].join(' ');
  var report_iter = AdWordsApp.report(query, API_VERSION).rows();
  var rows = [];
  while(report_iter.hasNext()) { 
    rows.push(report_iter.next());
  }
  return rows;
}
 
//This function will 兑换 row data into a format easily pushed into a 电子表格
function 兑换RowsToSpreadsheetRows(tab,rows) {
  var cols = getColumns(tab);
  var ret_val = [cols];
  for(var i in rows) {
    var r = rows[i];
    var ss_row = [];
    for(var x in cols) {
      ss_row.push(r[cols[x]]);
    }
    ret_val.push(ss_row);
  }
  return ret_val;
}

//Based on the tab name, this returns the report type to use for the query
function getReport(tab) {
  if(tab.indexOf('camp_') == 0) {
    return 'CAMPAIGN_PERFORMANCE_REPORT';
  }
  if(tab.indexOf('keyword_') == 0) {
    return 'KEYWORDS_PERFORMANCE_REPORT';
  }
  throw new Exception('tab name not recognized: '+tab);
}

//Based on the tab name, this returns the where clause for the query
function getWhereClause(tab) {
  if(tab.indexOf('camp_') == 0) {
    return 'where CampaignStatus = ENABLED';
  }
  if(tab.indexOf('keyword_') == 0) {
    return 'where CampaignStatus = ENABLED and AdGroupStatus = ENABLED and Status = ENABLED';
  }
  throw new Exception('tab name not recognized: '+tab);
}

//Based on the tab name, this returns the columns to 广告 d into the report
function getColumns(tab) {
  var ret_array = [];
  if(tab.indexOf('daily') >= 0) {
    ret_array.push('Date');
  }
  ret_array.push('CampaignName');
  ret_array.push('CampaignStatus');
  
  if(tab.indexOf('keyword_') == 0) {
    ret_array = ret_array.concat(['AdGroupName',
                                  'AdGroupStatus',
                                  'Id',
                                  'KeywordText',
                                  'KeywordMatchType']);
  }
  return ret_array.concat(['Clicks',
                           'Impressions',
                           'Ctr',
                           'AverageCpc',
                           'Cost',
                           'AveragePosition',
                           'Conversions',
                           'ConversionRate',
                           'ConversionValue']);
}

//Based on the tab name, this returns the date range for the data.
function getDateRange(tab) {
  if(tab.indexOf('7_days') >= 0) {
    return 'LAST_7_DAYS';
  }
  if(tab.indexOf('mtd') >= 0) {
    return 'THIS_MONTH';
  }
  if(tab.indexOf('last_month') >= 0) {
    return 'LAST_MONTH';
  }
  throw new Exception('tab name not recognized: '+tab);
}

2013年6月22日,星期六

广告创意测试自动化脚本

这是我已经工作了一段时间的脚本,我认为它确实很有用。我希望你也这样做。

每个有价值的SEM经理都在不断进行创造性的测试。而且,由于您正在阅读此博客,因此许多人可能以某种方式使用脚本来简化此过程。但是,您如何确定测试何时开始?对于每个广告组,它们可能会有所不同。

我见过有些人使用标签,有些人使用时间表,但是我从不真正喜欢跟踪那些东西。因此,我创建了此脚本,该脚本将自动跟踪创意测试的开始日期。

我采用的方法是将您的广告ID副本存储在Google电子表格中。然后,它会对照电子表格中的广告检查广告组中的当前广告,并通过查看广告ID找出是否有所更改。如果已经存在,则脚本假定已开始新的测试,并相应地在电子表格中记录了日期。使用此方法,营销人员可以确保脚本正在比较适当时间范围内的统计信息以确定测试获胜者。

但是后来一位读者提到,他们希望能够选择度量标准来衡量广告,并希望使用阈值仅在广告组中获得一定点击次数后才开始进行衡量。因此,我也将该功能添加到了脚本中。您只需要在脚本顶部调整一些参数,即可使用功能齐全的广告素材测试脚本。

每当它通过暂停对广告采取行动时,结果都会通过电子邮件发送给您,以便您可以为该广告组创建新的挑战者广告。

我用这个脚本做了一些不同的事情。我一直很讨厌让我的读者进入Google文档,并为我的脚本创建一个空白电子表格以用作存储。因此,为了解决这个问题,此脚本将检查存储电子表格ID的帐户中是否存在特殊标签。如果找到一个,它将使用它。并且如果缺少它(如第一次运行),它将创建电子表格和标签。这样,脚本中不会出现混乱的电子表格网址。这是一个变通办法,但是直到Google允许我们为脚本存储其他配置数据之前,我认为这是处理此问题的一种好方法。

与往常一样,我们欢迎您反馈此脚本是否对您有用。您还通过哪些其他指标来判断广告效果?该脚本还缺少什么?

谢谢,
拉斯

/************************************
* 广告创意测试自动化脚本
* Version: 1.3
* Changelog v1.3 - Data is written to the 电子表格 a little faster
* Changelog v1.2 - Added 广告 ditional threshold options
* Changelog v1.1 - Fixed issue with 日期 in 电子邮件
* Created By: 拉斯 Savage
* FreeAdWordsScripts.com
************************************/
// You can use any of the same values here as you can for METRIC below
var THRESHOLD = { metric : 'Clicks', value : 100 };
var TO = ['[email protected]'];
  
//Try any of these values for METRIC:
//AverageCpc, AverageCpm, AveragePageviews, AveragePosition, 
//AverageTimeOnSite, BounceRate, Clicks, ConversionRate, 
//Conversions, Cost, Ctr, Impressions
var METRIC = 'Ctr';
var ASC_OR_DESC = 'ASC'; //ASC - 暂停广告 with lowest value, DESC - 暂停广告 with highest value
  
function main() {
  //Start by finding what has changed in the account
  var 广告 _map = buildCurrentAdMap();
  var prev_ad_map = readMapFromSpreadsheet();
  prev_ad_map = 更新PreviousAdMap(prev_ad_map,ad_map);
  writeMapToSpreadsheet(prev_ad_map);
    
  //Now run through the 广告群组 to find creative tests
  var ag_iter = AdWordsApp.adGroups().get();
  var 暂停d_ads = [];
  while(ag_iter.hasNext()) {
    var ag = ag_iter.next();
    if(!prev_ad_map[ag.getId()]) { continue; }
      
    //Here is the date range for the test metrics
    var last_touched_str = _getDateString(prev_ad_map[ag.getId()].last_touched,'yyyyMMdd');
    var get_today_str = _getDateString(new Date(),'yyyyMMdd');
      
    var ag_stats = ag.getStatsFor(last_touched_str, get_today_str);
    if(ag_stats['get'+THRESHOLD.metric]() >= THRESHOLD.value) {
      var 广告 _iter = ag.ads().withCondition('Status = ENABLED')
                            .forDateRange(last_touched_str, get_today_str)
                            .orderBy(METRIC+" "+ASC_OR_DESC).get();
      var 广告  = 广告 _iter.next();
      var metric = 广告 .getStatsFor(last_touched_str, get_today_str)['get'+METRIC]();
      ad.pause();
      paused_ads.push({a : 广告 , m : metric});
    }
  }
  sendEmailForPausedAds(paused_ads);
}
  
// A function to send an 电子邮件 with an 在tached report of 广告 it has 暂停d
function sendEmailForPausedAds(ads) {
  if(ads.length == 0) { return; } //No 广告 暂停d, no 电子邮件
  var 电子邮件_body = '"' + ['CampaignName','AdGroupName','Headline','Desc1','Desc2','DisplayUrl',METRIC].join('","') + '"\n';
  for(var i in 广告) {
    var 广告  = 广告[i].a;
    var metric = 广告[i].m;
    email_body += '"' + [ad.getCampaign().getName(),
                         ad.getAdGroup().getName(),
                         ad.getHeadline(),
                         ad.getDescription1(),
                         ad.getDescription2(),
                         ad.getDisplayUrl(),
                         metric
                        ].join('","') +
                  '"\n';
  }
  var date_str = _getDateString(new Date(),'yyyy-MM-dd');
  var options = { 附件: [Utilities.newBlob(email_body, 'text/csv', "FinishedTests_"+date_str+'.csv')] };
  var subject = 'Finished Tests - ' + date_str;
  for(var i in TO) {
    MailApp.sendEmail(TO[i], subject, 'See 在tached.', options);
  }
}
  
//Given two lists of 广告, this checks to make sure they are the same.
function sameAds(ads1,ads2) {
  for(var i in 广告1) {
    if(ads1[i] != 广告2[i]) { return false; }
  }
  return true;
}
  
//This reads the stored data from the 电子表格
function readMapFromSpreadsheet() {
  var 广告 _map = {};
  var sheet = SpreadsheetApp.openById(findSpreadsheetId()).getActiveSheet();
  var data = sheet.getRange('A:C').getValues();
  for(var i in data) {
    if(data[i][0] == '') { break; }
    var [ag_id,last_touched,ad_ids] = data[i];
    ad_map[ag_id] = { 广告 _ids : (''+ad_ids).split(','), last_touched : new Date(last_touched) };
  }
  return 广告 _map;
}
  
//This will search for a 标签 containing the 电子表格 id
//If one isn't found, it will 创造 a new one and the 标签 as well
function findSpreadsheetId() {
  var 电子表格_id = "";
  var 标签_iter = AdWordsApp.labels().withCondition("Name STARTS_WITH 'history_script:'").get();
  if(label_iter.hasNext()) {
    var 标签 = 标签_iter.next();
    return 标签.getName().split(':')[1]; 
  } else {
    var sheet = SpreadsheetApp.create('AdGroups History');
    var sheet_id = sheet.getId();
    AdWordsApp.createLabel('history_script:'+sheet_id, 'stores sheet id for 广告群组 changes script.');
    return sheet_id;
  }
}
  
//This will store the data from the account into a 电子表格
function writeMapToSpreadsheet(ad_map) {
  var toWrite = [];
  for(var ag_id in 广告 _map) {
    var 广告 _ids = 广告 _map[ag_id].ad_ids;
    var last_touched = 广告 _map[ag_id].last_touched;
    toWrite.push([ag_id,last_touched,ad_ids.join(',')]);
  }
  writeToSpreadsheet(toWrite);
}

// Write the 关键词 data to the 电子表格
function writeToSpreadsheet(toWrite) {
  var sheet = SpreadsheetApp.openById(findSpreadsheetId()).getActiveSheet();
  sheet.clear();
  
  var numRows = sheet.getMaxRows();
  if(numRows < toWrite.length) {
    sheet.insertRows(1,toWrite.length-numRows); 
  }
  var range = sheet.getRange(1,1,toWrite.length,toWrite[0].length);
  range.setValues(toWrite);
}
  
//This builds a map of the 广告 in the account so that it is easy to compare
function buildCurrentAdMap() {
  var 广告 _map = {}; // { ag_id : { 广告 _ids : [ 广告 _id, ... ], last_touched : date } }
  var 广告 _iter = AdWordsApp.ads().withCondition('Status = ENABLED').get();
  while(ad_iter.hasNext()) {
    var 广告  = 广告 _iter.next();
    var ag_id = 广告 .getAdGroup().getId();
    if(ad_map[ag_id]) {
      ad_map[ag_id].ad_ids.push(ad.getId());
      ad_map[ag_id].ad_ids.sort();
    } else {
      ad_map[ag_id] = { 广告 _ids : [ad.getId()], last_touched : new Date() };
    }
  }
  return 广告 _map;
}
  
//This takes the old 广告  map and the current 广告  map and returns an
//updated map with all changes.
function 更新PreviousAdMap(prev_ad_map,ad_map) {
  for(var ag_id in 广告 _map) {
    var current_ads = 广告 _map[ag_id].ad_ids;
    var previous_ads = (prev_ad_map[ag_id]) ? prev_ad_map[ag_id].ad_ids : [];
    if(!sameAds(current_ads,previous_ads)) {
      prev_ad_map[ag_id] = 广告 _map[ag_id];
    }
  }
  return prev_ad_map;
}
  
//Helper function to format the date
function _getDateString(date,format) {
  return Utilities.formatDate(date,AdWordsApp.currentAccount().getTimeZone(),format); 
}

2013年3月20日,星期三

在Google文档中存储帐户效果报告

第2天,我仍在使用新的报告API。我想我会发布一些人们开始从我以前的帖子中询问的内容 存储帐户级别质量得分 它将所有帐户级别的效果存储在电子表格中。

您需要做的就是创建一个全新的Google文档来存储您的数据并将该URL粘贴到脚本中。脚本第一次运行时,将创建列标题。您可以根据需要通过移动列名来添加,删除或重新排列列。不过,您应该在执行此操作后重设电子表格。

谢谢,
拉斯

/**************************************
* 在Google文档中存储帐户效果报告
* Version 1.1
* Changelog v1.1 - Removed apiVersion, Removed get 电子表格
* Created By: 拉斯 Savage
* FreeAdWordsScripts.com
**************************************/
function main() {
  var 电子表格_url = "Your Spreadsheet Url Goes Here";
  var date_range = 'YESTERDAY';
  var columns = ['Date',
                 'AccountCurrencyCode',
                 'AccountDescriptiveName',
                 'AccountId',
                 'AccountTimeZoneId',
                 'CustomerDescriptiveName',
                 'ExternalCustomerId',
                 'PrimaryCompanyName',
                 'PrimaryUserLogin',
                 'Device',
                 'AverageCpc',
                 'AverageCpm',
                 'AveragePosition',
                 'Clicks',
                 'ConversionRate',
                 'ConversionRateManyPerClick',
                 'Conversions',
                 'ConversionsManyPerClick',
                 'ConversionValue',
                 'Cost',
                 'CostPerConversion',
                 'CostPerConversionManyPerClick',
                 'Ctr',
                 'Impressions',
                 'SearchBudgetLostImpressionShare',
                 'SearchExactMatchImpressionShare',
                 'SearchImpressionShare',
                 'SearchRankLostImpressionShare',
                 'ValuePerConversion',
                 'ValuePerConversionManyPerClick',
                 'ViewThroughConversions'];
  var columns_str = columns.join(',') + " ";
  
  var sheet = SpreadsheetApp.openByUrl(spreadsheet_url).getActiveSheet();
  if(sheet.getRange('A1:A1').getValues()[0][0] == "") {
    sheet.clear();
    sheet.appendRow(columns);
  }
  
  var report_iter = AdWordsApp.report(
    'SELECT ' + columns_str +
    'FROM ACCOUNT_PERFORMANCE_REPORT ' +
    'DURING ' +date_range).rows();
  
  while(report_iter.hasNext()) {
    var row = report_iter.next();
    var row_array = [];
    for(var i in columns) {
       row_array.push(row[columns[i]]);
    }
    sheet.appendRow(row_array); 
  }
}

2013年3月19日,星期二

在Google文档中存储搜索查询效果报告

好吧,我向您保证,一旦AdWords脚本小组解决了报告API的问题,我将开始添加一些示例。幸好他们今天修复了它,因为我想开始玩 搜索查询效果报告.

该报告将为您提供广泛匹配关键字的所有用户搜索查询。通常,您必须每天登录并手动生成报告。但是,借助AdWords脚本,您可以开始将所有数据存储到Google Spreadsheet中,以便于使用。

因此,今天我有一个简单的脚本,该脚本将存储搜索查询报告并向您发送一封电子邮件,提醒您它已准备就绪。您所需要做的就是用与您的AdWords帐户相同的登录名填写您有权访问的现有Google文档的网址,并设置您要发送通知的电子邮件地址,并且应该已经准备就绪。我还建议您使用一个标志来确定是否要从结果中忽略完全匹配(完全匹配)的关键字。

谢谢,
拉斯

/***************************************************
* Store 搜索 Query Perf Report in Google Doc
* Version 1.1
* CHangelog v1.1 - Removed apiVersion, Updated formatting
* Created By: 拉斯 Savage
* FreeAdWordsScripts.com
****************************************************/
var DATE_RANGE = 'LAST_7_DAYS';
var IGNORE_EXACT = true;
var TO = ["电子邮件[email protected]_company.com","电子邮件[email protected]_company.com"];
var SPREADSHEET_URL = "your 电子表格 url goes here";  

function main() {
  var columns = ['AccountDescriptiveName',
                 'CampaignName',
                 'AdGroupName',
                 'KeywordTextMatchingQuery',
                 'MatchType',
                 'Query',
                 'Device',
                 'Impressions',
                 'Clicks',
                 'Cost',
                 'Conversions',
                 'AverageCpc',
                 'CostPerConversion',
                 'ConversionRate',
                 'Ctr'];
  var columnsStr = columns.join(',') + " ";
   
  var sheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL).getActiveSheet();
  sheet.clear();
  sheet.appendRow(columns);
   
  var reportIter = AdWordsApp.report(
    'SELECT ' + columnsStr +
    'FROM SEARCH_QUERY_PERFORMANCE_REPORT ' +
    'DURING ' + DATE_RANGE, {
      includeZeroImpressions: false
    }).rows();
   
  while(reportIter.hasNext()) {
    var row = reportIter.next();
    if(IGNORE_EXACT && row['MatchType'].indexOf('exact') >= 0) { continue; }
    var rowArray = [];
    for(var i in columns) {
      rowArray.push(row[columns[i]]);
    }
    sheet.appendRow(rowArray); 
  }
   
  for(var i in TO) {
    MailApp.sendEmail(TO[i], "搜索 Query Report Ready", SPREADSHEET_URL);
  }
}

2013年2月26日,星期二

在Google电子表格中存储帐户级别的质量得分

EDIT 2013-04-22:签出此脚本的更新版本,该脚本存储 帐户,广告系列和广告组一级的质量得分.

EDIT 2013-03-18:我在.orderBy()子句中添加了DESC,以便它将印象从高到低排序。

我在读一篇关于 搜索EngineLand.com 前几天关于存储和 analyzing your 帐户级别的质量得分。

本文的作者提供了一个脚本,但是我认为我可以很容易地提出自己的版本。 在以下脚本中,我使用相同的逻辑来计算帐户一级的质量得分,但是我查看了过去30天内所有具有印象的广告系列和所有关键字。

根据您的帐户大小,这可能是太多数据 在AdWords规定的30分钟内进行分析,但是按展示次数排序应该可以使您获得展示次数最高的50000个关键字(同样,另一个AdWords限制)。

您可以在这里找到我存储数据的电子表格: //docs.google.com/spreadsheet/ccc?key=0Aotb6eheEOpodGNKMW1UWkZKekc5NWxkR3Zra3lzWVE

最好的选择是复制该工作表,擦除我的数据(标题除外),然后将新的电子表格网址复制到脚本中。如果您有多个要运行的帐户,则可以将数据存储在同一电子表格中,但可以为帐户名称添加其他标签。然后更新ACCOUNT_NAME变量,您应该已经准备就绪。

谢谢,
拉斯

/***************************************
* Store Account Level Quality Score in Google Spreadsheet.
* Version 1.1
* ChangeLog v1.1
*  - Changed ACCOUNT_NAME to SHEET_NAME and 更新d the default value.
*  - Removed getSpreadsheet function
*
* Created By: 拉斯 Savage
* Based on script originally found 在: http://goo.gl/rTHbF
* FreeAdWordsScripts.com
*********************************/
function main() {
  var SPREADSHEET_URL = "Your Spreadsheet Url Goes Here";
  var SHEET_NAME = 'Sheet1';
  var today = new Date();
  var date_str = [today.getFullYear(),(today.getMonth() + 1),today.getDate()].join("-");
  
  var 电子表格 = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
  var s_sheet = 电子表格.getSheetByName(SHEET_NAME);
  
  var kw_iter = AdWordsApp.keywords()
    .withCondition("Status = ENABLED")
    .forDateRange("LAST_30_DAYS")
    .withCondition("Impressions > 0")
    .orderBy("Impressions DESC")
    .withLimit(50000)
    .get();

  var tot_imps_weighted_qs = 0;
  var tot_imps = 0;
  
  while(kw_iter.hasNext()) {
    var kw = kw_iter.next();
    var kw_stats = kw.getStatsFor("LAST_30_DAYS");
    var imps = kw_stats.getImpressions();
    var s = kw.getQualityScore();
    tot_imps_weighted_qs += (qs * imps);
    tot_imps += imps;
  }
    
  var acct_qs = tot_imps_weighted_qs / tot_imps;
  
  s_sheet.appendRow([date_str,acct_qs]);
}

2013年1月16日,星期三

Update Ad Params 来自GoogleSpreadsheet

2013-07-11-注意:对于那些想要在广告组一级更新AdParam的用户,请查看 此脚本的更新版本.

今天,我们有了一个小脚本,可帮助您大规模调整关键字广告参数。  这是一个示例,说明如何使用与Google Spreadsheets的集成来更新关键字的param1和param2值。 我提供了一个示例电子表格,您可以对其进行复制。

只要Adwords帐户和Google Docs帐户使用相同的登录名,它就可以访问您拥有的任何电子表格。 建议您打开示例电子表格,然后将其复制到您的帐户中。 然后,您可以将以下脚本中的URL替换为电子表格副本的URL。

链接到我的示例电子表格: //docs.google.com/spreadsheet/ccc?key=0Aotb6eheEOpodC1yVjUwc2Y1NDIzUVFLLThJdTFPUnc#gid=0

谢谢,
拉斯
/************************************************
* Update Ad Params Using a Google Spreadsheet
* Version 1.1
* ChangeLog v1.1
*  - Added the ability to enable param1 or 2 individually
*  - Looks for Keywords on all sheets
*  - Runs much faster
* Created By: 拉斯 Savage
* FreeAdWordsScripts.com
************************************************/
var SPREADSHEET_URL = "THE URL FOR YOUR GOOGLE SPREADSHEET GOES HERE";
var SET_PARAM1 = true;
var SET_PARAM2 = false;
var DATA_RANGE = 'A:E'; // A - CampaignName, B - AdGroupName, 
                        // C - Keyword, D - Param1, E - Param2

function main() {
  var 电子表格 = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
  var allSheets = 电子表格.getSheets();
  var allData = [];
  for(var i in allSheets) {
    var sheet = allSheets[i];
    var data = sheet.getRange(DATA_RANGE).getValues();
    data.shift(); //get rid of headers
    allData = allData.concat(data);
  }
  
  var allDataHash = {};
  for(var i in allData) {
    var row = allData[i];
    if(row[0] === '') { continue; }
    var rowKey = [row[0],row[1],row[2]].join('~~!~~');
    allDataHash[rowKey] = { param1 : row[3], param2: row[4] };
  }
  
  var kwIter = AdWordsApp.keywords()
    .withCondition('CampaignStatus = ENABLED')
    .withCondition('AdGroupStatus = ENABLED')
    .withCondition('Status = ENABLED')
    .get();
  
  while(kwIter.hasNext()) { 
    var kw = kwIter.next();
    var campName = kw.getCampaign().getName();
    var 广告 GroupName = kw.getAdGroup().getName();
    var rowKey = [campName,adGroupName,kw.getText()].join('~~!~~');
    if(allDataHash[rowKey]) {
      if(SET_PARAM1) { kw.setAdParam(1, allDataHash[rowKey].param1); }
      if(SET_PARAM2) { kw.setAdParam(2, allDataHash[rowKey].param2); }
    }
  }
}