Google Ads Audit
Google Ads account audit and business context setup.
How to use it
Claude Code
- Run the line below. It pulls the whole folder into
~/.claude/skills/audit, including the files SKILL.md points to. - Describe your job in plain words. Claude Code follows the skill from there.
npx degit nowork-studio/notfair-plugin/google-ads/audit#main ~/.claude/skills/auditFor one project only, change the path to .claude/skills/audit. This skill also uses business-context.json, audit-history.json, account-health-scoring.md — copying SKILL.md alone won't be enough. See the folder on GitHub.
Claude (web or desktop app)
- On this page open ⋯ → Download .md.
- Save it as SKILL.md in a folder, zip the folder, then Customize → Skills → + → Create skill → Upload a skill.
- Pick the file and Save. Claude shows the name and description and runs a security scan.
- Check the skill is switched on.
- Start a new chat and describe your job in plain words. The AI follows the skill from there.
ChatGPT or another app
- ChatGPT: make a Project and paste it into Instructions.
- Neither? Paste it at the top of a new chat — it works for that chat.
Not working?
- Check which app you pasted it into — the steps above name the right one.
- Some skills need the paid tier of Claude or ChatGPT.
Paste into Claude, ChatGPT or Cursor.
Source of Google Ads Audit
Show the full text129 lines
| name | description | argument-hint |
|---|---|---|
| google-ads-audit | Google Ads account audit and business context setup. Use for account-health audits and business-context setup. Trigger on "audit my ads", "ads audit", "set up my ads", "onboard", "account overview", "how's my account", "ads health check", "what should I fix in my ads", or when the user is new to NotFair and hasn't run an audit before. | <account name or 'audit my ads'> |
Google Ads Audit
Diagnose account health and persist business context for downstream skills (/google-ads, /google-ads-copy, /google-ads-landing). Read-only — never mutates the account. The user runs /google-ads to execute fixes you recommend.
Setup
Follow ../shared/preamble.md (MCP detection, account selection) and ../shared/analysis-principles.md (evidence requirement, guardrails). Both apply throughout this skill.
Filesystem contract (must persist)
| Artifact | Path | When |
|---|---|---|
| Business context | {data_dir}/business-context.json |
First full audit, or refresh when audit_date is >90 days old. Skip on scoped audits if file is fresh. |
| Personas | {data_dir}/personas/{accountId}.json |
Every full audit. |
These are the handoff to every other ads skill — write them even if the report is short. Otherwise /google-ads-copy and /google-ads-landing operate without business context and produce generic output.
business-context.json schema: business_name, industry, website, services[], locations[], target_audience, brand_voice{tone, words_to_use[], words_to_avoid[]}, differentiators[], competitors[], seasonality{peak_months[], slow_months[], seasonal_hooks[]}, keyword_landscape{high_intent_terms[], competitive_terms[], long_tail_opportunities[]}, social_proof[], offers_or_promotions[], landing_pages{}, unit_economics{aov_usd, profit_margin, source}, notes, audit_date, account_id.
personas JSON schema: {account_id, saved_at, personas: [{name, demographics, primary_goal, pain_points[], search_terms[], decision_trigger, value}]}. See references/persona-discovery.md.
Policy freshness check (run first)
Read ../shared/policy-registry.json. For each entry where last_verified + stale_after_days < today:
- Any entry without a direct current first-party Google source is a hypothesis, not an audit rule or benchmark. Do not use it for a finding or recommendation without verification.
- High-volatility → search the official Google Ads Help, Ads & Commerce blog, or Google Ads developer documentation for the
category; compare the source with the recordedrule. If it drifted, omit the stale rule and banner the limitation. - Moderate-volatility → verify it when it could affect a material finding; otherwise omit it rather than repeating a stale caveat.
- Stable → skip silently.
Phase 1 — Pull the audit dataset
Choose available read capabilities for the requested audit scope. Batch related reads where useful and supported; consult current server guidance for schemas and limits.
You decide the exact GAQL shape, but a defensible audit needs to see, at minimum:
- Account-level rollups (
customer) - Campaign performance with bidding strategy, network, and impression-share metrics (
campaign, 90-day cap for impression-share data) - Ad-group performance (
ad_group) - Keyword performance with Quality Score and components (
keyword_view) - Search terms (
search_term_view) - Negative keywords and shared lists (
campaign_criterion+ shared sets) - Conversion actions (
conversion_action) — including counting type, attribution model, primary/secondary - Network segmentation (
segments.ad_network_type) when diagnosing CPA/CVR shifts or Search Partners - RSA assets (
ad_group_ad) - Geo targeting (
campaign_criterionLOCATION + PROXIMITY) - Recent change events (
change_event, last 30 days) — for explaining regressions
Aggregate inside the script. Return summarized JSON, not raw rows. The agent narrates; the script does the math.
Use platform recommendations or account-setup diagnostics as optional cross-checks when available and relevant to the question.
If a read fails, follow actionable recovery guidance. Clearly report missing evidence; continue independent findings only when the available data supports them.
Skip scoring entirely if totalSpend == 0 or activeCampaigns == 0. Go straight to business context.
Phase 2 — Scope handling
If the user narrows the audit ("focus on one campaign", "campaign X", "just check waste"):
- Match campaign names by case-insensitive substring. If no match, list available campaigns and ask.
- Filter the in-memory dataset before analysis — no extra API calls.
- Account-level dimensions (conversion tracking, account guardrails) stay account-wide. Note "Scoped to: X" in the report.
- Skip Phase 4 (business context refresh) on scoped audits if
business-context.jsonis fresh.
Phase 3 — Diagnose
The audit's headline output is three pulse metrics — Waste ($/mo), Demand captured (%), CPA ($) — each annotated with its top contributor and a pointer to the fix. Read references/account-health-scoring.md for the formula, annotation rules, signal-failure overrides, and audit-history.json schema. The pulse metric IS the verdict; you don't add a letter grade or 0–5 score on top.
To compute and back the pulse metrics, you'll need to look across these seven areas. They are diagnostic surface area, not graded dimensions:
- Signal Quality (account-level) — measurement integrity. If broken, STOP here and recommend pausing spend until it's fixed. Pulse metrics are meaningless without measurement (apply the signal-failure override on the Waste line per the reference).
- Campaign Structure — keywords per ad group, brand vs. non-brand separation, channel mixing, naming, budget logic.
- Keyword Health — Quality Score weighted by spend, zombie keywords, match-type discipline.
- Search-Term Quality — wasted spend, brand-leakage, negative coverage, conversion-worthy terms not yet keywords.
- Ad Copy & Creative — RSA coverage, asset variety, sitelink/callout/structured-snippet completeness, PMax asset-group health.
- Impression Share — read rank-lost vs budget-lost together (see the 2×2 matrix in
account-health-scoring.md); they're different problems with different fixes. - Spend Efficiency — waste vs. headroom, brand vs. non-brand split, concentration risk.
For Signal Quality and network-mix questions, read references/conversion-network-audit.md. It adds the prerequisite checks for conversion-action integrity, Search Partners, Display leakage in Search campaigns, and regression decomposition.
Per-area findings only show up in the report when the area surfaced something material. Cite specific entities, dollars, and time windows. "Some keywords are underperforming" is not a finding; "Campaign X has $1,840 in last-30-day spend on 12 keywords with 0 conversions and QS ≤ 4" is.
For unit-economics-aware framing: if business-context.json.unit_economics.aov_usd and profit_margin exist, frame waste and headroom in dollars saved / captured per month, not "above account average". See ../shared/ppc-math.md.
Phase 4 — Business context
Derive what you can from data already pulled:
| Field | Source |
|---|---|
business_name |
customer.descriptive_name |
services |
Campaign + ad-group names, top converting keywords |
locations |
campaign_criterion LOCATION + PROXIMITY |
brand_voice |
Top-performing RSA headlines / descriptions |
keyword_landscape.high_intent_terms |
Converting keywords with strong CVR |
keyword_landscape.competitive_terms |
Keywords in campaigns with high rank-lost-IS |
keyword_landscape.long_tail_opportunities |
Converting search terms not yet promoted to keywords |
website |
Apex domain from ad final URLs |
Then crawl the website (homepage + about + services + top 3 ad landing pages, parallel WebFetch) and merge into the schema. See references/business-context.md.
Ask the user — it's faster than guessing — for: differentiators, competitors, seasonality, unit economics (AOV, margin). Ask for everything else only if the data + crawl can't answer it.
Phase 5 — Personas
Discover 2–3 personas from search terms, top keywords, ad-group themes, landing pages, geo, and device split — all from the dataset already in memory. Persist to {data_dir}/personas/{accountId}.json. Each persona must be grounded in 5+ actual search terms; if not, drop it. See references/persona-discovery.md.
Phase 6 — Report
Structure: pulse metrics (3 lines, each with number + top contributor + fix pointer) → per-area findings (only those that surfaced something material) → Quick Wins section (per the rules in references/account-health-scoring.md). Cap at ~80 lines. Every claim cites a specific entity, number, and window.
End with a single closing line after the handoff to /google-ads:
State where any audit artifacts were actually saved. Do not claim hosted audit history unless a live result confirms it.
Guardrails
- Read-only skill. Diagnose; don't mutate. Every fix routes through
/google-ads(or/google-ads-copy,/google-ads-landing). End the report with one handoff tied to the #1 action. - STOP condition. If conversion tracking is broken, recommend pausing spend until it's fixed before recommending anything else.
- Always persist
business-context.jsonandpersonas/{accountId}.jsoneven if the report is short — downstream skills depend on them. - Name names. Every finding cites specific campaigns, keywords, search terms, and dollar amounts. No generic verdicts.
- Show the data, not the score. The pulse metrics are the verdict — three numbers with named contributors and pointers to the fix. No letter grades, no 0–5 ratings hiding the reasoning behind a label.
| 1 | |
| 2 | name google-ads-audit |
| 3 | description Google Ads account audit and business context setup. Use for account-health audits and business-context setup. Trigger on "audit my ads", "ads audit", "set up my ads", "onboard", "account overview", "how's my account", "ads health check", "what should I fix in my ads", or when the user is new to NotFair and hasn't run an audit before. |
| 4 | argument-hint "<account name or 'audit my ads'>" |
| 5 | |
| 6 | |
| 7 | # Google Ads Audit |
| 8 | |
| 9 | Diagnose account health and persist business context for downstream skills (`/google-ads`, `/google-ads-copy`, `/google-ads-landing`). **Read-only** — never mutates the account. The user runs `/google-ads` to execute fixes you recommend. |
| 10 | |
| 11 | ## Setup |
| 12 | |
| 13 | Follow `../shared/preamble.md` (MCP detection, account selection) and `../shared/analysis-principles.md` (evidence requirement, guardrails). Both apply throughout this skill. |
| 14 | |
| 15 | ## Filesystem contract (must persist) |
| 16 | |
| 17 | | Artifact | Path | When | |
| 18 | |---|---|---| |
| 19 | | Business context | `{data_dir}/business-context.json` | First full audit, or refresh when `audit_date` is >90 days old. Skip on scoped audits if file is fresh. | |
| 20 | | Personas | `{data_dir}/personas/{accountId}.json` | Every full audit. | |
| 21 | |
| 22 | These are the handoff to every other ads skill — write them even if the report is short. Otherwise `/google-ads-copy` and `/google-ads-landing` operate without business context and produce generic output. |
| 23 | |
| 24 | **business-context.json schema:** `business_name, industry, website, services[], locations[], target_audience, brand_voice{tone, words_to_use[], words_to_avoid[]}, differentiators[], competitors[], seasonality{peak_months[], slow_months[], seasonal_hooks[]}, keyword_landscape{high_intent_terms[], competitive_terms[], long_tail_opportunities[]}, social_proof[], offers_or_promotions[], landing_pages{}, unit_economics{aov_usd, profit_margin, source}, notes, audit_date, account_id`. |
| 25 | |
| 26 | **personas JSON schema:** `{account_id, saved_at, personas: [{name, demographics, primary_goal, pain_points[], search_terms[], decision_trigger, value}]}`. See `references/persona-discovery.md`. |
| 27 | |
| 28 | ## Policy freshness check (run first) |
| 29 | |
| 30 | Read `../shared/policy-registry.json`. For each entry where `last_verified + stale_after_days < today`: |
| 31 | Any entry without a direct current first-party Google source is a hypothesis, not an audit rule or benchmark. Do not use it for a finding or recommendation without verification. |
| 32 | **High-volatility** → search the official Google Ads Help, Ads & Commerce blog, or Google Ads developer documentation for the `category`; compare the source with the recorded `rule`. If it drifted, omit the stale rule and banner the limitation. |
| 33 | **Moderate-volatility** → verify it when it could affect a material finding; otherwise omit it rather than repeating a stale caveat. |
| 34 | **Stable** → skip silently. |
| 35 | |
| 36 | ## Phase 1 — Pull the audit dataset |
| 37 | |
| 38 | Choose available read capabilities for the requested audit scope. Batch related reads where useful and supported; consult current server guidance for schemas and limits. |
| 39 | |
| 40 | You decide the exact GAQL shape, but a defensible audit needs to see, at minimum: |
| 41 | |
| 42 | Account-level rollups (`customer`) |
| 43 | Campaign performance with bidding strategy, network, and impression-share metrics (`campaign`, 90-day cap for impression-share data) |
| 44 | Ad-group performance (`ad_group`) |
| 45 | Keyword performance with Quality Score and components (`keyword_view`) |
| 46 | Search terms (`search_term_view`) |
| 47 | Negative keywords and shared lists (`campaign_criterion` + shared sets) |
| 48 | Conversion actions (`conversion_action`) — including counting type, attribution model, primary/secondary |
| 49 | Network segmentation (`segments.ad_network_type`) when diagnosing CPA/CVR shifts or Search Partners |
| 50 | RSA assets (`ad_group_ad`) |
| 51 | Geo targeting (`campaign_criterion` LOCATION + PROXIMITY) |
| 52 | Recent change events (`change_event`, last 30 days) — for explaining regressions |
| 53 | |
| 54 | Aggregate inside the script. Return summarized JSON, not raw rows. The agent narrates; the script does the math. |
| 55 | |
| 56 | Use platform recommendations or account-setup diagnostics as optional cross-checks when available and relevant to the question. |
| 57 | |
| 58 | If a read fails, follow actionable recovery guidance. Clearly report missing evidence; continue independent findings only when the available data supports them. |
| 59 | |
| 60 | **Skip scoring entirely if** `totalSpend == 0` or `activeCampaigns == 0`. Go straight to business context. |
| 61 | |
| 62 | ## Phase 2 — Scope handling |
| 63 | |
| 64 | If the user narrows the audit ("focus on one campaign", "campaign X", "just check waste"): |
| 65 | |
| 66 | Match campaign names by case-insensitive substring. If no match, list available campaigns and ask. |
| 67 | Filter the in-memory dataset before analysis — no extra API calls. |
| 68 | Account-level dimensions (conversion tracking, account guardrails) stay account-wide. Note "Scoped to: X" in the report. |
| 69 | Skip Phase 4 (business context refresh) on scoped audits if `business-context.json` is fresh. |
| 70 | |
| 71 | ## Phase 3 — Diagnose |
| 72 | |
| 73 | The audit's headline output is **three pulse metrics** — Waste ($/mo), Demand captured (%), CPA ($) — each annotated with its top contributor and a pointer to the fix. Read `references/account-health-scoring.md` for the formula, annotation rules, signal-failure overrides, and `audit-history.json` schema. The pulse metric IS the verdict; you don't add a letter grade or 0–5 score on top. |
| 74 | |
| 75 | To compute and back the pulse metrics, you'll need to look across these seven areas. They are diagnostic surface area, not graded dimensions: |
| 76 | |
| 77 | **Signal Quality** *(account-level)* — measurement integrity. If broken, **STOP** here and recommend pausing spend until it's fixed. Pulse metrics are meaningless without measurement (apply the signal-failure override on the Waste line per the reference). |
| 78 | **Campaign Structure** — keywords per ad group, brand vs. non-brand separation, channel mixing, naming, budget logic. |
| 79 | **Keyword Health** — Quality Score weighted by spend, zombie keywords, match-type discipline. |
| 80 | **Search-Term Quality** — wasted spend, brand-leakage, negative coverage, conversion-worthy terms not yet keywords. |
| 81 | **Ad Copy & Creative** — RSA coverage, asset variety, sitelink/callout/structured-snippet completeness, PMax asset-group health. |
| 82 | **Impression Share** — read rank-lost vs budget-lost together (see the 2×2 matrix in `account-health-scoring.md`); they're different problems with different fixes. |
| 83 | **Spend Efficiency** — waste vs. headroom, brand vs. non-brand split, concentration risk. |
| 84 | |
| 85 | For Signal Quality and network-mix questions, read `references/conversion-network-audit.md`. It adds the prerequisite checks for conversion-action integrity, Search Partners, Display leakage in Search campaigns, and regression decomposition. |
| 86 | |
| 87 | Per-area findings only show up in the report when the area surfaced something material. Cite specific entities, dollars, and time windows. "Some keywords are underperforming" is not a finding; "Campaign X has $1,840 in last-30-day spend on 12 keywords with 0 conversions and QS ≤ 4" is. |
| 88 | |
| 89 | For unit-economics-aware framing: if `business-context.json.unit_economics.aov_usd` and `profit_margin` exist, frame waste and headroom in dollars saved / captured per month, not "above account average". See `../shared/ppc-math.md`. |
| 90 | |
| 91 | ## Phase 4 — Business context |
| 92 | |
| 93 | Derive what you can from data already pulled: |
| 94 | |
| 95 | | Field | Source | |
| 96 | |---|---| |
| 97 | | `business_name` | `customer.descriptive_name` | |
| 98 | | `services` | Campaign + ad-group names, top converting keywords | |
| 99 | | `locations` | `campaign_criterion` LOCATION + PROXIMITY | |
| 100 | | `brand_voice` | Top-performing RSA headlines / descriptions | |
| 101 | | `keyword_landscape.high_intent_terms` | Converting keywords with strong CVR | |
| 102 | | `keyword_landscape.competitive_terms` | Keywords in campaigns with high rank-lost-IS | |
| 103 | | `keyword_landscape.long_tail_opportunities` | Converting search terms not yet promoted to keywords | |
| 104 | | `website` | Apex domain from ad final URLs | |
| 105 | |
| 106 | Then crawl the website (homepage + about + services + top 3 ad landing pages, parallel `WebFetch`) and merge into the schema. See `references/business-context.md`. |
| 107 | |
| 108 | Ask the user — it's faster than guessing — for: differentiators, competitors, seasonality, unit economics (AOV, margin). Ask for everything else only if the data + crawl can't answer it. |
| 109 | |
| 110 | ## Phase 5 — Personas |
| 111 | |
| 112 | Discover 2–3 personas from search terms, top keywords, ad-group themes, landing pages, geo, and device split — all from the dataset already in memory. Persist to `{data_dir}/personas/{accountId}.json`. Each persona must be grounded in **5+ actual search terms**; if not, drop it. See `references/persona-discovery.md`. |
| 113 | |
| 114 | ## Phase 6 — Report |
| 115 | |
| 116 | Structure: pulse metrics (3 lines, each with number + top contributor + fix pointer) → per-area findings (only those that surfaced something material) → Quick Wins section (per the rules in `references/account-health-scoring.md`). Cap at ~80 lines. Every claim cites a specific entity, number, and window. |
| 117 | |
| 118 | End with a single closing line after the handoff to `/google-ads`: |
| 119 | |
| 120 | State where any audit artifacts were actually saved. Do not claim hosted audit history unless a live result confirms it. |
| 121 | |
| 122 | ## Guardrails |
| 123 | |
| 124 | **Read-only skill.** Diagnose; don't mutate. Every fix routes through `/google-ads` (or `/google-ads-copy`, `/google-ads-landing`). End the report with one handoff tied to the #1 action. |
| 125 | **STOP condition.** If conversion tracking is broken, recommend pausing spend until it's fixed before recommending anything else. |
| 126 | **Always persist** `business-context.json` and `personas/{accountId}.json` even if the report is short — downstream skills depend on them. |
| 127 | **Name names.** Every finding cites specific campaigns, keywords, search terms, and dollar amounts. No generic verdicts. |
| 128 | **Show the data, not the score.** The pulse metrics are the verdict — three numbers with named contributors and pointers to the fix. No letter grades, no 0–5 ratings hiding the reasoning behind a label. |
| 129 |
Discussion
Browse more free Claude skills or everything in Marketing.