Skip to content

@tank/google-search-ads

1.0.2
Skill

Description

Closed-loop decision engine for Google Search Ads. Generates Google Ads Editor-importable CSVs from a business brief, analyzes weekly CSV exports against industry benchmarks, proposes ranked revisions. SMB-owner focused. Search Network only โ€” no Display, no Performance Max.

Triggered by

'google ads''set up google ads''audit my ads''google ads bulk upload''search ads''ppc for SMB'
Download
Verified
tank install -g @tank/google-search-ads

Verified clean

No security issues detected in the latest scan.

Google Search Ads โ€” Closed-Loop Decision Engine

For SMB owners running their own Google Search Ads. The agent plans, the user imports, the agent analyzes, the agent revises โ€” every 7 days.

Core Philosophy

  1. Editor CSV is the contract. Skill output is what Google Ads Editor accepts. Never freeform suggestions; always import-ready files.
  2. campaign.json is the single source of truth. CSVs are emitted from it; never edited directly. Roll-back is just csv_emit.py on an older version.
  3. Search Network only at v1. No Display, no Smart Campaigns, no Performance Max. McDonald's Gotchas #3 and #4 are non-negotiable.
  4. Validate before users see it. Two-pass validator (schema + emitted CSV) catches every known Editor failure mode before the user opens Editor.
  5. The Search Terms Report drives everything. Weekly review = harvest negatives (burns) + promote winners (missed opportunities). That's where the money is.
  6. Phase out Marshall, lean on McDonald where they disagree on AI-era tactics. McDonald is 2023 vs Marshall's 2020 โ€” closer to current ground truth.

The Three Commands

plan      Brief โ†’ campaign.json + 8 importable CSVs + IMPORT_GUIDE.md
analyze   User's CSV exports โ†’ ranked findings vs benchmarks
revise    Findings + previous campaign.json โ†’ campaign_v{N+1}.json + DIFF.md + new CSVs
schedule  ASK user, only if host has cron primitive โ€” fall back to .ics + crontab line

Quick-Start: Common Problems

"Help me set up Google Ads for my business"

  1. Run prompt prompts/plan-brief.md โ€” 11 questions.
  2. Save user answers as brief.json (template in assets/brief-template.json).
  3. scripts/plan.py --brief brief.json --out campaign.json โ†’ produces campaign.json.
  4. scripts/csv_emit.py --in campaign.json --out-dir out/ โ†’ 8 CSV files.
  5. scripts/validate.py --in campaign.json --csv-dir out/ โ†’ must exit 0 before handoff.
  6. Hand out/ directory + assets/IMPORT_GUIDE.md to user.
  7. Run scripts/cron_detect.py to see if host has a scheduler.
  8. ASK the user (don't assume): "Want me to schedule a weekly check-in?"

"My Google Ads are wasting money"

  1. Ask the user to export the 5 CSVs listed in prompts/weekly-checkin.md (Campaign, Ad group, Search terms, Keyword with QS columns, Ad).
  2. scripts/normalize_report.py --in-dir reports/ --out report.json.
  3. scripts/diagnose.py --report report.json --campaign campaign.json --benchmarks assets/benchmarks.json --out findings.json --report-md diagnose-report.md.
  4. Show user the diagnose report (sorted by severity ร— confidence score).
  5. Ask: "Apply the auto-fixable items?" โ€” never auto-apply without confirmation.
  6. scripts/revise.py --campaign campaign.json --findings findings.json --apply all โ†’ produces campaign_v{N+1}.json + DIFF.md.
  7. Re-emit CSVs from the new version; re-validate.
  8. Hand new bundle to user for re-import.

"I imported the CSVs but Editor says 'Ambiguous row type'"

Don't combine entity files. Each CSV must hold one entity type only (Campaigns, AdGroups, Keywords, etc.). Re-emit via csv_emit.py โ€” it always emits one file per entity. If the error persists, run validate.py with --csv-dir and read the validation report.

"I want to revert a revision"

Every revise step keeps campaign_v{N}.json files. To revert:

python3 scripts/csv_emit.py --in campaign_v{N-1}.json --out-dir rollback/
# Import rollback/ in Editor โ€” it overrides the current state

Decision Trees

When to use which command

User asksRun
"Set up ads for [business]"plan + csv_emit + validate (handoff)
"Audit / improve / fix my ads"normalize_report + diagnose (show findings) โ†’ ask before revise
"Apply the fixes" / "Yes, go ahead"revise + csv_emit + validate (handoff)
"Roll back"csv_emit on campaign_v{N-1}.json
"Schedule weekly review"cron_detect โ†’ if found, call its _tool_call with payload; else emit .ics

Bid-strategy ramp (from references/01-plan-workflow.md)

Account stateStrategy
Brand new, 0 conversionsManual CPC
1โ€“49 conversions / month / campaignManual CPC
50โ€“99 conv / mo / campEnhanced CPC
100+ conv with lead genTarget CPA
100+ conv with ecom + wide price rangeTarget ROAS

"Should I emit a competitor campaign?"

SignalDecision
User named competitors AND opted in via run_competitor_campaign: trueYes โ€” 10% of budget
User named competitors but didn't opt inNo (default) โ€” list them as account negatives in non-brand instead
User has no listed competitorsNo

Hard Rules (Validator-Enforced)

RuleSource
No naked broad-match keywords without explicit broad_confirmed: trueMcDonald Gotcha #2
No Modified Broad (+keyword) โ€” discontinued since 2021Google deprecation
No Display Network in Networks columnMcDonald Gotcha #4
RSA has 3โ€“15 headlines (โ‰ค30 chars each) and 2โ€“4 descriptions (โ‰ค90 chars each)Google ad spec
Path 1, Path 2 โ‰ค15 chars, alphanumeric + hyphenGoogle ad spec
Match-type wrapping matches Criterion Type ([...] for Exact, "..." for Phrase)Editor strict parse
Each emitted CSV holds one entity type onlyEditor "Ambiguous row type" prevention
Geo cells in Locations.csv are numeric IDs onlyEditor "Unknown location" prevention
Headers in English, case-insensitiveEditor multilingual rejection
Multi-value cells use ; (semicolon) not ,Editor strict parse

scripts/validate.py enforces all of these. ALWAYS run it before handing CSVs to the user.

Reference Files

FileContents
references/01-plan-workflow.md11-question brief, prerequisites, USP six elements, HOT/WARM/COLD keyword tagging, RSA generation rules, campaign-separation matrix
references/02-csv-schema.mdcampaign.json schema, full per-entity CSV column layouts, validator Pass 1 + Pass 2 rule tables with severities
references/03-diagnose-playbook.mdIndustry benchmarks, diagnostic decision tree (search term burn / missed opportunity / lost IS / QS sub-components / etc), worked plumber example
references/04-cron-integration.mdHost capability detection, OpenClaw/Hermes/Agentic OS/generic payload shapes, .ics + crontab fallback

Bundled scripts

ScriptPurpose
scripts/plan.pybrief.json โ†’ campaign.json
scripts/csv_emit.pycampaign.json โ†’ 8 Editor-compatible CSVs
scripts/validate.pyTwo-pass validator: schema + emitted CSVs. Exit 0 only on zero ERRORs.
scripts/normalize_report.pyUser's UI CSV exports โ†’ unified report.json
scripts/diagnose.pyreport.json + campaign.json + benchmarks โ†’ ranked findings
scripts/revise.pyFindings โ†’ campaign_v{N+1}.json + DIFF.md
scripts/cron_detect.pyDetect host scheduler; emit payload or fallback

Bundled assets

AssetPurpose
assets/brief-template.jsonSkeleton for the 11-question interrogation
assets/benchmarks.jsonIndustry CTR/CPC/CVR/CPA medians (default + 9 verticals)
assets/geo-targets-seed.csv86 Geo Target IDs (top countries + US states + major cities). Fallback to https://developers.google.com/google-ads/api/data/geotargets for anything missing.
assets/IMPORT_GUIDE.mdStep-by-step Editor import instructions for the user

Prompts

PromptWhen
prompts/plan-brief.mdFirst-time setup. Use verbatim โ€” it lists the prerequisites the user MUST satisfy.
prompts/weekly-checkin.mdTriggered by cron OR by user request. Lists the 5 reports + UI paths.

What this skill does NOT do (anti-scope)

  • Display Network, Performance Max, Smart Campaigns, Shopping, YouTube, App campaigns โ€” out of scope.
  • Direct Google Ads API write access (developer token gate). Editor CSV bulk import is the supported path.
  • Auto-scraping the user's actual account performance โ€” user uploads CSVs explicitly.
  • Auto-applying fixes without user confirmation. Always show DIFF.md first.
  • Replacing human judgment on USP, brand voice, or unique offer crafting โ€” the skill mechanizes the boring parts.

Command Palette

Search packages, docs, and navigate Tank