Connect Google Ads to Claude Code: three ways, and what each one is for
The Google Ads UI is built for editing campaigns, not for answering questions — and Claude Code, out of the box, can't see your account at all. The fix is one OAuth round-trip: tablebi connect google_ads pipes the account into a data backend your agent queries with read-only SQL. From then on, "rank my campaigns by CPA" or "which campaigns spent money and converted nothing?" are one-line questions in the terminal where you already work — no tab-switching, no CSV exports, no pivot tables. This is the practical guide to connecting Google Ads to Claude Code: the three queries that replace the export ritual, and how to pin the result as a weekly report that refreshes itself.
The report you want is never one screen away
Everyone who runs Google Ads knows the ritual. The question is simple — "what's actually converting, and what's just spending?" — but the path is not: open the Campaigns view, adjust the date range, add a segment, realize the column you need lives one level down, drill into each campaign for its ad groups, download a CSV per view, rebuild the picture in a spreadsheet. Next week: the same ritual, from scratch. The UI is a competent editor; as a question-answering surface it makes you assemble every answer by hand, one drill-down at a time.
The official escape hatch is the Google Ads API, and it's a genuine project: a Google Cloud project approved for Google Ads API access (developer tokens were sunset on September 9, 2026), an OAuth application, GAQL (a query language you'll use nowhere else) and the account-hierarchy plumbing around it. Nobody stands all of that up to answer one weekly question. So the data stays trapped behind the UI — until an agent with a data backend inverts the deal: sync the account once, and every future question is just SQL.
Three ways to connect Google Ads to Claude, and what each one is for
"Connect Google Ads to Claude" now describes three different products, and they answer different needs. Google publishes an official Google Ads MCP server that is read-only. Data-connector vendors sell hosted Claude connectors that can also change campaigns. A synced data backend — the route this page sets up — keeps a copy of the account that your agent queries in SQL, next to your other channels.
| Route | What the agent reads | Can it change campaigns? | What you set up | Price |
|---|---|---|---|---|
| Google's official Google Ads MCP server | Live Google Ads API results through its search tool (Google Ads Query Language), plus the list of accounts you can access | No — read-only | Your own Google Ads API access (OAuth credentials from a Google Cloud project approved for the API); the server runs on your machine and works with Claude Code | Free, open source (Apache 2.0) |
| Supermetrics' Claude connector | Google Ads reporting data through a connector listed in Claude's directory | Yes — creates campaigns (paused for review), pauses, changes bids, adds negative keywords; changes are logged in Campaign History | Click Connect in Claude's directory, then authorize Google Ads | 14-day free trial, then a paid plan |
| Windsor.ai's Claude connector | Google Ads fields through Windsor.ai's hosted MCP connector | Yes — pauses or enables campaigns, sets budgets, switches bidding strategies, pushes keywords and negatives | Pick Google Ads at onboard.windsor.ai, then add the Windsor connector in Claude | Free and paid plans |
| TableBI (this page) | A synced copy of the account in read-only SQL, with the same definitions of cost, clicks and conversions as GA4, Search Console and Meta Ads (beta) | No — read-only by design | One OAuth: tablebi connect google_ads | See pricing |
Sources, read September 26, 2026: googleads/google-ads-mcp (tools, credentials, license), Supermetrics' Google Ads to Claude page, Windsor.ai's setup guide.
Pick by the job. An agent that should operate the account needs a connector that writes — and its change log switched on. Occasional questions from someone who already holds Google Ads API access are what Google's free MCP server is for. A question that comes back every week and crosses channels — Google Ads spend against Meta, paid clicks against Search Console — is what a synced backend is built for, because the numbers are stored once under shared definitions instead of being re-fetched and re-reconciled in every conversation. The rest of this page walks through that third route.
Connect Google Ads to Claude Code once
npm i -g @tablebi/cli
tablebi login
tablebi install
# browser opens for OAuth; the account starts syncing
tablebi connect google_ads
tablebi install plants a skill in ~/.claude/skills, so Claude Code recognizes these commands from then on — "how did Google Ads do last week?" in plain English is enough to trigger the right queries. (The broader multi-source setup — Search Console, GA4, Meta — is walked through in Claude Code for marketing.)
Synced data lands at two altitudes:
facts— the cross-channel table where Google Ads rows share one set of definitions with every other connected source. Dimensions:date,platform,account,campaign(the live connectors sync at campaign level, so that is the finest cut;ad_groupfills only from a CSV export that has an ad group or ad set column); measures:clicks,impressions,cost,conversions,conversion_value. Ranking and comparison queries live here.google_ads_raw— the platform-faithful table, fields as Google reports them, for when the unified view isn't granular enough.
Worth saying explicitly: this is a read-only path. tablebi ask executes read-only SQL over synced data; nothing your agent does here can touch bids, budgets or campaign settings in Google Ads itself.
Two operational notes. Very large accounts sync in segments, streamed — you're not waiting on one giant full-history load. And each new session starts with tablebi context --json, a single call that rehydrates the agent with definitions, connected sources and how fresh each one is.
Three queries that replace the export ritual
1. The campaign leaderboard: spend, conversions, CPA
tablebi ask "SELECT campaign, SUM(cost) AS spend, SUM(conversions) AS conv,
cpa(SUM(cost), SUM(conversions)) AS cpa
FROM facts
WHERE platform = 'google_ads'
AND date >= (SELECT MAX(date) FROM facts) - 28
GROUP BY campaign ORDER BY spend DESC LIMIT 20"
Two idioms to notice. cpa(…) is a definition macro — the arithmetic is frozen in the engine, alongside roas, ctr, cpc, cpm and cvr, so the agent never re-derives cost-per-anything wrong at 11pm. And the date window anchors to (SELECT MAX(date) FROM facts) - 28 — the newest synced day, not the wall clock; the query layer rejects current_date by design, so a window can never silently include days that haven't synced yet.
2. Campaigns burning money with zero conversions
# the cross-campaign scan that's painful to assemble in the UI tablebi ask "SELECT campaign, SUM(cost) AS spend, SUM(clicks) AS clicks FROM facts WHERE platform = 'google_ads' AND date >= (SELECT MAX(date) FROM facts) - 28 GROUP BY campaign HAVING SUM(cost) > 0 AND SUM(conversions) = 0 ORDER BY spend DESC"
This is the query that pays for the setup. In the web UI it means visiting every campaign or exporting everything; here it's one pass over the whole account. The follow-ups are exactly what an agent is good at: "show me its daily spend", "when did its CPC start climbing?", "how does it compare with the same campaign last month?" Each is another one-liner, not another export. The live connector syncs at campaign level, so ad group and keyword detail is not in this table; export the Ad groups report from Google Ads and load it with tablebi connect csv --platform google_ads when you need that grain.
3. Google versus Meta, one definition of ROAS
tablebi ask "SELECT platform, SUM(cost) AS spend,
roas(SUM(conversion_value), SUM(cost)) AS roas,
cpa(SUM(cost), SUM(conversions)) AS cpa
FROM facts
WHERE platform IN ('google_ads', 'meta_ads')
AND date >= (SELECT MAX(date) FROM facts) - 28
GROUP BY platform ORDER BY spend DESC"
This is the point of the facts altitude: platform is just another dimension, and cost and conversion value mean the same thing on every row, so a cross-network ROAS comparison is a GROUP BY rather than a data-engineering project. Treat the result as directional — Google and Meta attribute conversions differently, and the trust block that ships with every answer exists to surface exactly this kind of caveat, alongside per-source freshness and lineage, so a two-row table can't hide it. The Meta side of this workflow has its own guide: Meta Ads reporting.
These three are the skeleton, not the ceiling. The same handful of columns answers "which country converts cheapest?" (group by country), "is CTR decaying on my top spender?" (ctr(SUM(clicks), SUM(impressions)) over date) or "how does brand compare to non-brand?" (a campaign-name filter). The pattern never changes: a question in plain English, one deterministic query, an answer with its trust block attached — and no browser tab anywhere in the loop.
Pin it: a Google Ads weekly that refreshes itself
Once the queries above have earned a permanent place, stop re-running them and pin them:
tablebi pin --title "Google Ads weekly" \ --widget "Daily spend (28d)::line=SELECT date, SUM(cost) AS spend FROM facts WHERE platform = 'google_ads' AND date >= (SELECT MAX(date) FROM facts) - 28 GROUP BY date ORDER BY date" \ --widget "Campaign leaderboard=SELECT campaign, SUM(cost) AS spend, SUM(conversions) AS conv, cpa(SUM(cost), SUM(conversions)) AS cpa FROM facts WHERE platform = 'google_ads' AND date >= (SELECT MAX(date) FROM facts) - 28 GROUP BY campaign ORDER BY spend DESC LIMIT 10" ✓ published → https://dk.tablebi.com/d/dsh_… (public, read-only, self-refreshing)
Widgets tagged ::line render as line charts; the rest render as tables. The URL is public, read-only and self-refreshing — syncs run on a schedule and are also triggered when someone opens the page, so the Monday check-in shows Monday's numbers with no Monday exports. Hand it to the founder, the client or your own future self, and keep iterating on the queries behind it whenever a question comes back. For the full query-side repertoire beyond ads — raw-table forensics, freshness details, more macro patterns — see Claude Code analytics. The same three-way comparison for the other sources: Meta Ads, Google Analytics 4 and Search Console.
FAQ
Can Claude Code access Google Ads directly?
No — Claude Code has no built-in Google Ads connector, and the official API route requires a Google Cloud project approved for Google Ads API access, an OAuth application and GAQL. TableBI bridges the gap: one browser OAuth via tablebi connect google_ads, and the agent gets read-only SQL over the synced account.
Is there an official Google Ads MCP server?
Yes. Google publishes googleads/google-ads-mcp, an open-source MCP server under the Apache 2.0 license that works with Claude Code. It is read-only: it runs Google Ads Query Language searches and lists the accounts you can access, and it needs your own Google Ads API access (OAuth credentials from a Google Cloud project approved for the API).
Can the agent change my campaigns or budgets?
Not through TableBI. tablebi ask executes read-only SQL over synced data, and nothing in this workflow writes back to Google Ads — bid and budget changes stay in Google Ads, made by a human. If you want Claude to make changes, that is what the vendor connectors that write are for.
How fresh is the synced Google Ads data?
Every answer ships with a trust block showing exactly which date each source is synced through. Pinned dashboards refresh themselves: syncs run on a schedule and are also triggered when someone opens the page.
Does this work on very large Google Ads accounts?
Yes. Google Ads syncs are segmented and streamed rather than loaded as one giant window, so account size doesn't change the workflow.
Give your Claude Code a data backend in five minutes.
npm i -g @tablebi/cli && tablebi install