Category Archives: Ads Developer Blog

The official blog for information about the AdWords, AdSense, DoubleClick and AdMob APIs and SDKs

The Query Builder Blog Series: Part 3 – Creating a Resource Schema

This blog series follows the journey of building the new and improved Interactive Google Ads Query Builder. Part 2 of this series described the design of the detailed JSON resource schema that will serve as the canonical data set for the Interactive Query Builder Angular application. Part 3 will focus on how we can use the GoogleAdsFieldService to create that schema.

Retrieving the data

We can retrieve most of the data for the schema described in Part 2 by making an API call to the GoogleAdsFieldService with the following query:

SELECT name, category, data_type, selectable, filterable, sortable, selectable_with, metrics, segments, is_repeated, type_url, enum_values, attribute_resources

The result contains an array of JSON objects for every field available in the Google Ads API. Each object in the array will contain the fields in the SELECT clause above. For example, the ad_group list item would look like this:


{
"resourceName": "googleAdsFields/ad_group",
"name": "ad_group",
"category": "RESOURCE",
"dataType": "MESSAGE",
"selectable": false,
"filterable": false,
"sortable": false,
"selectableWith": [...],
"metrics": [...],
"segments": [...],
"isRepeated": false,
"typeUrl": "com.google.ads.googleads.v6.resources.AdGroup",
"enumValues": [],
"attributeResources": [...]
}


We’ll restructure this into key-value pairs, where the keys are the entity names and the values are the metadata for each entity, making it easier to lookup the metadata for a given entity. For example, the ad_group entry would look like this:


{
"ad_group": {
"resourceName": "googleAdsFields/ad_group",
"name": "ad_group",
"category": "RESOURCE",
"dataType": "MESSAGE",
"selectable": false,
"filterable": false,
"sortable": false,
"selectableWith": [...],
"metrics": [...],
"segments": [...],
"isRepeated": false,
"typeUrl": "com.google.ads.googleads.v6.resources.AdGroup",
"enumValues": [],
"attributeResources": [...]
}


As compared with the schema we designed in Part 2, this restructured object is missing several fields, which we’ll add in the following sections: attributes, fields, description, and display name.

Attributes

If you recall from the schema design, each resource should contain an array named attributes which contains the names of all fields present on the resource itself and any attributed resources. We can create this array by iterating through the results of our GoogleAdsFieldService query and adding the name of entries beginning with either our resource or one of its attributed resources, followed by a dot.

Fields

The fields entry in our schema is an object with an entry for each (a) item in the attributes array we just created, (b) metric on the resource, and (c) segment on the resource. The value of each entry will be each respective field’s value in the object we created earlier. However, we still need to add an incompatible_fields array to each field.

To construct the incompatible_fields array for each entry in our fields object, we’ll check to see if each of the fields, metrics, and segments present on the top level object is selectable_with the given field being evaluated. If not, we’ll add that field, metric, or segment to the incompatible_fields array.

Descriptions

Next, we need to add descriptions to each top level resource and item in its fields entry. It is important to note that a field may have a different description depending on the top level resource. For example, the description of ad_group.id is “Output only. The ID of the ad group.” but the description of campaign.id is “Output only. The ID of the campaign.” The REST discovery docs contain nested descriptions that we can use to create a canonical descriptions object, which we’ll use to populate our schema. This step entails parsing and formatting, the details of which we will not discuss here. We just want you to know that the REST discovery docs exist in case you ever need them. This is currently the best solution available, although it would be easier if the descriptions were returned from the GoogleAdsFieldService.

Display names

All that is left to do is populate the display names field in our resource schema. We can do this by simply replacing underscores with spaces and capitalizing the first letter of each word in the name.

Filtering for resources

Our resource schema is now fully populated. However, it contains every resource, field, segment, and metric returned from our GoogleAdsFieldService query. We can filter this schema to include only items with a category of RESOURCE.

Conclusion

We have now created an expanded resource schema containing detailed field information and a list of incompatible fields for each field, which we can use in our Angular application. In this post, we’ve covered:
  • How to use the GoogleAdsFieldService to retrieve field metadata.
  • Field compatibility in GAQL.
  • The REST discovery API.
Hopefully this has deepened your understanding of what is possible with the Google Ads API. If you have any questions or need additional help, contact us via the forum or at [email protected].

The Query Builder Blog Series: Part 2 – Designing a Resource Schema

This blog series follows the journey of building the recently released Interactive Google Ads Query Builder tool. Part 1 of this series outlined what we’ll be covering in the series as well as the rationale behind publishing this content. Part 2 will focus on designing a detailed JSON resource schema that will serve as the canonical data set for the Interactive Query Builder Angular application.

Background

As mentioned in Part 1, one of the major benefits of the new Interactive Query Builder is that it provides real-time feedback detailing why fields may or may not be selectable in a given clause of a Google Ads Query Language (GAQL) query.

For example, let’s say you are constructing a GAQL query with ad_group as the main resource in the FROM clause. Both segments.conversion_action and metrics.absolute_top_impression_percentage are selectable on the ad_group resource. However, taking a look at the detailed reference documentation for segments.conversion_action, we can see that there is a list of “Selectable With” fields, and that list does not include metrics.absolute_top_impression_percentage. Therefore, those two fields are incompatible. Regardless of what resource is in the FROM clause, if one of those two fields is present in the query, we know that the other cannot be. That is why metrics.absolute_top_impression_percentage is no longer selectable in the Interactive Query Builder once segments.conversion_action is selected.

Rather than trying to piece together all of this logic at runtime with various back-and-forth server calls, we thought it would be beneficial to feed that data into the application with static JSON files containing the resource schema. What might that optimal schema look like?

Schema Design (definition at the end of the blog post)

A GAQL string requires a single resource in the FROM clause. Given that constraint, the top level JSON schema will be a map from resources to detailed schemas for each resource. For example, the ad_group entry in our schema will look like this:



{

"ad_group": {

"name": "ad_group",
"display_name": "Ad Group",
"description": "An ad group.",
// Array of all attribute and attributed resource fields.
"attributes": [
"ad_group.ad_rotation_mode",
"ad_group.base_ad_group",
"ad_group.campaign",
...
"campaign.ad_serving_optimization_status",
"campaign.advertising_channel_sub_type",
"campaign.advertising_channel_type",
...
"customer.auto_tagging_enabled",
"customer.call_reporting_setting.call_conversion_action",
"customer.call_reporting_setting.call_conversion_reporting_enabled",
...
],
// Array of all metrics selectable with ad_group.
"metrics": [...],
// Array of all segments selectable with ad_group.
"segments": [...],
// Expanded info for all items listed in attributes, metrics, and segments arrays.
"fields": {...}

}




The crux of this enhanced schema is the fields entry. The keys of this object will be all of the attributes, metrics, and segments of the top level resource (e.g. ad_group). The value of each item in this object will be objects containing detailed information about that given field, as well as an additional field called incompatible_fields, an array of the fields that are incompatible with the given field. For example, the metrics.phone_impressions entry of the fields object would look like this:





"metrics.phone_impressions": {
"field_details": {
"name": "metrics.phone_impressions",
"category": "METRIC",
"selectable": true,
"filterable": true,
"sortable": true,
"data_type": "INT64",
"is_repeated": false,
"type_url": "",
"description": "Number of offline phone impressions.",
"enum_values": [],
"selectable_with": [
"ad_group",
"ad_group_ad",
"campaign",
"customer",
"extension_feed_item",
"segments.ad_network_type",
"segments.click_type",
"segments.date",
"segments.day_of_week",
"segments.interaction_on_this_extension",
"segments.keyword.ad_group_criterion",
"segments.keyword.info.match_type",
"segments.keyword.info.text",
"segments.month",
"segments.month_of_year",
"segments.quarter",
"segments.week",
"segments.year"
]
},
"incompatible_fields": [
"segments.slot",
"segments.device",
"segments.external_conversion_source",
"segments.conversion_action_category",
"segments.conversion_lag_bucket",
"segments.hour",
"segments.conversion_action_name",
"segments.conversion_action",
"segments.conversion_adjustment",
"segments.conversion_or_adjustment_lag_bucket"
]
},




The recursive nature of the schema may seem somewhat redundant, as some fields will appear in multiple resources. However, we will ultimately divide this main schema into individual JSON files for each resource to decrease load times, and we will only retrieve a single resource-specific schema depending on the resource in the FROM clause.


Schema Definition

For reference, the full schema definition is below:



interface ResourceSchema {
name: string; // the name of the resource
display_name: string; // the display name of the resource
description: string; // the description of the resource
attributes: string[]; // the resource's fields (including attributed resource fields)
metrics: string[]; // available metrics when the resource is in the FROM clause
segments: string[]; // available segments when the resource is in the FROM clause
fields: { // detailed info about all fields, metrics, and segments
[key: string]: {
field_details: FieldDetails; // details about the field (defined below)
incompatible_fields: string[]; // fields that are incompatible with the current field
}
};
}

interface FieldDetails {
name: string; // the name of the field
category: string; // the field's category (e.g. ATTRIBUTE, METRIC, SEGMENT)
selectable: boolean; // whether or not the field is allowed to be placed in the SELECT clause
filterable: boolean; // whether or not the field is allowed to be placed in the WHERE clause
sortable: boolean; // whether or not the field is allowed to be placed in the ORDER BY clause
data_type: string; // the field's data type
is_repeated: boolean; // whether or not the field is a repeated field
type_url: string; // the field's type_url
description: string; // the field's description
enum_values: string[]; // possible enum values if the field is of type ENUM
selectable_with: string[]; // the list of field the current field is selectable with
}


Conclusion

With that, we now have designed an expanded resource schema containing detailed field information and a list of incompatible fields for each field, which we can use in our Angular application. In part 3, we’ll discuss how to create this schema using the GoogleAdsFieldService.
Hopefully this has deepened your understanding of and shown you what is possible with the Google Ads API. If you have any questions or need additional help, contact us via the forum or at [email protected].

The Query Builder Blog Series: Part 1 – Setting the Stage

An important part of our role in Developer Relations is gathering your feedback, as developers using our APIs, so that we can improve products and create tools that will make for a better developer experience. This is particularly important now because the Google Ads API is now out of Beta. We have received several important pieces of feedback as it relates to the Google Ads Query Language (GAQL) and constructing GAQL queries. Specifically, we’ve learned that

  • GAQL is a powerful and flexible mechanism for retrieving data from the Google Ads API. In order to get the most out of it and construct queries efficiently, it is important to understand the details and nuances of this query language.
  • The previous version of the Interactive Google Ads Query Builder tool was useful for constructing GAQL query strings. However, there were opportunities to make the query building process faster while exposing some of the logic behind the tool to better understand how GAQL query string validation works.
As a result, we have released a new version of the Interactive Google Ads Query Builder tool that has several benefits, which you can view in the release blog post.

In developing this new tool, we approached the Google Ads API from a user's perspective to better understand developer use cases. Throughout the process, we documented our experience to share how we approach using the Google Ads API. This is the first in a series of blog posts following that journey. The Query Builder Blog Series will include the following topics.

  • Designing a resource schema: designing a detailed JSON resource schema that will serve as the canonical data set for the Interactive Query Builder Angular application.
  • Creating a resource schema: how we can use the GoogleAdsFieldService to create an enhanced resource schema that includes incompatible fields to make building this application easier.
  • Creating a resource service: how to create a resource service that determines which fields are displayed to users in various parts of the application.
  • Determining Field Selectability: how to create a selection service that determines whether a field is selectable or not in a given clause of a Google Ads Query Language (GAQL) query string.
  • Field Selection & Query Validation: how to update the selection service to select fields and validate the GAQL string.
  • Summary: a summary of key lessons learned from this process.

We hope you enjoy and learn from this blog series. Stay tuned for more interesting content.

If you have any questions or need additional help, contact us via the forum or at [email protected].

March 2021 update to Display & Video 360 API v1

Today we’re releasing an update to the Display & Video 360 API which includes the following features:
More detailed information about this update can be found in the Display & Video 360 API release notes.

Before using these new features, make sure to update your client library to the latest version.

If you run into issues or need help with these new features, please contact us using our support contact form.

Announcing the New and Improved Interactive Query Builder

Today, we are releasing a new and improved version of the Google Ads Query Language (GAQL) interactive query builder. The new version is resource-centric and helps you build a GAQL query based on the resource in the FROM clause. There are two ways to to access the query builder:


Navigate to the developer documentation Reports tab. Expand the Query Builder on the left side of the page. Choose your resource.

Click the Help me build a query button for any resource in the reporting reference documentation.







Highlights

As users type, the new search bar filters fields dynamically.





We also designed this tool with a goal of educating developers about the Google Ads Query Language as they use it. The query builder dynamically surfaces hints (such as field compatibility)





and prompts (for example, to notify users of requirements to add fields to multiple clauses of a query).





The new query builder features “pretty print” mode to display queries in an easy to read format, as well as “interactive” mode, which provides the ability to remove and reorder fields directly within the query box.





As you get started with the new query builder, please feel free to share feedback by clicking the Send feedback button on the top right of any page.




If you have any questions or need additional help, contact us via the forum or at [email protected].

Upcoming Change to the Enforcement of Temporary IDs with Product Partitions and Listing Groups

Beginning in May, 2021 we will enforce a requirement that temporary IDs be unique for all objects in newly created listing groups (used for Hotel Ads and Shopping Ads in the Google Ads API) and product partitions (used for Shopping Ads in the AdWords API). This change will affect all versions of both the AdWords and Google Ads APIs.

Temporary IDs must be unique across an entire mutate request–even if the objects are in separate listing group trees or product partition trees.

In order to avoid unnecessary breakages, API users should update their applications to ensure that all temporary IDs used in individual requests are unique.

Here is a snapshot of the expected behavior for requests that continue using non-unique temporary IDs:

API and mutate method Current Behavior New Behavior
BatchJobService with the Google Ads API Customers will receive a non-specific error, meaning it may not specify that the issue is related to temporary IDs. Customers will start receiving failed operations that contain the error: MutateError.MUTATE_ERROR_TEMP_ID_ALREADY_EXISTS
BatchJobService with the AdWords API Customers will receive a non-specific error, meaning it may not specify that the issue is related to temporary IDs. Customers will start receiving failed operations that contain the error: NewEntityCreationError.DUPLICATE_TEMP_IDS
AdGroupCriterionService or GoogleAdsService.Mutate with the Google Ads API Customers will not receive an error. Customers will start receiving the error: MutateError.MUTATE_ERROR_TEMP_ID_ALREADY_EXISTS
AdGroupCriterionService with the AdWords API Customers will not receive an error. Customers will start receiving the error: NewEntityCreationError.DUPLICATE_TEMP_IDS


If you have any questions or need additional help, contact us via the forum or at [email protected].

AdFormat in Search Query Performance Report will start returning UNKNOWN starting 2021-05-12

On 2021-05-12 we will deprecate the  AdFormat column in the Search Query Performance Report for AdWords API and Google Ads scripts. From then onwards, the report will return UNKNOWN for this field. This does not affect the Google Ads API.

The AdFormat column provides the type of creative that was triggered such as text, image, or video. If you still require this information, you can instead select AdGroupId and CreativeId from the same report, then call AdGroupAdService.get() to retrieve the Ad.type field.

This completes the migration that was started in January 2020 to remove AdFormat from all reports.

If you have any questions about this or anything else related to the AdWords API, please reach out to our support team on the forum.

Nick Birnie, Google Ads API Team

Securing Google Publisher Tags with Content Security Policy

The Google Publisher Tag (GPT) now supports integrating with a Content-Security-Policy (CSP). Using a CSP, you can precisely control which external sources are allowed to load on your site, on a page-by-page basis. In this way, CSPs help to detect and defend against common web vulnerabilities such as cross site scripting (XSS) attacks.

Although CSPs can be implemented in a number of ways, GPT only supports the strict CSP method, using nonces. For detailed instructions on setting this up, see our guide on Integrating with a Content Security Policy.

A note on existing CSPs

While GPT did not previously support CSPs, we're aware that some publishers worked around this by using CSPs based on an allowlist of domains. As previously mentioned, however, only nonce-based strict CSP implementations are supported. This is due to the fact that the set of domains GPT accesses is subject to change over time.

If you've been using GPT with an allowlist-based CSP, we strongly recommend that you supplement or replace it with a nonce-based strict CSP policy. This will reduce the risk that a future change to GPT may break ad serving on your page.

Sunset grace period for existing v2 users of the Content API for Shopping

As we’ve previously announced, we will stop supporting legacy v2.0 of the Content API for Shopping in favor of v2.1, which has been available since March 2019.

As this has been a difficult year for all of us, in order to provide you ample time to migrate to v2.1 we will be extending the sunset date for existing merchant accounts actively using v2.0 to September 30, 2021. However, we will not allow new merchant accounts onto v2.0 after April 30, 2021. The account restrictions will not impact users accessing new sub-accounts via an existing multi-client account (MCA), provided that MCA has been actively making v2.0 requests.

We will publish another blog post in the coming weeks with a process for requesting an exemption to add new accounts to your v2.0 integration after April 30, 2021.

Throughout this grace period, we will continue to provide support for your efforts to migrate to v2.1. We strongly encourage you to migrate to v2.1 as soon as possible.

What do I need to know?
In March 2019, we released version 2.1 of the Content API for Shopping with major improvements to the API management experience for Merchant Center programs, including: See the complete list of changes in the release notes and the migration guide to help with the transition.

If you have any questions or issues during migration, contact your Google representative for Merchant Center programs, or ask questions in the Content API for Shopping forum.

What do I need to do?
Migrate to v2.1 of the Content API as soon as possible.

New validation for line items in Display & Video 360 API

Beginning in May 2021, the Display & Video 360 API will start enforcing new validation when creating or updating line item resources.

This validation will require all Floodlight activity configurations in a line item to use the same lookback windows. All TrackingFloodlightActivityConfig objects assigned to conversionCounting.floodlightActivityConfigs in a line item must have the same postClickLookbackWindowDays value and the same postViewLookbackWindowDays value. The values of the two lookback window types do not have to be the same.

This validation will be enforced when creating new line items or updating the conversionCounting.floodlightActivityConfigs field of an existing line item. 
Requests that do not comply will return one of two errors, depending on the invalid field: “Floodlight click windows must be the same” or “Floodlight view windows must be the same.”

Once this validation is in effect, you will still be able to retrieve and update unrelated fields of line items that do not comply with this rule.

If you run into issues or have questions regarding this new validation, please contact us using our support contact form.