A Gemini CLI extension that gives you live Google Ads API access from your terminal. Ask questions about your campaigns, find wasted spend, audit accounts, get optimization recommendations — all through natural conversation.
Built from production learnings running an AI Google Ads agent at googleadsagent.ai — 28 custom API actions, 6 sub-agents, managing real Google Ads accounts via the Google Ads API v22.
# Check if you already have it
node --version
# If not, install via Homebrew (macOS)
brew install node
# Or download from https://nodejs.org (Windows/Linux/macOS)npm install -g @google/gemini-cli- Go to aistudio.google.com/apikey
- Click Create API Key
- Copy it, then save it:
mkdir -p ~/.gemini
echo 'GEMINI_API_KEY=your-key-here' > ~/.gemini/.envThe free tier gives you 60 requests/minute and 1,000/day — more than enough.
gemini extensions install https://github.com/itallstartedwithaidea/google-ads-gemini-extensionAs of v2.3, signing in is one command — the extension opens your browser, you pick any Google account with Google Ads access, and you're done. No copy-pasting session IDs, no OAuth Playground, no manual .env editing.
geminiThen in the CLI:
> /google-ads:login
What happens:
- Your default browser opens to Google's consent screen
- Pick any Google account that has Google Ads access
- Approve the one scope (
adwords) - The tab auto-closes — you're back in the terminal
- The extension prints
✅ Signed in as you@example.com — 123 accounts accessible
An opaque session ID is stored in your OS keychain (macOS Keychain / Windows Credential Manager / Linux libsecret) via keytar. If keychain isn't available, the extension falls back to a 0600-permission file that's gitignored. The Google refresh token never leaves googleadsagent.ai — it stays encrypted at-rest on the site and the CLI only ever sees the session handle.
Two independent lanes, both active at once:
| Lane | What it is | How to configure |
|---|---|---|
| Method 1 — Local API | Your static Google Ads API credentials in .env. One fixed identity. |
gemini extensions config google-ads-agent (see Getting Credentials) |
| Method 2 — Remote (browser sign-in) | Whatever Google email you just signed in with. Switchable at any time. | /google-ads:login |
You can have both, either, or neither. list_accounts automatically merges results from both lanes with deduplication.
Multi-identity: run /google-ads:login again with a different Google account to add another identity. Switch between them with zero re-auth:
> /google-ads:status # see all stored identities
> /google-ads:switch other@example.com # hop to another, no browser
> /google-ads:logout # revoke at Google and clear locally
That's it. The extension auto-loads every time. Just start asking questions:
> Show me my Google Ads accounts
> How are my campaigns performing this month?
> Which search terms are wasting money?
> Run an account health check on account 1234567890
> What's my ROAS if I spent $5,000 and made $18,000?
Once installed, type gemini to launch the interactive CLI. Here's what you can do:
> List my Google Ads accounts
> Show campaign performance for account 1234567890 for the last 30 days
> What keywords have low quality scores?
> Show me device performance breakdown — mobile vs desktop
> Compare this month vs last month
> What changes were made to my account recently?
> Run an account health check — flag anything critical
> Show me search terms with clicks but zero conversions
> Which campaigns are budget-limited?
> What's my impression share? How much traffic am I missing?
> Pause campaign 123456789 on account 1234567890
> Enable that campaign again
> Update the daily budget to $75 for that campaign
> Change the CPC bid to $2.50 on ad group 987654321
> Add negative keywords "free, cheap, diy" to campaign 123456789
> Create a responsive search ad for ad group 987654321
> Apply that recommendation Google suggested
> I spend $75/day, CPC is $1.80, conversion rate is 3.5% — project my month
> Calculate my ROAS: $5,000 spend, $18,500 revenue
> What's my CPA if I spent $3,000 on 42 conversions?
> I have 60% impression share with 10,000 impressions — what am I missing?
/google-ads:login # sign in with any Google account
/google-ads:status # show Method 1 + Method 2 auth state
/google-ads:switch other@example.com # hop to another stored identity
/google-ads:logout # revoke + clear the active identity
/google-ads:analyze "Brand Search last 30 days"
/google-ads:audit "full account, focus on wasted spend"
/google-ads:optimize "improve ROAS for ecommerce campaigns"
/theme google-ads # Dark theme with Google's color palette
/theme google-ads-light # Light theme matching Google Ads UI
This extension implements every feature type in the Gemini CLI extension spec:
| Feature | What's included |
|---|---|
| MCP Server | 26 tools — 15 read + 7 write + 4 auth, with live Google Ads API access |
| Commands | /google-ads:login, /google-ads:switch, /google-ads:status, /google-ads:logout, /google-ads:analyze, /google-ads:audit, /google-ads:optimize |
| Auth | Dual-lane: static .env API credentials and zero-setup browser OAuth via googleadsagent.ai for any Google account, switchable at runtime, opaque session stored in the OS keychain |
| Skills | google-ads-agent (PPC expertise + GAQL templates) and security-auditor (vulnerability scanning) |
| Context | GEMINI.md — persistent API reference loaded every session |
| Hooks | GAQL write-blocking + audit logging for every tool call |
| Policies | User confirmation required before any API call executes |
| Themes | google-ads (dark) and google-ads-light (light) |
| Settings | 7 settings — Method 1 API credentials (keychain) + Remote site URL/session |
These manage the Remote (browser-sign-in) lane. They never touch Method 1.
| Tool | Description |
|---|---|
remote_login |
Opens the browser at googleadsagent.ai's hosted OAuth flow, receives an opaque session, stores the identity (session ID in OS keychain), sets it active. No Cloud Console, no client IDs, no refresh tokens in the CLI. Works with any Google account that has Google Ads access. |
remote_switch |
Switch the active identity to a previously signed-in email. No browser, no re-auth — reuses the opaque session stored in your keychain. |
remote_status |
Shows both lanes side-by-side. Method 1 credential check (lists any missing env vars); Method 2 stored identities with active pointer, account counts, storage backend (keychain vs file). Never prints tokens. |
remote_logout |
Invalidates the opaque session at googleadsagent.ai, deletes the keychain entry, removes the identity from sessions.json. For legacy v2.3 identities that still carry a refresh token, also revokes at Google. Defaults to the active identity if no email is given. |
These tools query your Google Ads accounts:
| Tool | Description |
|---|---|
list_accounts |
List all accounts under your MCC |
campaign_performance |
Spend, conversions, clicks, impressions, CTR, CPC, CPA |
search_terms_report |
Search terms analysis with wasted spend detection |
keyword_quality |
Quality scores with component breakdowns (creative, landing page, expected CTR) |
ad_performance |
Ad creative performance and RSA strength scores |
budget_analysis |
Budget allocation, efficiency, and limited campaign detection |
geo_performance |
Performance breakdown by geographic location |
device_performance |
Performance by device — mobile, desktop, tablet |
impression_share |
Impression share and lost opportunity from budget or rank |
change_history |
Recent account changes — who changed what and when |
list_recommendations |
Google's optimization recommendations with estimated impact |
compare_performance |
Period-over-period comparison with deltas (e.g., this month vs last) |
calculate |
Google Ads math — budget projections, ROAS, CPA, conversion forecasts |
run_gaql |
Custom GAQL queries (read-only — all write operations blocked) |
account_health |
Quick health check with automatic anomaly detection |
These tools make changes to your Google Ads account. Every write tool requires your explicit confirmation before executing.
| Tool | Description |
|---|---|
pause_campaign |
Pause an active campaign (shows current status first) |
enable_campaign |
Re-enable a paused campaign |
update_bid |
Change the CPC bid for an ad group (shows before/after) |
update_budget |
Change a campaign's daily budget (shows before/after + monthly estimate) |
add_negative_keywords |
Add negative keywords to block unwanted search terms (up to 50 at a time) |
create_responsive_search_ad |
Build a new RSA with headlines and descriptions (created PAUSED for review) |
apply_recommendation |
Apply one of Google's optimization suggestions |
- Hosted OAuth (v2.4+): the CLI never sees your Google refresh token. googleadsagent.ai holds a verified OAuth client, does the consent dance, and hands back an opaque session ID only. No Cloud Console project, no client IDs, no
redirect_uri_mismatcherrors. - CSRF-protected handle: every sign-in uses a per-attempt random
device_idand a short-lived KV state with astateparameter verified on callback. The poll handle self-destructs on first read. - Secrets never in plaintext files by default: the opaque session ID lives in the OS keychain; only when keychain is unavailable does the extension fall back to a
0600-permission file that's gitignored. - Revocation on logout:
/google-ads:logoutinvalidates the session server-side at googleadsagent.ai so it can't be reused. Legacy v2.3 identities that still carry a refresh token are also revoked at Google. - Read-only by default:
run_gaqlonly allows SELECT queries — CREATE, UPDATE, DELETE, MUTATE, and REMOVE are all blocked. - Policy engine: every API tool requires your confirmation before it runs.
- Rate limiting: 10 calls per minute per tool to prevent runaway usage.
- Error sanitization: internal API details are never exposed — you get clean, actionable error messages.
- Audit logging: every tool call is logged to
~/.gemini/logs/google-ads-agent.log. - Lane isolation: Method 1's static API credentials and Method 2's opaque session are fully independent. Signing in or out of Method 2 never affects Method 1's
.envcredentials.
Do you actually need this? If you just want to read and edit accounts that your Google login can see, you don't — run
/google-ads:loginand you're done. This section covers Method 1 (the static API lane) which you only need if you want a fixed machine identity independent of whatever browser account you're signed in with. Many users run both.
Upgrading from v2.2? Your existing
GADS_SITE_SESSION_IDin.envis still honored as a fallback when no identity is stored, so nothing breaks. Run/google-ads:loginonce to migrate to the new identity store — afterwards you can deleteGADS_SITE_SESSION_IDfrom.enventirely.
You need 5 values from 3 places. This is a one-time setup.
- Go to ads.google.com
- Click Tools & Settings (wrench icon) → API Center
- Copy your Developer Token
- Note your Login Customer ID — this is your MCC (Manager) account ID, the 10-digit number at the top of the page (format:
123-456-7890)
Don't have API access? You'll need to apply for a developer token. Basic access is usually approved within a few days.
- Go to console.cloud.google.com
- Create a project (or select an existing one)
- Go to APIs & Services → Library → search for "Google Ads API" → Enable it
- Go to APIs & Services → Credentials → Create Credentials → OAuth client ID
- Choose Web application as the application type
- Add
https://developers.google.com/oauthplaygroundas an authorized redirect URI - Copy your Client ID and Client Secret
- Go to developers.google.com/oauthplayground
- Click the gear icon (top right) → check Use your own OAuth credentials
- Paste your Client ID and Client Secret from the previous step
- In the left panel, find Google Ads API v22 → select
https://www.googleapis.com/auth/adwords - Click Authorize APIs → sign in with the Google account that has access to your Google Ads
- Click Exchange authorization code for tokens
- Copy the Refresh Token
gemini extensions config google-ads-agentIt will prompt for each value. Sensitive fields (developer token, client secret, refresh token) are stored in your system keychain — not in plain text.
Three slash commands for structured analysis:
# Deep-dive into a specific campaign or metric
/google-ads:analyze "Brand Search campaign performance last 30 days"
# Structured audit across 7 dimensions
/google-ads:audit "Acme Corp, focus on wasted spend and quality scores"
# Prioritized optimization recommendations
/google-ads:optimize "Improve ROAS for ecommerce campaigns"Activates automatically when you ask about campaigns, budgets, keywords, ads, PPC, ROAS, bidding, or Performance Max. Includes:
- GAQL query templates for common reports
- Cost formatting (Google uses micros — the skill converts to dollars)
- Anomaly detection thresholds (CPA spikes >20%, zero conversions, budget limits)
- Write safety protocol: Confirm → Execute → Post-check
Activates when you ask to audit security, scan for secrets, or check for vulnerabilities. Includes:
- 10+ secret patterns (sk-, AIzaSy, ghp_, AKIA, xox, whsec_, etc.)
- Auth/authz, input validation, error handling, encryption checks
- Severity framework (Critical / High / Medium / Low)
google-ads-gemini-extension/
├── gemini-extension.json # Manifest — MCP server, settings, themes
├── GEMINI.md # Persistent context (loaded every session)
├── package.json # Node.js dependencies
├── server.js # MCP server — 22 Google Ads API tools (15 read + 7 write)
├── commands/
│ └── google-ads/
│ ├── analyze.toml # /google-ads:analyze
│ ├── audit.toml # /google-ads:audit
│ └── optimize.toml # /google-ads:optimize
├── skills/
│ ├── google-ads-agent/
│ │ └── SKILL.md # PPC management expertise
│ └── security-auditor/
│ └── SKILL.md # Security vulnerability scanning
├── hooks/
│ ├── hooks.json # GAQL validation + audit logging
│ └── log-tool-call.js # Audit trail logger
├── policies/
│ └── safety.toml # User confirmation rules for all 22 tools (write tools at higher priority)
├── LICENSE
└── README.md
gemini extensions update google-ads-agentgemini extensions uninstall google-ads-agentgit clone https://github.com/itallstartedwithaidea/google-ads-gemini-extension.git
cd google-ads-gemini-extension
npm install
gemini extensions link .Changes auto-reload — no need to reinstall.
| Problem | Solution |
|---|---|
command not found: gemini |
Run npm install -g @google/gemini-cli |
Please set an Auth method |
Create ~/.gemini/.env with GEMINI_API_KEY=your-key (get one free) |
Missing Google Ads credentials |
Run gemini extensions config google-ads-agent |
Authentication failed |
Your refresh token may have expired — regenerate it in OAuth Playground |
Permission denied |
Make sure the account is accessible under your MCC |
Rate limit exceeded |
Wait 60 seconds — the extension limits to 10 calls/min per tool |
- google-ads-api-agent — Full Python agent with 28 API actions and 6 sub-agents
- googleadsagent.ai — Live production system (Buddy) on Cloudflare
- Gemini CLI Extension Docs
- Extension Gallery
MIT