In addition to retrieving performance statistics, AdWords API developers often
use the reporting system to get structural information about accounts.
Zero impression stats in reports
In your reports, you may encounter zero impression stats for
entities that have not been viewed. This could be for various reasons:
the entities are ineligible to display, or they could
have been paused during the report’s date range.
These zero impressions are of little use when calculating performance,
but are needed to download the full contents of the account.
Zero impression reports are used to discover entity structures in an
account or to quickly synchronize a local database without having to make
a series of expensive
get() calls to
the API. By including zero impressions in results, you can discover the
structure of any account entity in a single call.
Including and excluding zero impressions
Zero impression data can be returned in all of the normal performance reports,
so you should always explicitly include or exclude
zero impressions according to your use case. This removes any ambiguity
from your requests and allows the API to provide a meaningful error if
your request contains an invalid combination of report fields and zero
When to include zero impressions
Zero impressions are useful in exposing entity structures in an account in
a single call.
The alternative is making numerous API requests which may trigger
For example, querying the Keyword Performance
Criteria while excluding zero impressions may only retrieve
minimal results; but by including zero
impressions and adding fields such as
it’s possible to process and build a structure of the
currently known keywords.
When to exclude zero impressions
Zero impressions are useful for discovering entity structures but should
typically be excluded from performance reporting. You may want to exclude
zero impressions to reduce response size or to focus
only on meaningful performance statistics for a given date range.
This is especially beneficial if there are many paused campaigns in a
given report, as zero impressions can unnecessarily inflate the result set.
Including zero impressions
To include zero impressions in your report output, set the
includeZeroImpressions HTTP header to
When set to
true, reports will not exclude any rows based on metric
values, and will include those with zero impressions.
Excluding zero impressions
There are two ways to explicity exclude zero impressions from reports:
- Set the
includeZeroImpressionsHTTP header to
- Use a predicate.
The simplest way to exclude zero impressions is to set the
includeZeroImpressions HTTP header to
When set to
false, reports will return only rows where at least one of
Metric fields has a non-zero value.
Excluding zero impressions with a predicate
You can exclude zero impressions by adding a predicate for the
Impressions field with an operator of
GREATER_THAN and a value of
The XML for this predicate looks like this
Impressions GREATER_THAN 0
and the AWQL statement like this
WHERE Impressions > 0
Implicitly excluding zero impressions
Zero impression rows are implicitly excluded when a report request
contains any field that doesn’t support zero impressions. You can see the zero impressions
behavior for each field in the
Supports Zero Impressions attribute of the
Report Types pages.
However, it’s best not to rely on implicit exclusions,
since adding or removing one field from your request could change your
Using the API services to collect comprehensive data on your account can
require a large number of requests, especially as your account grows.
Google Ads reporting provides an easier way to get
basic structural information for your account and its related entities:
you can use reports to quickly return data—including
object IDs, names, and values—to reproduce the basic skeleton of your
account. From there, you can identify elements you want to know more about,
and use their object IDs to retrieve details from the API.
The Report Types documentation indicates
which column entries can be retrieved for each account object. These column
titles can also be obtained programmatically using the
method of the ReportDefinitionService.
By carefully selecting report columns, you can obtain enough information
to build the structure of your account.
Retrieving ad group criteria
Since Google Ads accounts can have a large number of ad group criteria, issuing
query requests against
is inefficient compared to retrieving the same criteria via the
To use the
CRITERIA_PERFORMANCE_REPORT as a structure report, make sure your
request meets the following restrictions:
- All selected fields in the report request have
- All fields used in the predicates of the report request have
includeZeroImpressionsHTTP header is set to
- The request does not include a date range or
For example, the following AWQL will retrieve the ad group ID, criterion ID,
criterion type, criterion description, and targeting type for each ad group
criterion in your account:
SELECT AdGroupId, Id, CriteriaType, Criteria, IsNegative FROM CRITERIA_PERFORMANCE_REPORT
Retrieving campaign criteria
You can use the
to retrieve all campaign-level criteria in your account. Unlike the
CAMPAIGN_CRITERIA_REPORT can only be used as a structure report.
For example, the following AWQL will retrieve the campaign ID, criterion ID,
criterion type, criterion description, and targeting type for each campaign
criterion in your account:
SELECT CampaignId, Id, CriteriaType, Criteria, IsNegative FROM CAMPAIGN_CRITERIA_REPORT
This example demonstrates how to gather some relevant data about each campaign
in an account. Use an
AWQL request to gather
the data; then insert
the returned data into a local database. You can then make local
requests to build
the structural table in which you’re interested.
The following steps and code snippets show how to construct a campaigns table:
Query campaign data from reports by building the AWQL request string,
all the required column headings from the Campaign Performance
You also must state the report type and a date range for the query. Then
use the query to create the report,
specifying CSV as the download format.
SELECT CampaignStatus, CampaignId, CampaignName, ExternalCustomerId, CustomerDescriptiveName, Amount, BiddingStrategyId, Impressions FROM CAMPAIGN_PERFORMANCE_REPORT DURING YESTERDAY
Create a local campaigns table. This statement creates the table,
spelling out the column
titles and their type in our SQLite table:
CREATE TABLE campaigns (Status STRING, id LONG, name STRING, extCID LONG, custName STRING, amount FLOAT, biddingStrategyId LONG, impressions INTEGER)
Fill in campaigns table. The SQL statement below inserts entries into
Set a parameter value for each “?” using the values received in the
INSERT INTO campaigns (Status, id, name, extCID, custName, amount, biddingStrategyId, impressions) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
Reports are available in a number of formats (such as CSV or XML), but CSV
allows you to
simply feed the response stream through readily available libraries to
filter each entry into an object format of your choice. CSV output is also more
concise, so processing is often faster.
By default, CSV reports have a report header as the first line,
the column headers as the second line, followed by the results, and finally
Total line. Here’s a sample response from the
Campaign Performance Report
illustrating the default format:
"CAMPAIGN_PERFORMANCE_REPORT (Apr 1, 2015-Apr 6, 2015)" Campaign state,Campaign ID,Campaign,Customer ID,Account,Cost,Bid Strategy Name,Impressions paused,143072203,Search + DSAs,1234567890,My Google Ads Account,0, --,0 paused,168682400,Interplanetary Cruise 1396462861759,1234567890,My Google Ads Account,0, --,0 paused,168682099,Interplanetary Cruise 1396462699054,1234567890,My Google Ads Account,0, --,0 enabled,238539688,Campaign 1234,1234567890,My Google Ads Account,5970000, --,902 Total, --, --, --, --,5970000, --,902
The report header line in this default format is followed by the
column names requested in the second line. The returned columns are
in the same order specified in the request—unless you request duplicate
columns, in which case the second instance is omitted. The summary line
concludes the report.
When parsing and inserting the data into a database,
be sure to ignore the first two lines, then insert each of the
remaining lines until the
Total line which should also be ignored.
Alternatively, you can set optional
on the request so that the report header, column headers, and summary are
omitted from the response, leaving only the data itself.
You can repeat these tasks for ad groups, ads, and criteria; then use SQL
to query the local database you just populated. You can modify
this example to utilize the collected data however you wish, for instance:
SELECT * FROM campaigns LEFT OUTER JOIN adGroups ON campaigns.id=adGroups.campaignId LEFT OUTER JOIN ads ON ads.adAdGroupId=adGroups.adGroupId
SELECT * FROM criteria JOIN keywords WHERE criteria.critType='Keyword' AND keywords.keywordId=criteria.critId
Tips and tricks
When using this approach to retrieve account data, keep the following tips
When requesting certain reports, the inclusion of columns that prevent
rows with zero
impressions from returning will generate no results. The
Ad Performance Report is one
this is indicated in the Notes column for that field, and by the
in its Support Zero Impressions column.
Other columns can be mutually exclusive, for example,
You should avoid these column headings when downloading structural data:
use ones listed as Attributes in the Behavior column instead.
You should avoid requesting duplicate columns, since they’re removed from the
response and will likely confuse the parsing of the data. Refer to the
in the Report Types page for
specifications on how columns are formatted.
If you choose not to use the optional
to suppress the summary
Totalline, and instead signal the end of your
parsing by the presence of the word
Total, take care when selecting the first
column in your AWQL query so you won’t see the word
Totalas one of the values
for that column, or you’ll terminate your parsing prematurely.
For example, you could safely use IDs as the first column, which will be
Longs. In the example, we selected the
Statuscolumn, which contains Strings
with a limited set of values.
Ensure you get the right type for each column, as the parsing
of those values into the correct values from strings will throw exceptions if you
receive something unexpected and then call a type-specific string parser on it.