Alerts & notifications
Seven channels (email, Slack, Discord, Teams, Telegram, webhook, browser push), multi-stage escalation, smart deduplication against alert fatigue. XICTRAQ sends alerts where you'll actually see them — and merges repeated alerts of the same kind for one website within the deduplication window into a single message.
# Alert overview & management
Dedicated alerts page to view, acknowledge and resolve
Under /app/alerts you see every monitoring alert in one place — filtered by status (active, resolved, all) and severity. Click any alert for the detail view with its timeline (opened, acknowledged, resolved), delivery channels, the affected website and — if present — the linked incident. From there you acknowledge, resolve or delete individual alerts and download a postmortem. Bundled events (incidents) remain under /app/incidents.
# Seven channels
Email with HTML + plain-text
All plansHTML variant with severity highlighting and dashboard link, automatic plain-text fallback. Sent from our EU mail server (Germany, GDPR-compliant), with Reply-To set centrally to mail@xictraq.com.
Slack: Block Kit, Discord: embeds, Teams: MessageCard
Starter+Native, properly formatted messages — not generic webhook posts. Acknowledge and Open-in-dashboard buttons directly in Slack, in Discord and Teams as links in the message (their webhooks show no buttons), without recipients having to log into the dashboard (signed one-click token, expires after 14 days). All inbound text (title, message, website name) is escaped per channel so injected links or control characters are not rendered.
Telegram via bot
Starter+Set up with a bot token from @BotFather and your chat ID (e.g. via @userinfobot). HTML-formatted messages, all user strings escaped.
Generic webhook (JSON)
Business+JSON POST to any URL on every incident. The event is alert.opened when raised and alert.resolved when resolved. Per account a rotatable webhook secret (64 hex chars): when set, XICTRAQ signs the body via HMAC-SHA256 and sends the signature in the X-Xictraq-Signature header so receivers can verify authenticity. Every delivery is logged with HTTP status, response snippet, latency and a signed flag — re-trigger manually via the Resend button or rotate the secret when needed. Target URLs are protected against internal/private addresses (SSRF hardening).
Retry + dedupe (across channels)
The AlertDeliveryService retries each channel up to 2 times with backoff (0.5 s -> 1.0 s) — but only when no delivery can have happened: HTTP 429, no response (HTTP 0) or a pure connection error (DNS/connect). Already-delivered 5xx/408 responses and 4xx errors (e.g. invalid Slack URL) are not retried. The per-channel result (status, http, error, attempts) is stored as JSON in alerts.delivery_log; in the incident detail view you see exactly what happened per channel.
Browser push
All plansLogged-in users can subscribe each device to web push (VAPID, self-hosted — no Firebase, no OneSignal). The seventh channel — unlike the others it is enabled per device rather than toggled per category. Ideal for stand-by sessions in a browser tab. Per-device management under /app/settings/notifications.
# Deduplication
If your site flaps five times in ten minutes, you do not want five Slack pings. XICTRAQ groups related incidents automatically.
State-based alerts with a cooldown after resolution
For state-based findings (e.g. mixed content, broken links, missing email auth, blacklist listing, robots.txt blocking everything) and threshold-based degradations (SSL/domain expiry, visual change) an additional cooldown applies: if the same type was recently resolved for a website, it is not re-alerted immediately. This prevents spam from flapping persistent issues. The default is 24 hours; under /app/settings/notifications the cooldown can be set between 6 hours and 7 days or switched off.
Grace period before the downtime alert
Under /app/settings/notifications you set how long a website must be continuously unreachable before a downtime alert is sent (0 to 900 seconds). The default is “automatic”: twice the check interval of each website, at least 2 and at most 15 minutes – 10 minutes for a 5-minute check interval. To be alerted to every outage immediately, set 0. Measured from the last successful check; while the grace period is still running, the next check decides again. This dampens brief blips without lengthening your check intervals. The setting applies account-wide and to both check paths (monitoring nodes and on-demand scan).
Minimum security score
Also under /app/settings/notifications: if the security score of one of your websites falls below the configured minimum, exactly one open alert of type security_score_drop is created — not a new one per scan. Once the score rises above the threshold again, the recovery resolves it automatically. No new alert is created during a maintenance window.
# Granular control per category
Not every finding should land on every channel. XICTRAQ groups alerts into nine categories you can toggle on or off per channel.
Nine categories, toggleable per channel
The categories are uptime, SSL, security, compliance, SEO, performance, competitors, reports and system. For each you decide whether it is active and via which of the six channels it is delivered. By default everything goes by email; uptime additionally to all active push channels, since outages are the most urgent. Test alerts always go through regardless of these settings.
JavaScript errors (performance category)
When the tracker reports the same browser error from real visits for the fifth time, an alert of severity warning is raised in the “Performance and JS errors” category. There is one open alert per website and error message with the error text in the title; further sightings count up within it. If the error does not occur for seven days, XICTRAQ closes the alert with an all-clear. Known noise raises no alert, for example errors from browser extensions, generic errors without a source file or modules that no longer load after a deploy; they are still recorded.
Shop connection and capture rate
The “Changes and analytics” category holds the alerts of the Shopware connection: “Shop integration failing” (shop_integration_failed) when the daily patch level check fails twice in a row, and “Order import failing” (shop_import_failed) when the order import ends with the same error twice in a row or has not completed a sync for more than 60 minutes. Both send an all-clear on the next success. The capture rate (tracker_coverage_drop) is an insight of the automatic anomaly detection: if the share of online orders captured by the tracker over the last three days is below 80 % of its value in the 28 days before, an insight of severity warning appears in the dashboard, below 40 % of severity critical; like every such insight it additionally arrives as an “Analytics anomaly” alert.
Competitors: change types individually selectable
For the competitors category you additionally control which change types notify at all — such as tech changes, security incidents, price changes or job postings. Marketing-adjacent signals (messaging, WAF, ad or CTA changes) are muted by default to avoid noise.
Competitors and reports arrive bundled
These two categories do not report in real time. XICTRAQ collects competitor changes and sends them once a day at 08:00 as a single report; weekly and monthly reports go out on the configured date. The email contains the full evaluation; on the other channels a short notice with the dashboard link is delivered. The category setting applies here too: if you turn off the email, the report is still generated and waits in the dashboard.
# Escalation policies
Multi-stage escalation policies: one recipient + one time delay per stage. A dedicated cron endpoint checks every minute whether the next stage is due. If the incident is acknowledged first, escalation stops immediately.
Up to 10 stages per policy, up to 20 policies
Each policy has up to 10 stages, each account up to 20 policies. Stage 1 is the initial alert (immediate, via your default channels). Each subsequent stage carries a time delay (delay_minutes, 0 to 1440 = up to 24 hours) relative to incident start, plus its own channel selection from the six channels configurable per stage (email, Slack, Discord, Telegram, Teams, webhook) — browser push cannot be set individually here.
Recipient per stage: fixed address, on-call or team role
Per stage you choose who gets notified: a fixed contact address (static), the colleague currently on duty from an on-call schedule (on_call) or all team members with a role (team_role: admin, editor, viewer). What counts is the role on the alert's website, even where an invitation grants a different role there; each address receives the stage once per channel. So stage 1 escalates to the on-call person, stage 2 after 15 minutes to all team admins, for example.
Scope: websites and severity
A policy can be limited to individual websites and a minimum severity (warning and above, critical only). Matching alerts are then taken by the narrowest policy: first one with a website selection, then the one with the higher threshold, only then the default policy. The scope also applies to a policy that an on-call schedule activates for the day; if it does not match, the normal selection applies. Without a scope a policy only works as the default or via the on-call schedule.
On-call schedule with rotation
Schedules define shifts in layers with daily, weekly or fixed rotation plus optional restrictions (specific weekdays + time windows). Who is currently on duty is resolved live — including vacation/exception overrides (oncall_overrides) that temporarily replace a colleague. Managed under /app/settings/on-call. Per-schedule timezone (default Europe/Berlin).
Day-aware on-call assignment
A different mode can be set per weekday: activate a different escalation policy, send an additional on-call email, or stay on the default. This lets the weekend run a different recipient route than weekdays without touching the default configuration.
Acknowledge without login stops escalation
The acknowledge buttons and links in Slack, Discord, Teams and email open a signed one-click link (HMAC-signed, valid for 14 days). One click marks the incident as acknowledged and stops every further escalation stage immediately — the recipient does not need to log into the dashboard.
Snooze an alert
In the detail view under /app/alerts, an open alert that has not been acknowledged can be snoozed for 1, 4, 8 or 24 hours. While the snooze runs, no escalation stage advances and no reminders go out; afterwards it continues where the alert left off. The alert stays open, the list marks it as “Snoozed”, and the timeline records who snoozed it or lifted the snooze and when.
Reminders for open alerts
Under /app/settings/notifications you can have an open warning or critical alert sent again at a fixed interval – from every 30 minutes to daily. The reminder carries the prefix “Reminder:” in its title, goes only to the channels that received the original alert and never to the webhook. It ends when the alert is acknowledged or resolved, after ten reminders or seven days after the alert. Quiet hours, maintenance windows and snoozes apply to reminders as well. Reminders cover only alerts raised after the setting is switched on.
# Maintenance windows & quiet hours
Maintenance windows — one-time or recurring
Starter+Two variants: a one-time window with a concrete start and end time (for a planned relaunch) or a recurring weekly window (weekday + start/end time). Suppression follows a fixed precedence: one-time window before recurring per-website window before account-wide window. Checks keep running during this period, but alerts are suppressed. Managed under /app/settings/maintenance.
Quiet hours per channel
Starter+Configurable per channel (e.g. Telegram only 08:00 to 22:00, otherwise email only). You can define multiple time windows with weekdays and a dedicated timezone; windows spanning midnight (e.g. 22:00 to 07:00) are handled correctly. Unlike maintenance windows, quiet hours only suppress delivery on the affected channel, not the incident itself — critical alerts always go through. Once quiet hours end, each channel gets one summary of the alerts it skipped; the webhook does not. The summary can be switched off in the settings.
# Test delivery
One-click test per config
Endpoint POST /alert-config/test fires a dummy alert through every active channel and returns the per-channel result (status, HTTP code, error, attempts). Button right under /app/settings/notifications. Use cases: verify immediately after a Slack channel change, bot-token update or webhook URL change — no need to wait for a real incident.
# Webhook payload & signature
This is what a delivered webhook looks like. Verify the HMAC header X-Xictraq-Signature by computing HMAC-SHA256 over the raw body with your secret and comparing the result.
POST https://hooks.ihre-firma.invalid/xictraq
User-Agent: XICTRAQ-Webhook/1.0
Content-Type: application/json
X-Xictraq-Event: alert.opened
X-Xictraq-Delivery: dlv_8f3a91c2d4e6f0a1
X-Xictraq-Signature: sha256=8f3a91...
{
"event": "alert.opened",
"delivered_at": "2026-06-20T09:14:07+00:00",
"data": {
"alert_id": "019d7e3c-...",
"incident_id": "019d7e3c-...",
"type": "downtime",
"severity": "critical",
"title": "HTTP 503 — shop.invalid",
"message": "...",
"website": { "id": "019d7e3c-..." },
"is_resolved": false,
"created_at": "2026-06-20T09:14:06+00:00"
},
"source": "XICTRAQ"
}