agentsclimarketplace

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.

Install
npx -y skills add cgallic/kai-cmo-harness --skill kai-daily-ad-review

Assembled 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, --execute to 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, --execute to 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, --execute to 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, cpc
  • campaigns[].insights_7d → per-campaign performance
  • adsets[].audience_type → LAL vs custom vs interest vs advantage+ vs broad
  • adsets[].insights_daily → day-by-day trends for fatigue detection
  • ads[].insights_7d → per-ad creative performance
  • ads[].insights_7d.quality_ranking → Meta's diagnostic: ABOVE_AVERAGE_35, AVERAGE, BELOW_AVERAGE_35
  • breakdowns.age_gender → demographic performance
  • breakdowns.platform_position → FB Feed vs IG Reels vs Stories etc.

From Google (google.json):

  • campaigns[].insights_daily → day-by-day CPC/CPA trends
  • search_terms → wasted spend on irrelevant queries
  • keyword_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 engaging
  • campaigns[].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

MetricPoorOKGoodGreat
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< 1x1-2x2-4x> 4x
Frequency> 4.03.0-4.01.5-3.01.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:

IssueTriggerSeverity
OverspendDaily spend pace > 120% of budgetHIGH
Zero impressionsActive ad with 0 impressions todayHIGH
CTR crashCTR < 50% of 7-day avgHIGH
CPC spikeCPC > 150% of 7-day avgMEDIUM
No conversionsSpend > $50 today with 0 conversionsMEDIUM
Creative fatigueCTR declining 3+ consecutive daysMEDIUM
Frequency overloadFrequency > 3.5 on any ad setMEDIUM
Quality warningAny ad with BELOW_AVERAGE quality rankingMEDIUM
Budget underspend< 50% of daily budget used by middayLOW
Learning phaseAd set in learning phase > 7 daysLOW
LAL underperformLAL CPL > broad/interest CPLLOW
Wasted search spendGoogle search term with > $20 spend, 0 conversionsMEDIUM

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-campaign evaluation)
  • 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:

  • /schedule to create a recurring morning trigger
  • Or run manually with /kai-daily-ad-review

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.