This guide covers some best practices you can implement to optimize
the efficiency and performance of your AdWords API applications.
To ensure that your app runs uninterrupted:
Keep your developer contact email in the AdWords API Center up-to-date.
This is the alias we use to contact you. If we’re unable to contact you
regarding compliance with the API Terms and Conditions, your API access
may be revoked without your prior knowledge. Avoid using a personal email
address tied to an individual or an unmonitored account.
To be informed of issues, such as product changes, maintenance downtime,
deprecation dates, and so on, subscribe to our
The forum is regularly monitored by the AdWords
API team, making it the ideal place to post API questions.
- Keep your app compliant with the AdWords API
Terms and Conditions (T&C) and
Required Minimum Functionality
(RMF). If required, the token review and compliance team will reach out to
you via your contact email. If you have questions or concerns about the
T&C or RMF, you can reach out to the review team by responding to the
email they sent you when reviewing your developer token application.
Making a request to the API entails a number of fixed costs, such as
round-trip network latency, serialization and deserialization processing, and
calls to backend systems. To lessen the impact of these fixed costs and increase
overall performance, most
mutate() methods in the API are designed to accept
an array of operations. By batching multiple operations into each
request, you can reduce the number of requests you make and the associated
fixed costs. If possible, avoid making requests with only one operation.
For example, suppose you’re adding 50,000 keywords to a campaign across multiple ad
groups. Instead of making 50,000 requests with 1 keyword each, make 100 requests
with 500 keywords each, or even 10 requests with 5,000 keywords each. Note that
limits on the number of operations allowed in a request,
so you may need to adjust your batch size to achieve optimal performance.
An additional benefit of making fewer, larger requests is that your app is
less likely to encounter a request-based
Page large responses
Always specify the
pageSize parameter in requests to the API. This will split
the response into multiple chunks if necessary.
pageSize is not specified when using one of our client libraries, your
request will fail (
RESOURCE_EXHAUSTED) if the response exceeds 4 MB. Even if
you’re not using one of our client libraries, you should still set the
pageSize since large responses can exhaust the available memory on your
Start with a
pageSize of 1000 and fine tune as needed to improve performance.
Operations that all target the same ad group or campaign will process faster
than the same number of operations targeting many different ad groups or
campaigns. Grouping together operations that target the same ad group or
campaign reduces the total number of ad groups or campaigns targeted in the
request, improving overall performance.
Concurrent requests to the same ad group or campaign may generate a
error. Grouping operations that modify the same ad group or campaign
in a single request decreases the chance of such a conflict.
Take the example above of adding 50,000 keywords to a campaign across multiple
ad groups. Before breaking the operations into batches, a simple approach is to
sort the keywords by the ad group they target. This increases the chance that
all of the keywords for the same ad group will fall within the same request. It also
decreases the total number of ad groups targeted in a single request.
More advanced approaches can be applied to ensure that related operations are
grouped into as few requests as possible while still maintaining large batches.
Reuse access tokens
Reusing the same OAuth2 access token across threads and processes
reduces the overhead of periodically refreshing tokens, and reduces the
likelihood that your app will be rate limited due to excessive token
refreshes. Learn more about
optimizing OAuth2 requests.
Send sparse objects
When objects are sent to the API, fields must be deserialized,
validated, and stored in the database. Passing in full objects when you only
want to update a few fields can result in extra processing time and decreased
performance. To mitigate this, the AdWords API supports sparse updates, allowing
you to populate only the fields in an object that you wish to change or that are
required. Fields that are unpopulated or have null values are left unchanged,
increasing the performance of your requests.
For example, an app that updates keyword-level bids can benefit from
using sparse updates, as only the
fields would need to be populated. In a test using 150 keywords, a 20%
performance increase was seen using sparse updates instead of passing fully
The AdWords API supports gzip compression on SOAP messages in both requests and
responses. To enable gzip compression in a response, include these two HTTP
headers in your request:
User-Agent: containing the string “gzip”
Accept-Encoding: with the value gzip
User-Agent: My App (gzip) Accept-Encoding: gzip
If you’re using a client library, see its
documentation on enabling compression.
Error handling and management
During development, you’re likely to encounter errors. This section describes
considerations and strategies when building error management into your
In addition to this section, see the
troubleshooting guide for
more information on managing errors.
Distinguish request sources
Some apps are primarily interactive, issuing API calls directly in response
to user-initiated actions in a UI. Others work primarily offline, issuing API
calls as part of a periodic backend process. Many apps combine the two. When
thinking about error management, it can be useful to distinguish these different
types of requests.
For user-initiated requests, your primary concern should be providing a good
experience for your users. Use the specific error that occurred
to provide the user with as much context as possible in the UI. Where possible,
offer easy steps they can take to resolve the error (see suggestions below).
For backend-initiated requests, implement handlers for the different types of
errors your app may encounter (see suggestions below). Always include a
default handler to address rare or previously unseen errors. A good approach for
a default handler is to add the failed operation and error to a queue for a
human operator to review and determine an appropriate resolution.
Distinguish error types
Below are four broad categories of errors, each of which should be handled
differently. Though these categories don’t encompass all possible errors, and
some may fit into more than one category, they can nevertheless serve as a
starting point for structuring your app’s error handling. Refer to
Common Errors for more details about a
Authentication and authorization errors
Authentication refers to whether your app has been given
permission by a user to access Google Ads on their behalf. Authentication
is managed through credentials generated by the
refers to whether your app, authenticated and acting as a user, is
allowed to work with the particular Google Ads data it is trying to read or write.
The most common reason an authentication error arises from factors beyond your
control is when the authenticated user revokes the permission they gave your
app to act on their behalf. For example, if your app manages separate Google Ads
accounts for independent clients and authenticates separately as each client
when managing that client’s account, a client could revoke your app’s access
at any time. Depending on when your access was revoked, the API
may directly return an
AuthenticationError.OAUTH_TOKEN_REVOKEDerror, or the built-in credential
objects in the client libraries may throw
a token revoked exception. In either case, if your app has a UI for
your clients, it could ask them to relaunch the OAuth2 flow to reestablish
your app’s permission to act on their behalf.
Another common reason an authorization error arises from factors beyond your control
is due to changes in your manager account hierarchy. Apps working with a
single manager account hierarchy usually authenticate as an administrator
user of their top-level manager account, since this user has the authority to
access all of the sub-accounts in the hierarchy. If a user of a sub-account
removes the manager link, your app will receive an
AuthorizationError.USER_PERMISSION_DENIEDerror when attempting to access
that account. You can use
to check whether the sub-account has indeed been removed from the hierarchy.
Another reason an authorization error can arise is when the user your
app authenticated as has their access rights changed.
For example, suppose another user with administrator rights
on the Google Ads account changes your app’s authenticated user’s rights to
read-only. In this case, all mutate requests will fail with an
For either example, your app could provide directions for the user, or escalate
the issue to an account manager for resolution.
For user-initiated requests, one strategy is to immediately indicate an error
in your UI and give the user an option to trigger a retry. Alternatively, your
app could first automatically retry the request, only exposing the error
in the UI after reaching a maximum number of retries or total user wait time.
For backend-initiated requests, your app should automatically retry the
request up to a maximum number of retries.
When you retry requests, use an exponential backoff policy. For example, if you
first pause 5 seconds before the first retry, you could pause 10 seconds after
the second and 20 seconds after the third retry. Exponential backoff helps
ensure you are not calling the API too aggressively.
errors, the amount of time your app pauses before attempting to retry
should be at least longer than the
retryAfterSecondsfield in the error. See the
Rate Limits guide for more
details. Other retryable errors can be retried sooner but should still follow an
exponential backoff policy.
Validation errors indicate that an input to an operation was not acceptable.
Some examples include
UrlError, and many others.
Validation errors occur most commonly in user-initiated requests, where a
user has entered invalid input. In these cases, you should provide an
appropriate error message to the user based on the specific API error you
received. You can also validate user input for common mistakes before
making an API call, making your app more responsive and your API usage
For backend-initiated requests, your app could add the failed operation
to a queue for a human operator to review.
Many Google apps maintain a local database to store their Google Ads
objects. One challenge to this approach is that the local database may go
out of sync with the actual objects in Google Ads. For example, a user might delete
an ad group directly in Google Ads, but the app and local database are
unaware of the change and will issue API calls as if the ad group existed.
These sync issues can manifest as a variety of errors such as
CANNOT_OPERATE_ON_REMOVED_ADGROUPAD, and many others.
For user-initiated requests, one possible strategy is to alert the user to a
possible sync problem, immediately launch a job that retrieves the relevant class
of Google Ads objects and updates the local database, then prompt the user to refresh the UI.
For backend-initiated requests, some errors provide enough information for your
app to automatically and incrementally correct your local database. For
CANNOT_OPERATE_ON_REMOVED_ADGROUPADshould cause your app to
mark that ad as removed in your local database. Errors that you cannot handle
in this way could cause your app to launch a more complete sync job or
be added to a queue for a human operator to review.
Handle partial failures
By default, requests to the API are atomic: If an error occurs during
just one operation in the request, all of the operations are aborted. Atomicity
is a safe default, but in many cases is undesirable, as the operations might
be independent and only the failed ones need to be reviewed. There are two
strategies to address this default behavior.
The first strategy is to review the errors in the response, correlate them with
the operation(s) that threw the errors, and issue a new request with only the
operations that did not throw errors. These operations should now succeed.
You could also pass the operations that threw errors to your error
handling mechanism (see above) or queue them for review by a human operator.
The second strategy is to enable the
partial failure flag in
your API requests. When you enable this flag, each operation is treated
independently, and an error in one will not prevent the others from being
committed. Errors in specific operations are still returned normally.
All of our client libraries
support this flag.
The primary benefits of using the partial failure flag are simplicity and fewer
API calls, as valid operations are committed automatically without you needing
to retry them. For most apps, partial failure is appropriate.
However, in some apps it’s more useful to have greater control over error
handling. For example, suppose an app does not want policy errors in one
ad to prevent other ads from being committed, but it does want other errors
(such as those that signal a more significant issue) to abort the entire request. To
implement this idea, the app should employ the first strategy above.
In either case, note that certain errors can reflect a dependence between
operations either one of which would have been valid on its own. Examples
If your app’s users have manual access to Google Ads accounts, they may
make changes that your app is not aware of, causing your
app’s local database to go out of sync. As noted above, you can address
sync-related errors reactively when they occur, but you can also seek to
prevent them proactively. One proactive strategy is to run a nightly
sync job on all your accounts, retrieving the Google Ads objects in your
accounts and comparing against your local database. To make the retrieval
efficient, consider using
structure reports rather than the
regular API services.
All errors should be logged to facilitate debugging and monitoring. At a
minimum, log the request ID, the operations that caused the error, and the
error itself. Other information to log includes customer ID, API service,
round-trip request latency, number of retries, and the raw SOAP request and
Be sure to monitor trends in API errors so that you can detect and address
problems with your app. Consider building your own solution or employing
one of many available commercial tools that can use your logs to produce
interactive dashboards and send automated alerts.
Use test accounts
are Google Ads accounts that do not actually serve ads. You can use a
test account to experiment with the AdWords API and test that your app’s
connectivity, campaign management logic, or other processing are working as
expected. Your developer token does not need to be approved to use it on a test
account, so you can start developing with the AdWords API immediately after
requesting a developer token, even before your app is reviewed.
Batch targeting ideas
When generating targeting ideas using
STATS requests can be used to retrieve statistics of
known keywords. To retrieve statistics for multiple keywords, combine them in
a single request by listing the keywords in the
will be returned for each keyword. This is more efficient than making a separate
request for each keyword.