# Cro Weekly Recap

> Weekly CRO recap posted to #your-recap-channel every Friday at 9 AM CT (14:00 UTC). Summarizes experiments concluded, ship rate, and estimated impact. Runs as the cro-weekly-recap Oz cron.

- Skill: `warpdotdev/cro-weekly-recap` (Agent Skill)
- Install (CLI): `npx skillmds@latest add warpdotdev/cro-weekly-recap`
- Raw SKILL.md: https://api.skillmd.com/api/skills/warpdotdev/cro-weekly-recap/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Marketing & Growth
- Author: warpdotdev (https://skillmd.com/u/warpdotdev)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/warpdotdev/cro-weekly-recap

---


# Weekly CRO Recap

## Configuration

Read `.warp/skills/cro/references/config.md` for Notion IDs and data access.
Read `.warp/skills/cro/references/config-slack.md` for Slack posting config.

**Slack channel: `#your-recap-channel`** — this is the ONLY message that ever posts to #your-recap-channel. All other CRO notifications go to `#your-notifications-channel`.

## Procedure

### Step 1: Query experiments concluded in the last 7 days

Query the Roadmap & Backlog for experiments that reached a final status (`9-shipped`, `8-no-ship`, `8-inconclusive`) in the last 7 days:

```bash
curl -s -X POST "https://api.notion.com/v1/databases/NOTION_ROADMAP_DB_ID/query" \
  -H "Authorization: Bearer $NOTION_INTEGRATION_TOKEN" \
  -H "Notion-Version: 2022-06-28" \
  -H "Content-Type: application/json" \
  -d '{"filter": {"and": [
    {"or": [
      {"property": "Status", "select": {"equals": "9-shipped"}},
      {"property": "Status", "select": {"equals": "8-no-ship"}},
      {"property": "Status", "select": {"equals": "8-inconclusive"}}
    ]},
    {"property": "End Date", "date": {"on_or_after": "{{7_DAYS_AGO}}"}}
  ]}}'
```

For each concluded experiment, extract: Status, Lift, Page, Experiment Desc, End Date.

Exclude SEO-only entries as defined in `references/config.md` → Experiment Scope. The weekly CRO recap should report only CRO experiments.

### Step 2: Count active experiments

Query for experiments in active statuses (`3-building`, `4-ready for review`, `5-live:validating`, `6-live:running`, `7-analyzing`) to get a running + building count.

Exclude SEO-only entries from the running + building count.

### Step 3: Estimate impact from shipped experiments

For each experiment with Status = `9-shipped` and a non-null `Lift`:

1. Look up the page's `Daily Traffic` from the Page Registry
2. Look up the page's `CVR` from the Page Registry
3. Compute estimated additional signups/week = `Daily Traffic × CVR × (Lift / 100) × 7`

Sum across all shipped experiments for the total estimated weekly impact.

### Step 4: Post to #your-recap-channel

**Token: use ONLY `$EXPERIMENT_BUD_SLACK_BOT_TOKEN`.** If unset, abort — do NOT fall back to any other token.

**If experiments concluded this week:**

```
📊 Weekly CRO Recap — week of {date}
{n} experiments concluded · {ship_count} shipped · {kill_count} no-ship
Estimated impact: +{x} additional signups/week from shipped experiments
```

- Only include the "Estimated impact" line if `ship_count > 0`
- If all concluded experiments were no-ship/inconclusive, omit the impact line

**If no experiments concluded this week:**

```
📊 Weekly CRO Recap — week of {date}
No experiments concluded this week. {n} running · {n} building.
```

```python
import json, os, sys, urllib.request

token = os.environ.get('EXPERIMENT_BUD_SLACK_BOT_TOKEN', '').strip()
if not token:
    print("FATAL: EXPERIMENT_BUD_SLACK_BOT_TOKEN is unset. Refusing to post.", file=sys.stderr)
    sys.exit(1)

# Post to #your-recap-channel — this is the ONLY CRO message that goes to this channel
payload = {'channel': 'SLACK_RECAP_CHANNEL_ID', 'text': message_text}

req = urllib.request.Request(
    'https://slack.com/api/chat.postMessage',
    data=json.dumps(payload).encode('utf-8'),
    headers={'Authorization': f'Bearer {token}', 'Content-Type': 'application/json; charset=utf-8'},
)
with urllib.request.urlopen(req) as resp:
    result = json.loads(resp.read().decode('utf-8'))
    if not result.get('ok'):
        print(f"Slack post failed: {result.get('error')}", file=sys.stderr)
        sys.exit(1)
```

## Important Notes

- **This posts to #your-recap-channel, NOT #your-notifications-channel.** It is the only CRO notification in #your-recap-channel.
- **Slack token:** only `$EXPERIMENT_BUD_SLACK_BOT_TOKEN`. Abort if unset.
- `#your-recap-channel` channel ID: `SLACK_RECAP_CHANNEL_ID`
- Impact is an estimate based on observed lift × current traffic. It will naturally fluctuate with traffic changes.

