This blog series follows the journey of building the new and improved Interactive Google Ads Query Builder tool. Part 4 of this series described how we created a ResourceService
to display relevant fields given the resource in our FROM clause based on a user’s location in the app. In Part 5, we will discuss how to determine whether a field is selectable or not in a Google Ads Query Language (GAQL) query string.Background & Objective The determination of whether a field is selectable, or can be added to a clause of GAQL string, is dependent on both: 1) inherent properties of the main resource in the FROM clause and its fields’ properties as well as 2) the current state of the GAQL query string. The ResourceService
we created in Part 4 addresses item (1) because users will only be shown fields that are able to be selected based on those inherent properties. In order to address item (2), we will create a new service called the SelectionService
. The responsibilities of this service will include determining selectability, selecting fields, and deselecting fields. We will discuss determining field selectability in this post, and in Part 6 of this series, we’ll discuss how the SelectionService
selects and deselects fields.
Field Compatibility Not all fields are compatible with each other. When two fields are compatible, both can be present in a GAQL string. If two fields are incompatible, only one of the two fields may be present in any clause of a GAQL string at a time. Therefore, if there is a field in the GAQL string that is incompatible with the field being evaluated, the field being evaluated is not selectable, and the UI will reflect this by presenting users with a corresponding error message.
Implementation We will keep track of selected incompatible fields for each field on the main resource with an instance variable called incompatibleSelected
that maps each field to a Set of its incompatible fields that have been selected.interface IncompatibleSelected: {[key: string]: Set<string>} We’ll initialize this incompatibleSelected
such that the keys of the map are the aggregated list of fields on the resource, as determined by the ResourceService
, and the value of each entry is an empty Set. Each time a field is selected, we will add the selected field to the incompatibleSelected
Set of each field that is incompatible with the selected field. For example, let’s assume that ad_group
is the resource in our FROM clause. segments.ad_destination_type
is incompatible with metrics.absolute_top_impression_percentage
and metrics.active_view_cpm
, among other fields. The table below illustrates the incompatibility relationship among these fields.
Field
Incompatible Fields
segments.ad_destination_type
[metrics.absolute_top_impression_percentage, metrics.active_view_cpm, …]
metrics.absolute_top_impression_percentage
[segments.ad_destination_type, …]
metrics.active_view_cpm
[segments.ad_destination_type, …]
If segments.ad_destination_type
is selected, we’ll add segments.ad_destination_type
to the entries for metrics.absolute_top_impression_percentage
and metrics.active_view_cpm
in the incompatibleSelected
map. Following the addition of segments.ad_destination_type
to any clause in our query, a subset of our incompatibleSelected
field would look like this.
incompatibleSelected = { … 'segments.ad_destination_type': {}, 'metrics.absolute_top_impression_percentage': {'segments.ad_destination_type'} 'metrics.active_view_cpm': {'segments.ad_destination_type'} ... }
Each time a field is deselected, we’ll first check if that field is present in any clause of the query (more detail to be provided in Part 6) because if so, incompatibleSelected
should not be updated. For example, if segments.ad_destination_type
had been selected in the SELECT and ORDER BY clauses, but was only deselected from ORDER BY, we don’t want to make any adjustments to the incompatibleSelected
map because segments.ad_destination_type
is still present in the query. However, if the deselected field is absent from all clauses, we’ll delete the deselected field from the Set for each field that is incompatible with the deselected field. In our example, let’s assume we now deselect segments.ad_destination_type
from the SELECT clause, and it is no longer present in the query. Now, we’ll remove this field from the metrics.absolute_top_impression_percentage
and metrics.active_view_cpm
entries of the incompatibleSelected
map. At this point, every entry in the incompatibleSelected
map would contain an empty Set. With this data structure in place, we can create a method called isSelectable
that accepts a field name as a parameter. isSelectable
returns true if the Set for the field in incompatibleSelected
is empty and false if it is not. isSelectable(field: string): boolean { return this.incompatibleSelected[field]?.size === 0; }
Conclusion We have now implemented logic into a SelectionService
that determines whether a field is selectable. As we display each field to users, we can simply call isSelectable(field)
to determine what to show users in the UI. In this post we’ve covered field compatibility and how it relates to whether or not a field is selectable. In Part 6, we’ll build on this section to see how we can select fields, deselect fields, and keep track of the state of the GAQL query string with the SelectionService
.Hopefully this deepened your understanding how to construct GAQL queries using the Google Ads API. If you have any questions or need additional help, contact us via the
forum or at googleadsapi-support@google.com.
- Devin Chasanoff, on behalf of the Google Ads API Team