GAQL Queries: The Complete Reference
A comprehensive reference for Google Ads Query Language (GAQL). Covers syntax, common queries, filtering, sorting, date ranges, and how Xylo abstracts GAQL away.
What Is GAQL?
GAQL (Google Ads Query Language) is a SQL-like query language used to retrieve data from the Google Ads API. Unlike most REST APIs where you specify fields as query parameters, Google Ads requires you to write structured queries that define the resource, fields, filters, and sort order.
If you have used SQL, GAQL will look familiar. If you have not, it adds a significant learning curve to Google Ads API integration.
GAQL Syntax
The basic structure:
SELECT field1, field2, field3
FROM resource
WHERE condition1 AND condition2
ORDER BY field1 DESC
LIMIT 100
Clauses
| Clause | Required | Purpose |
|---|---|---|
SELECT |
Yes | Fields to return |
FROM |
Yes | Resource type (campaign, ad_group, etc.) |
WHERE |
No | Filter conditions |
ORDER BY |
No | Sort results |
LIMIT |
No | Maximum rows returned |
PARAMETERS |
No | Additional options (like include_drafts) |
Resources
GAQL queries operate on specific resources. The most common:
| Resource | Description |
|---|---|
campaign |
Campaign-level data |
ad_group |
Ad group-level data |
ad_group_ad |
Individual ad data |
keyword_view |
Keyword performance |
search_term_view |
Search term report |
campaign_budget |
Budget configuration |
customer |
Account-level data |
geographic_view |
Geographic performance |
age_range_view |
Age demographic data |
gender_view |
Gender demographic data |
Common Queries
Campaign Performance
SELECT
campaign.id,
campaign.name,
campaign.status,
campaign.advertising_channel_type,
campaign_budget.amount_micros,
metrics.impressions,
metrics.clicks,
metrics.cost_micros,
metrics.conversions,
metrics.cost_per_conversion,
metrics.click_through_rate,
metrics.average_cpc
FROM campaign
WHERE campaign.status != 'REMOVED'
AND segments.date DURING LAST_30_DAYS
ORDER BY metrics.cost_micros DESC
Note: cost_micros and amount_micros are in micros (1,000,000 = $1.00). You must divide by 1,000,000 to get dollars.
Ad Group Performance
SELECT
ad_group.id,
ad_group.name,
ad_group.status,
ad_group.type,
campaign.name,
metrics.impressions,
metrics.clicks,
metrics.cost_micros,
metrics.conversions,
metrics.average_cpc
FROM ad_group
WHERE ad_group.status = 'ENABLED'
AND campaign.status = 'ENABLED'
AND segments.date DURING LAST_7_DAYS
ORDER BY metrics.conversions DESC
LIMIT 50
Keyword Performance
SELECT
ad_group_criterion.keyword.text,
ad_group_criterion.keyword.match_type,
ad_group.name,
campaign.name,
metrics.impressions,
metrics.clicks,
metrics.cost_micros,
metrics.conversions,
metrics.search_impression_share,
metrics.quality_score
FROM keyword_view
WHERE segments.date DURING LAST_7_DAYS
AND ad_group_criterion.status = 'ENABLED'
ORDER BY metrics.cost_micros DESC
LIMIT 100
Search Terms Report
See what actual search queries triggered your ads:
SELECT
search_term_view.search_term,
search_term_view.status,
campaign.name,
ad_group.name,
metrics.impressions,
metrics.clicks,
metrics.cost_micros,
metrics.conversions
FROM search_term_view
WHERE segments.date DURING LAST_7_DAYS
AND metrics.impressions > 10
ORDER BY metrics.impressions DESC
LIMIT 200
Daily Performance Breakdown
SELECT
segments.date,
campaign.name,
metrics.impressions,
metrics.clicks,
metrics.cost_micros,
metrics.conversions
FROM campaign
WHERE segments.date BETWEEN '2026-03-01' AND '2026-03-31'
AND campaign.status != 'REMOVED'
ORDER BY segments.date DESC
Geographic Performance
SELECT
geographic_view.country_criterion_id,
geographic_view.location_type,
campaign.name,
metrics.impressions,
metrics.clicks,
metrics.cost_micros,
metrics.conversions
FROM geographic_view
WHERE segments.date DURING LAST_30_DAYS
ORDER BY metrics.cost_micros DESC
LIMIT 50
Filtering with WHERE
Comparison Operators
WHERE metrics.impressions > 1000
WHERE campaign.status = 'ENABLED'
WHERE campaign.status != 'REMOVED'
WHERE metrics.cost_micros >= 1000000 -- at least $1
WHERE campaign.name LIKE '%Brand%'
WHERE campaign.name NOT LIKE '%Test%'
Date Filtering
GAQL supports predefined date ranges and custom ranges:
-- Predefined ranges
WHERE segments.date DURING LAST_7_DAYS
WHERE segments.date DURING LAST_30_DAYS
WHERE segments.date DURING THIS_MONTH
WHERE segments.date DURING LAST_MONTH
WHERE segments.date DURING THIS_QUARTER
WHERE segments.date DURING LAST_YEAR
-- Custom range
WHERE segments.date BETWEEN '2026-01-01' AND '2026-03-31'
-- Single date
WHERE segments.date = '2026-03-15'
Enum Filtering
Many fields use enum values that must be referenced exactly:
-- Campaign status
WHERE campaign.status IN ('ENABLED', 'PAUSED')
-- Campaign type
WHERE campaign.advertising_channel_type = 'SEARCH'
-- Keyword match type
WHERE ad_group_criterion.keyword.match_type = 'EXACT'
Combining Conditions
WHERE campaign.status = 'ENABLED'
AND metrics.impressions > 100
AND segments.date DURING LAST_7_DAYS
AND campaign.advertising_channel_type IN ('SEARCH', 'SHOPPING')
GAQL supports AND but does not support OR at the top level. To achieve OR-like behavior, you need to run multiple queries.
Segments
Segments add dimensional breakdowns to your data. When you include a segment in the SELECT clause, the data is broken down by that dimension:
-- Daily breakdown
SELECT
segments.date,
campaign.name,
metrics.cost_micros,
metrics.conversions
FROM campaign
WHERE segments.date DURING LAST_7_DAYS
-- Device breakdown
SELECT
segments.device,
campaign.name,
metrics.cost_micros,
metrics.conversions
FROM campaign
WHERE segments.date DURING LAST_7_DAYS
-- Hour of day breakdown
SELECT
segments.hour,
campaign.name,
metrics.impressions,
metrics.clicks
FROM campaign
WHERE segments.date = '2026-03-15'
Segment Compatibility
Not all segments work with all resources. Mixing incompatible segments causes an error. Common compatible combinations:
| Resource | Compatible Segments |
|---|---|
| campaign | date, device, ad_network_type, click_type |
| ad_group | date, device, ad_network_type |
| keyword_view | date, device |
| search_term_view | date |
| geographic_view | date |
GAQL Gotchas
1. Micros Everywhere
All monetary values are in micros. This is easy to forget:
metrics.cost_micros = 15234560 → $15.23
metrics.average_cpc = 234500 → $0.23
campaign_budget.amount_micros = 50000000 → $50.00
2. No Joins
GAQL does not support JOIN operations. You cannot combine data from different resources in a single query. To correlate campaign and ad group data, run separate queries and join in your application code.
3. Field Compatibility
Not every field combination is valid. You cannot select campaign.name from customer resource, for example. Google's documentation lists compatible fields for each resource.
4. Rate Limits
Each GAQL query counts as one API operation. With Basic access, you get 15,000 operations per day. Complex queries that return large result sets may consume additional quota.
5. Date Segment Requirement
If you use segments.date in the WHERE clause, you must also include it in the SELECT clause. Omitting it causes an error.
How Xylo Abstracts GAQL Away
If you are using Xylo, you never need to write GAQL. Xylo translates standard REST query parameters into GAQL internally:
| What You Want | GAQL | Xylo |
|---|---|---|
| Last 7 days of campaign data | Write the full SELECT/FROM/WHERE query | ?date_preset=last_7d |
| Only active campaigns | WHERE campaign.status = 'ENABLED' |
?status=active |
| Sort by spend | ORDER BY metrics.cost_micros DESC |
?sort=spend&order=desc |
| Limit results | LIMIT 25 |
?limit=25 |
Example -- fetching campaign performance:
# GAQL approach (raw API)
# 1. Set up OAuth, developer token, client library
# 2. Write GAQL query
# 3. Parse micros, enum values, nested objects
# Xylo approach
curl "https://api.xyloapi.dev/v1/campaigns?date_preset=last_7d&status=active" \
-H "x-api-key: xylo_live_abc123" \
-H "x-ad-account: customers/1234567890"
Both return the same data. Xylo converts micros to dollars, maps enum values to readable strings, and returns a normalized JSON structure identical to what you get from Meta and TikTok campaigns.
When to Use GAQL Directly
GAQL is worth learning if:
- You need custom segmentation beyond what Xylo exposes (e.g., hour-of-day breakdowns)
- You are building a Google Ads-specific product that needs maximum flexibility
- You need search term reports or keyword-level data with specific filters
- You are debugging performance issues and need raw data access
Getting Started
If you want to skip GAQL and use a clean REST interface:
- Sign up for Xylo and connect your Google Ads account.
- Use standard query parameters instead of GAQL syntax.
- Get normalized responses with dollars (not micros) and readable status values.
If you need the raw Google Ads API, start with our Google Ads API getting started guide for authentication setup.
For cross-platform reporting that combines Google and Meta data, read our cross-platform reporting guide. Check the API documentation for the complete Xylo endpoint reference.
Ready to simplify your ads API integration?
Get started with Xylo in minutes. One API key for every ad platform.