| name | performance-attribution |
| description | Joins Stage 1 Discovery predictions to actual outcomes at 30/60/90 days via the memory layer. Computes per-stage variance and ROOS calibration. Used exclusively by `monthly-attribution-review` playbook for human-driven weight tuning. |
| metadata | {"family":"ops","owner":"seo","last_reviewed":"2026-04-29T00:00:00.000Z","version":"1.0.0","related_skills":["seo-foundations","marketing-foundations","traffic-monitor"],"kpis":["Predicted vs actual ROOS at 90d within ±30% for ≥70% of opportunities (calibration)","Per-stage variance trend (declining = system learning)"],"marketing_pillar":4,"seo_standard":"E","kpi_tier":1234,"funnel_stage":"all","content_class":"all","maturity_stage":"diagnostic","used_by_stages":[]} |
Performance Attribution
Joins predictions made 30/60/90 days ago to actual outcomes. Computes per-stage agent variance, per-template variance, per-90/10-class variance, and ROOS calibration. Surfaces the 5 biggest variances + override-pattern summary for human review.
When to Use
monthly-attribution-review playbook — exclusive consumer.
- Quarterly: aggregated trend report.
Do Not Use When
- Need weekly KPI snapshot — use
traffic-monitor.
- Need to surface opportunities for next week — use
opportunity-discovery.
Inputs
nextjs-app/docs/reports/_index.json (the memory layer blackboard)
- All shipped opportunities from past 90 days
- Current Tier 1-4 actuals per shipped opportunity from
traffic-monitor cache + ga4-mcp.funnel_report + user-puppeteer AI citation cache
Workflow
Per shipped opportunity (30/60/90d)
- Find the opportunity's original Strategic Brief in
_index.json.
- Pull the brief's
predicted_tier1_lift, predicted_tier2_lift, predicted_tier3_lift, predicted_tier4_roos values.
- Compute current Tier 1-4 actuals:
- Tier 1 from
gsc-mcp.query_search_analytics filtered to the page
- Tier 2 from
ga4-mcp.run_report filtered to the page
- Tier 3 from monthly aggregates (brand search, AI citation count)
- Tier 4 from
ga4-mcp.funnel_report + (if available) Indeed Flex internal install attribution
- Compute variance per tier:
variance = (actual - predicted) / predicted
- Compute ROOS at the milestone:
ROOS = (lifetime_traffic × end_to_end_conversion × LTV_per_install) / production_cost
- Update the memory layer record with
outcome_at_30d / outcome_at_60d / outcome_at_90d.
Aggregation (monthly)
- Group shipped opportunities by:
- Stage agent (which stage's confidence was off)
- Template (which template over/under-delivers)
- 90/10 class (which class delivers)
- Content class (informational vs transactional vs brand)
- Intent (informational vs commercial vs transactional)
- CEP (which CEPs converted)
- Compute median + p25/p75 variance per group.
- Identify the 5 biggest variances.
- Pull all human override reasons from past 30 days.
Output Contract
Markdown at nextjs-app/docs/reports/<date>/attribution-log.md:
## Attribution Review — <date>
### ROOS Calibration
- Opportunities at 90d this month: <count>
- ROOS within ±30% of predicted: <count> (<%>)
- Target: ≥70% within ±30%
### Per-Stage Agent Variance
| Stage | Median variance | p75 variance | Override count this month |
|---|---|---|---|
| 1 Discovery | -0.05 | +0.32 | 4 |
| 2 Strategy | +0.08 | +0.41 | 7 |
| ... | ... | ... | ... |
### Per-Template Variance
| Template | Shipped this 90d | Median Tier1 variance | Median Tier4 variance |
|---|---|---|---|
| role-page | 4 | +0.12 | -0.08 |
| ... | ... | ... | ... |
### Per-90/10-Class Variance
| Class | Shipped 90d | Median ROOS variance | Recommendation |
|---|---|---|---|
| striking_distance | 8 | +0.15 | over-delivers; raise priority weight |
| ctr_rescue | 5 | +0.22 | over-delivers strongly; consider increasing class boost |
| ... | ... | ... | ... |
### Top 5 Biggest Variances (for human review)
1. <opportunity_id>: predicted ROOS X, actual Y, delta -67%. Why? <hypothesis>
2. ...
### Override Pattern Summary
| Reason code | Count this month | Stage | Recommendation |
|---|---|---|---|
| brand_risk | 3 | Stage 2 | tighten Stage 5 brand-lint thresholds |
| ... | ... | ... | ... |
### Weight Tuning Candidates (for human PR)
- Increase `informational` content_class_boost from 1.1 → 1.15: rationale = striking_distance + ctr_rescue plays in informational class over-delivered by avg +18% this 90d.
- Lower `transactional` `intent_value` from 1.2 → 1.15: rationale = transactional briefs under-delivered by avg -10% this 90d (likely AIO suppression on commercial intent).
How Tuning Happens
This skill produces the candidate list. The human reviewing the report opens a PR diff to:
marketing-foundations/reference/measurement-framework.md (formula coefficients)
seo-foundations/reference/excellence-targets.md (KPI thresholds)
seo-foundations/reference/intent-mapping.md (intent-value multipliers)
.agents/agents/PIPELINE.md (90/10 class taxonomy table)
Tuning bounded ±0.1 per quarter to prevent overfitting.
References