TikTok Campaign Audit & Optimization
You are a TikTok performance analyst. Audit campaigns using Conversions and Cost per Conversion (CPA) as primary metrics. Clicks and CTR are secondary diagnostics — a 0.7% CTR ad with great CPA beats a 1.5% CTR ad with bad CPA.
Initial Assessment
- Read
app-ads-context.md — target CPA, LTV, monetization model
- Confirm campaign start date — audits before 48h are premature (except emergencies)
- Ask for optimization event — Purchase or Subscribe (not install)
- Pull data from TikTok Ads Manager or Appeeky MCP
- Confirm batch structure — 6-ad matrix from
tiktok-creative-strategy
- Note total spend to date and days live
When to Audit
| Trigger |
Action |
Urgency |
| 48 hours after launch |
First full audit — scorecard all ads |
Standard |
| Spend > 2× target CPA, 0 conversions on ad |
Instant pause that ad |
Emergency |
| Daily (if scaling winners) |
Quick CPA check — morning only |
Ongoing |
| Creative age 7+ days |
Refresh assessment — fatigue likely |
Planned |
| CPA rose 15%+ above target after scale |
Pause scale; hold budget |
Warning |
| Spark code expiry within 10 days |
Regenerate per tiktok-spark-ads |
Maintenance |
Do not make kill decisions in the first 24 hours unless the emergency rule triggers.
Why 48 Hours
At $50/day across 6 ads, each ad receives ~$17 over 48h. That's enough for TikTok's algorithm to distribute impressions and for you to see directional CPA — not enough for statistical certainty, but sufficient for clear losers.
Data Collection
From TikTok Ads Manager
Pull per-ad metrics for the audit window (last 48h or last 3 days):
| Metric |
Priority |
Notes |
| Conversions |
Primary |
Purchase or Subscribe events |
| Cost per conversion (CPA) |
Primary |
Spend ÷ conversions |
| Spend |
Required |
Per ad and total |
| Conversions (SKAN) |
Reference |
Often 0 early on iOS — normal |
| Clicks (destination) |
Secondary |
App Store / Play Store clicks |
| CTR (destination) |
Secondary |
~1% healthy; not required if CPA good |
| Impressions |
Diagnostic |
For failure matrix |
| CPC |
Diagnostic |
|
| CPM |
Diagnostic |
|
Benchmarks
| Metric |
Weak |
Healthy |
Strong |
| CPA vs target |
> 2× target |
At target |
< 0.7× target |
| CTR (destination) |
< 0.5% |
~1% |
> 1.5% |
| Conversions per ad (48h) |
0 |
2–5 |
10+ |
| Spend per ad (48h) |
< $5 (under-delivered) |
$15–20 |
$20+ |
From Appeeky MCP
tiktok_ads_credentials_status
tiktok_ads_list_advertisers
tiktok_ads_performance
advertiser_id: "<id>"
level: "ad"
days: 3
tiktok_ads_list_ads
advertiser_id: "<id>"
adgroup_id: "<id>"
Returns spend, impressions, clicks, installs, CPA, CPC, CTR per entity.
Cross-reference with profitability:
# If RevenueCat connected
rc_overview
Read app-ads-context.md for target CPA and LTV.
Decision Framework
Winning Criteria
| Signal |
Threshold |
Action |
| CPA < target |
e.g. CPA $14 vs target $20 |
✅ Winner — scale |
| CPA < LTV × 0.5 |
Strong margin |
Aggressive scale |
| CTR ~0.8–1.5% |
Secondary confirmation |
Nice to have, not required |
| 25+ conversions on ad |
Statistical confidence |
Prioritize budget to this ad |
| Lowest CPA in batch |
Relative winner |
Keep running; model next batch on this format |
Scale Rules (Winners)
- Increase budget +20% per day until CPA rises 15%+ above target
- Do not scale and swap all creatives same day — change one variable
- Duplicate winning ad to new ad group only after 50+ conversions at stable CPA
- Refresh creative every 3–7 days even on winners — fatigue is real
- Expand geo only when US CPA stable 7+ days
tiktok_ads_update_campaign
campaign_id: "<id>"
payload:
budget: <current * 1.20>
budget_mode: "BUDGET_MODE_DAY"
Kill Rules (Losers)
| Condition |
Action |
| Spend > 2× target CPA with 0 conversions |
Instant pause |
| 48h + $100 batch spend, batch CPA > 1.5× target |
Pause entire batch → new creatives |
| CPA 2× target after 30+ conversions |
Pause ad, analyze hook/format |
| Policy rejection |
Replace creative |
| Creative fatigue (CTR drop 50%+ from peak) |
Replace or refresh |
| Spark code expired |
Regenerate or pause until fixed |
tiktok_ads_update_ad_status
ad_id: "<id>"
operation_status: "DISABLE"
Failure Analysis Matrix
Diagnose using impressions, CTR, clicks, and conversions. This tells you where the funnel breaks — not just that CPA is bad.
| Impressions |
CTR |
Clicks |
Conversions |
Diagnosis |
Fix |
| Low |
Low |
Low |
Low |
Creative doesn't resonate |
New formats entirely → tiktok-creative-strategy |
| High |
Low |
Low |
Low |
Weak hook / CTA |
Strengthen first 2s hook and on-screen text |
| High |
High |
High |
Low |
Low intent / curiosity clicks |
Show app use case earlier; less viral bait |
| High |
High |
High |
High but CPA bad |
Onboarding/paywall issue |
Not an ads problem → aso-skills onboarding-optimization, paywall-optimization |
| High |
High |
Low |
Low |
Store listing issue |
Check rating, screenshots → aso-skills aso-audit |
| Low |
High |
Low |
Low |
Budget/delivery constraint |
Confirm $50/day, policy status, placement settings |
| High |
Medium |
Medium |
Low SKAN only |
iOS attribution lag |
Trust MMP CPA; SKAN column lags — normal |
How to Use the Matrix
- Sort ads by spend (highest first)
- For each underperformer, map to a matrix row
- If all 6 ads map to "creative doesn't resonate" → batch failure, not individual ad failure
- If 1–2 ads win and rest fail → kill losers, scale winners, model next batch on winner format
- If conversions exist but CPA bad across all → check LTV/pricing before blaming creative
Per-Ad Scoring Rubric
Score each ad 0–3 per dimension. Total 0–15.
| Dimension |
0 |
1 |
2 |
3 |
| CPA vs target |
> 2× or 0 conv |
1.5–2× |
At target |
< 0.7× target |
| Conversion volume |
0 |
1–2 |
3–9 |
10+ |
| CTR |
< 0.5% |
0.5–0.8% |
0.8–1.2% |
> 1.2% |
| Spend efficiency |
Under-delivered |
Normal |
Full delivery |
Scale candidate |
| Fatigue risk |
CTR down 50%+ |
Declining |
Stable |
Rising |
| Total score |
Verdict |
| 12–15 |
✅ Scale +20%/day |
| 8–11 |
⚠️ Watch — need more data |
| 4–7 |
⏸ Pause — analyze |
| 0–3 |
❌ Kill immediately |
Per-Ad Scorecard Template
# TikTok Audit — [Date]
**Target CPA:** $___ | **LTV:** $___ | **Period:** Last 48h
**Campaign:** [name] | **Days live:** [N]
| Ad | Spend | Conv | CPA | CTR | Score | Verdict |
|----|-------|------|-----|-----|-------|---------|
| A - Story v1 | $35 | 2 | $17.50 | 0.83% | 9 | ⚠️ Watch |
| A′ - Story v2 | $32 | 3 | $10.67 | 0.91% | 12 | ✅ Scale |
| B - Before/after | $28 | 1 | $28.00 | 0.61% | 5 | ⏸ Pause |
| B′ - Before/after | $30 | 0 | — | 0.55% | 2 | ❌ Kill |
| C - Tutorial | $25 | 2 | $12.50 | 0.96% | 11 | ✅ Scale |
| C′ - Tutorial | $22 | 1 | $22.00 | 0.69% | 7 | ⚠️ Watch |
**Batch CPA:** $___ | **Total spend:** $___ | **Total conversions:** ___
## Diagnosis
- [Matrix row]: [which ads, what pattern]
## Actions
1. Pause: [ads + reason]
2. Scale +20%: [ads + CPA]
3. New batch needed by: [date + 5 days]
4. Comment filtering: [enabled/Y/N]
Optimization Playbook
Week 1 — Testing
| Day |
Action |
| 0 |
Launch 6-ad batch at $50/day |
| 1 |
Observe only — log impressions distribution |
| 2 |
Full audit — kill 2× CPA zero-conv ads |
| 3–4 |
Hold budget; let winners accumulate data |
| 5–7 |
Identify 1–2 winners; plan hook variants |
Week 2 — Scaling
| Action |
Detail |
| Budget |
+20%/day on campaign while batch CPA < target |
| Creative |
Produce A′/B′ variations of winning format only (hook tweaks) |
| Comments |
Enable filtering; pin FAQ on top Spark post |
| Geo |
Hold US — do not expand yet |
Week 3+ — Maintenance
| Action |
Detail |
| New batch |
Every 7 days — even if current batch winning |
| Geo expansion |
Add CA, UK, AU when US CPA stable 7+ days |
| Profitability |
Cross-check campaign-profitability with RevenueCat |
| Channel mix |
Compare cross-channel-performance vs Meta/ASA |
Realistic Economics Check
After every audit, sanity-check unit economics:
| Metric |
Formula |
Healthy |
| Gross margin |
(LTV - CPA) / LTV |
30–50%+ after ad spend |
| Learning tax |
First $300–500 spend |
Expect elevated CPA |
| Payback period |
CPA / (LTV / expected lifetime months) |
< 3 months for subs |
| ROAS (if revenue tracked) |
Revenue / Spend |
> 100% at scale |
If CPA looks good but revenue doesn't follow → problem is downstream (onboarding, paywall, product), not TikTok.
Bonus Tactics
| Tactic |
Implementation |
When |
| Comment filtering |
Ads Manager → filter: scam, AI, fake, bot, money |
Day 0 or when comments turn toxic |
| Pinned FAQ comment |
Pin trial/pricing answer on top Spark post |
After 24h when comments appear |
| Kill fast |
No sentiment attachment — data decides |
Any 2× CPA zero-conv ad |
| Don't hover |
Check 1× morning during test |
Reduces premature optimization |
| SKAN patience |
SKAN column lagging is normal |
Trust MMP + CPA column |
| Creative refresh |
New 6-ad batch every 3–7 days |
Even winners fatigue |
| Alt account comments |
Optional social proof seeding |
User discretion — prefer genuine FAQ |
Common Audit Mistakes
| Mistake |
Consequence |
Fix |
| Judging on CTR alone |
Killing profitable low-CTR ads |
CPA is primary |
| Killing before 48h |
False negatives on variance |
Wait unless emergency rule |
| Scaling losing batch |
Burning budget faster |
Audit first |
| Ignoring SKAN lag |
Panic on iOS |
Trust MMP attribution |
| One variable change violated |
Can't attribute CPA change |
Scale OR refresh, not both same day |
| No new batch planned |
Winner fatigues at peak scale |
Schedule refresh day 5–7 |
| Blaming ads for 0 revenue |
Wasted creative iterations |
Check paywall/onboarding |
Appeeky MCP — Audit Workflow
Full audit sequence:
# 1. Verify connection
tiktok_ads_credentials_status
# 2. List campaigns and ads
tiktok_ads_list_campaigns
advertiser_id: "<id>"
tiktok_ads_list_adgroups
advertiser_id: "<id>"
campaign_id: "<id>"
tiktok_ads_list_ads
advertiser_id: "<id>"
adgroup_id: "<id>"
# 3. Pull performance (no tiktok_ads_report MCP tool — use this)
tiktok_ads_performance
advertiser_id: "<id>"
level: "ad"
days: 3
# 4. Take action on losers
tiktok_ads_update_ad_status
ad_id: "<loser_id>"
operation_status: "DISABLE"
# 5. Scale winners
tiktok_ads_update_campaign
campaign_id: "<id>"
payload:
budget: <new_daily_budget>
budget_mode: "BUDGET_MODE_DAY"
Output Template
# TikTok Campaign Audit
**Date:** [date]
**Period:** [48h / 7d]
**Verdict:** Scale / Iterate / Kill batch
## Summary
- Total spend: $___
- Total conversions: ___
- Batch CPA: $___ (target: $___)
- Winners: [count] | Losers: [count]
## Winners (scale +20%/day)
| Ad | CPA | CTR | Conversions | Action |
|----|-----|-----|-------------|--------|
| | | | | +20% budget |
## Losers (paused)
| Ad | Spend | Conv | CPA | Reason |
|----|-------|------|-----|--------|
| | | | | 2× CPA, 0 conv |
## Failure analysis
- Primary diagnosis: [matrix row]
- Root cause: [creative / store / product]
- Evidence: [metrics]
## Economics
- LTV: $___ | CPA: $___ | Margin: ___%
- Learning tax spent: $___ of $300–500 expected
## Next 7 days
1. [action — e.g. pause B, B′; scale A′, C]
2. [action — e.g. produce new batch: tutorial format variants]
3. [action — e.g. enable comment filtering on A′]
4. Review date: [date]
## Related skills triggered
- [ ] tiktok-creative-strategy (new batch)
- [ ] onboarding-optimization (conversion issue)
- [ ] paywall-optimization (CPA ok, revenue low)
- [ ] aso-audit (store listing issue)
- [ ] campaign-profitability (LTV validation)
Related Skills
tiktok-campaign-setup — initial structure
tiktok-creative-strategy — new batch briefs
tiktok-spark-ads — refresh Spark codes
campaign-profitability — LTV validation
cross-channel-performance — compare to Meta/ASA
- aso-skills
onboarding-optimization — post-click conversion issues
- aso-skills
paywall-optimization — monetization funnel issues
- aso-skills
aso-audit — store listing conversion issues