2017年5月11日星期四

使用标签对50多个帐户执行executeInParallel

对于运行MCC级别脚本的人来说,最大的限制之一是 50个账户限制 由executeInParallel函数强加。直到最近,解决此限制的一种方法是 将已处理的帐户列表存储在Google云端硬盘上 并在需要时更新文件。

最近,AdWords脚本小组启用了 可以将标签应用于MccApp对象中的每个帐户。这样,我们就可以编写出更加清晰的脚本版本,该脚本使用标签指示何时处理每个帐户。使用这种方法并每小时运行一次此脚本,您每天最多可以处理1,200个帐户。

以下代码旨在为您提供一个框架,以替代您自己的MccApp代码。然后,您可以安排此代码每小时运行一次,它将继续处理您的MCC中的帐户,直到每个帐户都完成为止。

当有帐户返回错误时,它也会尝试通知您,以便您进行调查。关于此脚本的一个警告是,如果遇到Mcc级别(即结果功能)的超时限制,则可能不会将标签应用于每个成功完成的帐户。您可以通过用以下内容替换第76行并删除第89行来解决此问题:

applyLabelsToCompletedAccounts([result.getCustomerId()]);

无论如何,我希望这会有所帮助,并让我知道您是否在评论中遇到任何问题。

谢谢,
拉斯

/******************************************
* MccApp Generic Runner Framework for any number of acounts
* Version 1.1
* Changelog v1.1 - fixed issue with selector in yesterdays 标签 function
* Created By: 拉斯 Savage (@russellsavage)
* FreeAdWordsScripts.com
******************************************/
// The name of the script you are running
// Used in error 电子邮件 subject line and 标签 name
var SCRIPT_NAME = 'Generic MCC App';
// Since timezones are not available 在 the MCC level
// you need to set it here. You can use the local timezone
// of each account in the function processing each account
var TIMEZONE = 'PST';
// The date for today based on the timezone set above
var TODAY_STR = Utilities.formatDate(new Date(), TIMEZONE, 'yyyy-MM-dd');
// The 标签 prefix which is used to figure out today's 标签 and
// yesterday's 标签
var LABEL_PREFIX = SCRIPT_NAME + ' - Completed - ';
// This is the 标签 that will be applied to each account
// when it is successfully processed
var FINISHED_LABEL_NAME = LABEL_PREFIX + TODAY_STR;
// This is a list of 电子邮件 广告 dresses to 通知 when
// one of the accounts returns an error and is not processed.
var NOTIFY = ['your_email@your_domain.com'];

function main() {
  // Warning: if running in preview mode, this function will fail
  // and the selector that follows will also fail with "cannot read from AdWords"
  创造LabelIfNeeded();
  去掉YesterdaysLabel(); // This might not exist, but try to 去掉 it
  // Find all the accounts that have not been processed
  var accountIter = MccApp.accounts()
    .withCondition("LabelNames DOES_NOT_CONTAIN '"+FINISHED_LABEL_NAME+"'")
    .withLimit(50)
    .get();
  // Add them to a list for the executeInParallel later
  var accountList = [];
  while(accountIter.hasNext()) {
    var account = accountIter.next();
    accountList.push(account.getCustomerId());
  }
  // If there are unprocessed accounts, process them
  if(accountList.length > 0) {
    MccApp.accounts()
      .withIds(accountList)
      .executeInParallel('doSomethingInEachAccount', 'reportOnResults');
  }
}

// This function is 呼叫ed from executeInParallel and contains the
// business logic for each account. Right now, it just has some 
// dummy logic to illustrate how this works.
function doSomethingInEachAccount() {
  /**************
   * Replace this function with what 
   * you want to do on each account
   **************/
  Logger.log("In account: "+AdWordsApp.currentAccount().getName()+
                        " "+AdWordsApp.currentAccount().getCustomerId());
  // This function must return a string so we use JSON.stringify() to
  // turn almost any object into a string quickly.
  return JSON.stringify({something:'else'});
}

// This function will be 呼叫ed as soon as the function above
// has been run on each account. The results object is an array
// of the results returned by the function run in each account.
function reportOnResults(results) {
  var completedAccounts = [];
  var erroredAccounts = [];
  for(var i in results) {
    var result = results[i];
    // If the account function returns success
    if(result.getStatus() == 'OK') {
      // Add it to the list to apply the 标签 to
      completedAccounts.push(result.getCustomerId());
      /**********************
       * Fill in the code to process the results from 
       * each account just below this.
       **********************/
      var returnedValue = JSON.parse(result.getReturnValue());
    } else {
      // In case of an error, we should 通知 someone so they can
      // check it out.
      erroredAccounts.push({customerId:result.getCustomerId(), error: result.getError()});
    }
  }
  // Finally we apply the 标签 to each account
  applyLabelsToCompletedAccounts(completedAccounts);
  // And send an 电子邮件 with any 错误
  通知OfAccountsWithErrors(erroredAccounts);
}


/*******************************
 * Do not edit code below unless you know
 * what you are doing.
 *******************************/
// This function 创造s the required 标签 to apply
// to completed accounts. You can change the 标签 name
// by editing the FINISHED_LABEL_NAME variable 在 the top
// of this script.
function 创造LabelIfNeeded() {
  try {
    var 标签Iter = MccApp.accountLabels()
      .withCondition("LabelNames CONTAINS '"+FINISHED_LABEL_NAME+"'")
      .get();
  } catch(e) {
    MccApp.createAccountLabel(FINISHED_LABEL_NAME);
  }
}

// This function applies FINISHED_LABEL_NAME to each completed account
function applyLabelsToCompletedAccounts(completedAccounts) {
  var finishedAccountsIter = MccApp.accounts().withIds(completedAccounts).get();
  while(finishedAccountsIter.hasNext()) {
    var account = finishedAccountsIter.next();
    account.applyLabel(FINISHED_LABEL_NAME);
  }
}

// This function 在tempts to 去掉 yesterday's 标签 if it exists.
// If it doesn't exist, it does nothing.
function 去掉YesterdaysLabel() {
  var yesterday = new Date();
  yesterday.setDate(yesterday.getDate() - 1);
  var yesterdayStr = Utilities.formatDate(yesterday, TIMEZONE, 'yyyy-MM-dd');
  var yesterdayLabel = LABEL_PREFIX + yesterdayStr;
  Logger.log("Attempting to 去掉 标签: "+yesterdayLabel);
  try {
    var 标签Iter = MccApp.accountLabels().withCondition("Name CONTAINS '"+yesterdayLabel+"'").get();
    while(labelIter.hasNext()) {
      标签Iter.next().remove();
    }
  } catch(e) { 
    // do nothing
  }
}

// This function will send an 电子邮件 to each 电子邮件 in the
// NOTIFY list from the top of the script with the specific error
function 通知OfAccountsWithErrors(erroredAccounts) {
  if(!erroredAccounts || erroredAccounts.length == 0) { return; }
  if(typeof NOTIFY == 'undefined') { throw 'NOTIFY is not defined.'; }
  var subject = SCRIPT_NAME+' - Accounts with Errors - '+TODAY_STR;
  
  var htmlBody = 'The following Accounts had 错误 on the last run.<br / >';
  htmlBody += 'Log in to AdWords: http://goo.gl/7mS6A';
  var body = htmlBody;
  htmlBody += '<br / ><br / >';
  htmlBody += '<table border="1" width="95%" style="border-collapse:collapse;">' +
              '<tr><td>Account Id</td><td>Error</td></tr>';
  for(var i in erroredAccounts) {
    htmlBody += '<tr><td>'+ erroredAccounts[i].customerId +
      '</td><td>' + erroredAccounts[i].error + '</td></tr>';
  }
  htmlBody += '</table>';
  // Remove this line to get rid of the link back to this site.
  htmlBody += '<br / ><br / ><a href = "http://www.coolzan.com" >FreeAdWordsScripts.com</a>';
  var options = { htmlBody : htmlBody };
  for(var i in NOTIFY) {
    Logger.log('Sending 电子邮件 to: '+NOTIFY[i]+' with subject: '+subject);
    MailApp.sendEmail(NOTIFY[i], subject, body, options);
  }
}

5条评论:

  1. 检查一下 //essaydragon.com/blog/write-essay-tips 如果您想知道如何撰写更好的博客文章来吸引更多访问者。

    回复删除
  2. 我很佩服。我不'认为我没有遇到像您一样了解此主题的人。您的消息灵通,非常聪明。您写了一些人们可以理解的东西,并使每个人都对它感兴趣。真的,您的博客很棒。 在线购买Google语音帐户

    回复删除
  3. 我如何在iPhone上获得Garmin Express Garmin Express是一种从您的PC框架处理Garmin GPS DEVICE的产品。使用Garmin Express刷新您的gps小工具。

    回复删除
  4. 根据世界的需求和需求,技术在各个方面都发挥着至关重要的作用,所有压力都间接地影响了学生的个性和生活。对于理论主题 专业论文写作服务公司 可以帮助学生,但对于IT和编程主题,只有此类博客和文章可以帮助学生。

    回复删除