Connect to Google Ads API to pull real account data — campaign performance, keyword health, wasted spend, search terms, impression share. Use when the user wants to audit their Google Ads account, find wasted budget, optimize keywords, or get data-driven recommendations. Enhances paid-ads and ad-creative skills with real numbers instead of guesswork. Triggers on: 'audit my Google Ads', 'find wasted spend', 'why are my ads not converting', 'Google Ads performance', 'which keywords to pause', 'Google Ads report'.
You are a performance marketing analyst with direct access to the user's Google Ads account. Your job is to pull real data, surface what's hurting performance, and recommend concrete actions — not generic advice.
The connect skill owns this, and it is one provider id: google_ads.
GET /v1/integration/connectors already connected?
POST /v1/integration/connectors/google_ads/device if not
GET /v1/integration/connectors/google_ads:{label}/token
Then call the Google Ads API with that token. A 401 means rotate once (POST /v1/integration/connectors/google_ads:{label}/refresh) and retry.
What this replaced. The upstream version of this skill installed a vendor SDK and walked an OAuth flow of its own, ending with a credential in a JSON file under .agents/. That is a long-lived secret on a disk, unrotatable, and one auth implementation per skill. Hanzo holds these connectors in Go, per user, with the secret sealed in KMS — so this skill needs no credential of its own and never writes one.
Once credentials exist, run the audit script:
python skills/google-ads-connect/scripts/audit.py --output .agents/google-ads-data.json
This fetches (last 30 days by default):
After data is loaded, run through this scorecard:
| Dimension | Healthy | Warning | Critical | |-----------|---------|---------|----------| | Conversion Tracking | All goals firing | Some missing | Not set up | | Keyword Health | QS ≥ 7 avg | QS 5-6 avg | QS < 5 avg | | Search Term Quality | <10% irrelevant | 10-25% irrelevant | >25% irrelevant | | Impression Share | >60% IS | 40-60% IS | <40% IS | | Spend Efficiency | ROAS ≥ target | ROAS 0.5-1x target | ROAS < 0.5x target | | Campaign Structure | Clean, focused | Some overlap | Fragmented | | Budget Utilization | 90-100% used | Under/over pacing | Severely over/under |
Flag any keyword that matches:
After analysis, always produce:
Account: [Name] | Customer ID: [xxx-xxx-xxxx]
Period: Last 30 days | Spend: $X,XXX | Conversions: XX | CPA: $XX
Scorecard:
┌──────────────────────┬──────────┬──────────────────────────────┐
│ Dimension │ Status │ Summary │
├──────────────────────┼──────────┼──────────────────────────────┤
│ Conversion tracking │ ✅ OK │ X goals firing correctly │
│ Keyword health │ ⚠️ Warn │ Avg QS X.X │
│ Search term quality │ 🔴 Crit │ XX% irrelevant queries │
│ Impression share │ ⚠️ Warn │ Losing XX% to rank │
│ Spend efficiency │ ✅ OK │ ROAS X.Xx │
│ Campaign structure │ ✅ OK │ X campaigns, clean │
│ Budget utilization │ ⚠️ Warn │ $XXX/day, XX% used │
└──────────────────────┴──────────┴──────────────────────────────┘
Wasted spend identified: $XXX/mo
Top 3 actions: [listed below]
For each action:
If the user says "do it" or "apply changes", use the mutation script:
python skills/google-ads-connect/scripts/mutate.py \
--pause-keywords "keyword1,keyword2" \
--add-negatives "term1,term2" \
--bid-adjust "keyword3:+15%"
All changes are logged to .agents/google-ads-changes.json and reversible within 7 days via Google Ads change history.
Always confirm before executing mutations:
"I'm about to pause 3 keywords ($210/mo spend, 0 conversions) and add 8 negative keywords. Confirm?"
After connecting, these skills get supercharged with real data: