"Query any Google Ads account via GAQL. Use when the user asks about Google Ads campaigns, conversions, keywords, ad performance, or bidding. Triggered by: Google Ads, campaign, conversion, PPC, CPC, keyword, click, impression, ROAS, CPA."
Resources
3Install
npx skillscat add aivokone/ak-skills/google-ads-query Install via the SkillsCat registry.
Google Ads Query
Setup
Check prerequisites before querying:
- Virtual environment:
.claude/skills/google-ads-query/scripts/.venv/must exist - Config file:
google-ads.yamlmust be findable (see Config section)
First-time setup
# 1. Install dependencies
bash .claude/skills/google-ads-query/scripts/setup.sh
# 2. Create google-ads.yaml in project root or ~/.config/google-ads-query/
# (see Config section for template)
# 3. Test
gads "SELECT customer.id FROM customer"Config
The script searches for google-ads.yaml in this order:
--configCLI parameter (explicit path)./google-ads.yaml(project root)~/.config/google-ads-query/google-ads.yaml(user-level)
Template (google-ads.yaml):
# Service account authentication:
developer_token: "YOUR_TOKEN"
json_key_file_path: "/path/to/service-account.json"
customer_id: "YOUR_CUSTOMER_ID"
use_proto_plus: true
# OR OAuth2 authentication:
# developer_token: "YOUR_TOKEN"
# client_id: "YOUR_CLIENT_ID.apps.googleusercontent.com"
# client_secret: "YOUR_SECRET"
# refresh_token: "1//YOUR_REFRESH_TOKEN"
# customer_id: "YOUR_CUSTOMER_ID"
# use_proto_plus: true
# Optional (manager accounts):
# login_customer_id: "MANAGER_CUSTOMER_ID"Usage
Use the gads alias for queries:
alias gads='.claude/skills/google-ads-query/scripts/.venv/bin/python3 .claude/skills/google-ads-query/scripts/query.py'# Basic query (customer ID from config)
gads "SELECT campaign.name, metrics.clicks FROM campaign"
# Override customer ID
gads --customer-id 9876543210 "SELECT ..."
# Explicit config path
gads --config /path/to/google-ads.yaml "SELECT ..."Output: JSON array to stdout. Enums returned as names (e.g., "ENABLED", not 2).
Errors: JSON to stderr + exit code 1.
Field Notes
These fields may cause issues depending on API version:
campaign.start_date,campaign.end_date— may be unrecognizedconversion_action.type— can return cryptic errorsconversion_action.tag_snippets— repeated composite, may fail in some versions
The script handles repeated fields (both scalar and composite) correctly via protobuf serialization. If a query fails, remove suspected fields one at a time to isolate the issue.
Query Patterns
Campaign overview
SELECT campaign.id, campaign.name, campaign.status,
campaign.advertising_channel_type, campaign.bidding_strategy_type,
metrics.impressions, metrics.clicks, metrics.cost_micros,
metrics.conversions, metrics.all_conversions
FROM campaign
WHERE campaign.status != 'REMOVED'Conversion actions (full list)
SELECT conversion_action.id, conversion_action.name,
conversion_action.status, conversion_action.category,
conversion_action.origin, conversion_action.counting_type,
conversion_action.include_in_conversions_metric,
conversion_action.primary_for_goal
FROM conversion_actionCampaign conversion goals
SELECT campaign.id, campaign.name,
campaign_conversion_goal.category, campaign_conversion_goal.origin,
campaign_conversion_goal.biddable
FROM campaign_conversion_goal
WHERE campaign.id = CAMPAIGN_IDConversion goal config (account vs campaign level)
SELECT campaign.id, campaign.name,
conversion_goal_campaign_config.goal_config_level
FROM conversion_goal_campaign_configMetrics with date range
SELECT campaign.name, metrics.impressions, metrics.clicks,
metrics.cost_micros, metrics.conversions, segments.date
FROM campaign
WHERE segments.date >= 'YYYY-MM-DD' AND segments.date <= 'YYYY-MM-DD'
AND campaign.status != 'REMOVED'Ad group details
SELECT ad_group.id, ad_group.name, ad_group.status,
ad_group.cpc_bid_micros, campaign.name
FROM ad_group
WHERE campaign.status != 'REMOVED'Keywords
SELECT ad_group_criterion.keyword.text,
ad_group_criterion.keyword.match_type,
ad_group_criterion.status, metrics.clicks,
metrics.impressions, metrics.cost_micros
FROM keyword_view
WHERE campaign.status != 'REMOVED'Search terms report
SELECT search_term_view.search_term, metrics.clicks,
metrics.impressions, metrics.cost_micros, metrics.conversions
FROM search_term_view
WHERE segments.date >= 'YYYY-MM-DD' AND segments.date <= 'YYYY-MM-DD'Enum Reference
The script returns enum values as human-readable names (e.g., "ENABLED", "MAXIMIZE_CONVERSIONS"), so you typically don't need to decode numeric codes. For raw numeric references, see references/enums.md.
Key enum values for GAQL WHERE clauses (these use string names):
| Field | WHERE value | Meaning |
|---|---|---|
| campaign.status | 'ENABLED' |
Active campaign |
| campaign.status | 'PAUSED' |
Paused campaign |
| campaign.status | 'REMOVED' |
Deleted campaign |
Conversion Tracking Audit
- Query customer settings — confirm
conversion_tracking_statusandauto_tagging_enabled - Query all
conversion_action— list actions, check status, primary_for_goal, include_in_conversions_metric - Query
campaign_conversion_goalfor the campaign — verify biddable goals match campaign objective - Query
conversion_goal_campaign_config— check if campaign uses campaign-level or account-level goals - If GA4-imported conversions: verify GA4 tag fires on target pages (recommend Google Tag Assistant)
- Check metrics: compare
metrics.conversions(primary only) vsmetrics.all_conversions(includes secondary)
Notes
metrics.cost_microsis in micros (divide by 1,000,000 for currency)- GAQL WHERE uses string enum values (
'REMOVED'), not numeric codes segments.daterequires both>=and<=bounds- Campaign-level goals override account-level defaults when
goal_config_level= CAMPAIGN