---
name: skoa-seo-weekly
description: Runs and interprets the weekly SEO check for www.skoa.online (site health, brand-query positions, search traffic), fixes failed checks in the repo and reports to the owner. Use when asked to review SEO, run seo:check, read the Hermes SEO report or act on the SEO playbook.
---

# Weekly SEO check for skoa.online

Goal: rank first for "Skool of Agents", climb for "School of Agents" and "SKOA", then grow search traffic to the blog. The source of truth for what is done and pending is `docs/seo/PLAYBOOK.md`.

## Run

1. In the repo: `git pull --ff-only`, then `npm run seo:check` (about 25 s, needs network). Add `--json` for machine-readable output. Set `SKOA_ADMIN_PASSWORD` (and `SKOA_ADMIN_USER` if not `admin`) in the environment to include search-engine visits from `/admin`; never paste the password into a file or a message.
2. History of every run is appended to `~/.hermes/skoa-seo/history.json` (override with `SKOA_SEO_HISTORY`). The Hermes job `SKOA SEO semanal` runs `~/.hermes/scripts/skoa-seo.sh` on Mondays at 09:00 Europe/Madrid and delivers the report by push notification (ntfy) and macOS notification. On a laptop the job actually fires when the machine wakes, so a run timestamped later than 09:00 is normal, not a failure.
3. Before interpreting, confirm the machine is online: one request to `https://www.skoa.online/` with a short timeout. If it fails, wait about 60 s and retry once. If it still fails, this is an offline run (see below).
4. Read the report top-down: failed health checks first (those are bugs), then the positions table with the change since last run, then traffic.

## Interpret

- `blocked`, `http 429` or `error` in a ranking cell means the search engine rate-limited this IP, not a ranking drop. Do not rerun more than once per hour; Brave recovers fastest.
- `fetch failed` on the health check plus `error` in every ranking cell and null traffic means there was no network when the job fired (laptop asleep or offline), not a site outage. Report it as "offline run", rerun by hand once online, and never record it as a regression or a "site broken" alert.
- An offline run still lands in `history.json`. Do not use it as the baseline for "change since last run": compare with the last successful run instead, and say so in the report.
- A failed health check on a run that was online is real: fix it in the repo (titles, visible brand name, JSON-LD Organization/WebSite, sitemap `lastmod`, real 404, hreflang) and rerun until all checks pass.
- `not in top 20` for the brand queries while the site is healthy means indexing, not content: the first manual item in the playbook (Google Search Console) is the fix.

## Act

- Fix failed checks, run `npm test`, commit and push `main`; Vercel deploys automatically. Confirm with a second `npm run seo:check`.
- Remind the owner of the playbook items still unchecked, Search Console first, Bing Webmaster Tools second.
- Google positions are not scraped (Google blocks scripts). If a web search tool is available, check the brand queries manually and compare with the baseline in `~/.hermes/skoa-seo/google.json`.

## Limits

- Hermes kills `--no-agent` scripts after 120 s. Keep `SKOA_SEO_RANKING_BUDGET_MS` at or below 70000 so the run fits.
- The report shows what the engines returned; never invent a position.

## After the run

If something surprised you (a check that misfired, an engine that changed its markup, a wrong interpretation), write a run note in `runs/` as described in the `skill-evolve` skill so this skill gets improved.
