Get FREE Book - THE AI Playbook For PPC Pros
The AI Playbook for PPC Pros
The AI Playbook for PPC Pros
Now available
GET for FREE
GAQL Google Ads Query Language guide for PPC marketers

Every AI tool that connects to Google Ads speaks the same language. It’s called GAQL.

When you ask Claude “show me where I’m wasting money,” it writes a GAQL query. When you connect the Google Ads MCP and ask “which campaigns have a CPA above $50,” it writes a GAQL query. When your Google Ads Scripts pull search term data, they run GAQL queries. The 12 agents we’re building at PPC.io ? Every single one of them generates GAQL under the hood.

I use the Google Ads API every day across 100+ accounts, and I’ve never manually typed a GAQL query from scratch. AI writes them for me. But understanding what GAQL is and how it works made me dramatically better at getting what I need from these tools.

This article is the guide I wish existed when I started. Not a developer reference. Not API documentation. A practical walkthrough for PPC professionals who want to understand the language their AI tools speak, with 10 real queries you can use today.

Want ready-made PPC tools that use GAQL?

Grab our free prompt collection . 50+ expert-grade prompts for audits, scripts, and analysis that generate GAQL queries for you.

What Is GAQL (And Why Should a Marketer Care)?

GAQL stands for Google Ads Query Language. It’s the structured way you ask the Google Ads API questions. If the API is the door to your Google Ads data, GAQL is the key.

Think of it this way. You already ask Google Ads questions every day when you click through the UI. “Show me campaigns sorted by spend.” “Filter to enabled keywords only.” “Give me the last 30 days.” GAQL is just those same questions written in a format the API can understand.

The latest API version (v23) has 181 queryable resources. That covers everything from campaigns and keywords to search terms, geographic data, change history, and Performance Max channel breakdowns. If a data point exists in Google Ads, there’s a GAQL query that can pull it.

Here’s why this matters even if you never write a single query yourself. Every AI tool that touches your Google Ads data, whether it’s Claude Code , the Google Ads MCP , Google Ads Scripts, or PPC.io, generates GAQL behind the scenes. When you understand the structure, you understand what these tools can and can’t do. You ask better questions. You spot when something is wrong with the output.

I write zero GAQL manually. My AI tools write it for me. But knowing what it is changed how I work. It’s the difference between being a passenger and being the navigator.

How GAQL turns your plain English question into actionable data

GAQL vs SQL vs the Google Ads UI

If you’ve used SQL or even seen a database query before, GAQL will look familiar. It uses SELECT, FROM, WHERE, and ORDER BY, just like SQL. But there are important differences.

SQLGAQLGoogle Ads UI
Data sourceDatabase tablesGoogle Ads resourcesScreens and tabs
RelationshipsJOIN tables togetherImplicit via resource graphClick through one at a time
GroupingGROUP BY columnsSegments (automatic grouping)Column selectors
AccessDirect database connectionAPI with authenticationBrowser login
SpeedDepends on databaseSeconds per queryMinutes of clicking
ScopeOne database at a timeOne account per query (loop for multi)One account at a time

In SQL, you query tables and JOIN them together. In GAQL, you query “resources” like campaign, ad_group, keyword_view, or search_term_view. The relationships between resources are already defined by Google, so you don’t need JOINs. You just pick the resource and select the fields you want.

Instead of SQL’s GROUP BY, GAQL uses “segments.” Adding segments.date to your query automatically groups results by day. Adding segments.device groups by device type. It’s a cleaner model for ad data because Google has already figured out which groupings make sense.

The Google Ads UI gives you one screen at a time. Click campaigns, then click into an ad group, then switch to keywords, then change the date range, then add a column. GAQL gives you everything in one shot. And if you’ve ever written a Google Ads Script , you’ve already seen GAQL in action. The AdsApp.search() function takes a GAQL string as input.

The Anatomy of a GAQL Query

Let me break down a real query line by line. This one pulls campaign performance for the last 30 days:

SELECT
  campaign.name,
  campaign.status,
  metrics.cost_micros,
  metrics.clicks,
  metrics.conversions
FROM campaign
WHERE campaign.status = 'ENABLED'
  AND segments.date DURING LAST_30_DAYS
ORDER BY metrics.cost_micros DESC

Color-coded anatomy of a GAQL query showing SELECT, FROM, WHERE, and ORDER BY clauses

Here’s what each part does:

SELECT picks the fields you want back. campaign.name is the campaign name. metrics.cost_micros is spend (in micros, more on that in a second). metrics.clicks and metrics.conversions are exactly what they sound like. You can select as many fields as you want.

FROM specifies which resource to query. This example uses campaign, which gives you campaign-level data. Other common resources include ad_group, keyword_view, search_term_view, landing_page_view, and geographic_view. The resource determines what fields are available.

WHERE filters the results. campaign.status = 'ENABLED' removes paused and removed campaigns. segments.date DURING LAST_30_DAYS sets the date range. You can chain multiple filters with AND.

ORDER BY sorts the output. metrics.cost_micros DESC puts the highest-spending campaigns first. Without this, results come back in no particular order.

Two optional clauses you’ll also see:

LIMIT caps the number of rows returned. LIMIT 100 gives you the top 100 results. Useful when you’re working with large accounts.

PARAMETERS sits outside the main query and controls things like whether to include drafts or return zero-impression rows. Most queries don’t need it.

One thing that trips up every new user: metrics.cost_micros returns spend in micros, which means you need to divide by 1,000,000 to get actual dollars. So if a query returns 96810000, that’s $96.81. Every AI tool handles this conversion automatically, but it’s worth knowing so you’re not confused when you see raw numbers.

10 GAQL Queries Every PPC Manager Should Know

This is the practical core of the article. Each query answers a real question you face as a PPC manager. I’ve included the full GAQL for the four most important ones and condensed versions for the rest.

Overview of 10 essential GAQL queries for PPC managers

1. “Where am I wasting money?”

This is the query I run most often. It pulls every search term that triggered your ads, sorted by spend:

SELECT
  campaign.name,
  ad_group.name,
  search_term_view.search_term,
  metrics.cost_micros,
  metrics.conversions,
  metrics.clicks,
  metrics.impressions
FROM search_term_view
WHERE campaign.status = 'ENABLED'
  AND segments.date DURING LAST_90_DAYS
  AND metrics.clicks >= 1
ORDER BY metrics.cost_micros DESC
LIMIT 1000

The output shows you exactly which search terms are eating budget with nothing to show for it. When I ran this on a client account, I found “scrape linkedin” had burned $96.81 across 33 clicks with zero conversions. Three variations of that same irrelevant term added up to over $200 wasted. These are things you’d miss clicking through the UI, but the API surfaces them in seconds.

I feed results like this into Claude and ask it to cluster the waste into themes and suggest negative keywords. The whole process takes two minutes instead of an hour.

2. “Which keywords have bad quality scores?”

Quality scores are buried in the Google Ads interface. This query pulls all three components for every keyword at once:

SELECT
  campaign.name,
  ad_group.name,
  ad_group_criterion.keyword.text,
  ad_group_criterion.quality_info.quality_score,
  ad_group_criterion.quality_info.creative_quality_score,
  ad_group_criterion.quality_info.post_click_quality_score,
  ad_group_criterion.quality_info.search_predicted_ctr,
  metrics.cost_micros,
  metrics.conversions
FROM keyword_view
WHERE ad_group_criterion.status = 'ENABLED'
  AND campaign.status = 'ENABLED'
  AND segments.date DURING LAST_90_DAYS
  AND metrics.impressions > 50
ORDER BY metrics.cost_micros DESC
LIMIT 500

This tells you exactly which keywords have a landing page problem versus an ad relevance problem versus a CTR problem. “Your quality scores are low” is useless feedback. “These 12 keywords have below-average landing page experience and they’re costing you $4,200/month” is actionable.

3. “Am I losing impression share?”

Three metrics tell the whole visibility story. This query pulls them at the campaign level:

SELECT
  campaign.name,
  metrics.search_impression_share,
  metrics.search_budget_lost_impression_share,
  metrics.search_rank_lost_impression_share,
  metrics.cost_micros,
  metrics.clicks,
  metrics.conversions
FROM campaign
WHERE campaign.status = 'ENABLED'
  AND segments.date DURING LAST_30_DAYS
  AND campaign.advertising_channel_type = 'SEARCH'
ORDER BY metrics.cost_micros DESC

If search_budget_lost_impression_share is high, you’re capping your own growth by running out of daily budget. If search_rank_lost_impression_share is high, your ad rank needs work, either through better quality scores or higher bids. I pull these across all accounts every Monday morning. Patterns jump out immediately.

4. “What’s performing across all my accounts?”

If you manage multiple accounts through an MCC (manager account), this query lists every child account:

SELECT
  customer_client.id,
  customer_client.descriptive_name,
  customer_client.status
FROM customer_client
WHERE customer_client.status = 'ENABLED'
  AND customer_client.manager = false

Note: this query runs against your MCC, not a child account. It returns the list of accounts. You then loop through each account ID to pull individual metrics. One connection, full portfolio visibility. It replaces that 45-minute Monday morning ritual of logging into each account individually.

5. “Which landing pages get traffic?”

Condensed: query landing_page_view with landing_page_view.unexpanded_final_url, metrics.clicks, metrics.cost_micros, and metrics.conversions. Filter for pages with at least 10 clicks in the last 90 days. Sort by clicks descending.

I pair this with browser automation. The API tells me which pages get traffic. Then I use Playwright to visit each page, screenshot it, and check for message match with the ad copy. That workflow caught a client whose Scotland traffic was landing on the homepage instead of a dedicated location page. Nobody had noticed for months.

6. “How are my RSA headlines performing?”

Condensed: query ad_group_ad_asset_view with asset.text_asset.text, ad_group_ad_asset_view.performance_label, and ad_group_ad_asset_view.field_type. Filter for HEADLINE field type and enabled campaigns. This shows you which individual headlines Google has labeled as “BEST,” “GOOD,” “LOW,” or “LEARNING.”

Most advertisers never check individual asset performance. This query reveals which headlines are actually pulling their weight and which are dead weight.

7. “What devices convert best?”

Condensed: query campaign and add segments.device to your SELECT. Pull metrics.clicks, metrics.conversions, and metrics.cost_micros. This breaks performance into MOBILE, DESKTOP, TABLET, and CONNECTED_TV.

I’ve seen accounts where mobile had 3x the clicks but half the conversion rate. That single insight led to a bid adjustment that saved 22% of spend within a week.

8. “Where are conversions coming from geographically?”

Condensed: query geographic_view with geographic_view.country_criterion_id, metrics.conversions, metrics.cost_micros, and metrics.clicks. Sort by conversions descending. For more granular data, use geographic_view.resource_name to get city-level breakdowns.

Geographic data is one of the most underused dimensions in Google Ads. I’ve found clients spending heavily in regions where they don’t even operate.

9. “What changed in my account?”

Condensed: query change_event with change_event.change_date_time, change_event.change_resource_type, change_event.client_type, and change_event.user_email. Filter by date range. This shows every change made to the account, including who made it and when.

This is incredibly useful for audits. When a client says “performance dropped last Tuesday,” you pull the change log and see exactly what happened. No guessing.

10. “How is PMax spending across channels?”

This one is newer. Starting with API v23, you can break down Performance Max campaigns by network:

SELECT
  campaign.name,
  segments.ad_network_type,
  metrics.cost_micros,
  metrics.conversions,
  metrics.clicks,
  metrics.impressions
FROM campaign
WHERE campaign.advertising_channel_type = 'PERFORMANCE_MAX'
  AND segments.date DURING LAST_30_DAYS
  AND metrics.impressions > 0
ORDER BY metrics.cost_micros DESC

The segments.ad_network_type field splits PMax spend into SEARCH, YOUTUBE_WATCH, CONTENT (Display), GMAIL, CROSS_NETWORK, and MIXED. Before v23, this was a black box. Now you can see exactly how much of your PMax budget is going to Search versus YouTube versus Display. This is the kind of transparency PPC managers have been asking for.

Copy these queries

You don’t need to memorize any of this. Copy a query, paste it into Claude or your Google Ads Script, and adjust the filters for your account. AI handles the rest. For a full library of ready-to-use prompts, grab our free collection .

The Google Ads Query Builder

Google has a visual tool that builds GAQL queries for you. It lives at developers.google.com/google-ads/api/fields/v19/overview_query_builder (update the version number in the URL for the latest API version).

Here’s how it works. You select a resource from a dropdown (like campaign or search_term_view). Then you check the boxes for the fields you want. Add filters. Pick a sort order. The tool generates the complete GAQL query on the right side of the screen.

I still use this when I’m exploring a resource I haven’t queried before. There are 181 resources in the API, and each one has dozens of available fields. The query builder shows you exactly which fields are compatible with each resource and which segments you can use. It’s faster than reading documentation.

The tool also validates your query. If you try to combine incompatible fields or use a segment that doesn’t work with your selected resource, it tells you before you waste time running a broken query.

One limitation: the query builder doesn’t run queries. It just generates the GAQL string. You still need to run it through one of the tools covered in the next section.

Where GAQL Actually Runs

Nobody runs raw GAQL. It’s always wrapped in a tool that handles authentication, sends the query to the API, and formats the results. Here are the four places you’ll encounter it.

Architecture flow showing how your question becomes GAQL, hits the API, and returns as an insight

Google Ads MCP. The MCP server exposes a search tool that accepts GAQL as input. When you ask Claude “show me campaigns with high CPA,” Claude generates the GAQL, passes it to the MCP’s search tool, and formats the results as a readable table. You never see the query unless you ask to.

Claude Code. Claude Code takes it further. It writes Python scripts that initialize a Google Ads API client, run GAQL queries, process the results, and present analysis. It can chain multiple queries together, pull data from different resources, and cross-reference the results. If you ask “find search terms that are wasting money and suggest negative keywords,” Claude writes two or three GAQL queries, runs them, analyzes the output, and gives you a recommendation.

Google Ads Scripts. If you’ve written or used a Google Ads Script , you’ve used GAQL. The AdsApp.search(gaqlQuery) function takes a GAQL string and returns results. Every script that pulls reporting data uses this under the hood.

PPC.io agents. The 12 agents we’re building at PPC.io each generate GAQL queries tailored to their specific job. The wasted spend agent queries search_term_view. The quality score agent queries keyword_view. The impression share agent queries campaign with IS metrics. You interact with the agent in plain English. GAQL happens behind the scenes.

When I ask Claude “show me wasted spend,” it writes a GAQL query, runs it against the API, and gives me back English. You don’t need to learn GAQL. You need to understand what it is. That understanding lets you ask better questions and recognize when the output doesn’t look right.

We’re seeing a world where agents, not just humans, are becoming the primary consumers of our API.

–Cory Liseno , Google Developer Relations

Common GAQL Gotchas

After running thousands of GAQL queries across 100+ accounts, these are the things that trip people up the most.

cost_micros is not dollars. Every cost field in GAQL returns values in micros. Divide by 1,000,000 to get actual currency. A value of 96810000 equals $96.81. Every AI tool handles this conversion, but if you’re reading raw API output or debugging a script, this is usually the first confusion.

Date filtering has two modes. For common ranges, use the DURING keyword: DURING LAST_30_DAYS, DURING LAST_7_DAYS, DURING THIS_MONTH, DURING LAST_QUARTER. For custom date ranges, use BETWEEN:

WHERE segments.date BETWEEN '2026-01-01' AND '2026-03-31'

You can’t mix both in the same query. Pick one approach.

Not all fields work together. Some metrics are incompatible with certain segments. If you try to pull metrics.search_impression_share segmented by segments.hour, the API will reject it. The error message usually tells you which fields conflict. The Query Builder tool catches these before you run the query.

Manager accounts can’t return metrics directly. If you query an MCC for metrics.clicks, you’ll get an error: “Metrics cannot be requested for a manager account.” You need to query each child account individually. Use the customer_client resource on the MCC to get the list of accounts, then loop through them.

Rate limits exist but are generous. The Explorer access tier gives you 2,880 operations per day. That’s enough for most agencies. I run audits across multiple accounts daily and rarely hit it. If you need more, the Basic tier gives you 15,000 daily operations (requires a brief application).

GotchaWhat HappensFix
cost_micros confusionNumbers look absurdly largeDivide by 1,000,000
Wrong date syntaxQuery failsUse DURING or BETWEEN, not both
Incompatible segmentsAPI errorCheck Query Builder first
Querying MCC for metrics”Metrics cannot be requested”Query child accounts instead
Rate limit hit429 errorSpace requests or upgrade tier

Pro tip

When debugging a failed GAQL query, paste it into the Google Ads Query Builder. The builder validates field compatibility instantly and shows you exactly which fields work with your chosen resource.

You Don’t Need to Memorize GAQL

That’s what AI is for. The 10 queries in this article cover the questions PPC managers ask most often. But the real point isn’t the queries themselves.

Understanding GAQL means you understand the building blocks. You know that when an AI tool says it “analyzed your search terms,” it queried search_term_view. You know that when it shows you “impression share data,” it pulled specific metrics from the campaign resource. You know that when it segments by device or geography, it added a segment to the query.

That understanding makes you a better collaborator with your AI tools. You ask sharper questions. You catch errors faster. You know what’s possible and what isn’t.

Three things to do next:

  1. Try a query. Copy the wasted spend query from this article, paste it into Claude or a Google Ads Script, and run it against your account. Seeing real data come back is the best way to internalize how this works.

  2. Explore the Query Builder. Open Google’s GAQL Query Builder , pick a resource you’re curious about, and browse the available fields. You’ll discover data you didn’t know existed.

  3. Read the related guides. This article is part of a series on AI and the Google Ads API:

Build AI-powered PPC tools with us

At PPC.io, we’re building 12 AI agents that generate GAQL under the hood to answer real PPC questions. No code. No query writing. Just plain English in, actionable insights out. Join the waitlist .

Stewart Dunlop

Stewart

CEO