Objects, Methods, and Services

This guide introduces AdWords API objects and methods, using some common campaign management tasks as examples. It then describes the services offered by the API, with links to corresponding reference pages.

The AdWords API is meant for advanced AdWords users. If you're new to AdWords, or need to brush up on basic AdWords concepts, check out the AdWords basics pages.

Object hierarchy and scope

Every AdWords account can be viewed as a hierarchy of objects.

Under each account, there are one or more Campaigns that represent advertising campaigns you are running.

Each campaign has multiple AdGroups, used to group your ads into logical collections.

Each AdGroup has multiple AdGroupAds and AdGroupCriteria. An AdGroupAd represents an ad that you're running. An AdGroupCriterion represents a criterion - a keyword - that defines how the ads get triggered.

You can designate campaign criteria, that define campaign-wide rules on how ads get triggered. You can also specify campaign-wide budgets and dates.

Finally, there are ad extensions at the campaign level, that allow you to provide extra information to your ads, like phone number, street address, etc.

Every object in AdWords is identified by its own ID. Some of these IDs are unique on a global level across all AdWords accounts, while others are unique only within a confined scope. The uniqueness of each object ID within AdWords is listed below.

Object ID Scope of uniqueness Globally unique?
Budget ID Global Yes
Campaign ID Global Yes
AdGroup ID Global Yes
Ad ID Ad Group No. (AdGroupId, AdId) pair is globally unique.
AdGroupCriterion ID Ad Group No. (AdGroupId, CriterionId) pair is globally unique.
CampaignCriterion ID Campaign No. (CampaignId, CriterionId) pair is globally unique.
Ad Extensions Campaign No. (CampaignId, AdExtensionId) pair is globally unique.
Feed ID Global Yes
Feed Item ID Global Yes
Feed Attribute ID Feed No
Feed Mapping ID Global Yes
Label ID Global Yes

These ID rules can be useful when designing a local database to store your AdWords objects.

If an object is derived from another object, it will also have a Type field. For instance, TextAd has a Type field to indicate that it's derived from the Ad object. If you're using a dynamic language, you can use this field to check an object's type, for example, to see if an Ad object is of type TextAd.

Methods and operations

The AdWords API provides services to manage AdWords objects. For instance, CampaignService manages Campaigns, AdGroupService manages AdGroups, and so on.

All such services expose two standard methods: get() and mutate().

The get() method

The get() method is used to retrieve AdWords objects. For instance, you can use CampaignService.get() to retrieve the list of campaigns.

Every get() method takes a selector as input, and returns a page as a result. The AdWords API doesn't return all the fields of an object by default; you need to specify the list of fields you want to retrieve when building the selector.

You can use predicates to filter your results, ordering to sort your results, and dateRange to limit the time period for which you're retrieving the results.

You also need to specify paging if you are pulling a lot of objects. The AdWords API will raise a SizeLimitError.RESPONSE_SIZE_LIMIT_EXCEEDED error if you try to pull a lot of objects without paging.

The following code snippet, which retrieves and displays all the campaigns in an account, demonstrates these concepts in action:

Java

// Get the CampaignService.
CampaignServiceInterface campaignService =
    adWordsServices.get(session, CampaignServiceInterface.class);

int offset = 0;

// Create selector.
SelectorBuilder builder = new SelectorBuilder();
Selector selector = builder
    .fields(CampaignField.Id, CampaignField.Name)
    .orderAscBy(CampaignField.Name)
    .offset(offset)
    .limit(PAGE_SIZE)
    .build();

CampaignPage page = null;
do {
  // Get all campaigns.
  page = campaignService.get(selector);

  // Display campaigns.
  if (page.getEntries() != null) {
    for (Campaign campaign : page.getEntries()) {
      System.out.printf("Campaign with name '%s' and ID %d was found.%n", campaign.getName(),
          campaign.getId());
    }
  } else {
    System.out.println("No campaigns were found.");
  }

  offset += PAGE_SIZE;
  selector = builder.increaseOffsetBy(PAGE_SIZE).build();
} while (offset < page.getTotalNumEntries());

C#

// Get the CampaignService.
CampaignService campaignService =
    (CampaignService)user.GetService(AdWordsService.v201708.CampaignService);

// Create the selector.
Selector selector = new Selector() {
  fields = new string[] {
    Campaign.Fields.Id, Campaign.Fields.Name, Campaign.Fields.Status
  },
  paging = Paging.Default
};

CampaignPage page = new CampaignPage();

try {
  do {
    // Get the campaigns.
    page = campaignService.get(selector);

    // Display the results.
    if (page != null && page.entries != null) {
      int i = selector.paging.startIndex;
      foreach (Campaign campaign in page.entries) {
        Console.WriteLine("{0}) Campaign with id = '{1}', name = '{2}' and status = '{3}'" +
          " was found.", i + 1, campaign.id, campaign.name, campaign.status);
        i++;
      }
    }
    selector.paging.IncreaseOffset();
  } while (selector.paging.startIndex < page.totalNumEntries);
  Console.WriteLine("Number of campaigns found: {0}", page.totalNumEntries);
} catch (Exception e) {
  throw new System.ApplicationException("Failed to retrieve campaigns", e);
}

Python

# Initialize appropriate service.
campaign_service = client.GetService('CampaignService', version='v201708')

# Construct selector and get all campaigns.
offset = 0
selector = {
    'fields': ['Id', 'Name', 'Status'],
    'paging': {
        'startIndex': str(offset),
        'numberResults': str(PAGE_SIZE)
    }
}

more_pages = True
while more_pages:
  page = campaign_service.get(selector)

  # Display results.
  if 'entries' in page:
    for campaign in page['entries']:
      print ('Campaign with id "%s", name "%s", and status "%s" was '
             'found.' % (campaign['id'], campaign['name'],
                         campaign['status']))
  else:
    print 'No campaigns were found.'
  offset += PAGE_SIZE
  selector['paging']['startIndex'] = str(offset)
  more_pages = offset < int(page['totalNumEntries'])
  time.sleep(1)

PHP

$campaignService = $adWordsServices->get($session, CampaignService::class);

// Create selector.
$selector = new Selector();
$selector->setFields(['Id', 'Name']);
$selector->setOrdering([new OrderBy('Name', SortOrder::ASCENDING)]);
$selector->setPaging(new Paging(0, self::PAGE_LIMIT));

$totalNumEntries = 0;
do {
  // Make the get request.
  $page = $campaignService->get($selector);

  // Display results.
  if ($page->getEntries() !== null) {
    $totalNumEntries = $page->getTotalNumEntries();
    foreach ($page->getEntries() as $campaign) {
      printf(
          "Campaign with ID %d and name '%s' was found.\n",
          $campaign->getId(),
          $campaign->getName()
      );
    }
  }

  // Advance the paging index.
  $selector->getPaging()->setStartIndex(
      $selector->getPaging()->getStartIndex() + self::PAGE_LIMIT);
} while ($selector->getPaging()->getStartIndex() < $totalNumEntries);

printf("Number of results found: %d\n", $totalNumEntries);

Perl

# Create selector.
my $paging = Google::Ads::AdWords::v201708::Paging->new({
    startIndex    => 0,
    numberResults => PAGE_SIZE
});
my $selector = Google::Ads::AdWords::v201708::Selector->new({
    fields   => ["Id", "Name"],
    ordering => [
      Google::Ads::AdWords::v201708::OrderBy->new({
          field     => "Name",
          sortOrder => "ASCENDING"
        })
    ],
    paging => $paging
  });

# Paginate through results.
# The contents of the subroutine will be executed for each campaign.
Google::Ads::AdWords::Utilities::PageProcessor->new({
    client   => $client,
    service  => $client->CampaignService(),
    selector => $selector
  }
  )->process_entries(
  sub {
    my ($campaign) = @_;
    printf "Campaign with name \"%s\" and id \"%d\" was found.\n",
      $campaign->get_name(), $campaign->get_id();
  });

Ruby

campaign_srv = adwords.service(:CampaignService, API_VERSION)

# Get all the campaigns for this account.
selector = {
  :fields => ['Id', 'Name', 'Status'],
  :ordering => [
    {:field => 'Name', :sort_order => 'ASCENDING'}
  ],
  :paging => {
    :start_index => 0,
    :number_results => PAGE_SIZE
  }
}

# Set initial values.
offset, page = 0, {}

begin
  page = campaign_srv.get(selector)
  if page[:entries]
    page[:entries].each do |campaign|
      puts "Campaign ID %d, name '%s' and status '%s'" %
          [campaign[:id], campaign[:name], campaign[:status]]
    end
    # Increment values to request the next page.
    offset += PAGE_SIZE
    selector[:paging][:start_index] = offset
  end
end while page[:total_num_entries] > offset

if page.include?(:total_num_entries)
  puts "\tTotal number of campaigns found: %d." % [page[:total_num_entries]]
end

VB.NET

' Get the CampaignService.
Dim campaignService As CampaignService = CType(user.GetService(
    AdWordsService.v201708.CampaignService), CampaignService)

' Create the selector.
Dim selector As New Selector
selector.fields = New String() {
  Campaign.Fields.Id, Campaign.Fields.Name, Campaign.Fields.Status
}
selector.paging = Paging.Default

Dim page As New CampaignPage

Try
  Do
    ' Get the campaigns.
    page = campaignService.get(selector)

    ' Display the results.
    If ((Not page Is Nothing) AndAlso (Not page.entries Is Nothing)) Then
      Dim i As Integer = selector.paging.startIndex
      For Each campaign As Campaign In page.entries
        Console.WriteLine("{0}) Campaign with id = '{1}', name = '{2}' and status = " &
            "'{3}' was found.", i + 1, campaign.id, campaign.name, campaign.status)
        i += 1
      Next
    End If
    selector.paging.IncreaseOffset()
  Loop While (selector.paging.startIndex < page.totalNumEntries)
  Console.WriteLine("Number of campaigns found: {0}", page.totalNumEntries)
Catch e As Exception
  Throw New System.ApplicationException("Failed to retrieve campaign(s).", e)
End Try

Refer to the selector fields reference page for the available selector fields for different services.

Our client libraries include code samples using the get() method for all the campaign management services. You can find the client library examples for campaign management services for each language below.

The query() method

The query() method is an alternative to get() that uses a SQL-like language called the AdWords Query Language (AWQL), instead of selectors. Coding the same request in AWQL is usually more efficient. The query() method is supported by most common services. Note that AWQL does not support mutating data.

To show the efficiency of AWQL, consider the example above. Instead of writing four lines for the selector, you could write a single string that contains all the same information.

Java

String query = "SELECT Id, Name, Status ORDER BY Name";

C#

// Create the query.
string query = "SELECT Id, Name, Status ORDER BY Name";

Python

query = 'SELECT Id, Name, Status ORDER BY Name'

PHP

$query = 'SELECT Id, Name, Status ORDER BY Name';

Perl

my $query = "SELECT Id, Name, Status ORDER BY Name";

Ruby

# Get all the campaigns for this account.
query = 'SELECT Id, Name, Status ORDER BY Name'

VB.NET

' Create the query.
Dim query As String = "SELECT Id, Name, Status ORDER BY Name"

Note that there is no FROM clause. This is because the service whose query() method you're using already dictates what you're selecting from. AWQL only supports the FROM clause when used for reports. To use this string, you would simply call the service's query method.

Java

CampaignPage page = null;
do {
  String pageQuery = query + String.format(" LIMIT %d, %d", offset, PAGE_SIZE);
  // Get all campaigns.
  page = campaignService.query(pageQuery);

  // Display campaigns.
  if (page.getEntries() != null) {
    for (Campaign campaign : page.getEntries()) {
      System.out.printf("Campaign with name '%s' and ID %d was found.%n", campaign.getName(),
          campaign.getId());
    }
  } else {
    System.out.println("No campaigns were found.");
  }

  offset += PAGE_SIZE;
} while (offset < page.getTotalNumEntries());

C#

int offset = 0;
int pageSize = 500;

CampaignPage page = new CampaignPage();

try {
  do {
    string queryWithPaging = string.Format("{0} LIMIT {1}, {2}", query, offset, pageSize);

    // Get the campaigns.
    page = campaignService.query(queryWithPaging);

    // Display the results.
    if (page != null && page.entries != null) {
      int i = offset;
      foreach (Campaign campaign in page.entries) {
        Console.WriteLine("{0}) Campaign with id = '{1}', name = '{2}' and status = '{3}'" +
          " was found.", i + 1, campaign.id, campaign.name, campaign.status);
        i++;
      }
    }
    offset += pageSize;
  } while (offset < page.totalNumEntries);
  Console.WriteLine("Number of campaigns found: {0}", page.totalNumEntries);
} catch (Exception e) {
  throw new System.ApplicationException("Failed to retrieve campaigns", e);
}

Python

more_pages = True
while more_pages:
  page = campaign_service.query(query + ' LIMIT %s, %s' % (offset, PAGE_SIZE))

  # Display results.
  if 'entries' in page:
    for campaign in page['entries']:
      print ('Campaign with id "%s", name "%s", and status "%s" was '
             'found.' % (campaign['id'], campaign['name'],
                         campaign['status']))
  else:
    print 'No campaigns were found.'
  offset += PAGE_SIZE
  more_pages = offset < int(page['totalNumEntries'])
  time.sleep(1)

PHP

$totalNumEntries = 0;
$offset = 0;
do {
  $pageQuery = sprintf('%s LIMIT %d,%d', $query, $offset, self::PAGE_LIMIT);
  // Make the query request.
  $page = $campaignService->query($pageQuery);

  // Display results from the query.
  if ($page->getEntries() !== null) {
    $totalNumEntries = $page->getTotalNumEntries();
    foreach ($page->getEntries() as $campaign) {
      printf(
          "Campaign with ID %d and name '%s' was found.\n",
          $campaign->getId(),
          $campaign->getName()
      );
    }
  }

  // Advance the paging offset.
  $offset += self::PAGE_LIMIT;
} while ($offset < $totalNumEntries);

printf("Number of results found: %d\n", $totalNumEntries);

Perl

Google::Ads::AdWords::Utilities::PageProcessor->new({
    client    => $client,
    service   => $client->CampaignService(),
    query     => $query,
    page_size => PAGE_SIZE
  }
  )->process_entries(
  sub {
    my ($campaign) = @_;
    printf "Campaign with name \"%s\" and id \"%d\" was found.\n",
      $campaign->get_name(), $campaign->get_id();
  });

Ruby

# Set initial values.
offset, page = 0, {}

begin
  page_query = query + ' LIMIT %d,%d' % [offset, PAGE_SIZE]
  page = campaign_srv.query(page_query)
  if page[:entries]
    page[:entries].each do |campaign|
      puts "Campaign ID %d, name '%s' and status '%s'" %
          [campaign[:id], campaign[:name], campaign[:status]]
    end
    # Increment values to request the next page.
    offset += PAGE_SIZE
  end
end while page[:total_num_entries] > offset

if page.include?(:total_num_entries)
  puts "\tTotal number of campaigns found: %d." % page[:total_num_entries]
end

VB.NET

Dim offset As Long = 0
Dim pageSize As Long = 500

Dim page As New CampaignPage()

Try
  Do
    Dim queryWithPaging As String = String.Format("{0} LIMIT {1}, {2}", query, offset,
        pageSize)

    ' Get the campaigns.
    page = campaignService.query(queryWithPaging)

    ' Display the results.
    If ((Not page Is Nothing) AndAlso (Not page.entries Is Nothing)) Then
      Dim i As Integer = CInt(offset)
      For Each campaign As Campaign In page.entries
        Console.WriteLine("{0}) Campaign with id = '{1}', name = '{2}' and status = " &
            "'{3}' was found.", i, campaign.id, campaign.name, campaign.status)
        i += 1
      Next
    End If
    offset = offset + pageSize
  Loop While (offset < page.totalNumEntries)
  Console.WriteLine("Number of campaigns found: {0}", page.totalNumEntries)
Catch e As Exception
  Throw New System.ApplicationException("Failed to retrieve campaign(s).", e)
End Try

The above code produces the same results as a call to the get() method. AWQL can be a more succinct and intuitive way to write the same requests you would with calling get(). To learn more, see the AWQL guide.

The mutate() method

The mutate() method is used to mutate (create, update, or remove) an AdWords object.

To mutate an object, you must build a corresponding Operation object. For instance, you must create a CampaignOperation to mutate a Campaign.

The operator field defines the type of operation you want to perform (ADD, SET, or REMOVE). The operand field holds the object you want to mutate. The following code snippet adds campaigns:

Java

// Get the CampaignService.
CampaignServiceInterface campaignService =
    adWordsServices.get(session, CampaignServiceInterface.class);

// Create campaign.
Campaign campaign = new Campaign();
campaign.setName("Interplanetary Cruise #" + System.currentTimeMillis());

// Recommendation: Set the campaign to PAUSED when creating it to prevent
// the ads from immediately serving. Set to ENABLED once you've added
// targeting and the ads are ready to serve.
campaign.setStatus(CampaignStatus.PAUSED);

BiddingStrategyConfiguration biddingStrategyConfiguration = new BiddingStrategyConfiguration();
biddingStrategyConfiguration.setBiddingStrategyType(BiddingStrategyType.MANUAL_CPC);

// You can optionally provide a bidding scheme in place of the type.
ManualCpcBiddingScheme cpcBiddingScheme = new ManualCpcBiddingScheme();
cpcBiddingScheme.setEnhancedCpcEnabled(false);
biddingStrategyConfiguration.setBiddingScheme(cpcBiddingScheme);

campaign.setBiddingStrategyConfiguration(biddingStrategyConfiguration);

// You can optionally provide these field(s).
campaign.setStartDate(new DateTime().plusDays(1).toString("yyyyMMdd"));
campaign.setEndDate(new DateTime().plusDays(30).toString("yyyyMMdd"));
campaign.setAdServingOptimizationStatus(AdServingOptimizationStatus.ROTATE);
campaign.setFrequencyCap(new FrequencyCap(5L, TimeUnit.DAY, Level.ADGROUP));

// Only the budgetId should be sent, all other fields will be ignored by CampaignService.
Budget budget = new Budget();
budget.setBudgetId(budgetId);
campaign.setBudget(budget);

campaign.setAdvertisingChannelType(AdvertisingChannelType.SEARCH);

// Set the campaign network options to Search and Search Network.
NetworkSetting networkSetting = new NetworkSetting();
networkSetting.setTargetGoogleSearch(true);
networkSetting.setTargetSearchNetwork(true);
networkSetting.setTargetContentNetwork(false);
networkSetting.setTargetPartnerSearchNetwork(false);
campaign.setNetworkSetting(networkSetting);

// Set options that are not required.
GeoTargetTypeSetting geoTarget = new GeoTargetTypeSetting();
geoTarget.setPositiveGeoTargetType(GeoTargetTypeSettingPositiveGeoTargetType.DONT_CARE);
campaign.setSettings(new Setting[] {geoTarget});

// You can create multiple campaigns in a single request.
Campaign campaign2 = new Campaign();
campaign2.setName("Interplanetary Cruise banner #" + System.currentTimeMillis());
campaign2.setStatus(CampaignStatus.PAUSED);
BiddingStrategyConfiguration biddingStrategyConfiguration2 = new BiddingStrategyConfiguration();
biddingStrategyConfiguration2.setBiddingStrategyType(BiddingStrategyType.MANUAL_CPC);
campaign2.setBiddingStrategyConfiguration(biddingStrategyConfiguration2);

Budget budget2 = new Budget();
budget2.setBudgetId(budgetId);
campaign2.setBudget(budget2);

campaign2.setAdvertisingChannelType(AdvertisingChannelType.DISPLAY);

// Create operations.
CampaignOperation operation = new CampaignOperation();
operation.setOperand(campaign);
operation.setOperator(Operator.ADD);
CampaignOperation operation2 = new CampaignOperation();
operation2.setOperand(campaign2);
operation2.setOperator(Operator.ADD);

CampaignOperation[] operations = new CampaignOperation[] {operation, operation2};

// Add campaigns.
CampaignReturnValue result = campaignService.mutate(operations);

// Display campaigns.
for (Campaign campaignResult : result.getValue()) {
  System.out.printf("Campaign with name '%s' and ID %d was added.%n", campaignResult.getName(),
      campaignResult.getId());
}

C#

List<CampaignOperation> operations = new List<CampaignOperation>();

for (int i = 0; i < NUM_ITEMS; i++) {
  // Create the campaign.
  Campaign campaign = new Campaign();
  campaign.name = "Interplanetary Cruise #" + ExampleUtilities.GetRandomString();
  campaign.advertisingChannelType = AdvertisingChannelType.SEARCH;

  // Recommendation: Set the campaign to PAUSED when creating it to prevent
  // the ads from immediately serving. Set to ENABLED once you've added
  // targeting and the ads are ready to serve.
  campaign.status = CampaignStatus.PAUSED;

  BiddingStrategyConfiguration biddingConfig = new BiddingStrategyConfiguration();
  biddingConfig.biddingStrategyType = BiddingStrategyType.MANUAL_CPC;
  campaign.biddingStrategyConfiguration = biddingConfig;

  campaign.budget = new Budget();
  campaign.budget.budgetId = budget.budgetId;

  // Set the campaign network options.
  campaign.networkSetting = new NetworkSetting();
  campaign.networkSetting.targetGoogleSearch = true;
  campaign.networkSetting.targetSearchNetwork = true;
  campaign.networkSetting.targetContentNetwork = false;
  campaign.networkSetting.targetPartnerSearchNetwork = false;

  // Set the campaign settings for Advanced location options.
  GeoTargetTypeSetting geoSetting = new GeoTargetTypeSetting();
  geoSetting.positiveGeoTargetType = GeoTargetTypeSettingPositiveGeoTargetType.DONT_CARE;
  geoSetting.negativeGeoTargetType = GeoTargetTypeSettingNegativeGeoTargetType.DONT_CARE;

  campaign.settings = new Setting[] { geoSetting };

  // Optional: Set the start date.
  campaign.startDate = DateTime.Now.AddDays(1).ToString("yyyyMMdd");

  // Optional: Set the end date.
  campaign.endDate = DateTime.Now.AddYears(1).ToString("yyyyMMdd");

  // Optional: Set the campaign ad serving optimization status.
  campaign.adServingOptimizationStatus = AdServingOptimizationStatus.ROTATE;

  // Optional: Set the frequency cap.
  FrequencyCap frequencyCap = new FrequencyCap();
  frequencyCap.impressions = 5;
  frequencyCap.level = Level.ADGROUP;
  frequencyCap.timeUnit = TimeUnit.DAY;
  campaign.frequencyCap = frequencyCap;

  // Create the operation.
  CampaignOperation operation = new CampaignOperation();
  operation.@operator = Operator.ADD;
  operation.operand = campaign;

  operations.Add(operation);
}

try {
  // Add the campaign.
  CampaignReturnValue retVal = campaignService.mutate(operations.ToArray());

  // Display the results.
  if (retVal != null && retVal.value != null && retVal.value.Length > 0) {
    foreach (Campaign newCampaign in retVal.value) {
      Console.WriteLine("Campaign with name = '{0}' and id = '{1}' was added.",
          newCampaign.name, newCampaign.id);
    }
  } else {
    Console.WriteLine("No campaigns were added.");
  }
} catch (Exception e) {
  throw new System.ApplicationException("Failed to add campaigns.", e);
}

Python

# Initialize appropriate services.
campaign_service = client.GetService('CampaignService', version='v201708')
budget_service = client.GetService('BudgetService', version='v201708')

# Create a budget, which can be shared by multiple campaigns.
budget = {
    'name': 'Interplanetary budget #%s' % uuid.uuid4(),
    'amount': {
        'microAmount': '50000000'
    },
    'deliveryMethod': 'STANDARD'
}

budget_operations = [{
    'operator': 'ADD',
    'operand': budget
}]

# Add the budget.
budget_id = budget_service.mutate(budget_operations)['value'][0][
    'budgetId']

# Construct operations and add campaigns.
operations = [{
    'operator': 'ADD',
    'operand': {
        'name': 'Interplanetary Cruise #%s' % uuid.uuid4(),
        # Recommendation: Set the campaign to PAUSED when creating it to
        # stop the ads from immediately serving. Set to ENABLED once you've
        # added targeting and the ads are ready to serve.
        'status': 'PAUSED',
        'advertisingChannelType': 'SEARCH',
        'biddingStrategyConfiguration': {
            'biddingStrategyType': 'MANUAL_CPC',
        },
        'endDate': (datetime.datetime.now() +
                    datetime.timedelta(365)).strftime('%Y%m%d'),
        # Note that only the budgetId is required
        'budget': {
            'budgetId': budget_id
        },
        'networkSetting': {
            'targetGoogleSearch': 'true',
            'targetSearchNetwork': 'true',
            'targetContentNetwork': 'false',
            'targetPartnerSearchNetwork': 'false'
        },
        # Optional fields
        'startDate': (datetime.datetime.now() +
                      datetime.timedelta(1)).strftime('%Y%m%d'),
        'adServingOptimizationStatus': 'ROTATE',
        'frequencyCap': {
            'impressions': '5',
            'timeUnit': 'DAY',
            'level': 'ADGROUP'
        },
        'settings': [
            {
                'xsi_type': 'GeoTargetTypeSetting',
                'positiveGeoTargetType': 'DONT_CARE',
                'negativeGeoTargetType': 'DONT_CARE'
            }
        ]
    }
}, {
    'operator': 'ADD',
    'operand': {
        'name': 'Interplanetary Cruise banner #%s' % uuid.uuid4(),
        'status': 'PAUSED',
        'biddingStrategyConfiguration': {
            'biddingStrategyType': 'MANUAL_CPC'
        },
        'endDate': (datetime.datetime.now() +
                    datetime.timedelta(365)).strftime('%Y%m%d'),
        # Note that only the budgetId is required
        'budget': {
            'budgetId': budget_id
        },
        'advertisingChannelType': 'DISPLAY'
    }
}]
campaigns = campaign_service.mutate(operations)

# Display results.
for campaign in campaigns['value']:
  print ('Campaign with name "%s" and id "%s" was added.'
         % (campaign['name'], campaign['id']))

PHP

$campaignService = $adWordsServices->get($session, CampaignService::class);

$operations = [];

// Create a campaign with required and optional settings.
$campaign = new Campaign();
$campaign->setName('Interplanetary Cruise #' . uniqid());
$campaign->setAdvertisingChannelType(AdvertisingChannelType::SEARCH);

// Set shared budget (required).
$campaign->setBudget(new Budget());
$campaign->getBudget()->setBudgetId($budget->getBudgetId());

// Set bidding strategy (required).
$biddingStrategyConfiguration = new BiddingStrategyConfiguration();
$biddingStrategyConfiguration->setBiddingStrategyType(
    BiddingStrategyType::MANUAL_CPC);

// You can optionally provide a bidding scheme in place of the type.
$biddingScheme = new ManualCpcBiddingScheme();
$biddingScheme->setEnhancedCpcEnabled(false);
$biddingStrategyConfiguration->setBiddingScheme($biddingScheme);

$campaign->setBiddingStrategyConfiguration($biddingStrategyConfiguration);

// Set network targeting (optional).
$networkSetting = new NetworkSetting();
$networkSetting->setTargetGoogleSearch(true);
$networkSetting->setTargetSearchNetwork(true);
$networkSetting->setTargetContentNetwork(true);
$campaign->setNetworkSetting($networkSetting);

// Set additional settings (optional).
// Recommendation: Set the campaign to PAUSED when creating it to stop
// the ads from immediately serving. Set to ENABLED once you've added
// targeting and the ads are ready to serve.
$campaign->setStatus(CampaignStatus::PAUSED);
$campaign->setStartDate(date('Ymd', strtotime('+1 day')));
$campaign->setEndDate(date('Ymd', strtotime('+1 month')));
$campaign->setAdServingOptimizationStatus(
    AdServingOptimizationStatus::ROTATE);

// Set frequency cap (optional).
$frequencyCap = new FrequencyCap();
$frequencyCap->setImpressions(5);
$frequencyCap->setTimeUnit(TimeUnit::DAY);
$frequencyCap->setLevel(Level::ADGROUP);
$campaign->setFrequencyCap($frequencyCap);

// Set advanced location targeting settings (optional).
$geoTargetTypeSetting = new GeoTargetTypeSetting();
$geoTargetTypeSetting->setPositiveGeoTargetType(
    GeoTargetTypeSettingPositiveGeoTargetType::DONT_CARE);
$geoTargetTypeSetting->setNegativeGeoTargetType(
    GeoTargetTypeSettingNegativeGeoTargetType::DONT_CARE);
$campaign->setSettings([$geoTargetTypeSetting]);

// Create a campaign operation and add it to the operations list.
$operation = new CampaignOperation();
$operation->setOperand($campaign);
$operation->setOperator(Operator::ADD);
$operations[] = $operation;

// Create a campaign with only required settings.
$campaign = new Campaign();
$campaign->setName('Interplanetary Cruise #' . uniqid());
$campaign->setAdvertisingChannelType(AdvertisingChannelType::DISPLAY);

// Set shared budget (required).
$campaign->setBudget(new Budget());
$campaign->getBudget()->setBudgetId($budget->getBudgetId());

// Set bidding strategy (required).
$biddingStrategyConfiguration = new BiddingStrategyConfiguration();
$biddingStrategyConfiguration->setBiddingStrategyType(
    BiddingStrategyType::MANUAL_CPC);
$campaign->setBiddingStrategyConfiguration($biddingStrategyConfiguration);

$campaign->setStatus(CampaignStatus::PAUSED);

// Create a campaign operation and add it to the operations list.
$operation = new CampaignOperation();
$operation->setOperand($campaign);
$operation->setOperator(Operator::ADD);
$operations[] = $operation;

// Create the campaigns on the server and print out some information for
// each created campaign.
$result = $campaignService->mutate($operations);
foreach ($result->getValue() as $campaign) {
  printf("Campaign with name '%s' and ID %d was added.\n",
      $campaign->getName(),
      $campaign->getId()
  );
}

Perl

# Create campaigns.
my $num_campaigns = 2;
my @operations    = ();
for (my $i = 0 ; $i < $num_campaigns ; $i++) {
  my (undef, undef, undef, $mday, $mon, $year) = localtime(time);
  my $today = sprintf("%d%02d%02d", ($year + 1900), ($mon + 1), $mday);
  (undef, undef, undef, $mday, $mon, $year) = localtime(time + 60 * 60 * 24);
  my $tomorrow = sprintf("%d%02d%02d", ($year + 1900), ($mon + 1), $mday);
  my $campaign = Google::Ads::AdWords::v201708::Campaign->new({
      name => "Interplanetary Cruise #" . uniqid(),
      # Bidding strategy (required).
      biddingStrategyConfiguration =>
        Google::Ads::AdWords::v201708::BiddingStrategyConfiguration->new({
          biddingStrategyType => "MANUAL_CPC",
          # You can optionally provide a bidding scheme in place of the type.
        }
        ),
      # Budget (required) - note only the budgetId is required.
      budget =>
        Google::Ads::AdWords::v201708::Budget->new({budgetId => $budgetId}),
      # Create a Search Network with Display Select campaign.
      # To create a Display Only campaign, omit networkSetting and use the
      # DISPLAY advertisingChannelType.
      # NetworkSetting (optional).
      networkSetting => Google::Ads::AdWords::v201708::NetworkSetting->new({
          targetGoogleSearch         => 1,
          targetSearchNetwork        => 1,
          targetContentNetwork       => 1,
          targetPartnerSearchNetwork => 0
        }
      ),
      # Advertising channel type (required).
      advertisingChannelType => "SEARCH",
      # Frequency cap (non-required).
      frequencyCap => Google::Ads::AdWords::v201708::FrequencyCap->new({
          impressions => 5,
          timeUnit    => "DAY",
          level       => "ADGROUP"
        }
      ),
      settings => [
        # Advanced location targeting settings (non-required).
        Google::Ads::AdWords::v201708::GeoTargetTypeSetting->new({
            positiveGeoTargetType => "DONT_CARE",
            negativeGeoTargetType => "DONT_CARE"
          }
        ),
      ],
      # Additional properties (non-required).
      startDate                   => $today,
      endDate                     => $tomorrow,
      # Recommendation: Set the campaign to PAUSED when creating it to stop
      # the ads from immediately serving. Set to ENABLED once you've added
      # targeting and the ads are ready to serve.
      status                      => "PAUSED",
      adServingOptimizationStatus => "ROTATE"
    });

  # Create operation.
  my $campaign_operation =
    Google::Ads::AdWords::v201708::CampaignOperation->new({
      operator => "ADD",
      operand  => $campaign
    });
  push @operations, $campaign_operation;
}

# Add campaigns.
my $result = $client->CampaignService()->mutate({operations => \@operations});

# Display campaigns.
foreach my $campaign (@{$result->get_value()}) {
  printf "Campaign with name \"%s\" and id \"%s\" was added.\n",
    $campaign->get_name(), $campaign->get_id();
}

Ruby

campaign_srv = adwords.service(:CampaignService, API_VERSION)

# Create campaigns.
campaigns = [
  {
    :name => "Interplanetary Cruise #%d" % (Time.new.to_f * 1000).to_i,
    # Recommendation: Set the campaign to PAUSED when creating it to stop the
    # ads from immediately serving. Set to ENABLED once you've added
    # targeting and the ads are ready to serve.
    :status => 'PAUSED',
    :bidding_strategy_configuration => {
      :bidding_strategy_type => 'MANUAL_CPC'
    },
    # Budget (required) - note only the budget ID is required.
    :budget => {:budget_id => budget_id},
    :advertising_channel_type => 'SEARCH',
    # Optional fields:
    :start_date =>
        DateTime.parse((Date.today + 1).to_s).strftime('%Y%m%d'),
    :ad_serving_optimization_status => 'ROTATE',
    :network_setting => {
      :target_google_search => true,
      :target_search_network => true,
      :target_content_network => true
    },
    :settings => [
      {
        :xsi_type => 'GeoTargetTypeSetting',
        :positive_geo_target_type => 'DONT_CARE',
        :negative_geo_target_type => 'DONT_CARE'
      }
    ],
    :frequency_cap => {
      :impressions => '5',
      :time_unit => 'DAY',
      :level => 'ADGROUP'
    }
  },
  {
    :name => "Interplanetary Cruise banner #%d" % (Time.new.to_f * 1000).to_i,
    :status => 'PAUSED',
    :bidding_strategy_configuration => {
      :bidding_strategy_type => 'MANUAL_CPC'
    },
    :budget => {:budget_id => budget_id},
    :advertising_channel_type => 'DISPLAY'
  }
]

# Prepare for adding campaign.
operations = campaigns.map do |campaign|
  {:operator => 'ADD', :operand => campaign}
end

# Add campaign.
response = campaign_srv.mutate(operations)
if response and response[:value]
  response[:value].each do |campaign|
    puts "Campaign with name '%s' and ID %d was added." %
        [campaign[:name], campaign[:id]]
  end
else
  raise new StandardError, 'No campaigns were added.'
end

VB.NET

Dim operations As New List(Of CampaignOperation)

For i As Integer = 1 To NUM_ITEMS
  ' Create the campaign.
  Dim campaign As New Campaign
  campaign.name = "Interplanetary Cruise #" & ExampleUtilities.GetRandomString
  campaign.advertisingChannelType = AdvertisingChannelType.SEARCH

  ' Recommendation: Set the campaign to PAUSED when creating it to prevent
  ' the ads from immediately serving. Set to ENABLED once you've added
  ' targeting and the ads are ready to serve.
  campaign.status = CampaignStatus.PAUSED

  Dim biddingConfig As New BiddingStrategyConfiguration()
  biddingConfig.biddingStrategyType = BiddingStrategyType.MANUAL_CPC
  campaign.biddingStrategyConfiguration = biddingConfig

  ' Set the campaign budget.
  campaign.budget = New Budget
  campaign.budget.budgetId = budget.budgetId

  ' Set the campaign network options.
  campaign.networkSetting = New NetworkSetting
  campaign.networkSetting.targetGoogleSearch = True
  campaign.networkSetting.targetSearchNetwork = True
  campaign.networkSetting.targetContentNetwork = False
  campaign.networkSetting.targetPartnerSearchNetwork = False

  ' Set the campaign geo target and keyword match settings.
  Dim geoSetting As New GeoTargetTypeSetting
  geoSetting.positiveGeoTargetType = GeoTargetTypeSettingPositiveGeoTargetType.DONT_CARE
  geoSetting.negativeGeoTargetType = GeoTargetTypeSettingNegativeGeoTargetType.DONT_CARE

  campaign.settings = New Setting() {geoSetting}

  ' Optional: Set the start date.
  campaign.startDate = DateTime.Now.AddDays(1).ToString("yyyyMMdd")

  ' Optional: Set the end date.
  campaign.endDate = DateTime.Now.AddYears(1).ToString("yyyyMMdd")

  ' Optional: Set the campaign ad serving optimization status.
  campaign.adServingOptimizationStatus = AdServingOptimizationStatus.ROTATE

  ' Optional: Set the frequency cap.
  Dim frequencyCap As New FrequencyCap
  frequencyCap.impressions = 5
  frequencyCap.level = Level.ADGROUP
  frequencyCap.timeUnit = TimeUnit.DAY
  campaign.frequencyCap = frequencyCap

  ' Create the operation.
  Dim operation As New CampaignOperation
  operation.operator = [Operator].ADD
  operation.operand = campaign
  operations.Add(operation)
Next

Try
  ' Add the campaign.
  Dim retVal As CampaignReturnValue = campaignService.mutate(operations.ToArray())

  ' Display the results.
  If ((Not retVal Is Nothing) AndAlso (Not retVal.value Is Nothing) AndAlso
      (retVal.value.Length > 0)) Then
    For Each newCampaign As Campaign In retVal.value
      Console.WriteLine("Campaign with name = '{0}' and id = '{1}' was added.",
            newCampaign.name, newCampaign.id)
    Next
  Else
    Console.WriteLine("No campaigns were added.")
  End If
Catch e As Exception
  Throw New System.ApplicationException("Failed to add campaigns.", e)
End Try

Our client libraries include code examples using the mutate() method for all the campaign management services.

When mutating objects, there are limits to the number of objects of a given type an AdWords account can hold. The limits for various types of AdWords objects are listed in this help center article. You should use these limits only as a guide when planning your campaigns, rather than hard-coding them into your application.

When calling mutate(), it's better to send multiple operations per request, than to send multiple requests with one operation per request. Sending multiple operations per request reduces the number of roundtrips to the server and improves your app's performance.

Another optimization trick is to group your requests by operations to a single parent entity. For example, if you're adding ads, try grouping your requests to one ad group at a time, instead of one request to multiple ad groups. See the Best Practices guide for more information.

The operator field

As mentioned above, the operator field indicates the type of mutate operation you wish to perform: ADD, SET, or REMOVE.

ADD is for creating a new object, SET is for updating an existing object, and REMOVE is for removing an existing object. However, some operators may not be applicable for some services.

For example, an AdWords campaign cannot be permanently removed once you create it—you can only mark it as REMOVED. While it is REMOVED you can still query its details and stats.

The AdWords API doesn't support the REMOVE operator in CampaignService; you need to update a Campaign by changing its status to REMOVED using the SET operator.

In contrast, campaign targets cannot be changed—you can only use ADD or REMOVE on these objects.

The table below details how to control the flow of different AdWords objects to achieve a desired status:

Type Add new object Enable Pause Remove / Disable
Campaign action : mutate()
operation: ADD
status : ENABLED
action : mutate()
operation: SET
status : ENABLED
action : mutate()
operation: SET
status: PAUSED
action : mutate()
operation : SET
status: REMOVED
AdGroup action: mutate()
operation: ADD
status: ENABLED
action : mutate()
operation: SET
status : ENABLED
action: mutate()
operation: SET
status : PAUSED
action : mutate()
operation: SET
status: REMOVED
AdGroupAd action : mutate()
operation: ADD
status: ENABLED
action : mutate()
operation : SET
status : ENABLED
action : mutate()
operation : SET
status : PAUSED
action: mutate()
operation : REMOVE
status: DISABLED
BiddableAdGroupCriterion action: mutate()
operation: ADD
status: ENABLED
action: mutate()
operation: SET
status: ENABLED
action: mutate()
operation: SET
status: PAUSED
action: mutate
operation: REMOVE
status: REMOVED
UserList action: mutate()
operation: ADD
status: OPEN
N/A N/A action: mutate()
operation: SET
status: CLOSED
Experiment action: mutate()
operation: ADD
status: ENABLED
N/A N/A action: mutate()
operation: SET
status: REMOVED
Feed action: mutate()
operation: ADD
status: ENABLED
N/A N/A action: mutate()
operation: REMOVE
status: REMOVED
FeedMapping action: mutate()
operation: ADD
status: ENABLED
N/A N/A action: mutate()
operation: REMOVE
status: REMOVED
FeedItem action: mutate
operation: ADD
status: ENABLED
N/A N/A action: mutate()
operation: REMOVE
status: REMOVED
CustomerFeed action: mutate()
operation: ADD
status: ENABLED
N/A N/A action: mutate()
operation: REMOVE
status: REMOVED
CampaignFeed action: mutate()
operation: ADD
status: ENABLED
N/A N/A action: mutate()
operation: REMOVE
status: REMOVED
AdGroupFeed action: mutate()
operation: ADD
status: ENABLED
N/A N/A action: mutate()
operation: REMOVE
status: REMOVED

Concurrent mutates

If you have multiple users updating the same object with your app, or if you're mutating AdWords objects in parallel using multiple threads for better throughput, it's important to understand how AdWords handles concurrent mutate requests for the same object.

An AdWords object cannot be modified concurrently by more than one source. This includes updating the object from multiple threads in the same application, or from different applications (for example, your app and a simultaneous AdWords Editor session). The API doesn't provide a way to lock an object before updating: If two sources try to simultaneously mutate an object, the API raises a CONCURRENT_MODIFICATION_ERROR.

You can learn more about AdWords API concurrency management in this blog post.

Asynchronous vs. synchronous mutates

AdWords API mutate() methods are synchronous: API calls return a response only after the objects are mutated, requiring you to wait for a response to each request. While this approach is relatively simple to code, it could negatively impact load balancing, and cause wasted resources while the machines wait for a call to complete.

An alternate approach is to mutate the objects asynchronously using BatchJobService, which provides a way to perform batches of operations on multiple services without waiting for the operations to complete. Once the batch job is submitted, AdWords API servers execute the operations asynchronously, freeing your machine to perform other operations, and to periodically check the job status for completion.

See the Batch Processing guide for more on asynchronous processing.

Mutate validation

The validateOnly SOAP header allows you to test your API calls without actually executing the call against real data: You can test for missing parameters and incorrect field values without actually executing the operation.

To use this feature, set the validateOnly field to true in the RequestHeader. The client libraries set this to false by default.

The request is fully validated as if it were going to be executed, but the final execution is skipped. If no errors are found, an empty response is returned. If validation fails, error messages indicate the failure points.

Here's an example of how to set up validateOnly, using the Java library.

Credential oAuth2Credential = new OfflineCredentials.Builder()
    .forApi(Api.ADWORDS)
    .fromFile()
    .build()
    .generateCredential();

AdWordsSession session = new AdWordsSession.Builder()
    .fromFile()
    .withOAuth2Credential(oAuth2Credential)
    .build();

session.setValidateOnly(true);

All API calls made using this session will have the validateOnly header set to true.

The validateOnly header is particularly useful in testing ads for common policy violations. Ads are automatically rejected if they violate policies like using specific words, punctuation, capitalization, or length. If you try to upload ads in batches, one bad ad could cause your entire batch to fail. Testing a new ad with validateOnly allows you to easily see which ads would be rejected. Refer to the code example for handling policy violation errors to see this in action.

If you're not using a client library, all you need to do is set up the right SOAP header and you can still validate your mutate() requests.

AdWords API services

This section describes the services provided by the AdWords API, with links to reference pages containing additional details for each service.

The AdWords API services can be grouped into four functional categories:

Campaign data management

Use the campaign data management services to work with AdWords campaigns and their associated entities. Each campaign data management service corresponds to an entity in the campaign data hierarchy.

Service Description
CampaignService Create, update, and remove campaigns. A campaign organizes one or more ad groups, and has its own budget, bidding strategy, serving date range, and targeting settings.
AdGroupService Create, update, and remove ad groups. An ad group organizes a set of ads and criteria together, and also provides the default bid for its criteria.
AdGroupAdService Create, update, and remove ads.
CampaignExtensionSettingService Create, update, and remove ad extensions. Campaign ad extensions enrich standard text ads by adding location information, additional links, or a phone number, to all ads within a campaign.
CampaignCriterionService
AdGroupCriterionService
Create, update, and remove criteria. A criterion describes the conditions that determine whether an ad should appear.
ConversionTrackerService
OfflineConversionFeedService
Measure the effectiveness of your ads and keywords by learning what happens after a user clicks on your ad. OfflineConversionFeedService handles importing offline conversions.
DataService Retrieve ads campaign management data, based on specified criteria.
FeedService
FeedItemService
FeedMappingService
AdGroupFeedService
CampaignFeedService
Create custom data feeds to manage site, phone, and app link extensions.
AdwordsUserListService Create, update, and remove user lists. User lists and user list criteria display ads to people who have previously triggered a conversion event on your website.
BudgetService Create, update, and remove budgets. Used to manage budgets that can be shared across campaigns.

Optimization

Use the optimization services to retrieve performance statistics and discover ideas for new criteria.

Service Description
ReportDefinitionService Create and download a variety of performance reports.
TargetingIdeaService Generate new keyword and placement ideas based on parameters you specify.
TrafficEstimatorService Get traffic estimates for proposed campaigns, ad groups, and keywords.
ExperimentService Create and run campaign experiments where you can test keywords, bids, and placements.

Account Management

Use the account management services to track your account activity.

Service Description
CustomerService Retrieve basic details about a client account.
CustomerSyncService Retrieve a record of campaign data changes within a specified date range.
ManagedCustomerService Manage client accounts and links between manager and client accounts.

Utility

Use these utility services to perform various useful tasks with the AdWords API.

Service Description
BatchJobService Process a large batch of campaign data operations asynchronously. Batch processing jobs take longer to complete than synchronous calls to the standard web services, but offer other advantages as described in the Batch Processing guide.
MediaService Upload and retrieve IDs for media you use in media-based ads (such as image or video ads).
ConstantDataService Retrieve constant values used by the API.
LocationCriterionService Retrieve the ID of a Location criterion.

Campaign data

Working with campaign data is one of the fundamental tasks you perform with the AdWords API. The table below describes each campaign data entity and its relationship with other campaign data.

Entity
Child Entities (quantity)
Data Type Description
Campaign
Ad groups (1+)
Campaign target lists (7)
Campaign ad extensions (0+)
Campaign criteria (0+)
Campaign Campaigns organize one or more ad groups, and have their own budget, bidding strategy, and serving date range.
Ad Group
Ads (1+)
Criteria (1+)
AdGroup
An ad group organizes a set of ads and criteria, and also provides the default bid for its criteria.
Ad
Ad extension overrides (0+)
AdGroupAd Available ad types are documented in the API reference as subclasses of the abstract Ad type.
Criterion
None
AdGroupCriterion, CampaignCriterion A criterion describes the conditions that determine if an ad should appear (biddable criterion) or should not appear (negative criterion). An ad group criterion affects ads in the parent ad group. A campaign criterion, which is always a negative criterion, defines conditions that prevent the campaign's ads from showing.
Ad Extension
None
CampaignExtensionSetting Campaign ad extensions enrich standard text ads by adding location information, additional links, or a phone number, to all ads within a campaign.
Feed
None
Feed Feeds act as conduits for data to ad extensions (sitelink, phone, app).
User List
None
UserList User lists keep track of which users have previously expressed interest in your website. You can target ads to this set of users by creating a user list criterion and linking it to an existing user list.
Budget
None
Budget Budgets are used for managing the amount of money spent on campaigns. A Budget can be shared across different campaigns and the system will determine the optimal allocation.

Send feedback about...

AdWords API
AdWords API
Need help? Visit our support page.