Page Summary
-
Filter selectors to request only necessary entities to improve code simplicity and execution speed.
-
Use appropriate collection methods or specific parent accessor methods instead of traversing the campaign hierarchy for better performance.
-
Prefer filtering entities by their IDs or parent IDs when possible to make queries faster.
-
Use labels for filtering when dealing with numerous conditions or long IN clauses to simplify code and maintain performance.
-
Batch changes and use builders when creating new objects to allow Google Ads scripts to combine multiple operations into fewer requests.
-
Consider using bulk uploads for large updates and group them by campaigns for improved efficiency and reduced conflicts.
-
Use reports, specifically the
searchmethod with GAQL, for fetching large amounts of entities and their stats to bypass standard quotas and gain better performance. -
For manager accounts, use
executeInParallel()instead of serial execution to get more processing time. -
When updating spreadsheets, use batch operations like
getRange()instead of updating cells one by one to improve performance.
This page covers various best practices for developing with Google Ads scripts.
Selectors
Filter with selectors
When possible, use filters to request only the entities you need. Applying proper filters has the following benefits:
- The code is simpler and easier to understand.
- The script will execute much faster.
Compare the following code snippets:
| Coding approach | Code snippet |
|---|---|
| Filter using selectors (recommended) |
var keywords = AdsApp.keywords()
.withCondition('Clicks > 10')
.forDateRange('LAST_MONTH')
.get();
while (keywords.hasNext()) {
var keyword = keywords.next();
// Do work here.
}
|
| Filter in code (not recommended) |
var keywords = AdsApp.keywords().get();
while (keywords.hasNext()) {
var keyword = keywords.next();
var stats = keyword.getStatsFor(
'LAST_MONTH');
if (stats.getClicks() > 10) {
// Do work here.
}
}
|
The second approach is not recommended because it attempts to retrieve the list of all the keywords in your account only to apply a filter to the list.
Avoid traversing the campaign hierarchy
When you want to retrieve entities at a particular level, use a collection method at that level instead of traversing the entire campaign hierarchy. In addition to being simpler, this will also perform much better: the system won't have to unnecessarily read in all the campaigns and ad groups.
Compare the following code snippets that retrieve all ads in your account:
| Coding approach | Code snippet |
|---|---|
| Use appropriate collection method (Recommended) |
var ads = AdsApp.ads(); |
| Traverse the hierarchy (Not recommended) |
var campaigns = AdsApp.campaigns().get();
while (campaigns.hasNext()) {
var adGroups = campaigns.next().
adGroups().get();
while (adGroups.hasNext()) {
var ads = adGroups.next().ads().get();
// Do your work here.
}
}
|
The second approach is not recommended since it attempts to fetch entire hierarchies of objects (campaigns, ad groups) when only ads are required.
Use specific parent accessor methods
Sometimes you need to obtain a retrieved object's parent entity. In this case, you should use a provided accessor method instead of fetching entire hierarchies.
Compare the following code snippets that retrieve the ad groups that have text ads with more than 50 clicks last month:
| Coding approach | Code snippet |
|---|---|
| Use appropriate parent accessor method (recommended) |
var ads = AdsApp.ads()
.withCondition('Clicks > 50')
.forDateRange('LAST_MONTH')
.get();
while (ads.hasNext()) {
var ad = ads.next();
var adGroup = ad.getAdGroup();
var campaign = ad.getCampaign();
// Store (campaign, adGroup) to an array.
}
|
| Traverse the hierarchy (not recommended) |
var campaigns = AdsApp.campaigns().get();
while (campaigns.hasNext()) {
var adGroups = campaigns.next()
.adGroups()
.get();
while (adGroups.hasNext()) {
var ads = adGroups.ads()
.withCondition('Clicks > 50')
.forDateRange('LAST_MONTH')
.get();
if (ads.totalNumEntities() > 0) {
// Store (campaign, adGroup) to an array.
}
}
}
|
The second approach is not recommended since it fetches the entire campaign and ad group hierarchies in your account, when you need only a subset of campaigns and ad groups that is associated with your set of ads. The first approach restricts itself to fetch only the relevant ads collection, and uses an appropriate method to access its parent objects.
Use specific parent filters
To access entities within a specific campaign or ad group, use a specific filter in the selector instead of fetching then traversing through a hierarchy.
Compare the following code snippets that retrieve the list of text ads within a specified campaign and ad group having more than 50 clicks last month.
| Coding approach | Code snippet |
|---|---|
| Use appropriate parent level filters (recommended) |
var ads = AdsApp.ads()
.withCondition('CampaignName = "Campaign 1"')
.withCondition('AdGroupName = "AdGroup 1"')
.withCondition('Clicks > 50')
.forDateRange('LAST_MONTH')
.get();
while (ads.hasNext()) {
var ad = ads.next();
var adGroup = ad.getAdGroup();
var campaign = ad.getCampaign();
// Store (campaign, adGroup, ad) to
// an array.
}
|
| Traverse the hierarchy (not recommended) |
var campaigns = AdsApp.campaigns()
.withCondition('Name = "Campaign 1"')
.get();
while (campaigns.hasNext()) {
var adGroups = campaigns.next()
.adGroups()
.withCondition('Name = "AdGroup 1"')
.get();
while (adGroups.hasNext()) {
var ads = adGroups.ads()
.withCondition('Clicks > 50')
.forDateRange('LAST_MONTH')
.get();
while (ads.hasNext()) {
var ad = ads.next();
// Store (campaign, adGroup, ad) to
// an array.
}
}
}
|
The second approach is not recommended since it iterates on campaign and ad group hierarchy in your account, when you need only a selected set of ads and their parent campaigns and ad groups. The first approach limits the iteration to the list of ads by applying a specific filter for parent entities on the selector.
Use IDs for filtering when possible
When filtering for entities, it is preferable to filter for entities by their IDs instead of other fields.
Consider the following code snippets that select a campaign.
| Coding approach | Code snippet |
|---|---|
| Filter by ID (recommended) |
var campaign = AdsApp.campaigns()
.withIds([12345])
.get()
.next();
|
| Filter by Name (less optimal) |