Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Marketing analytics covering campaign analysis, attribution and marketing mix modeling, ROI measurement, and performance reporting. Use when analyzing campaign ROI, comparing attribution models, or optimizing budget allocation.
.claude/skills/borghei-marketing-analyst/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 13% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 259% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 380% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 154% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 82% | 0% |
The agent operates as a senior marketing analyst, delivering campaign performance analysis, multi-touch attribution, marketing mix modeling, ROI measurement, and data-driven budget optimization.
Before running the analysis, confirm these inputs. If any is unknown or vague, ASK — do not assume:
Stop rule: ask only the 2-3 that most change the output. If the user says "just draft it," proceed and list your assumptions at the top of the artifact.
| Metric | Formula | Benchmark | |--------|---------|-----------| | CPL | Spend / Leads | Varies by industry | | CAC | S&M Spend / New Customers | LTV/CAC > 3:1 | | CPA | Spend / Acquisitions | Target specific | | ROAS | Revenue / Ad Spend | > 4:1 |
| Metric | Formula | Benchmark | |--------|---------|-----------| | Engagement Rate | Engagements / Impressions | 1-5% | | CTR | Clicks / Impressions | 0.5-2% | | Conversion Rate | Conversions / Visitors | 2-5% | | Bounce Rate | Single-page sessions / Total | < 50% |
| Metric | Formula | Benchmark | |--------|---------|-----------| | Churn Rate | Lost Customers / Total | < 5% monthly | | NRR | (MRR - Churn + Expansion) / MRR | > 100% | | LTV | ARPU x Gross Margin x Lifetime | 3x+ CAC |
The agent should apply multiple models and compare results to identify channel over/under-valuation:
| Model | Logic | Best For | |-------|-------|----------| | First-touch | 100% credit to first interaction | Measuring awareness channels | | Last-touch | 100% credit to final interaction | Measuring conversion channels | | Linear | Equal credit across all touches | Balanced view of full journey | | Time-decay | More credit to recent touches | Short sales cycles | | Position-based | 40% first, 40% last, 20% middle | Most B2B scenarios |
pythondef calculate_attribution(touchpoints, model='position'): """Calculate attribution credit for a conversion journey. Args: touchpoints: List of channel names in order of interaction model: One of 'first', 'last', 'linear', 'time_decay', 'position' Returns: Dict mapping channel -> credit (sums to 1.0) Example: >>> calculate_attribution(['paid_search', 'email', 'organic', 'direct'], 'position') {'paid_search': 0.4, 'email': 0.1, 'organic': 0.1, 'direct': 0.4} """ n = len(touchpoints) credits = {} if model == 'first': credits[touchpoints[0]] = 1.0 elif model == 'last': credits[touchpoints[-1]] = 1.0 elif model == 'linear': for tp in touchpoints: credits[tp] = credits.get(tp, 0) + 1.0 / n elif model == 'time_decay': decay = 0.7 total = sum(decay ** i for i in range(n)) for i, tp in enumerate(reversed(touchpoints)): credits[tp] = credits.get(tp, 0) + (decay ** i) / total elif model == 'position': if n == 1: credits[touchpoints[0]] = 1.0 elif n == 2: credits[touchpoints[0]] = 0.5 credits[touchpoints[-1]] = credits.get(touchpoints[-1], 0) + 0.5 else: credits[touchpoints[0]] = 0.4 credits[touchpoints[-1]] = credits.get(touchpoints[-1], 0) + 0.4 for tp in touchpoints[1:-1]: credits[tp] = credits.get(tp, 0) + 0.2 / (n - 2) return credits
markdown# Campaign Analysis: Q1 2026 Product Launch ## Performance Summary | Metric | Target | Actual | vs Target | |--------------|---------|---------|-----------| | Impressions | 500K | 612K | +22% | | Clicks | 25K | 28.4K | +14% | | Leads | 1,200 | 1,350 | +13% | | MQLs | 360 | 410 | +14% | | Pipeline | $1.2M | $1.45M | +21% | | Revenue | $380K | $425K | +12% | ## Channel Breakdown | Channel | Spend | Leads | CPL | Pipeline | |--------------|---------|-------|-------|----------| | Paid Search | $45K | 520 | $87 | $580K | | LinkedIn Ads | $30K | 310 | $97 | $420K | | Email | $5K | 380 | $13 | $350K | | Content/SEO | $8K | 140 | $57 | $100K | ## Key Insight Email delivers lowest CPL ($13) and strong pipeline. Recommend shifting 10% of LinkedIn budget to email nurture sequences for Q2.
Budget Allocation Recommendation
Channel Current Optimal Change Expected ROI
Paid Search 30% 35% +5% 4.2x
Social Paid 25% 20% -5% 2.8x
Display 15% 10% -5% 1.5x
Email 10% 15% +5% 8.5x
Content 10% 12% +2% 5.2x
Events 10% 8% -2% 2.2x
Projected Impact: +15% pipeline with same budgetpythonfrom scipy import stats import numpy as np def analyze_ab_test(control_conv, control_total, treatment_conv, treatment_total, alpha=0.05): """Analyze A/B test for statistical significance. Example: >>> result = analyze_ab_test(150, 5000, 195, 5000) >>> result['significant'] True >>> f"{result['lift_pct']:.1f}%" '30.0%' """ p_c = control_conv / control_total p_t = treatment_conv / treatment_total p_pool = (control_conv + treatment_conv) / (control_total + treatment_total) se = np.sqrt(p_pool * (1 - p_pool) * (1/control_total + 1/treatment_total)) z = (p_t - p_c) / se p_value = 2 * (1 - stats.norm.cdf(abs(z))) return { 'control_rate': p_c, 'treatment_rate': p_t, 'lift_pct': ((p_t - p_c) / p_c) * 100, 'p_value': p_value, 'significant': p_value < alpha, }
bash# Campaign analyzer python scripts/campaign_analyzer.py --data campaigns.csv --output report.html # Attribution calculator python scripts/attribution.py --touchpoints journeys.csv --model position # ROI calculator python scripts/roi_calculator.py --spend spend.csv --revenue revenue.csv # Forecast generator python scripts/forecast.py --historical data.csv --periods 6
references/metrics.md - Marketing metrics guidereferences/attribution.md - Attribution modelingreferences/reporting.md - Reporting best practicesreferences/forecasting.md - Forecasting methods| Symptom | Likely Cause | Resolution | |---------|-------------|------------| | Attribution models give wildly different channel credit allocations | No single model captures full truth; each has structural bias | Run 3+ models (first-touch, last-touch, position-based) and compare; use position-based as default for B2B | | ROAS calculations look great but pipeline is flat | Revenue attribution counting existing customers, not new pipeline | Separate new business attribution from expansion; report pipeline separately from revenue | | Marketing reports and sales reports show different lead counts | Marketing counts MQLs at form fill, sales counts at CRM entry with different criteria | Align on shared definitions: document exact MQL, SQL, and opportunity criteria in a shared SLA | | Forecast consistently over-predicts by 20%+ | Model uses linear extrapolation without accounting for seasonality or saturation | Apply dampening factors for longer forecasts; use ensemble method (linear + growth rate + moving average) | | Executive dashboard takes too long to build each month | Manual data pulls from 5+ platforms with different schemas | Automate data collection; standardize UTM and naming conventions so cross-platform analysis is consistent | | Channel ROI is negative but still generating pipeline | Long B2B sales cycle means revenue attribution has not caught up to spend | Use pipeline-based attribution for channels with 3+ month sales cycles rather than closed-won revenue |
In Scope: Campaign performance analysis, multi-touch attribution modeling, marketing mix optimization, ROI/ROAS calculation, budget allocation recommendations, executive reporting, cohort retention analysis, marketing forecasting.
Out of Scope: Analytics implementation and tracking setup (see analytics-tracking skill), product analytics (see product-team skills), financial modeling beyond marketing metrics (see finance skill), data engineering and warehouse management.
Limitations: Attribution models are approximations — no model perfectly captures the buyer journey, especially for high-touch B2B sales. Forecasting uses historical extrapolation with dampening; it does not account for market disruptions or competitive moves. Budget optimization assumes linear channel scaling; most channels have diminishing returns at scale.
| Script | Purpose | Usage | |--------|---------|-------| | scripts/channel_mix_optimizer.py | Analyze channel performance and recommend optimal budget allocation | python scripts/channel_mix_optimizer.py channels.json --budget 100000 --demo | | scripts/cohort_analyzer.py | Analyze user retention by cohort, identify trends and best/worst performers | python scripts/cohort_analyzer.py cohort_data.json --demo | | scripts/marketing_forecast_generator.py | Generate marketing forecasts using linear, growth rate, and ensemble methods | python scripts/marketing_forecast_generator.py historical.json --periods 6 |
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 22,818 | 8,254 | -64% | 1 | 1 | 0% | 4,014 | 4,526 | +13% | 0 | 0 | — |
case-02 | fail→fail | 22,419 | 29,763 | +33% | 1 | 1 | 0% | 3,781 | 9,374 | +148% | 0 | 0 | — |
case-03 | fail→pass | 7,536 | 5,823 | -23% | 1 | 1 | 0% | 1,131 | 4,061 | +259% | 0 | 0 | — |
case-04 | fail→pass | 7,802 | 17,693 | +127% | 1 | 1 | 0% | 1,329 | 6,380 | +380% | 0 | 0 | — |
case-05 | pass→pass | 5,010 | 8,497 | +70% | 1 | 1 | 0% | 899 | 4,745 | +428% | 0 | 0 | — |
case-06 | pass→pass | 12,080 | 10,706 | -11% | 1 | 1 | 0% | 1,802 | 4,889 | +171% | 0 | 0 | — |
case-07 | fail→pass | 15,397 | 20,964 | +36% | 1 | 1 | 0% | 2,807 | 7,127 | +154% | 0 | 0 | — |
case-08 | fail→fail | 8,335 | 4,326 | -48% | 1 | 1 | 0% | 1,394 | 3,794 | +172% | 0 | 0 | — |
case-09 | pass→pass | 11,536 | 9,880 | -14% | 1 | 1 | 0% | 2,004 | 4,765 | +138% | 0 | 0 | — |
case-10 | pass→pass | 7,374 | 7,072 | -4% | 1 | 1 | 0% | 1,174 | 4,363 | +272% | 0 | 0 | — |
case-11 | pass→pass | 14,064 | 26,906 | +91% | 1 | 1 | 0% | 2,135 | 7,120 | +233% | 0 | 0 | — |
case-12 | pass→pass | 41,532 | 18,527 | -55% | 1 | 1 | 0% | 2,259 | 6,153 | +172% | 0 | 0 | — |
case-13 | pass→pass | 15,065 | 21,199 | +41% | 1 | 1 | 0% | 2,254 | 6,815 | +202% | 0 | 0 | — |
case-14 | pass→pass | 18,204 | 17,641 | -3% | 1 | 1 | 0% | 2,255 | 5,994 | +166% | 0 | 0 | — |
case-15 | pass→pass | 10,119 | 2,238 | -78% | 1 | 1 | 0% | 1,469 | 3,450 | +135% | 0 | 0 | — |
case-16 | fail→pass | 24,330 | 3,549 | -85% | 1 | 1 | 0% | 2,006 | 3,644 | +82% | 0 | 0 | — |
case-17 | pass→pass | 8,680 | 15,056 | +73% | 1 | 1 | 0% | 1,743 | 6,145 | +253% | 0 | 0 | — |
case-18 | fail→pass | 6,233 | 2,533 | -59% | 1 | 1 | 0% | 1,015 | 3,566 | +251% | 0 | 0 | — |
case-19 | fail→pass | 7,807 | 2,254 | -71% | 1 | 1 | 0% | 1,174 | 3,485 | +197% | 0 | 0 | — |
case-20 | fail→fail | 12,797 | 16,787 | +31% | 1 | 1 | 0% | 2,468 | 6,456 | +162% | 0 | 0 | — |
case-21 | fail→fail | 13,269 | 6,917 | -48% | 1 | 1 | 0% | 2,410 | 4,178 | +73% | 0 | 0 | — |
case-22 | fail→fail | 24,789 | 29,900 | +21% | 1 | 1 | 0% | 5,175 | 9,349 | +81% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +32 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.