Docs
/ Guides / Webhooks & alerts
Webhooks & alerts
The scheduler watches every tracked site — ranks, audits, watched pages, decay, mentions — and pushes an alert the moment something regresses. Delivery is operator-configured: a signed webhook, Telegram, email, or all three at once.
What raises an alert
Nine alert types, each with a default threshold. Thresholds are per-site tunable (see tuning).
rank_dropa keyword fell ≥3 positions vs the previous check (warning) · ≥5 (critical)
audit_score_dropoverall audit score fell ≥10 between re-audits
new_critical_issuea critical issue appeared in the latest audit
geo_regressionGEO score fell ≥10 between re-audits
ai_bot_newly_blockedan AI crawler that could read the site is now blocked
drift_<rule>a named regression between re-audits — schema removed, content gutted, noindex added
page_changea watched page changed — field-level from → to (title, meta, noindex, schema…)
content_decaythe decay scan found warning-or-worse pages losing clicks
brand_mentionfresh mentions of the brand found in monitoring
Channels & payload
An alert is delivered to every configured channel in parallel — webhook, Telegram, and email (email only at or above its severity floor). Each alert is delivered at most once per suppression window. The webhook POST looks like this:
POST ALERT_WEBHOOK_URL
{ "id": 14, "site": "example.com", "type": "page_change", "severity": "critical",
"payload": { "url": "/pricing", "changes": [{ "field": "title", "from": "Old", "to": "New" }]},
"createdAt": "2026-10-06T09:12:00.000Z" }
→ X-Alert-Signature: <hmac-sha256 hex> · any 2xx within 5s = delivered
Severity runs watch < warning < critical < emergency — the same tiers the monitor_drift tool reports.
Channels are instance-level settings on the server — this is the same operator model as the MCP token. Set what you need; unset channels simply stay off.
server env
ALERT_WEBHOOK_URL=https://ops.example.com/hooks/sitetr
ALERT_WEBHOOK_SECRET=$(openssl rand -hex 32) # signs bodies → X-Alert-Signature
# optional parallel channels
TELEGRAM_BOT_TOKEN=… TELEGRAM_CHAT_ID=…
ALERT_EMAIL_MIN_SEVERITY=warning # email floor; SMTP settings required
Verify the signature
The signature is HMAC-SHA256 (hex) of the raw request body with ALERT_WEBHOOK_SECRET. Reject anything that doesn’t match:
node
node -e 'const c=require("crypto");const a=Buffer.from(c.createHmac("sha256",process.env.ALERT_WEBHOOK_SECRET).update(process.argv[1],"utf8").digest("hex"));const b=Buffer.from(process.argv[2]);console.log(a.length===b.length&&c.timingSafeEqual(a,b)?"valid":"FORGED")' "$(cat body.json)" "$SIG"
Delivery is best-effort: 5-second timeout, no retries — alerts are also persisted, so nothing is lost when an endpoint is briefly down. The compare above is constant-time, as a signature check should be.
Read alerts in your agent
agent
you any alerts since Friday?
SiteTR // alerts_list — newest first, one site or all
1. example.com · page_change · critical · /pricing // title changed
2. example.com · rank_drop · warning · "seo audit tool" 8 → 12 // suppressed next 24h
Suppression & tuning
Every alert key fires at most once per 24h window — flapping pages don’t spam channels. Per-site thresholds overlay the defaults: rank-drop positions (3 / 5), audit and GEO score drops (10 / 10), and the suppression window itself are all tunable in the site’s stored settings. Tuning must never silence alerting: invalid values fall back to defaults.