Ad Account Audit
Audit a paid search or paid social account export for conversion-tracking gaps, budget pacing outliers, disapproved and limited ads, naming-convention drift, negative-keyword coverage and stale creative, returning severity-ranked findings…
At a glance
Ad Account Audit is an AI skill that you can use in Claude Code, Codex, or type.com.
- Updated
See an example
Example output from a sample run. Company names and figures are sample data.
Paid account audit: Aurora Bikeworks — Google Ads (US/CA), 2026-09-01 to 2026-09-21
14 findings across 9 campaigns and $16,583 of spend. $608 (3.7%) went to search terms that converted zero times and that no negative blocks, and $3,150 (19.0%) sits in a campaign with no recorded conversion. Conversion tracking covers 80.3% of spend.
| Bucket | Amount | % of spend |
|---|---|---|
| Wasted spend | $608 | 3.7% |
| Unmeasured spend | $3,150 | 19.0% |
| Unspent capacity | $4,030 | 24.3% |
| Spend at risk | $7,290 | 44.0% |
| Unattributable by naming | $780 | 4.7% |
Buckets overlap by design, so don't add them together. Only wasted spend can be stopped outright.
| # | Severity | Campaign | Check | Finding | Impact |
|---|---|---|---|---|---|
| 1 | HIGH | AB_US_PMax_AllProducts | Conversion tracking | 4,200 clicks, zero conversions | $3,150 unmeasured |
| 2 | HIGH | AB_US_YouTube_Awareness | Ad approvals | Every enabled ad is disapproved | $2,100 at risk |
| 3 | HIGH | AB_US_YouTube_Awareness | Budget pacing | Delivering only 5.7% of its daily cap | $1,980 unspent |
| 4 | HIGH | AB_US_NonBrand_Search | Negative keywords | 2 unblocked terms, 0 conversions | $235 wasted |
| 5 | HIGH | AB_CA_NonBrand_Search | Negative keywords | 2 unblocked terms, 0 conversions | $208 wasted |
| 6 | HIGH | AB_US_Shopping_Core | Negative keywords | "ebike battery replacement", 0 conversions | $165 wasted |
| 8 | MEDIUM | AB_CA_NonBrand_Search | Negative keywords | No negative keywords configured | $2,520 at risk |
| 9 | MEDIUM | AB_US_Shopping_Core | Budget pacing | Delivering only 61.0% of its daily cap | $2,050 unspent |
…plus 6 more findings in the full report, including 150.0% over-delivery on AB_CA_NonBrand_Search and creative last touched 310 and 356 days ago.
Next actions
- AB_US_PMax_AllProducts: confirm the conversion action is enabled, set as a primary goal, and included in bidding. Re-audit after one full conversion window.
- AB_US_YouTube_Awareness: fix the policy violation on ad-101001 and ad-101002 or rebuild the ads. Until then, move the $100.00/day budget to a campaign that can serve.
- Negatives: block "how to fix a flat bike tire", "bike mechanic salary", "velo electrique occasion" and "bike insurance canada" as phrase negatives, and promote jobs, salary, free and DIY repair to the shared negative list.
- AB_CA_NonBrand_Search: apply the shared negative list as a baseline, then reconcile $120.00/day of spend against its $80.00 daily cap.
Inputs: campaigns, ads, keywords and search-terms exports. AB_US_Legacy_Remarketing (not enabled, $240) is in totals but excluded from every check.
Produced by running bash examples/run.sh on the sample data bundled with this skill.
How to use Ad Account Audit
- type.com: Choose Use Skill to add Ad Account Audit to your type.com workspace.
- Claude Code: Download the skill and extract it into
~/.claude/skills/ad-account-audit/(or.claude/skills/ad-account-audit/in a project). Then ask Claude to use Ad Account Audit. - Codex: Download the skill and extract it into
~/.agents/skills/ad-account-audit/(or.agents/skills/ad-account-audit/in a repository). Then ask Codex to use Ad Account Audit.
AI agents can read this page as Markdown or fetch the raw SKILL.md.
Frequently asked questions
What is Ad Account Audit?
Ad Account Audit is an AI skill that you can use in Claude Code, Codex, or type.com.
What does Ad Account Audit do?
Audit a paid search or paid social account export for conversion-tracking gaps, budget pacing outliers, disapproved and limited ads, naming-convention drift, negative-keyword coverage and stale creative, returning severity-ranked findings…
Can I use Ad Account Audit in Claude Code or Codex?
Yes. Ad Account Audit is a standard Agent Skills folder with a SKILL.md file. Download it and extract it into ~/.claude/skills/ for Claude Code or ~/.agents/skills/ for Codex.
Who created Ad Account Audit?
The type.com team created Ad Account Audit. The type.com team reviews every skill before it is published in the Skills Library.
Related guide
Browse the technical files
---
name: ad-account-audit
description: Audit a paid search or paid social account export for conversion-tracking gaps, budget pacing outliers, disapproved and limited ads, naming-convention drift, negative-keyword coverage and stale creative, returning severity-ranked findings with the dollars each one puts at issue.
---
# Ad account audit
Runs six hygiene checks against four local exports and returns a ranked findings
list. Every finding names the campaign, shows the evidence it was derived from,
attaches a dollar figure, and states the fix.
## Before you run
This skill ships scripts and sample data alongside this SKILL.md. Before running any command:
1. **Get the files.** Make sure the skill's other files (`scripts/`, `examples/` and anything else listed with this skill) are in your working folder at the same relative paths. Some environments load only SKILL.md; if yours did, fetch each file from this skill's published files and write it to the matching path. In Type, read them with the skill-file tools. Anywhere else, the Type Skills Library API lists every file with its path, content and `sha256`: GET `https://api.type.com/api/public/library/skills` and take the entry with slug `ad-account-audit`.
2. **Check the copies are exact.** Compare each file's size in bytes, not characters (and its hash, where your tools report one), with the published version before running. A copy written out from the published file is fine once its byte size and hash match; never run a script you summarised or reconstructed from memory.
3. **Run from the skill's folder**, calling interpreters explicitly: `python3 scripts/…` and `bash examples/run.sh`.
4. **Try the sample first.** If the skill ships `examples/run.sh` and `examples/expected_output.txt`, run `bash examples/run.sh`; its output should match the expected file exactly. If it doesn't, stop and report the first differing line rather than running on real data.
## When to use this
- Onboarding a new account and needing a defensible first-week findings list.
- A recurring (monthly or quarterly) hygiene pass on accounts under management.
- Performance dropped and the first question is whether the account is broken
rather than the market.
- Preparing a pitch: run it on a prospect's export to ground the conversation in
their numbers. (`new-business-pitch-builder` turns the opportunity into a
proposal; this skill finds the problems.)
## Gathering the inputs
Four CSVs, all for the same account and the same date range. Exact columns are
in `DATA_CONTRACT.md`. The script reads local files only — it never calls an ad
platform and never handles credentials.
1. **`campaigns.csv`** — campaign report for the period, with status, daily
budget, spend and conversions. Google Ads: Campaigns view with the date range
set. Meta Ads: Campaigns tab with Amount Spent, Results and Budget columns.
2. **`ads.csv`** — ad-level export including `ad_status`, `approval_status` and
`last_modified`. In Google Ads the policy column is "Status details"/"Policy
details"; map it to `APPROVED`, `LIMITED`, `DISAPPROVED` or `UNDER_REVIEW`.
In Meta, map "Active", "Rejected" and "In Review" to the same four values.
3. **`keywords.csv`** — targeting keywords and negative keywords, with match
type. Use `list_type=negative` for negatives and the literal campaign name
`ACCOUNT` for shared/account-level negative lists.
4. **`search_terms.csv`** — search terms report for the same period, with spend,
clicks and conversions per term.
**Paid-social accounts (Meta, TikTok, LinkedIn) have no keywords or search
terms.** Pass `keywords.csv` and `search_terms.csv` containing only their header
rows (copy the first line of the files in `examples/data/`). The audit then
skips the search-term waste and negative-keyword checks and lists them under
"Audit notes" as not applicable; the other four checks run normally. Wasted
spend will read `$0` because it was not measured, not because none exists.
Set `--period-start` and `--as-of` to the exact first and last day of the export
window. Pacing arithmetic uses that day count, so a mismatch between the export
window and the flags produces wrong pacing findings.
## Running it
First run: `bash examples/run.sh` audits the bundled sample account in
`examples/data/`. To reproduce it by hand, or to point it at your own exports
(replace the `examples/data/` paths with wherever you saved them):
```bash
python3 scripts/audit_account.py \
--campaigns examples/data/campaigns.csv \
--ads examples/data/ads.csv \
--keywords examples/data/keywords.csv \
--search-terms examples/data/search_terms.csv \
--account "Aurora Bikeworks — Google Ads (US/CA)" \
--period-start 2026-09-01 \
--as-of 2026-09-21
```
Tuning flags, all with defaults that suit a mid-size account:
- `--naming-pattern` (default `{brand}_{geo}_{funnel}_{type}`) — set it to the
agency's actual convention. Ask the user rather than guessing; a wrong pattern
turns every campaign into a false positive.
- `--pace-tolerance` (default `0.25`) — fraction above or below the daily cap
before pacing is flagged.
- `--tracking-floor` (default `300`) — minimum campaign spend before a
zero-conversion campaign is reported.
- `--term-floor` (default `50`) and `--waste-share-high` (default `5` percent) —
minimum per-term spend to count as waste, and the share of campaign spend at
which uncovered waste escalates to high severity.
- `--stale-days` (default `90`) and `--material-spend` (default `500`).
- `--json` — same analysis, machine-readable.
## Reading and presenting the output
- **Spend at issue** splits dollars into five buckets that deliberately do not
sum: wasted, unmeasured, unspent, at risk, and unattributable by naming. Only
*wasted* is money that can be stopped outright. Quote that number in client
conversations and describe the others in their own terms — presenting the sum
as "money we found" is the fastest way to lose credibility on the follow-up.
- **Findings** are sorted by severity, then by dollars. Work them top-down. Each
finding's evidence lines are quotable in a client email as-is.
- **Checks that passed** exists so the audit reads as a complete pass rather
than a list of complaints. Keep it in the deliverable.
- **Audit notes** records what could not be checked (campaigns with no ad rows,
shared budgets, paused campaigns, and search-term checks skipped for
paid-social accounts). Close those gaps before claiming full
coverage.
Before sending, sanity-check the highest-value finding against the live account.
Exports go stale, and a disapproval that was fixed yesterday still appears in
yesterday's file.
## Limits
- It audits structure and delivery hygiene, not strategy. It has no opinion on
offer, landing page, audience choice or creative quality.
- Negative-keyword matching approximates the platforms' own matching (exact,
phrase, broad) on tokenized text. It ignores close variants, plurals, stemming
and misspellings, so it can report a term as uncovered that a platform would
in practice have blocked.
- Shared budgets and portfolio bid strategies are not modeled. Campaigns with no
daily budget are skipped for pacing and listed in the notes.
- Wasted spend is measured against the exported period only. It is not
annualized, and it is not a savings guarantee — blocking a query moves budget,
it does not always remove it.
- Zero conversions on real spend is reported as *unmeasured*, never as proven
waste. The skill cannot tell a broken tag from a genuinely unproductive
campaign.
- One account per run. There is no cross-account rollup.