Google Ads

Best Practices  |  AdWords API  |  Google Developers

This guide covers some best practices you can implement to optimize
the efficiency and performance of your AdWords API applications.

Ongoing maintenance

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.


Batch operations

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
there are
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
rate limit.

Page large responses

Always specify the pageSize parameter in requests to the API. This will split
the response into multiple chunks if necessary.

If 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.

Group operations

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
populated objects.

Use compression

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
particular error.

  1. 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
      OAuth2 flow.

    • Authorization
      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_REVOKED error, 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_DENIED error 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
      AuthorizationError.USER_HAS_READONLY_PERMISSION error.

      For either example, your app could provide directions for the user, or escalate
      the issue to an account manager for resolution.

  2. Retryable errors

    Some errors can indicate a temporary problem that may be resolved by
    retrying the request after a short pause. These include

    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 retryAfterSeconds field 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.

  3. Validation errors

    Validation errors indicate that an input to an operation was not acceptable.
    Some examples include PolicyViolationError, DateError, DateRangeError,
    StringLengthError, 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
    more efficient.

    For backend-initiated requests, your app could add the failed operation
    to a queue for a human operator to review.

  4. Sync-related errors

    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 INVALID_ID,

    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
    example, CANNOT_OPERATE_ON_REMOVED_ADGROUPAD should 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

Sync backends

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.

Log errors

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

The client libraries provide built-in SOAP
logging capabilities as well as the ability to retrieve the
requestId header.

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

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
accepts a
of either IDEAS or STATS. 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
One TargetingIdea
will be returned for each keyword. This is more efficient than making a separate
request for each keyword.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button