The AdWords API is no longer supported. Use the Google Ads API instead.

Zero Impression and Structure Reports

Stay organized with collections Save and categorize content based on your preferences.

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 to false.
  • 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


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:

  1. All selected fields in the report request have fieldBehavior of ATTRIBUTE.
  2. All fields used in the predicates of the report request have fieldBehavior of ATTRIBUTE.
  3. The includeZeroImpressions HTTP header is set to true.
  4. 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:

  1. 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
  2. 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)
  3. 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 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 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 the False value in its Support Zero Impressions column. Other columns can be mutually exclusive, for example, ConversionTypeName and Clicks. 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 word Total, take care when selecting the first column in your AWQL query so you won't see the word Total 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 the Status 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.