Log in / Create free account🌐 ES☀️

Advanced training · Module 8 — GAQL and the API — reading what the interface does not show

Anatomy of a GAQL query: clauses, operators, dates, micros and the rules that get you rejected

⏱️ 10 min read · 🥷 Scripts · updated on 2026-09-02

🎧 Listen to the lesson · ≈ 4 min🔒 Subscribers only

In short: a GAQL query has six clauses and only two are mandatory: SELECT and FROM. The traps that explain almost every error are five: whatever you filter must be selected, one resource per query, dates need a range, not everything is compatible with everything, and segments multiply rows. Amounts come in micros: divide by a million.

A GAQL query has six clauses, two of which are compulsory. This lesson takes them apart with a real annotated query and the rules the validator applies — so you understand why a query works or throws an error.

A GAQL query annotated line by line

SELECT
  campaign.id,                          -- attribute: the ID (stable key)
  campaign.name,                        -- attribute: the name (for display only)
  segments.date,                        -- segment: one row per day
  metrics.cost_micros,                  -- metric: cost in micros (÷ 1,000,000)
  metrics.conversions,                  -- metric: primary conversions
  metrics.search_budget_lost_impression_share   -- metric: IS lost to budget
FROM campaign                           -- resource: the campaigns table
WHERE
  campaign.status = 'ENABLED'           -- enum: in quotes, in capitals
  AND campaign.advertising_channel_type = 'SEARCH'
  AND segments.date DURING LAST_30_DAYS -- a date range is compulsory when segmenting by date
  AND metrics.clicks > 0                -- filter on a metric
ORDER BY metrics.cost_micros DESC       -- ordering
LIMIT 500                               -- row cap

Which clauses does a GAQL query have?

Clause Compulsory What it does
SELECT Yes The list of attributes, metrics and segments you want
FROM Yes A single resource (table)
WHERE No Conditions joined with AND (there is no OR between different conditions; you use IN)
ORDER BY No A field with ASC/DESC
LIMIT No Maximum number of rows
PARAMETERS No Options (for example, including drafts)

Which operators does WHERE accept?

Type Operators Example
Comparison =, !=, >, >=, <, <= metrics.clicks > 100
Set IN (...), NOT IN (...) campaign.id IN (123, 456)
Text LIKE, NOT LIKE (with %), CONTAINS ANY/ALL/NONE campaign.name LIKE '%Brand%'
Range BETWEEN ... AND ... segments.date BETWEEN '2026-07-01' AND '2026-07-31'
Date DURING segments.date DURING LAST_7_DAYS
Nulls IS NULL, IS NOT NULL ad_group_criterion.keyword.text IS NOT NULL
Regex REGEXP_MATCH campaign.name REGEXP_MATCH '^SEARCH.*'

How do you filter dates in GAQL?

Why do amounts come out multiplied by a million?

Why is my GAQL query failing?

  1. Whatever you filter on, you select: a field in the WHERE (in particular segments such as segments.conversion_action_name) must be in the SELECT.
  2. One resource per query: there is no JOIN; each resource already carries its "parents'" attributes (from keyword_view you can ask for campaign.name).
  3. Segmenting by date requires a date range.
  4. Compatible segments and metrics: not every segment works with every metric in every resource (the validator will tell you).
  5. Every segment multiplies the rows: segments.date + segments.device = one row per campaign, day and device. Ask only for the segments you need.

How do you learn GAQL without programming?

Google's query builder: you pick the resource, tick fields and metrics, add filters and it hands you the query. The validator tells you whether it is correct. And inside a script, AdsApp.search(query) returns the rows so you can write them to a sheet. With that, any question from this course ("search terms with conversions that are not keywords", "IS lost to budget by campaign and day") turns into a ten-line query.

💡 Ninja trick: two details from how the Suite works in practice: queries are run with frozen date windows (calculated once and stored) so that incremental downloads spread over several days reconcile with each other; and large accounts are queried in batches (LIMIT + filters by campaign or by date) so as not to hit the 30-minute limit on scripts.

What you should remember

📎 Sources and further reading

⚠️ Free training with no support. Ninja Scripts support channels (email and Telegram) are only for the use of the scripts, not for Google Ads questions or questions about this training.

Pick up here

← BeforeWhat GAQL is: the language you use to ask Google Ads what the interface does not showGAQL and the API — reading what the interface does not showAfter →The resources that matter: the map of GAQL tables for every question in this courseGAQL and the API — reading what the interface does not showRelacionadaAutomating with judgement: rules, scripts and AI — what to delegate, what to supervise and what never to automateScripts I — what they are, what they solve and how to install the SuiteRelacionadaLead quality: scoring every contact and teaching Google the difference between a customer and a browserMeasurement II — offline conversions, values, GA4, attribution and lead qualityRelacionadaAuditing your tracking: the routine that tells you your data is trustworthyBasic measurement — conversions, the Google tag and consentRelacionadaControlling monthly spend: pacing, variances, alerts and a month-end with no surprisesBudgets and planning — impression share, curves, allocation and spend control

Ver el temario completo

🎓
You're reading the Ninja Academy in the open

Create your free account (no card) to save your progress, take the graded quizzes, earn the Basic level certificate and unlock part of the Intermediate and Advanced training.

Create my free account →
🥷

Subscriber feature

This option is part of the Ninja Scripts Suite subscription.

See the subscription →