SEO Drift Monitor (April 2026)
Git for your SEO. Capture baselines, detect regressions, track changes over time.
Commands
What It Captures
Every baseline records these SEO-critical elements:
How Comparison Works
The comparison engine applies 17 rules across 3 severity levels. Load
references/comparison-rules.md for the full rule set with thresholds,
recommended actions, and cross-skill references.
Severity Levels
Storage
All data is stored locally in SQLite:
Tables
- baselines: Captured snapshots with all SEO elements
- comparisons: Diff results with triggered rules and severities
URL normalization ensures consistent matching: lowercase scheme/host, strip default ports (80/443), sort query parameters, remove UTM parameters, strip trailing slashes.
Command: baseline
Captures the current state of a page and stores it.
Steps:
- Validate URL (SSRF protection via
google_auth.validate_url()) - Fetch page via
"${CLAUDE_PLUGIN_ROOT}/scripts/claude-seo" run fetch_page.py <URL> - Parse HTML via
"${CLAUDE_PLUGIN_ROOT}/scripts/claude-seo" run parse_html.py <URL> - Optionally fetch CWV via
"${CLAUDE_PLUGIN_ROOT}/scripts/claude-seo" run pagespeed_check.py <URL>(use--skip-cwvto skip) - Hash HTML body and schema content (SHA-256)
- Store snapshot in SQLite
Execution:
Output: JSON with baseline ID, timestamp, URL, and summary of captured elements.
Command: compare
Fetches the current page state and diffs it against the most recent baseline.
Steps:
- Validate URL
- Load most recent baseline from SQLite (or specific
--baseline-id) - Fetch and parse current page state
- Run all 17 comparison rules
- Classify findings by severity
- Store comparison result
- Output JSON diff report
Execution:
Output: JSON with all triggered rules, old/new values, severity, and actions.
After comparison, offer to generate an HTML report:
Command: history
Shows all baselines and comparisons for a URL.
Execution:
Output: JSON array of baselines (newest first) with timestamps and comparison summaries.
Cross-Skill Integration
When drift is detected, recommend the appropriate specialized skill:
Error Handling
Security
- All URL fetching goes through
"${CLAUDE_PLUGIN_ROOT}/scripts/claude-seo" run fetch_page.py, which enforces SSRF protection (blocks private IPs, loopback, reserved ranges, GCP metadata endpoints) - No curl, no subprocess HTTP calls -- only the project's validated fetch pipeline
- All SQLite queries use parameterized placeholders (
?), never string interpolation - TLS always verified -- no
verify=Falseanywhere in the pipeline
