A common use case of the AdWords API is to manage campaigns in an AdWords account. This guide will introduce you to the basic AdWords objects like Campaigns, AdGroups, etc. that are required for campaign management, explain how they are related to one another and how to work with them.
We recommend that you brush up your knowledge of AdWords as an advertising platform, and basic concepts about how the AdWords API works before reading this guide. Code examples in this guide use the AdWords API Java library. If you are looking for a client library in another programming language, you can check our complete list of client libraries. Also, the use of a client library is recommended but optional; you may use any SOAP kit in the programming language of your choice to make calls to the API.
Understanding AdWords objects
Every AdWords account can be viewed as a hierarchy of objects. Under each account, there are Campaigns that represent advertisement campaigns you are running. Each campaign has multiple AdGroups, which are used to group your ads into logical collections. Each AdGroup has multiple AdGroupAds and AdGroupCriteria. AdGroupAd represents an ad that you are running, and AdGroupCriterion represents a criterion (e.g. keyword) that defines how the ads get triggered. You may designate criteria at the campaign level which define campaign-wide rules on how the ads get triggered. Finally, there are ad extensions at the campaign level that allow you to provide extra information like phone numbers, street address, etc. to your ads. You may also override these settings at the ad level.
Every object in AdWords is identified by its own ID. Some of these IDs are unique on a global level, while others are only unique within a confined scope, (i.e. not on a global level). The uniqueness of each object ID within AdWords is listed below.
Object ID | Scope of uniqueness | Globally unique? |
---|---|---|
Campaign ID | Global | Yes |
AdGroup ID | Global | Yes |
Ad ID | Within an ad group. | No. (AdGroupId, AdId) pair is globally unique. |
AdGroupCriterion ID | Within an ad group. | No. (AdGroupId, CriterionId) pair is globally unique. |
CampaignCriterion ID | Within a campaign. | No. (CampaignId, CriterionId) pair is globally unique. |
Ad Extensions | Within a campaign. | No. (CampaignId, AdExtensionId) pair is globally unique. |
Ad Extension overrides | Within an ad group. | No. (AdGroupid, AdExtensionId) pair is globally unique. |
The above ID rules can be useful when designing a local database to store your AdWords objects.
If an object is derived from another type, then it will also have a Type field. For instance, TextAd
has a Type field to denote the type of the object, since TextAd
is derived from the Ad
object. If you are using a dynamic language, you can use this field to check if an object belongs to a certain type (e.g. check if an Ad
object is of type TextAd
).
AdWords API Campaign management services
The AdWords API provides campaign management services to manage the exposed AdWords objects. For instance, CampaignService manages Campaigns, AdGroupService manages AdGroups, and so on. All campaign management services expose two standard methods: get
and mutate
.
get method
As the name implies, get
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 are retrieving the results. You also need to specify paging if you are pulling a lot of objects since 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 shows the above concepts in action, where we retrieve and display all the campaigns in an account.
final int PAGE_SIZE = 100; int offset = 0; // Create selector. Selector selector = new Selector(); selector.setFields(new String[] {"Id", "Name"}); selector.setOrdering(new OrderBy[] {new OrderBy("Name", SortOrder.ASCENDING)}); selector.setPaging(new Paging(offset, PAGE_SIZE)); CampaignPage page = null; do { // Get all campaigns. page = campaignService.get(selector); // Display campaigns. if (page.getEntries() != null) { for (Campaign campaign : page.getEntries()) { System.out.println("Campaign with name \"" + campaign.getName() + "\" and id \"" + campaign.getId() + "\" was found."); } } else { System.out.println("No campaigns were found."); } offset += PAGE_SIZE; selector.getPaging().setStartIndex(offset); } while (offset < page.getTotalNumEntries());
You can learn more about selectors and their behaviors in this blog post or this video. In case you need to quickly look up the available selector fields for different services, you can refer to this Selector Fields guide.
Our client library distribution includes code examples for get methods of all the campaign management methods. For example, you can find the Java client library examples for campaign management services under the basicoperations and campaignmanagement folders of the code examples section.
mutate method
As the name implies, the mutate
method is used to mutate (create, update or delete) an AdWords object. For instance, CampaignService.mutate mutates a Campaign.
To mutate any object, you need to build an appropriate Operation object. For instance, you need to create a CampaignOperation to mutate a Campaign. The operator field defines the type of operation you wish to perform (ADD, SET, REMOVE), and the operand field holds the object you want to mutate. For example, the code snippet to add a campaign is given below:
// Create campaign. Campaign campaign = new Campaign(); campaign.setName("Interplanetary Cruise #" + System.currentTimeMillis()); campaign.setStatus(CampaignStatus.PAUSED); campaign.setBiddingStrategy(new ManualCPC()); // You can optionally provide these field(s). campaign.setStartDate(new DateTime().plusDays(1).toString("yyyyMMdd")); campaign.setStartDate(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. // You can use BudgetService to create a shared budget. Budget budget = new Budget(); budget.setBudgetId(budgetId); campaign.setBudget(budget); // 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); GeoTargetTypeSetting geoTarget = new GeoTargetTypeSetting(); geoTarget.setPositiveGeoTargetType(GeoTargetTypeSettingPositiveGeoTargetType.DONT_CARE); KeywordMatchSetting keywordMatch = new KeywordMatchSetting(); keywordMatch.setOptIn(Boolean.FALSE); TargetRestrictSetting targetRestrict = new TargetRestrictSetting(); targetRestrict.setUseAdGroup(Boolean.TRUE); campaign.setSettings(new Setting[] {geoTarget, keywordMatch, targetRestrict}); // Create operations. CampaignOperation operation = new CampaignOperation(); operation.setOperand(campaign); operation.setOperator(Operator.ADD); CampaignOperation[] operations = new CampaignOperation[] {operation}; // Add campaigns. CampaignReturnValue result = campaignService.mutate(operations); // Display campaigns. for (Campaign campaignResult : result.getValue()) { System.out.println("Campaign with name \"" + campaignResult.getName() + "\" and id \"" + campaignResult.getId() + "\" was added."); }
Our client library distribution includes code examples for the mutate method of all the campaign management services. For example, you can find the Java client library examples for campaign management services under the basicoperations and campaignmanagement folders of the code examples section.
A common question associated with mutating objects is about 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. However, you should use this limit only as a guide when planning your campaigns and should not hard code these limits into your application.
Another point to keep in mind while making mutate calls is that it is better to send multiple operations per request than sending multiple requests with one operation per request, since this reduces the number of roundtrips to the server and thus increase your application performance. You should also try to group your requests by operations to a particular parent entity to increase performance. For example, if you are adding ads, then try to group your requests to add ads to one ad group at a time instead of a single request that adds ads to multiple ad groups. You can read more about these on our best practices guide.
operator field
As discussed previously with the mutate
method, the operator field tells the AdWords API the nature of the mutate operation you wish to perform - ADD, SET or REMOVE. As the name implies, ADD is for creating a new object, SET is for updating an existing object, and REMOVE is for removing an existing object. However, depending on how AdWords manages a certain type of object, some of the operators may not be applicable for some services.
For example, an AdWords campaign cannot be permanently deleted once you create it. You can only mark a campaign as deleted, and you may undelete a campaign by marking it as paused or active. So the AdWords API doesn’t support the REMOVE operator in CampaignService; you need to update a Campaign by changing its status to DELETED using the SET operator. Similarly, you cannot SET a campaign target, you can only ADD or REMOVE targets. More details on how AdWords treats different objects are shown below:
Type | Newly Added | Enable/ Active | Paused | Delete / Deactivated |
---|---|---|---|---|
Campaign | action : mutate operation: ADD status : ACTIVE |
action : mutate operation: SET status : ACTIVE |
action : mutate operation: SET status: PAUSED |
action : mutate operation : SET status: DELETED |
AdGroup | action: mutate operation: ADD status: ENABLED |
action : mutate operation: SET status : ENABLED |
action: mutate operation: SET status : PAUSED |
action : mutate operation: SET status: DELETED |
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: ACTIVE |
action: mutate operation: SET status: ACTIVE |
action: mutate operation: SET status: PAUSED |
action: mutate operation: REMOVE status: DELETED |
AdExtensionOverride | action: mutate operation: ADD status: ACTIVE |
N/A | N/A | action: mutate operation: REMOVE status: DELETED |
CampaignAdExtension | action:mutate operation: ADD status: ACTIVE |
N/A | N/A | action: mutate operation: SET status: DELETED |
UserList | action: mutate operation: ADD status: OPEN |
N/A | N/A | action: mutate operation: SET status: CLOSED |
Experiment | action: mutate operation: ADD status: ACTIVE |
N/A | N/A | action: mutate operation: SET status: DELETED |
Dealing with concurrent mutates
When building an AdWords API application, you will often find yourself mutating AdWords objects in parallel, such as when you are using multiple threads to get better throughput for your application or maybe you have multiple users updating the same object using your application. So it is important to understand how AdWords handles concurrent mutate requests for the same object and to develop your application accordingly.
The general rule of mutating an AdWords object is that you cannot modify the same object concurrently. This includes updating the object from multiple threads in the same application or from different applications (e.g. your application and a simultaneous AdWords Editor session). The AdWords API doesn’t provide a way to lock an object before updating, rather, it uses an optimistic approach for locking the objects. If the AdWords API finds that an object is being updated simultaneously by more than one source, it will raise a CONCURRENT_MODIFICATION_ERROR. You can learn more about AdWords API concurrency management in this blog post.
Asynchronous v/s synchronous mutates
AdWords API mutate methods are synchronous - meaning that if you make an API call, then the call returns only after the objects are mutated, or the call fails. While this approach is relatively simple to code, you also need to worry about several other things like load balancing, wasted resources while the machines wait for API calls to complete, etc.
An alternate approach is to mutate the objects asynchronously using MutateJobService. Using MutateJobService, you can create jobs that consist of potentially large batches of operations. Once the job is submitted, AdWords API servers execute the jobs in an asynchronous manner. This frees up your machine to perform other operations and periodically check the job status for completion. Another benefit of using asynchronous APIs is that they incur only 50% of the API cost of synchronous API calls. You can learn more about asynchronous APIs in this video or in batch processing guide.
Validating your mutate calls
All AdWords API mutate calls allow you to validate if a call will succeed or fail due to a missing parameter or incorrect value for a field. To use this feature, you need to set the validateOnly field of the RequestHeader
field to true. Your call will fail if your operations have errors, but the service will not perform the operations if there aren’t any errors.You can learn more about validateOnly mode in this blog post. The validateOnly mode is useful in checking ads for common policy violations. You can refer to this code example for details.