Meta Ads Audit

Meta Ads (Facebook + Instagram) account audit and business context setup.

How to use it

Claude Code
  1. Run the line below. It pulls the whole folder into ~/.claude/skills/audit-2, including the files SKILL.md points to.
  2. Describe your job in plain words. Claude Code follows the skill from there.
Claude Code — installs the whole folder, not just SKILL.md
npx degit nowork-studio/notfair-plugin/meta-ads/audit#main ~/.claude/skills/audit-2

For one project only, change the path to .claude/skills/audit-2. This skill also uses business-context.json — copying SKILL.md alone won't be enough. See the folder on GitHub.

Claude (web or desktop app)
  1. On this page open ⋯ → Download .md.
  2. Save it as SKILL.md in a folder, zip the folder, then Customize → Skills → + → Create skill → Upload a skill.
  3. Pick the file and Save. Claude shows the name and description and runs a security scan.
  4. Check the skill is switched on.
  5. Start a new chat and describe your job in plain words. The AI follows the skill from there.
ChatGPT or another app
  1. ChatGPT: make a Project and paste it into Instructions.
  2. 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.
Step-by-step guide with screenshots · Ask in the forum

Paste into Claude, ChatGPT or Cursor.

Source of Meta Ads Audit

Show the full text148 lines
namedescriptionargument-hint
meta-ads-auditMeta Ads (Facebook + Instagram) account audit and business context setup. Use for account-health audits and business-context setup. Trigger on "audit my Meta ads", "audit my Facebook ads", "Meta ads audit", "set up my Meta ads", "onboard Meta", "Meta account overview", "how's my Meta account", "Meta health check", "what should I fix in my Facebook ads", or when the user is new to NotFair Meta and hasn't run an audit before.<account name or 'audit my Meta ads'>

Meta Ads Audit

Diagnose Meta (Facebook + Instagram) account health and persist business context for downstream skills (/meta-ads). Read-only — never mutates the account. The user runs /meta-ads to execute fixes you recommend.

Setup

Follow ../shared/preamble.md — MCP detection, OAuth, ad account selection.

Filesystem contract (MUST persist)

Artifact Path When
Business context {data_dir}/meta/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}/meta/personas/{accountId}.json Every full audit.

These are the handoff to /meta-ads — write them even if the report itself is short. Otherwise downstream skills operate without business context and produce generic output.

If a {data_dir}/business-context.json exists from /google-ads-audit (no meta/ subdir), read it as a starting point — most fields (services, brand voice, differentiators, locations, seasonality) are platform-agnostic. Then write the Meta-specific version to {data_dir}/meta/business-context.json with any Meta-specific overrides (different creative angles, different audiences, different funnel events).

business-context.json schema (shared with Google Ads where fields apply): 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[]}, social_proof[], offers_or_promotions[], landing_pages{}, unit_economics{aov_usd, profit_margin, ltv_usd, source}, notes, audit_date, account_id.

Meta-specific extensions: meta_funnel_events{top_of_funnel, mid_of_funnel, conversion}, creative_inventory{concepts[], formats[], aspect_ratios[]}, custom_audiences{purchasers, abandoners, engagers, list_uploads[]}, pixel_health{pixel_id, capi_enabled, emq_score, last_event_at}.

personas JSON schema: {account_id, saved_at, personas: [{name, demographics, primary_goal, pain_points[], decision_trigger, value, meta_creative_angles[], visual_cues[]}]}. The Meta version adds meta_creative_angles (e.g. "before/after demonstration", "founder-led explainer", "UGC review") and visual_cues (objects, settings, emotions that resonate with this persona). 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:

  • High-volatility → WebSearch the area for recent Meta Ads changes; compare to assumption. If drift, banner the report and suggest registry update.
  • Moderate-volatility → one-line "may warrant a check" note.
  • Stable → skip silently.

The Meta platform changes faster than Google Ads (Advantage+, attribution, learning behaviors) — check high-volatility entries every audit.

Phase 1 — Pull the audit dataset

Choose available read capabilities for the requested audit scope. Batch related reads where useful and supported; the rubric below describes evidence to consider, not a fixed call sequence.

A complete audit needs at minimum:

  • Ad account info (/{accountId}) — currency, timezone, business id, spend cap, account status, balance.
  • Pixel health (/{accountId}/customconversions + /{accountId}/adspixels) — pixel id, last activity, CAPI status, Event Match Quality (EMQ) score.
  • Campaigns (/{accountId}/campaigns) — id, name, objective, status, daily/lifetime budget, special_ad_categories, buying_type, bid_strategy, created_time. Last 90 days.
  • Ad sets (/{accountId}/adsets) — id, name, status, campaign_id, optimization_goal, billing_event, bid_strategy, daily_budget, lifetime_budget, attribution_spec, targeting (summary), promoted_object, learning_stage_info.
  • Ads (/{accountId}/ads) — id, name, status, ad set, creative summary (image/video, primary text, headline, description, CTA), effective_status.
  • Insights at campaign level — spend, impressions, reach, frequency, cpm, link CTR, link clicks, purchases (or other primary action), purchase value, ROAS, CPA.
  • Insights at ad set level — same fields, last 30 days.
  • Insights at ad level — top 50 ads by spend; same fields plus video metrics (3-sec views, ThruPlays) for video creatives.
  • Insights with breakdowns — placement (publisher_platform,platform_position), age/gender, device. Use these to spot placement losers and audience composition.
  • Recent edit activity — when available via /{adsetId} last_modified or /{adsetId} change history.

Compute aggregates in the script, return summarized JSON. Don't return all rows — rank, slice, summarize. The agent narrates the result; the script does the math.

Use available platform recommendations as an optional cross-check when they would help the analysis.

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 creative fatigue"):

  • Match campaign names by case-insensitive substring. If no match, list available campaigns and ask.
  • Filter the in-memory dataset before scoring — no extra API calls.
  • Account-level dimensions (Pixel health, attribution defaults) stay account-wide. Note "Scoped to: X" in the report.
  • Skip Phase 4 (business context refresh) on scoped audits if business-context.json is fresh.

Phase 3 — Score

Score each of the 7 dimensions 0–5 using references/account-health-scoring.md. Overall = round(sum × 100 / 35).

Score Label Meaning
0 Critical Broken or missing — actively losing money
1 Poor Major waste or missed opportunity
2 Needs Work Several clear issues
3 Acceptable Functional, room to improve
4 Good Well-managed, minor opportunities
5 Excellent Best-practice

Scope-aware: campaign-level dimensions reflect in-scope data; account-level dimensions (Pixel + CAPI, attribution setup) score account-wide with a note on scope impact.

Encoded heuristics — apply these, they aren't obvious
  • Pixel + CAPI is upstream of everything. EMQ < 7.0 means Meta can't match events well — Smart Bidding starves regardless of how good the creative is. STOP-condition input.
  • Reported ROAS systematically overstates true ROAS. Cross-check Meta-reported numbers against Shopify / GA4 / MMM where possible. The gap is the modeled-conversion premium and is typically 20–40% in ecom.
  • Frequency × CPM trend = creative diagnosis. Frequency > 3.0 with CPM rising ≥ 30% w/w is fatigue — recommend creative refresh, not budget cuts.
  • One ad set carrying > 70% of a campaign is fragility, not concentration. When it fatigues, the campaign collapses.
  • Audience overlap > 50% between sibling ad sets fragments signal. Consolidate; don't try to "fix" with bid caps.
  • Special Ad Category misclassification is a takedown risk, not just a policy nit. Surface as Critical regardless of current performance.
  • Manual placements without evidence is a sign of inherited-from-2018 thinking. Default should be Advantage+ Placements; deviations need data.
Pixel + Tracking Diagnosis Matrix
EMQ < 5 EMQ 5–6.9 EMQ 7.0+
CAPI off Critical — flying blind Critical — most events lost High — leaving 15–25% of events on the table
CAPI on, dedup off Critical — duplicated and weak signal High — duplicate counting risk Medium — match quality improves with dedup
CAPI on, dedup on High — match quality is the bottleneck Medium — improve event_id coverage Healthy

Phase 4 — Business context

Derive what you can from the data already pulled:

Field Source
business_name Ad account name (/{accountId} name field)
services Top campaigns by spend, ad set names, top-converting ad creatives
locations Targeting geo summary (countries / regions in active ad sets)
brand_voice Top-performing ad copy (primary text + headline)
creative_inventory.formats Mix of image / video / carousel observed in active ads
creative_inventory.aspect_ratios Aspect ratios across active ads (1:1, 4:5, 9:16)
meta_funnel_events.conversion Most common optimization event on top-spending ad sets
custom_audiences Custom audiences referenced in active ad set targeting
pixel_health From the Pixel detail call
website Apex domain from active ad final URLs

Then crawl the website (homepage + about + 1–2 top landing pages, parallel WebFetch) and merge into the schema. See references/business-context.md for the full crawl procedure.

Always ask the user: differentiators, competitors, seasonality, AOV + profit margin (essential for ROAS-aware scoring). Ask for everything else only if data + crawl can't answer it.

Phase 5 — Personas

Discover 2–3 personas from creative performance (which angles convert), top-spending audiences, and landing-page content — all from the dataset already in memory. Persist to {data_dir}/meta/personas/{accountId}.json. Each persona must be grounded in observable evidence (a converting ad set, a converting creative angle, a landing-page section) — no inventing. See references/persona-discovery.md.

Phase 6 — Report

Lead with the verdict, then the top 3 actions (with dollar impact when possible), then the scorecard, then evidence for dimensions scoring 0–2 only. Cite specific campaigns, ad sets, ads, and dollar amounts. Cap at ~80 lines.

State where any audit artifacts were actually saved. Do not claim hosted audit history unless a live result confirms it.

Guardrails

  1. Read-only skill. Diagnose; don't mutate. Every fix routes through /meta-ads. End the report with one handoff tied to the #1 action.
  2. STOP condition — if Pixel health scores 0–1 (EMQ < 5 or CAPI off in an ecom account), recommend pausing scaling decisions until tracking is fixed before recommending anything else. Everything downstream is unreliable.
  3. Always persist meta/business-context.json and meta/personas/{accountId}.json even if the report itself is short — downstream skills depend on them.
  4. Name names. Every finding cites specific campaigns, ad sets, ad creatives, and dollar amounts. "Some ad sets are underperforming" is not a finding.
  5. Never report Meta-reported ROAS without footnoting the modeled-conversion premium. "ROAS 3.2× (Meta-reported, 7DC1DV — typically overstates Shopify-attributed ROAS by 20–40%)" is honest. "ROAS 3.2×" is misleading.
1---
2name: meta-ads-audit
3description: Meta Ads (Facebook + Instagram) account audit and business context setup. Use for account-health audits and business-context setup. Trigger on "audit my Meta ads", "audit my Facebook ads", "Meta ads audit", "set up my Meta ads", "onboard Meta", "Meta account overview", "how's my Meta account", "Meta health check", "what should I fix in my Facebook ads", or when the user is new to NotFair Meta and hasn't run an audit before.
4argument-hint: "<account name or 'audit my Meta ads'>"
5---
6 
7# Meta Ads Audit
8 
9Diagnose Meta (Facebook + Instagram) account health and persist business context for downstream skills (`/meta-ads`). **Read-only** — never mutates the account. The user runs `/meta-ads` to execute fixes you recommend.
10 
11## Setup
12 
13Follow `../shared/preamble.md` — MCP detection, OAuth, ad account selection.
14 
15## Filesystem contract (MUST persist)
16 
17| Artifact | Path | When |
18|---|---|---|
19| Business context | `{data_dir}/meta/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}/meta/personas/{accountId}.json` | Every full audit. |
21 
22These are the handoff to `/meta-ads` — write them even if the report itself is short. Otherwise downstream skills operate without business context and produce generic output.
23 
24If a `{data_dir}/business-context.json` exists from `/google-ads-audit` (no `meta/` subdir), read it as a starting point — most fields (services, brand voice, differentiators, locations, seasonality) are platform-agnostic. Then write the Meta-specific version to `{data_dir}/meta/business-context.json` with any Meta-specific overrides (different creative angles, different audiences, different funnel events).
25 
26**business-context.json schema (shared with Google Ads where fields apply):**
27`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[]}, social_proof[], offers_or_promotions[], landing_pages{}, unit_economics{aov_usd, profit_margin, ltv_usd, source}, notes, audit_date, account_id`.
28 
29**Meta-specific extensions:**
30`meta_funnel_events{top_of_funnel, mid_of_funnel, conversion}, creative_inventory{concepts[], formats[], aspect_ratios[]}, custom_audiences{purchasers, abandoners, engagers, list_uploads[]}, pixel_health{pixel_id, capi_enabled, emq_score, last_event_at}`.
31 
32**personas JSON schema:** `{account_id, saved_at, personas: [{name, demographics, primary_goal, pain_points[], decision_trigger, value, meta_creative_angles[], visual_cues[]}]}`. The Meta version adds `meta_creative_angles` (e.g. "before/after demonstration", "founder-led explainer", "UGC review") and `visual_cues` (objects, settings, emotions that resonate with this persona). See `references/persona-discovery.md`.
33 
34## Policy freshness check (run first)
35 
36Read `../shared/policy-registry.json`. For each entry where `last_verified + stale_after_days < today`:
37- **High-volatility** → WebSearch the `area` for recent Meta Ads changes; compare to `assumption`. If drift, banner the report and suggest registry update.
38- **Moderate-volatility** → one-line "may warrant a check" note.
39- **Stable** → skip silently.
40 
41The Meta platform changes faster than Google Ads (Advantage+, attribution, learning behaviors) — check high-volatility entries every audit.
42 
43## Phase 1 — Pull the audit dataset
44 
45Choose available read capabilities for the requested audit scope. Batch related reads where useful and supported; the rubric below describes evidence to consider, not a fixed call sequence.
46 
47A complete audit needs at minimum:
48 
49- **Ad account info** (`/{accountId}`) — currency, timezone, business id, spend cap, account status, balance.
50- **Pixel health** (`/{accountId}/customconversions` + `/{accountId}/adspixels`) — pixel id, last activity, CAPI status, Event Match Quality (EMQ) score.
51- **Campaigns** (`/{accountId}/campaigns`) — id, name, objective, status, daily/lifetime budget, special_ad_categories, buying_type, bid_strategy, created_time. Last 90 days.
52- **Ad sets** (`/{accountId}/adsets`) — id, name, status, campaign_id, optimization_goal, billing_event, bid_strategy, daily_budget, lifetime_budget, attribution_spec, targeting (summary), promoted_object, learning_stage_info.
53- **Ads** (`/{accountId}/ads`) — id, name, status, ad set, creative summary (image/video, primary text, headline, description, CTA), effective_status.
54- **Insights at campaign level** — spend, impressions, reach, frequency, cpm, link CTR, link clicks, purchases (or other primary action), purchase value, ROAS, CPA.
55- **Insights at ad set level** — same fields, last 30 days.
56- **Insights at ad level** — top 50 ads by spend; same fields plus video metrics (3-sec views, ThruPlays) for video creatives.
57- **Insights with breakdowns** — placement (`publisher_platform,platform_position`), age/gender, device. Use these to spot placement losers and audience composition.
58- **Recent edit activity** — when available via `/{adsetId}` last_modified or `/{adsetId}` change history.
59 
60Compute aggregates **in the script**, return summarized JSON. Don't return all rows — rank, slice, summarize. The agent narrates the result; the script does the math.
61 
62Use available platform recommendations as an optional cross-check when they would help the analysis.
63 
64If a read fails, follow actionable recovery guidance. Clearly report missing evidence; continue independent findings only when the available data supports them.
65 
66**Skip scoring entirely if** `totalSpend == 0` or `activeCampaigns == 0`. Go straight to business context.
67 
68## Phase 2 — Scope handling
69 
70If the user narrows the audit ("focus on one campaign", "campaign X", "just check creative fatigue"):
71 
72- Match campaign names by case-insensitive substring. If no match, list available campaigns and ask.
73- Filter the in-memory dataset before scoring — no extra API calls.
74- Account-level dimensions (Pixel health, attribution defaults) stay account-wide. Note "Scoped to: X" in the report.
75- Skip Phase 4 (business context refresh) on scoped audits if `business-context.json` is fresh.
76 
77## Phase 3 — Score
78 
79Score each of the 7 dimensions 0–5 using `references/account-health-scoring.md`. Overall = `round(sum × 100 / 35)`.
80 
81| Score | Label | Meaning |
82|---|---|---|
83| 0 | Critical | Broken or missing — actively losing money |
84| 1 | Poor | Major waste or missed opportunity |
85| 2 | Needs Work | Several clear issues |
86| 3 | Acceptable | Functional, room to improve |
87| 4 | Good | Well-managed, minor opportunities |
88| 5 | Excellent | Best-practice |
89 
90Scope-aware: campaign-level dimensions reflect in-scope data; account-level dimensions (Pixel + CAPI, attribution setup) score account-wide with a note on scope impact.
91 
92### Encoded heuristics — apply these, they aren't obvious
93 
94- **Pixel + CAPI is upstream of everything.** EMQ < 7.0 means Meta can't match events well — Smart Bidding starves regardless of how good the creative is. STOP-condition input.
95- **Reported ROAS systematically overstates true ROAS.** Cross-check Meta-reported numbers against Shopify / GA4 / MMM where possible. The gap is the modeled-conversion premium and is typically 20–40% in ecom.
96- **Frequency × CPM trend = creative diagnosis.** Frequency > 3.0 with CPM rising ≥ 30% w/w is fatigue — recommend creative refresh, not budget cuts.
97- **One ad set carrying > 70% of a campaign is fragility, not concentration.** When it fatigues, the campaign collapses.
98- **Audience overlap > 50% between sibling ad sets fragments signal.** Consolidate; don't try to "fix" with bid caps.
99- **Special Ad Category misclassification is a takedown risk, not just a policy nit.** Surface as Critical regardless of current performance.
100- **Manual placements without evidence is a sign of inherited-from-2018 thinking.** Default should be Advantage+ Placements; deviations need data.
101 
102### Pixel + Tracking Diagnosis Matrix
103 
104| | EMQ < 5 | EMQ 5–6.9 | EMQ 7.0+ |
105|---|---|---|---|
106| **CAPI off** | Critical — flying blind | Critical — most events lost | High — leaving 15–25% of events on the table |
107| **CAPI on, dedup off** | Critical — duplicated and weak signal | High — duplicate counting risk | Medium — match quality improves with dedup |
108| **CAPI on, dedup on** | High — match quality is the bottleneck | Medium — improve event_id coverage | Healthy |
109 
110## Phase 4 — Business context
111 
112Derive what you can from the data already pulled:
113 
114| Field | Source |
115|---|---|
116| `business_name` | Ad account name (`/{accountId}` `name` field) |
117| `services` | Top campaigns by spend, ad set names, top-converting ad creatives |
118| `locations` | Targeting geo summary (countries / regions in active ad sets) |
119| `brand_voice` | Top-performing ad copy (primary text + headline) |
120| `creative_inventory.formats` | Mix of image / video / carousel observed in active ads |
121| `creative_inventory.aspect_ratios` | Aspect ratios across active ads (1:1, 4:5, 9:16) |
122| `meta_funnel_events.conversion` | Most common optimization event on top-spending ad sets |
123| `custom_audiences` | Custom audiences referenced in active ad set targeting |
124| `pixel_health` | From the Pixel detail call |
125| `website` | Apex domain from active ad final URLs |
126 
127Then crawl the website (homepage + about + 1–2 top landing pages, parallel `WebFetch`) and merge into the schema. See `references/business-context.md` for the full crawl procedure.
128 
129Always ask the user: differentiators, competitors, seasonality, **AOV + profit margin** (essential for ROAS-aware scoring). Ask for everything else only if data + crawl can't answer it.
130 
131## Phase 5 — Personas
132 
133Discover 2–3 personas from creative performance (which angles convert), top-spending audiences, and landing-page content — all from the dataset already in memory. Persist to `{data_dir}/meta/personas/{accountId}.json`. Each persona must be grounded in **observable evidence** (a converting ad set, a converting creative angle, a landing-page section) — no inventing. See `references/persona-discovery.md`.
134 
135## Phase 6 — Report
136 
137Lead with the verdict, then the top 3 actions (with dollar impact when possible), then the scorecard, then evidence for dimensions scoring 0–2 only. Cite specific campaigns, ad sets, ads, and dollar amounts. Cap at ~80 lines.
138 
139State where any audit artifacts were actually saved. Do not claim hosted audit history unless a live result confirms it.
140 
141## Guardrails
142 
1431. **Read-only skill.** Diagnose; don't mutate. Every fix routes through `/meta-ads`. End the report with one handoff tied to the #1 action.
1442. **STOP condition** — if Pixel health scores 0–1 (EMQ < 5 or CAPI off in an ecom account), recommend pausing scaling decisions until tracking is fixed before recommending anything else. Everything downstream is unreliable.
1453. **Always persist** `meta/business-context.json` and `meta/personas/{accountId}.json` even if the report itself is short — downstream skills depend on them.
1464. **Name names.** Every finding cites specific campaigns, ad sets, ad creatives, and dollar amounts. "Some ad sets are underperforming" is not a finding.
1475. **Never report Meta-reported ROAS without footnoting the modeled-conversion premium.** "ROAS 3.2× (Meta-reported, 7DC1DV — typically overstates Shopify-attributed ROAS by 20–40%)" is honest. "ROAS 3.2×" is misleading.
148 

Discussion

Alternatives

Also in Social & retail adsSee all 364 in Marketing →
Ad creativeWhen the user wants to generate, iterate, or scale ad creative — headlines, descriptions, primary text, or full ad variations — for any paid advertising platform. Also use when the user mentions 'ad copy variations,' 'ad creative,' 'generate headlines,' 'RSA headlines,' 'bulk ad copy,' 'ad iterations,' 'creative testing,' 'write me some ads,' 'Facebook ad copy,' 'Google ad headlines,' 'LinkedIn ad text,' 'static ads,' 'ad templates,' 'iMessage ad,' 'chat reveal ad,' 'ChatGPT ad,' 'Apple Notes ad,' 'AirDrop ad,' 'creative strategy,' 'creative roadmap,' 'creative retro,' 'hook writing,' 'creative review page,' 'present ad creative for approval,' 'motion video ad,' 'faceless video ad,' 'UGC ad,' 'greenscreen ad,' 'TikTok/Reels ad format,' 'which ad format to make,' 'Meta ad format tier list,' or 'creative format taxonomy.' Use this whenever someone needs to produce ad copy at scale or iterate on existing ads. For campaign strategy and targeting, see ads. For landing page copy, see copywriting.Marketing · MITAmazon Ads AuditYou share your Amazon advertising numbers and goals; you get back a plain-language review of what's draining your budget and what to change first.Business & ops · MITApple Ads AuditPaste what you're spending on Apple Search Ads and your recent numbers; get back a plain review of what's wasting money and what to fix first.Business & ops · MITAd campaign managementUse when creating, managing, or optimizing paid advertising campaigns across any platform. Covers ad copy generation, ad creative strategy, campaign management, and competitive intelligence. Triggers on: ad copy, ad creative, paid ads, paid advertising, Facebook ads, LinkedIn ads, Google ads, Meta ads, ad campaign, ad strategy, ad testing, competitive ads, competitor ads, ad library, ad analysis, ad creative generation, campaign management, ROAS, CPC, CTR. Use this skill whenever the user mentions ads, paid channels, ad campaigns, ad copy, ad performance, or wants to analyze competitor advertising.Marketing · MIT