AdWords Scripts 101Chapter four

AdWords Script Code: Advanced

This section will help you understand how scripts actually work, so you can customize scripts for your needs beyond what the included settings allow (or even write your own AdWords Script).

This section assumes you already understand basic JavaScript. (If you’re not familiar with JavaScript yet, start with the previous chapter.)

Global Objects

There are a few custom built-in objects that are available to any AdWords script.  These encompass all the necessary functions for working with your AdWords data, other Google services, and a few handy tools.

App Objects

The “app” objects are built-in objects that make it easy to interact with a few Google platforms. These app objects are available to AdWords scripts by default:

  • AdWordsApp is central to any AdWords script, providing read and write access to AdWords configurations and report data.  You’ll learn more about it in the next section.
  • MccApp (My Client Center accounts only) is used to run scripts across an entire MCC.
  • SpreadsheetApp allows you to read from and write to Google sheets.
  • DriveApp lets you create and manage files in Google Drive.
  • MailApp lets you send, read and manage messages in Gmail.
  • ChartApp allows you to create charts though Google Chart Tools.

You can enable additional app objects for advanced integrations:

  • Analytics
  • BigQuery (for Google Analytics 360 customers)
  • Calendar
  • FusionTables
  • Prediction
  • ShoppingContent
  • Tasks
  • YouTube & YouTubeAnalytics

Utility Objects

There are also a number of built-in utility objects, which provide a variety of useful functions for performing calculations, working with various data formats, and connecting to external services.

  • BigNumber
  • Jdbc
  • UrlFetchApp is used to interact with external APIs over http.
  • Utilities
  • XmlService
The standard Math and JSON libraries are available as well.  When troubleshooting either of these, it can be easier to use the console in your browser to do lots of testing and tweaking for small bits of code.

All of these are JavaScript objects, but they’re not used to store data (by you—the script editor—anyway).  All of their data is accessed via methods.  You can explore all the available methods within these objects in Google’s documentation (under ‘Script Services’ in the left navigation) and by using the autocomplete feature in the AdWords scripts editor.

There is also the Logger object, which is only for debugging.  It offers a single method: Logger.log(), which prints its passed argument as a string to the AdWords Script editor’s execution log.  (You’ll learn how to view the log in the next section.) When the script is not running correctly, using Logger.log() allows you to trace the order of execution and make sure the values of variables are what you expect.

AdWordsApp

The AdWordsApp global object is the core of the AdWords scripts API.  It provides access to both management and reporting.

All of its methods return objects, and those returned objects also have methods that return other objects.  Each object is distinguished by its intended use.  In Google’s documentation, these uses are identified by these terms:

Entities are the central objects, Selectors are used to select existing Entities, Iterators are used to loop through and access each selected Entity, and Builders are used create new Entities.

Entities

AdWords data and configurations are represented in a script as Entities.  Here are some of the core Entities:

  • Ad
  • AdGroup
  • AdGroupCallout
  • AdGroupReview
  • AdGroupSitelink
  • AdParam
  • AdSchedule
  • Audience
  • BiddingStrategy
  • Budget
  • Callout
  • Campaign
  • CampaignCallout
  • CampaignReview
  • CampaignSitelink
  • DisplayKeyword
  • ExcludedAudience
  • Keyword
  • Label
  • MobileApp
  • NegativeKeyword
  • PhoneNumber
  • Placement
  • Platform
  • ProductAd
  • ProductGroup
  • Review
  • ShoppingAdGroup
  • ShoppingCampaign
  • Sitelink
  • Topic

Each of these are objects, and each of them have corresponding Selector and Iterator objects to allow accessing those Entities.  Some of the Entities also have corresponding Builder objects, which create new Entities.

You can find the details of the methods for each Entity, as well as the methods of their corresponding Selectors, Iterators, and Builders in the AdWords documentation.

Here are some additional Entities:

  • Account
  • ManagedAccount (MCC only)
  • AccountCallout
  • AccountMobileApp
  • AccountReview
  • AccountLabel (MCC only)
  • AccountExtensions
  • AdCustomizerItem
  • AdCustomizerSource
  • AdGroupExtensions
  • AdGroupMobileApp
  • AdGroupPhoneNumber
  • CampaignExtensions
  • CampaignMobileApp
  • CampaignPhoneNumber
  • ExcludedDisplayKeyword
  • ExcludedLocation
  • ExcludedPlacement
  • ExcludedPlacementList
  • ExcludedTopic
  • ExtensionSchedule
  • Extensions
  • NegativeKeywordList
  • SharedExcludedPlacement
  • SharedNegativeKeyword
  • AdGroupBidding
  • AdGroupOperation and other *Operation
  • AdGroupUrls and other *Urls
  • BulkUploads
  • CsvUpload
  • FileUpload
  • AdWordsDate
  • ExecutionInfo
  • Stats
  • AdGroupDisplay
  • CampaignDisplay
  • Display
  • Report
  • ReportColumnHeader
  • ReportRow
  • ReportRowIterator
  • ProductBrand
  • ProductBrandBuilder
  • ProductBrandOperation
  • ProductCategory
  • ProductCategoryBuilder
  • ProductCategoryOperation
  • ProductChannelExclusivity
  • ProductChannelExclusivityBuilder
  • ProductChannelExclusivityOperation
  • ProductChannel
  • ProductChannelBuilder
  • ProductChannelOperation
  • ProductCondition
  • ProductConditionBuilder
  • ProductConditionOperation
  • ProductCustomLabel
  • ProductCustomLabelBuilder
  • ProductCustomLabelOperation
  • ProductGroupBuilderSpace
  • ProductItemId
  • ProductItemIdBuilder
  • ProductItemIdOperation
  • ProductType
  • ProductTypeBuilder
  • ProductTypeOperation
  • Address
  • Targeting
  • TargetedLocation
  • TargetedProximity
  • ExecutionResult
  • ManagedAccountStats (MCC only)

Accessing Entities

Selectors are used to retrieve a list of Entities.

Each Entity has its own type of Selector.  Some Entity Selectors are accessed directly from the AdWordsApp object, and others are accessed using methods in the Entity that contains them.

Example:

// ads Selector
var adsSelector = 
  AdWordsApp.ads();

Selectors have methods called conditions that filter and sort the list of retrieved Entities.

Selectors for various Entities may have unique condition methods specific to that Entity, but most Selectors have a few core condition methods:

  • withIds()
  • forDateRange()
  • orderBy()
  • withLimit()
  • withCondition()

Only Entities that match every given condition are retrieved.  You can apply multiple conditions one-by-one:

var adsSelector = 
  AdWordsApp.ads();
adsSelector =
  adsSelector.withCondition("Clicks < 2");
adsSelector = 
  adsSelector.forDateRange("TODAY");

Or string them together:

adsSelector = AdWordsApp.ads()
 .withCondition("Clicks < 2")
 .forDateRange("TODAY");
Selector conditions are optional, but using Selectors without conditions can cause your script to run much more slowly than necessary.  It may be easier to select all instances of a particular Entity, then act conditionally based on specific parameters later in the script, but it’s worthwhile to use Selector conditions instead.
You can only process 50K Entities using a single Iterator, and 250K Entities total across the entire script. (Details)

All Selectors have a get() method which returns an Iterator, which is used to loop through the retrieved Entities and access each Entity.

Usually, to traverse a list and handle each item one-by-one, we would use a for loop.  But in AdWords scripts, Iterators provide the next() and hasNext() methods, which allow us to use a simplified while loop.

Example:

var adsSelector = 
  AdWordsApp.ads();
var adsIterator = 
  adsSelector.get();
while( adsIterator.hasNext() ){
 var ad = adsIterator.next();
 // do stuff with `ad`
}

The next() method of Iterators returns a reference to an individual Entity.  The first time it’s called for a particular Iterator, it will return the first Entity in the list, and every subsequent call gets the next Entity in the list.

It’s important next() is only called at one point within a loop, or else Entities could be inadvertently skipped.  If you do want to skip an Entity for any reason, use the continue command inside the loop.

Editing Entities

An Entity can be modified using a reference to an individual Entity (returned by an Iterator’s next() method).  Each Entity has its own methods, which you can explore in the documentation (under AdWordsApp on the left).

Example:

var ad = adsIterator.next();
ad.pause();

Creating Entities

A new Entity can be created using a Builder.

Unlike Selectors and Iterators, Builders are only available for a subset of Entities:

  • AdCustomizerItem
  • AdCustomizerSource
  • Callout
  • MobileApp
  • PhoneNumber
  • Review
  • Sitelink
  • AdGroup
  • Ad
  • Audience
  • DisplayKeyword
  • Placement
  • Topic
  • Keyword
  • ExcludedPlacementList
  • NegativeKeywordList
  • ShoppingAdGroup
  • ProductAd

Builders are created using the parent Entity under which the new Entity will be created.  These parent Entities have methods that look like new*Builder(), which return the Builder. Example:

// Create an Ad Group Builder
var campaign = 
  campaignIterator.next();
var adGroupBuilder = 
  campaign.newAdGroupBuilder();

Using the Builder, then set the Entity attributes using methods specific to that Entity’s Builder.  You can see all the methods in Google’s documentation (e.g. Ad Builder).

Once the attributes are set, call the Builder’s build() method to create an Operation.  Calling the getResult() method of the Operation object will create and return a reference to the new Entity.

// Create an Ad Group
var adGroup = 
  adGroupBuilder
    .build()
    .getResult();
A single script cannot create more than 250K Entities (Details).
Pro Tip: Creating Entities can fail for a number of reasons.  Use the getErrors() method of the Operation (which returns an array of strings) to check for problems, and log errors in a spreadsheet or send an email notification.
Pro Tip: Rather than calling Operation object methods as soon as the Operation is created, place all Operations into an array and then loop through to getResults() or getErrors() once all Operations are created.  (This allows the script to run more efficiently by leveraging back-end optimizations.)

What’s Next?

Make sense?  If you’re ready to get testin’, proceed to the next chapter and find the best script for you!

Going Further

This overview should be a strong starting point to help you get cracking with some pre-built scripts!  If you’re interested in doing heavy customization or writing your own scripts, you’ll need to learn more about the nuances of Javascript and get closely acquainted with Google’s AdWords Scripts documentation.

If you’re looking to integrate with other Google services, be sure to acquaint yourself with the various quotas before designing your scripts.


// Copyright 2015, Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License.
/** * @name Ad Performance Report * * @overview The Ad Performance Report generates a Google Spreadsheet that * contains ad performance stats like Impressions, Cost, Click Through Rate, * etc. as several distribution charts for an advertiser account. See * https://developers.google.com/adwords/scripts/docs/solutions/ad-performance * for more details. * * @author AdWords Scripts Team [adwords-scripts@googlegroups.com] * * @version 1.0 * * @changelog * - version 1.0 * - Released initial version. */
// Comma-separated list of recipients. Comment out to not send any emails. var RECIPIENT_EMAIL = 'email@example.com'; // URL of the default spreadsheet template. This should be a copy of // https://goo.gl/21FW5i var SPREADSHEET_URL = 'INSERT_SPREADSHEET_URL_HERE';
/** * This script computes an Ad performance report * and outputs it to a Google spreadsheet. */ function main() { Logger.log('Using template spreadsheet - %s.', SPREADSHEET_URL); var spreadsheet = copySpreadsheet(SPREADSHEET_URL); Logger.log('Generated new reporting spreadsheet %s based on the template ' + 'spreadsheet. The reporting data will be populated here.', spreadsheet.getUrl()); var headlineSheet = spreadsheet.getSheetByName('Headline'); headlineSheet.getRange(1, 2, 1, 1).setValue('Date'); headlineSheet.getRange(1, 3, 1, 1).setValue(new Date()); var finalUrlSheet = spreadsheet.getSheetByName('Final Url'); finalUrlSheet.getRange(1, 2, 1, 1).setValue('Date'); finalUrlSheet.getRange(1, 3, 1, 1).setValue(new Date()); spreadsheet.getRangeByName('account_id_headline').setValue( AdWordsApp.currentAccount().getCustomerId()); spreadsheet.getRangeByName('account_id_final_url').setValue( AdWordsApp.currentAccount().getCustomerId()); outputSegmentation(headlineSheet, 'Headline', function(ad) { return ad.getHeadline(); }); outputSegmentation(finalUrlSheet, 'Final Url', function(ad) { return ad.urls().getFinalUrl(); }); Logger.log('Ad performance report available at\n' + spreadsheet.getUrl()); if (RECIPIENT_EMAIL) { MailApp.sendEmail(RECIPIENT_EMAIL, 'Ad Performance Report is ready', spreadsheet.getUrl()); } } /** * Retrieves the spreadsheet identified by the URL. * @param {string} spreadsheetUrl The URL of the spreadsheet. * @return {SpreadSheet} The spreadsheet. */ function copySpreadsheet(spreadsheetUrl) { return SpreadsheetApp.openByUrl(spreadsheetUrl).copy( 'Ad Performance Report ' + new Date()); } /** * Generates statistical data for this segment. * @param {Sheet} sheet Sheet to write to. * @param {string} segmentName The Name of this segment for the header row. * @param {function(AdWordsApp.Ad): string} segmentFunc Function that returns * a string used to segment the results by. */ function outputSegmentation(sheet, segmentName, segmentFunc) { // Output header row. var rows = []; var header = [ segmentName, 'Num Ads', 'Impressions', 'Clicks', 'CTR (%)', 'Cost' ]; rows.push(header); var segmentMap = {}; // Compute data. var adSelector = AdWordsApp.ads() .forDateRange('LAST_WEEK') .withCondition('Impressions > 0'); var adIterator = adSelector.get(); while (adIterator.hasNext()) { var ad = adIterator.next(); var stats = ad.getStatsFor('LAST_WEEK'); var segment = segmentFunc(ad); if (!segmentMap[segment]) { segmentMap[segment] = { numAds: 0, totalImpressions: 0, totalClicks: 0, totalCost: 0.0 }; } var data = segmentMap[segment]; data.numAds++; data.totalImpressions += stats.getImpressions(); data.totalClicks += stats.getClicks(); data.totalCost += stats.getCost(); } // Write data to our rows. for (var key in segmentMap) { if (segmentMap.hasOwnProperty(key)) { var ctr = 0; if (segmentMap[key].numAds > 0) { ctr = (segmentMap[key].totalClicks / segmentMap[key].totalImpressions) * 100; } var row = [ key, segmentMap[key].numAds, segmentMap[key].totalImpressions, segmentMap[key].totalClicks, ctr.toFixed(2), segmentMap[key].totalCost]; rows.push(row); } } sheet.getRange(3, 2, rows.length, 6).setValues(rows); }