This blog series follows the journey of building the new and improved Interactive Google Ads Query Builder tool. Part 5 of this series described how we determine whether or not a field is selectable. In Part 6, we will discuss how we add fields to a Google Ads Query Language (GAQL) string using the SelectionService
.GAQL String State In order to track which fields have been selected, we need to keep track of the GAQL string’s state, which we can do in an instance variable called selectedFields
that has the following interface definition:
interface SelectedFields { select: string[]; where: Array<{field: string, context: string}>; orderBy: Array<{field: string, context?: string}>; limit?: string; params?: string; }
The select
field holds an array of field names. The where
field holds an array of objects, each of which contains a field
name and context
string. By context, we mean the filtering condition to apply to the field (or operator and operand). For example, if we added the filtering condition, ad_group.id = 1234567890
to the WHERE clause, the field would be ad_group.id
, and the context would be = 1234567890.
Similarly, the orderBy
field holds an array of field
names and optional context
strings. Here, context
is the optional ASC or DESC direction (default ASC). The limit
field is the optional string representation of the integer LIMIT . Finally, the optional params
field represents the optional string value of the PARAMETERS clause. We don’t need an array here because there is currently only a single option for this clause.Selecting Fields Now that we have a data structure in place to track the state of a user’s query, we can implement a method to select a field in any clause.
selectField(field: string, clause: string, context?: string): void { ... }
If the clause
is SELECT, we’ll add the provided field to the select
array in selectedFields
. When users add a field in the SELECT clause, no context is provided. If the clause
is WHERE, all three parameters are required because a filtering condition containing an operator and operand must be provided as a context
string. When users click the checkbox to add a field in the WHERE clause, we’ll open a dialog prompting them to specify the operator, and then an operand once the operator has been set. Depending on the data_type
of the field being selected, we’ll pre-populate the list of available operators a user can select, and depending on the operator selected, we’ll show the user a different component to input the operand. Once a user adds the filtering criteria, we’ll join the operator and operand into a single string to create the context
string. If the clause
is ORDER BY, context
is optional. When a user selects a field in the ORDER BY clause, we’ll call selectField
without any context and add the field to the orderBy
array of selectedFields
without any context. We’ll also present users with radio buttons under the field name to specify an order of ASC or DESC. Upon clicking one of the options, we’ll update the respective field’s entry in the orderBy
array to add the order context
. If the clause
is LIMIT or PARAMETERS, we’ll update the limit
and params
entries of selectedFields
, respectively, with the provided string as the field
parameter. The limit must be a positive integer, the validation for which is performed in the related UI component. The only parameter currently available is include_drafts
, and the default value is false. Therefore, we’ll present users with a checkbox in the UI component for PARAMETERS with a single option ‘include_drafts=true’. If the user clicks the checkbox, we’ll pass the string include_drafts=true
to selectField
as the field
.SELECT Presence While the logic of selecting fields is straight-forward, there are two rules regarding selectability that we intentionally skipped in part 5 . Certain fields must be present in the SELECT clause before they can be inserted into the WHERE or ORDER BY clauses.Rule #1: with the exception of “core date segments” (segments.date , segments.week , segments.month , segments.quarter , segments.year ), all segments and segmenting resources must be present in the SELECT clause before they can be inserted into the WHERE clause. Rule #2: all segments , segmenting resources , metrics , and attributed resource fields must be present in the SELECT clause before they can be inserted into the ORDER BY clause. In other words, only fields on the resource in the FROM clause can be placed in the ORDER BY clause without first being inserted into the SELECT clause. In these cases, we’ll present a dialog that enables the user to add the field to the SELECT clause as well as the desired clause in a single step.Deselecting Fields In order to deselect fields, we’ll implement a method in the SelectionService
called deselectField
.
deselectField(field: string, clause: string): void { … }
Deselecting a field is similar to selecting a field. As a safeguard, we’ll first check if the field is selected. Then, if the clause
is SELECT, WHERE, or ORDER BY, we’ll remove the deselected field from the respective array entry of selectedFields
. In the event the field that is required to be present in SELECT before being added to WHERE or ORDER BY according to the rules described above and is removed from SELECT, we’ll automatically remove the field from SELECT in a single operation. If the clause is LIMIT or PARAMETERS, we’ll update the respective entry of selectedFields
to undefined
.Updating the Output With the selectedFields
variable, selectField
method, and deselectField
method in place, we can now track the state of the query string. In order to keep track of changes throughout the application, we’ll create an Observable in the SelectionService
and call next
on it each time selectField
or deselectField
is called. Then, we can subscribe to the observable in any component that needs to be aware of the GAQL query state.Conclusion We have now updated the SelectionService
to select fields and deselect fields. In this post, we’ve covered:GAQL query and clause structure. Additional detail regarding selectability. Using Observables in Angular. Hopefully this has deepened your understanding of constructing GAQL queries with 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