← All Skills
AI Skill

seo-rhythm-daily

Last updated: 2026-05-17

Daily SEO operating rhythm — 06:05 data collection, 10:07 CTR repair sprint. TRIGGER automatically by cron or Tycoon RoutineScheduler; never called ad-hoc. The

Quick Install
npx skills add seo-rhythm-daily

seo-rhythm-daily — Two Moments, Every Day

Every day, two things happen. That's it. More than two daily moments produces thrash and blurs signal.

Moment 1 — 06:05: Data collection

Invoke seo-monitor with today's date. Expected output:

  • reports/seo/raw/gsc-{YYYY-MM-DD}.json
  • reports/seo/raw/ga4-{YYYY-MM-DD}.json
  • reports/seo/raw/indexing-{YYYY-MM-DD}.json
  • Appends a row to reports/seo/data/kpi-history.json
Sanity checks (halt if any fail):
  • [ ] GSC data has ≥ 100 rows (if not, API auth likely broken)
  • [ ] GA4 sessions > 0 (if not, tracking likely broken)
  • [ ] Indexed-page count is within ±20% of yesterday (if not, trigger seo-postmortem)
Write a 1-line status to reports/seo/daily-status/{YYYY-MM-DD}.log:
06:07 ✅ GSC=1243rows GA4=412sessions Index=324pages

Moment 2 — 10:07: CTR repair sprint

This is where the agent ships 1–2 experiments per day. It is not optional and it is not more than 2.

Why 1–2 not 5: each experiment needs to breathe. Shipping 5 at once on 5 different pages makes attribution messy when a Google algo update lands mid-week.

Step 1: Read memory

Before picking a candidate, read:

  • memory/playbooks/.md — which patterns are proven?
  • memory/lessons/.md — which patterns are known bad?
  • memory/experiments/.yaml where status=open — don't double-ship a page already mid-experiment

Step 2: Pick candidates

Invoke seo-optimize.find_ctr_candidates(window=7d). It returns pages sorted by:

priority_score = impressions × (benchmark_CTR_at_position - actual_CTR)

Filter out:

  • Pages currently in an open experiment (experiments/.yaml has this page with status=open)
  • Pages listed in recent lessons as "don't touch"
  • Pages already optimized in last 60 days (cool-off period)
Take top 2.

Step 3: For each candidate

  1. Match playbook — which playbook applies (title-number, desc-frontload, etc.)?
  2. Log experiment — invoke seo-experiment-log with hypothesis derived from playbook evidence
  3. Ship change — invoke seo-optimize.apply(page, change, playbook_name)
  4. Commit + deploy — the change only counts as "shipped" when deployed

Step 4: Update dashboard

Append to reports/seo/dashboard.md the day's 2 experiments with their measure_at dates, so the owner sees the pipeline filling.

Step 5: Return

Tell the caller:

10:12 ✅ Shipped 2 experiments
  exp-2026-04-16-a7k: /alternatives/cursor (title-number playbook)
  exp-2026-04-16-b3m: /compare/openrouter-vs-litellm (desc-frontload playbook)
  Measure on: 2026-04-30

Edge cases

No good candidates today (all top-priority pages are in cool-off or existing experiments):
  • Skip the sprint. Note in daily-status.log: 10:12 ⏸ No candidates (all in cooldown)
  • Don't invent experiments just to hit a count.
Recent lesson contradicts the playbook:
  • Skip that candidate. Pick the next one.
High-severity regression detected at 06:05:
  • Skip the 10:07 sprint entirely. The postmortem takes priority.
  • Note: 10:07 ⏸ Deferred — postmortem-{id} in progress

Quality bar

  • [ ] Both moments ran (or a documented reason for skipping)
  • [ ] Every shipped change has a corresponding experiment file
  • [ ] No changes shipped for pages in cool-off
  • [ ] daily-status.log has both entries

What I refuse

  • To ship more than 2 experiments per day. It pollutes attribution.
  • To ship without consulting playbooks + lessons. That defeats the whole learning loop.
  • To skip Moment 1 because "we don't need data today". Data compounds.
  • To ship at 10:07 when 06:05 flagged a regression. Fix the leak before pouring more water in.

Integration

Called by:

  • Tycoon RoutineScheduler (cron rule: 5 6 and 7 10 )
  • Standalone cron: ~/.claude/scripts/seo-daily.sh
Composes:
  • seo-monitor (Moment 1)
  • seo-optimize + seo-experiment-log (Moment 2)
  • seo-postmortem (if regression)
Reads workspace seo-config.yaml for override cadence (some customers may want 09:00 / 14:00 instead).