In large AdWords accounts (over 250,000 Keywords), you will quickly see this message: “Not completed: Timeout”. Apart from the timeout, there are three more limits in AdWords Scripts that lead to runtime errors:
- Single selector entity limit (currently max 10,000 entities)
- Single iterator entity limit (currently max 50,000 entities)
- Single script entity limit (250,000 entities/ uploads)
- Timeout (currently 30 minutes)
There is an obvious workaround for number 1 and 2 – instead of using one big selector/ iterator, split it up into smaller pieces.
If you keep seeing error 3 or 4, there is only one method to deal with it: instead of running the script once, run it several times. Labels can be used to “remember” which entities still need to be processed.
With the following step-by-step guide you can add a campaign-by-campaign iteration to an existing account-level script. It should be working for most scripts and most accounts.
Step 1: Split up your existing script
Step 2: Adapt your script to work on campaign level
Step 3: Add the limit-checker to your script
Step 4: Add the following code to prevent timeouts
- Timeout prevention
- Prevention of “exceeded total limit” errors
- Option to stop executing the script after the whole account has been finished (“stop-after-completion mode”)
- Workaround to enable previewing your script (“preview mode”)
Please Make Sure
- You will need coding skills to use this step-by-step guide. (If you are familiar with the usage of functions, objects, variables and loops, you should be fine.)
- Have you already tried everything else to speed up your code? Often, a simple condition in the selector (take only active keywords in active accounts) will do it. You can also try to find out which part of your script is particularly slow and adjust it. If you have multiple AdWords accounts within a MCC, you can increase the timeout to 60 or even 90 minutes by running your script on MCC level.
- This approach is meant for simple scripts that consist of only the main(). You can also use it for scripts with higher complexity, but the necessary adjustments will be more difficult.
This Approach Won’t Work For You…
- … if your script cannot be split up to work on campaign level/ campaign iteration is not possible or wouldn’t make sense.
- … on MCC level. (The script is not thought to be used on MCC level. But you might get some inspiration.)
- … if you want to process more than 250,000 entities in one single campaign. (But you could adjust this script to work on adgroup level.)
- … if processing in one single campaign lasts longer than 25 minutes. (But you could still try out the adgroup level adjustment mentioned above.)
Now, let’s get started!
Step 1: Split Up Your Existing Script
First of all, you have to split up your script into five parts.
(1) Function doStuffBeforeFirstRun () will run once when you first start the script. It won’t be executed on 2nd, 3rd, … run (until the whole account has been completed). You can use it to set up a Google Doc, create labels, etc.
(2) Function doSomeCalculations() contains the core functionality of your script. You shouldn’t commit any changes within this function (unless you are 100% sure, that it doesn’t matter if some of these changes are committed twice). Instead, you may store all results to an object/ array called “results” and return it to the main function (optional).
(3) Function outputResults() will upload the results or output them in the desired way once the calculation has been completed for a whole campaign.
(4) Function doStuffBeforeTermination() contains everything that has to be done in every run, before you allow the script to terminate:
(5) Function doFinalStuff() contains everything that you want to do once that the whole account has been processed (after several runs of the script):
In many cases, you won’t have code for each of the five functions. That’s fine; just leave the according function(s) blank.
Step 2: Adapt Your Script to Work on Campaign Level
The first two functions doSomeCalculations() and outputResults() provide the variable „campaign“, make sure to use it.
Case A) Change your selectors by replacing AdWordsApp.adgroups() with campaign.adgroups(), AdWordsApp.keywords() with campaign.keywords() and so on.
Case B) If you’re script already works on campaign level, completely remove the campaign selector and the campaign iterator from your script. Make sure that your campaign-variable is called “campaign” and not something else like “myCampaign” (use find & replace to change it if necessary).
If your campaign selector contains any conditions, you probably don’t want to lose them. You can add them to the campaign selector in the new main function (see below).
Example for Case B
Cut the conditions (blue) and delete both campaign selector and campaign iterator (red):
Replace all occurences of “myCampaign” with “campaign” (yellow).
Code after change:
Paste the campaign selector conditions (blue) into the new main() function
Step 3: Add the Limit-Checker to Your Script
Add the following code inside all loops within the function doSomeCalculations(), or at least to all iterators:
Step 4: Add the Following Code to Prevent Timeouts
Finally, here is the code that will prevent timeouts. Be sure to go through the options before running the script. (Lines that might be worth a second view are marked with =>)
Don’t forget to include the functions that you have prepared before. They should be looking similar to this now:
If you are seeing a timeout error within the function outputResults() and “WARNING: Some results for this campaign might have been uploaded already. Please check!”, you’re outputResults() code probably needs more than 6 minutes.
To solve this, you can either shorten your outputResults() function or increase the timeframe for final steps in the options (START_FINAL_STEPS_COUNTDOWN).