Kai daily ad review
Skill cgallic/kai-cmo-harness/harness/skills/kai-daily-ad-review
Open-source AI CMO for Claude Code: marketing agent skills for SEO, content, email, ads, launches, CRO, AEO/GEO, and AI-search visibility.
npx -y skills add cgallic/kai-cmo-harness --skill kai-daily-ad-reviewAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
Daily ad performance check-in across platforms. Pulls live metrics from Meta, Google, and LinkedIn via deterministic scripts, compares against benchmarks and previous period, flags overspend/underperformers/policy issues, and outputs a quick daily summary with action items. Use when "daily ad review", "how are my ads doing today", "ad check-in", "morning ad report", "daily ad summary", "check ad performance", "ad dashboard", "daily ads", or any request for a recurring or quick-glance ad performance review.
SKILL.md
10.2 KB, as published. Nobody here has run it
Daily ad performance check-in. Pull live data via scripts, compare against benchmarks, flag problems, output a summary with action items.
This is NOT the same as /kai-ad-campaign (which creates/evaluates campaigns end-to-end). This is a fast daily pulse check — meant to run every morning or on-demand.
Phase 0: Pull Ad Data
Run the unified pull script. It auto-detects which platforms have credentials and pulls everything.
python scripts/ads/pull_all.py
This writes structured JSON to workspace/ads/pulls/YYYY-MM-DD/:
meta.json— Full Meta/Facebook/Instagram data (if META_ACCESS_TOKEN configured)google.json— Full Google Ads data (if GOOGLE_ADS_* configured)linkedin.json— Full LinkedIn Ads data (if LINKEDINADS_* configured)summary.json— Cross-platform totals
To pull a specific platform only: python scripts/ads/pull_all.py --platforms meta
What the scripts pull (comprehensive)
Meta (scripts/ads/meta.py pull):
- Account insights: today, yesterday, 7d, 14d, 28d
- Campaign insights: 7d aggregate + 14d daily breakdown
- Ad set insights: 7d aggregate + 14d daily + targeting spec with LAL/audience classification
- Ad insights: 7d with creative details
- Breakdowns: age/gender, platform/position, device
- Fields include: impressions, reach, frequency, spend, clicks, unique_clicks, ctr, unique_ctr, cpc, cpm, actions, cost_per_action_type, conversions, quality_ranking, engagement_rate_ranking, conversion_rate_ranking, video_p25/50/75/100, video_thruplay
- Mutations:
meta.py pause/activate/budget/create-campaign/create-adset/create-ad/upload-image/upload-video/duplicate-adset(dry-run by default,--executeto apply)
Google (scripts/ads/google.py pull):
- Campaign performance: 30d daily breakdown
- Ad group performance: 14d daily
- Ad performance: 14d aggregate with RSA headline/description details
- Search terms report: top 100 by spend (7d)
- Audience segments: campaign-level
- Keyword quality scores: quality_score, creative_quality, post_click_quality, predicted_ctr
- Mutations:
google.py pause/activate/budget/add-negative(dry-run by default,--executeto apply)
LinkedIn (scripts/ads/linkedin.py pull):
- Campaign group and campaign insights: 7d, 14d daily, 28d
- Creative-level insights: 7d
- Audience breakdowns: company size, industry, job function, seniority, country
- Audience classification from targeting criteria
- Mutations:
linkedin.py pause/activate/budget(dry-run by default,--executeto apply)
If a platform isn't configured
The script will skip it and log which env vars are missing. At minimum, Meta should be configured:
META_ACCESS_TOKEN=<long-lived token>
META_AD_ACCOUNT_ID=<numeric, without act_ prefix>
Phase 1: Read and Analyze Pull Data
Read the JSON files from today's pull:
import json
from pathlib import Path
date = "YYYY-MM-DD" # today's date
pull_dir = Path(f"workspace/ads/pulls/{date}")
# Read whatever's available
> **Kai root note:** `knowledge/`, `harness/`, and `scripts/` paths in this skill live in the Kai install, not the user's project. Resolve them against the first ancestor directory of this SKILL.md that contains a `knowledge/` folder (the Kai plugin root, `~/.claude/kai`, or the kai-cmo-harness repo). `MARKETING.md`, `memory/`, and any output files live in the current project. If a referenced `scripts/` command is not available in this install, say so, skip it, and continue with the file-based guidance — never fabricate its output.
for f in pull_dir.glob("*.json"):
with open(f) as fh:
data = json.load(fh)
# Analyze...
Key metrics to extract per platform
From Meta (meta.json):
account_insights.last_7d→ spend, impressions, reach, frequency, ctr, cpccampaigns[].insights_7d→ per-campaign performanceadsets[].audience_type→ LAL vs custom vs interest vs advantage+ vs broadadsets[].insights_daily→ day-by-day trends for fatigue detectionads[].insights_7d→ per-ad creative performanceads[].insights_7d.quality_ranking→ Meta's diagnostic: ABOVE_AVERAGE_35, AVERAGE, BELOW_AVERAGE_35breakdowns.age_gender→ demographic performancebreakdowns.platform_position→ FB Feed vs IG Reels vs Stories etc.
From Google (google.json):
campaigns[].insights_daily→ day-by-day CPC/CPA trendssearch_terms→ wasted spend on irrelevant querieskeyword_quality→ quality score distribution (flag anything < 5)audience_segments→ which audiences are converting
From LinkedIn (linkedin.json):
campaigns[].insights_7d→ engagement rate (higher baseline than Meta/Google)breakdowns.industry+breakdowns.job_function→ who's engagingcampaigns[].audience_type→ matched audience vs professional targeting
Phase 2: Cross-Reference with PostHog
Load: harness/references/posthog-marketing-queries.md
If PostHog is connected, pull:
- Today's ad traffic — pageviews with UTM breakdown (query #2)
- Conversion events — campaign attribution (query #8)
- Landing page bounce — for pages receiving ad traffic
This connects ad spend to actual on-site behavior.
Phase 3: Benchmark Comparison
Performance Benchmarks
| Metric | Poor | OK | Good | Great |
|---|---|---|---|---|
| CTR | < 0.5% | 0.5-1% | 1-2% | > 2% |
| CPC | > $5 | $3-5 | $1.50-3 | < $1.50 |
| CPL | > $50 | $30-50 | $15-30 | < $15 |
| ROAS | < 1x | 1-2x | 2-4x | > 4x |
| Frequency | > 4.0 | 3.0-4.0 | 1.5-3.0 | 1.0-1.5 |
Adjust benchmarks to the vertical (from MARKETING.md if available).
Trend Detection
Compare today vs 7-day average:
- Spend: flag if today's pace > 120% of daily average (overspend)
- CTR: flag if today < 70% of 7-day avg (creative fatigue)
- CPC: flag if today > 130% of 7-day avg (competition spike or audience saturation)
- Conversions: flag if today < 50% of daily avg (broken funnel or tracking issue)
- Frequency: flag if > 3.0 (audience seeing ads too often — fatigue incoming)
- Quality ranking: flag if BELOW_AVERAGE_35 on any diagnostic dimension
Audience Performance (from LAL tagging)
Compare ad set performance by audience_type:
- LAL audiences should have lower CPL than broad
- Custom retarget audiences should have highest CTR
- If Advantage+ is outperforming manual targeting, note it
- If LAL is underperforming interest targeting, flag for investigation
Phase 4: Issue Detection
Flag these automatically:
| Issue | Trigger | Severity |
|---|---|---|
| Overspend | Daily spend pace > 120% of budget | HIGH |
| Zero impressions | Active ad with 0 impressions today | HIGH |
| CTR crash | CTR < 50% of 7-day avg | HIGH |
| CPC spike | CPC > 150% of 7-day avg | MEDIUM |
| No conversions | Spend > $50 today with 0 conversions | MEDIUM |
| Creative fatigue | CTR declining 3+ consecutive days | MEDIUM |
| Frequency overload | Frequency > 3.5 on any ad set | MEDIUM |
| Quality warning | Any ad with BELOW_AVERAGE quality ranking | MEDIUM |
| Budget underspend | < 50% of daily budget used by midday | LOW |
| Learning phase | Ad set in learning phase > 7 days | LOW |
| LAL underperform | LAL CPL > broad/interest CPL | LOW |
| Wasted search spend | Google search term with > $20 spend, 0 conversions | MEDIUM |
Phase 5: Daily Summary Output
Output format — keep it scannable:
# Daily Ad Review — [Date]
## Snapshot
| Metric | Today | 7-Day Avg | Trend |
|--------|-------|-----------|-------|
| Spend | $X | $X/day | up/down/flat |
| Impressions | X | X/day | |
| Reach | X | X/day | |
| Frequency | X.X | X.X | |
| Clicks | X | X/day | |
| CTR | X% | X% | |
| CPC | $X | $X | |
| Conversions | X | X/day | |
| CPL | $X | $X | |
## Flags
- [HIGH] Overspend: Campaign "X" pacing 140% of daily budget
- [MEDIUM] Frequency: Ad set "Y" at 3.8 — rotate creative or expand audience
- [MEDIUM] Quality: Ad "Z" has BELOW_AVERAGE engagement ranking
## Audience Performance
| Audience Type | Ad Sets | Spend | Leads | CPL | CTR |
|---------------|---------|-------|-------|-----|-----|
| Lookalike 1% | 2 | $X | X | $X | X% |
| Custom Retarget | 1 | $X | X | $X | X% |
| Interest | 1 | $X | X | $X | X% |
| Advantage+ | 1 | $X | X | $X | X% |
## Campaign Breakdown
| Campaign | Spend | Clicks | CTR | CPC | Conversions | CPL | Status |
|----------|-------|--------|-----|-----|-------------|-----|--------|
## Top Performers
1. [Ad name] — [metric that makes it stand out]
2. [Ad name] — [metric]
## Underperformers
1. [Ad name] — [what's wrong] — **Action:** [pause/adjust/replace creative]
2. [Ad name] — [what's wrong] — **Action:** [specific fix]
## Quality Diagnostics
| Ad | Quality | Engagement | Conversion |
|----|---------|------------|------------|
(only show non-ABOVE_AVERAGE entries)
## Action Items
- [ ] [Specific action with campaign/ad name]
- [ ] [Specific action]
- [ ] [Specific action]
Write output to workspace/ads/daily-reviews/[YYYY-MM-DD]-daily-review.md.
Phase 6: Historical Tracking
If previous daily reviews exist in workspace/ads/daily-reviews/, compare:
- Week-over-week spend trend
- Which flags are recurring (persistent issues need
/kai-ad-campaignevaluation) - Which action items from yesterday were addressed
If previous pull data exists in workspace/ads/pulls/, diff today's metrics against yesterday's for precise trend detection.
If the same flag appears 3+ days in a row, escalate: recommend running /kai-ad-campaign in evaluation mode for a deeper audit.
Scheduling
This skill is designed to run daily. Recommend the user set up a schedule:
/scheduleto create a recurring morning trigger- Or run manually with
/kai-daily-ad-review