Run a GAQL query
run_gaql_reportRun an arbitrary read-only Google Ads Query Language (GAQL) SELECT against an account and return the raw rows. The power tool for anything the structured tools don't cover. Only SELECT is allowed.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| gaql | Yes | A GAQL SELECT statement, e.g. "SELECT campaign.name, metrics.clicks FROM campaign WHERE segments.date DURING LAST_7_DAYS". Enum-typed fields only accept their exact string name in WHERE (e.g. `campaign.status = 'ENABLED'`), never the field's underlying numeric/ordinal value (e.g. NOT `= '2'` or `= 2`) and never LIKE/wildcards. Use IN (...) with the exact enum name(s), e.g. WHERE campaign.status IN ('ENABLED','PAUSED'), or omit the filter and inspect the returned enum values in a first pass. Any metrics/segments field requires a `segments.date` filter that bounds a finite range - bound `segments.date` with either `segments.date DURING LAST_30_DAYS` (or another named range: TODAY, YESTERDAY, LAST_7_DAYS, THIS_MONTH, LAST_MONTH, ...) or `segments.date BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'`. A single-sided comparison (`segments.date >= '...'`) does not count as a finite range. Otherwise Google errors with "Expects filters on the following field to limit a finite date range: 'segments.date'". For keyword-level metrics (impressions, clicks, cost, conversions, ...), query `FROM keyword_view`, not `FROM ad_group_criterion` - ad_group_criterion only exposes the criterion's own config (status, keyword.text, keyword.match_type, quality_info, ...) and has no metrics. On keyword_view, name the keyword with the `ad_group_criterion.keyword.text` / `ad_group_criterion.keyword.match_type` fields, not `segments.keyword.info.text` / `segments.keyword.info.match_type` - that segment labels a different resource's rows by the keyword involved (e.g. search_term_view), and keyword_view rows are already one per keyword. Otherwise Google errors with "metric/segment is incompatible with the resource in the FROM clause". `change_event` and `change_status` don't support `segments.date` at all - use their own date/time field instead: `change_event.change_date_time` on change_event, `change_status.last_change_date_time` on change_status. Conversion-related segments (segments.conversion_action_name, segments.conversion_action_category, segments.conversion_lag_bucket, ...) only combine with conversion-specific metrics (metrics.conversions, metrics.all_conversions, metrics.conversions_value, ...) - ordinary metrics like clicks, impressions, and cost_micros aren't computed per conversion action, and Google names the ones actually blocking the query as "unsupported metrics" above. Drop those metrics from this query, or run them separately without the conversion segment. GAQL requires that any field used in WHERE or ORDER BY also appear in the SELECT list - add the named field there too. `DURING` only accepts a fixed set of named ranges: TODAY, YESTERDAY, LAST_7_DAYS, LAST_14_DAYS, LAST_30_DAYS, LAST_BUSINESS_WEEK, THIS_WEEK_SUN_TODAY, THIS_WEEK_MON_TODAY, LAST_WEEK_SUN_SAT, LAST_WEEK_MON_SUN, THIS_MONTH, LAST_MONTH - there's no LAST_90_DAYS or other custom-length range. For anything else, use `segments.date BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'` with explicit dates instead. `change_event` and `change_status` cap how far back `segments.date`/the relevant date field can start - 30 days for change_event, 90 for change_status - Google simply doesn't retain older history. Narrow the `BETWEEN`/`DURING` range to stay within that limit. `change_event` and `change_status` queries must end with an explicit `LIMIT n` where n <= 10000, e.g. `LIMIT 1000` - Google rejects them outright with no LIMIT clause at all. `change_event` has no `resource_type` field - that name belongs to `change_status`. On `change_event` the equivalent is `change_event.change_resource_type` (an enum, e.g. AD, CAMPAIGN, AD_GROUP, ...). GAQL's WHERE clause doesn't support parentheses or boolean grouping - conditions can only be ANDed together as a flat list, and there's no OR at all. Remove the parentheses; if you need an OR over the same field's values, use `IN (...)` instead, and if you need an OR across different fields, run separate queries and merge the results. | |
| customerId | No |