In addition to retrieving performance statistics, AdWords API developers often use the reporting system to get structural information about accounts.
This guide goes over how to interpret and manage zero impression stats in reports as well as how to use them in constructing an account structure.
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 impressions behavior.
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 rate limits.
For example, querying the Keyword Performance
Report for
Id
and Criteria
while excluding zero impressions may only retrieve
minimal results; but by including zero
impressions and adding fields such as CampaignId
and AdGroupId
,
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 true
.
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
includeZeroImpressions
HTTP header tofalse
. - Use a predicate.
Setting the includeZeroImpressions HTTP header to false
The simplest way to exclude zero impressions is to set the
includeZeroImpressions
HTTP header to false
.
When set to false
, reports will return only rows where at least one of
the requested 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 0
.
The XML for this predicate looks like this
<predicates>
<field>Impressions</field>
<operator>GREATER_THAN</operator>
<values>0</values>
</predicates>
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 report's behavior.
Structure reports
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
getReportFields()
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
get
or query
requests against
AdGroupCriterionService
is inefficient compared to retrieving the same criteria via the
CRITERIA_PERFORMANCE_REPORT.
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
fieldBehavior
ofATTRIBUTE
. - All fields used in the predicates of the report request have
fieldBehavior
ofATTRIBUTE
. - The
includeZeroImpressions
HTTP header is set totrue
. - The request does not include a date range or
DURING
clause.
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
CAMPAIGN_CRITERIA_REPORT
to retrieve all campaign-level criteria in your account. Unlike the
CRITERIA_PERFORMANCE_REPORT,
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
Campaigns example
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 SELECT
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, specifying all the required column headings from the Campaign Performance Report. 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 the
campaigns
table. Set a parameter value for each "?" using the values received in the report download.INSERT INTO campaigns (Status, id, name, extCID, custName, amount, biddingStrategyId, impressions) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
Report formats
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
a summary
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
headers
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
or
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 in mind:
When requesting certain reports, the inclusion of columns that prevent rows with zero impressions from returning will generate no results. The
KeywordId
field in the Ad Performance Report is one such case; this is indicated in the Notes column for that field, and by theFalse
value in its Support Zero Impressions column. Other columns can be mutually exclusive, for example,ConversionTypeName
andClicks
. 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 Notes column in the Report Types page for specifications on how columns are formatted.
If you choose not to use the optional headers to suppress the summary
Total
line, and instead signal the end of your parsing by the presence of the wordTotal
, take care when selecting the first column in your AWQL query so you won't see the wordTotal
as 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 theStatus
column, 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.