Reusable Code For MCC Scripts Will Save You Tons Of Time In AdWords

Writing reusable code is something all developers strive for. Any developer worth his/her salt is continuously building a library of reusable code snippets to use in future development. You don’t need to re-invent the wheel each time a common problem is encountered because you can use the code you’ve already written. It also makes legacy […]

Chat with SearchBot

Writing reusable code is something all developers strive for.html-code-schema-300px

Any developer worth his/her salt is continuously building a library of reusable code snippets to use in future development. You don’t need to re-invent the wheel each time a common problem is encountered because you can use the code you’ve already written. It also makes legacy code easier to update later.

I’m in the process of updating some of my scripts for the new MCC level format, and I’ve been thinking about some common code snippets I seem to use in almost every script I write.

So I thought I’d share some of these ideas and combine them in a script that monitors your MCC for Ads that have been disapproved.

Handling More Than 50 Accounts

The executeInParallel method is great for processing multiple accounts at the same time, but there is still a limit of 50 accounts per run. Anyone with a decent-sized MCC (including sub MCCs) is going to hit that limit quickly.

In order to run a script across more than 50 accounts, you need to keep track of which accounts have already been processed by the script so that the next run can continue processing where the previous one left off.

For this, I prefer storing a small text file on your Google Drive that contains the customer ID of the account as well as the last time it was processed. That way, I can process an unlimited number of accounts in batches of 50 per hour.

function main() {
  var accountsList = readJSONFile(ACCOUNTS_FILE_NAME);
  if(!accountsList) { accountsList = []; }
  if(accountsList.length === 0) {
    var acctIter = MccApp.accounts().get();
    while(acctIter.hasNext()) {
      var acct = acctIter.next();
      accountsList.push({ id : acct.getCustomerId(), 
                          lastChecked : null });
    }
  }
  accountsList.sort(sortByLastChecked);
  writeJSONFile(ACCOUNTS_FILE_NAME,accountsList);
  var toCheck = [];
  for(var i in accountsList) {
    toCheck.push(accountsList[i].id);
    if(toCheck.length==50) { break; }
  }
  Logger.log('Checking the following accounts: '+
              JSON.stringify(toCheck));
  MccApp.accounts()
    .withIds(toCheck)
    .executeInParallel('checkAdDisapprovalReasons', 
                       'reportResults');
}

Let’s walk through what the code above is doing. First, it attempts to find an existing list of accounts stored on Google Drive that it can use to know which accounts to process.

For that, I am using a function that reads a JSON file from Google Drive. If the file doesn’t exist (this could be the first run), the script builds an account list by iterating through all of the accounts in the MCC and adding them to the list.

Next, it sorts the accounts by the date they were last checked so that the first one in the list is the account that hasn’t been checked recently. It then writes that account list to the same file as before so that the next time it runs, it has the accounts already available.

Finally, the script pulls the next 50 accounts to process from the list and sends them into the executeInParallel function.

Avoiding Server Errors

This tip doesn’t only apply to MCC Scripts, but might be useful if you read and write frequently from DriveApp.

I have noticed when I use the DriveApp object in scripts, I encounter server errors more frequently (“We’re sorry, a server error occurred. Please wait a bit and try again”). It is incredibly frustrating since it causes scheduled scripts to fail randomly and without notice.

I started digging through the support forums and a common answer for this issue is to catch the error, wait one second, and retry the request to DriveApp up to three times. I started implementing this across my scripts and saw a dramatic decrease in errors.

function getFile(fileName) {
  var maxRetries = 3,errors = [];
  while(maxRetries > 0) {
    try {
      var fileIter = DriveApp.getFilesByName(fileName);
      if(!fileIter.hasNext()) {
        return DriveApp.createFile(fileName,'');
      } else {
        return fileIter.next();
      }
    } catch(e) {
      errors.push(e);
      maxRetries--;
      Utilities.sleep(1000);
    }
  }
  if(maxRetries === 0) {
    throw errors.join('. ');
  }
}

Whenever I make a call to the DriveApp object, I always surround it with a while loop and retry three times before giving up. It is also important to have the sleep of one second in there so that the DriveApp object doesn’t complain about too many requests in a short period of time.

Reporting Format

This might be the most subjective part of any script, but I’ll share what works best for me when it comes to reporting. For MCC level scripts, because you will be processing many accounts and potentially reporting on lots of information, it isn’t always best to place all the data directly into a notification email. Emails do have length limits, and believe me, you will quickly hit them.

You may have seen this in my previous scripts, but what works best for me is to create a summary email with the number of issues found in each account and a link directly to a Google Spreadsheet with the full information for that account.

mcc scripts summary email

An example of a summary email. (Click to enlarge.)

This gives the person receiving the email an overview of where the biggest problems are so they can see at a quick glance what is happening. It also allows a manager to quickly see what is going on while providing the team with the details needed to make changes. I also like to add a timestamp and the number of items checked to the bottom of the emails, as well as a little bit of branding.

For the detailed Google Spreadsheet, I make sure that I always create a new file with a timestamp in the name for every script run.

In the past I would try to update existing spreadsheets but it got really complicated and broke frequently. In the end, having a spreadsheet snapshot of each script run provides some level of history tracking which can be useful. Each account gets its own tab so that I can deep link directly from the email to the account’s data.

Google_spreadsheet_with_detailed_results

Example Google spreadsheet with detailed results. (Click to enlarge.)

The most important thing for reporting is to choose a format that works for you and try to stick to that format as much as possible. Reformatting reports over and over again can quickly eat up a large portion of the time you spend on a script.

Monitoring Ad Disapprovals

Finally, we get to the actual script that combines these into something I hope you find useful. The AdWords Scripts Team recently announced that Ad disapproval reasons can be pulled from the Ad object in your scripts. Using this, you can monitor the Ads that have been disapproved across all the accounts in your MCC.

The full script I put together can be found on GitHub. Simply copy it into your AdWords MCC account, update the email address, hit preview, and you should get an email and a Google spreadsheet that contains all the Ads that have been disapproved.

Following common design patterns in your scripts can help speed up new script creation and reduce issues when revisiting legacy code. Also, if you don’t already, I recommend using a standard coding style guide, especially if multiple people are editing your scripts. If all your code has a common style, copying functions across scripts will be much easier.

A good portion of your time writing scripts is performing the same task in a slightly different way. Building code that you can re-use with minimal edits will make your life much easier. Also, as you re-write your scripts to work at the MCC level, it is a good time to start implementing these practices if you haven’t already.

Now go and fix those disapproved Ads!

 (Stock image via Shutterstock.com. Used under license.)

Opinions expressed in this article are those of the guest author and not necessarily Search Engine Land. Staff authors are listed here.


About the author

Russell Savage
Contributor
Russell Savage is an Application Engineer for Cask Data and loves tinkering with marketing data and automation in his spare time. He is the creator of FreeAdWordsScripts.com, where he posts AdWords Scripts for anyone to use.

Get the must-read newsletter for search marketers.