Live demo

15 series in. 4 alerts out.

One property, four content clusters, 60 days, 15 series. On day 41 something reranked. Total site sessions never left its weekly band, direct and paid never moved, and conversion rate held. Find the cluster and the day. Watch average position: lower is better in ranking, so its regression is a rise.

Every number on this page is computed in your browser right now, by the same CUSUM and Bayesian changepoint code that runs in production. Nothing here is a screenshot.

The comparison that matters

Against the rule most teams actually ship

The standard configuration is a percentage or sigma threshold against a trailing mean, evaluated per metric. Run it over the exact same 15 series and count what lands in the channel.

Naive rule
59
alerts sent · alert if |Δ| > 2.5σ vs 7-day mean
Of those, false
31
fired before anything was wrong
This engine
4
alerts sent, all correct
Noise reduction
93%
fewer messages, same catch

The false-alarm count is not a judgement call. The incident was injected at a known index, so every naive alert before that index is wrong by construction.

What the engine found

Detection run

Detection run4 alerts15 series tested · 4 fired · 0 suppressed by BH at FDR=0.05
MetricTrendBaselineNowChangeConfidenceMethod
Organic sessions
cluster=product-comparisons
9342.536272.56−32.9%99.9%CUSUM
Average position
cluster=product-comparisons
6.34110.737+69.3%99.9%CUSUM
Search impressions
cluster=product-comparisons
215.1k157.0k−27.0%99.9%CUSUM
Click-through rate
cluster=product-comparisons
4.34%3.11%−28.2%99.9%CUSUM

Show your work

Organic sessions · cluster=product-comparisons

Baseline
9342.53
After changepoint
6272.56
Change
−32.9%
Confidence
99.9%
CUSUM (Page 1954)
The series60 daysdashed line = baseline mean · red = detected changepoint
5357.567728.5010.1kchangepointJun 29Aug 27
The CUSUM accumulatorsmall deviations stack slowly; a real shift stacks fast
h = 0.144 (decision boundary)0.380

Baseline mean μ = 0.0011 and σ = 0.0361, both computed from the first two thirds of the day-over-day percentage changes. The slack k = 0.0181 is half a sigma, and the decision boundary h = 0.1445 is four. The accumulator runs on percentage changes rather than raw levels so a healthy growing series cannot drift across the boundary on its own.

What the naive rule did on this same series

alert if |Δ| > 2.5σ vs 7-day mean fired 5 times across this one metric, including 1 before anything was actually wrong. The statistical pipeline sent one message, on the day the regime actually changed.

What lands in Slack

One message, with the work already done

O
OrganicAPP#eng-alerts
🔴 Organic sessions dropped −32.9%cluster=product-comparisons
Baseline
9342.53
Now
6272.56
Confidence
99.9%
Started
Aug 10
Property
www (4 clusters tracked)
Cluster
product-comparisons
URLs
412
Break
Aug 9
Likely cause · Position, impressions, and click-through all break on the same day for the product-comparison cluster and for no other cluster. The order rules out a tracking bug: a broken tag drops sessions without moving impressions or position, and this moved position first. It also rules out seasonality, since the other three clusters run through the same date unchanged. Total site sessions moved less than 3%, which is why the weekly report looked fine.
  1. 1.Pull the 412 comparison URLs and diff serving position by query before and after Aug 9.
  2. 2.Split impressions by surface to see whether the loss is classic search, the answer-engine panel, or both.
  3. 3.Check whether the lost queries are now answered inline without a click, which is a different problem from a ranking loss.
AcknowledgeFalse positiveCUSUM · q < 0.0001 · BH-corrected

The written cause is generated only after the statistics confirm the change. The model never decides whether something is an anomaly — it explains one that has already been established. Getting that order backwards is how these products hallucinate.