Alerting on campaign anomalies without crying wolf
An alert nobody trusts is worse than no alert, because it creates the belief that something is watching.
Campaign alerting fails in a predictable way: fixed thresholds fire every Monday, every holiday and every promotion, the team mutes the channel, and the one real outage arrives into silence. The fix is three design choices. Compare against a seasonal baseline rather than a fixed number, require a violation to persist before it becomes an incident, and route by severity so that the channel a human reads only carries things a human must act on.
Why fixed thresholds always end in a muted channel
A rule like "alert if daily spend drops below $400" is correct on a Tuesday in October and wrong on Boxing Day, wrong during the client's seasonal shutdown, and wrong the week they doubled budget. Every one of those produces an alert that is technically accurate and operationally useless.
The failure is not the threshold, it is the comparison. Spend, conversions and cost per acquisition all have weekly and annual shape. Comparing today to a constant compares it to nothing.
The cost of getting this wrong compounds. Once a channel carries mostly false positives, people stop reading it, and the delay on the real incident goes up rather than down. You have spent effort to make detection worse.
Compare against a rolling seasonal baseline
The workable default is a trailing same-weekday median. Compare Tuesday to the median of the last four to eight Tuesdays, not to yesterday and not to a constant. That single change removes the weekly pattern, which is the largest source of false alarms in paid media.
Express the band as a ratio, not an absolute. Below 40% or above 250% of the baseline is a starting point for spend, and you tighten or loosen it per account after two months of observation rather than guessing on day one.
For annual seasonality, add a floor: suppress alerts when the baseline itself is below a volume where ratios stop meaning anything. A campaign averaging three conversions a day will breach any percentage band by chance, and alerting on it teaches everyone to ignore the channel.
Known events get an explicit suppression window. Promotions, site migrations, budget changes and client shutdowns are calendar entries, and a system that knows about them is a system whose alerts stay credible.
Require persistence before you call it an incident
Monitoring platforms encode this as a retest window, and the mechanic is worth borrowing whatever you build on. In Cloud Monitoring, a metric threshold condition is met only when every aligned measurement across the retest window violates the threshold, and the window resets the moment one measurement does not.
The stated design goal is the one you want on your own thresholds: set the window long enough to minimise false positives, but short enough that incidents still open in time to matter. That is a trade you make deliberately per metric, not a default you inherit.
The same documentation covers the other end, how an alerting policy defines conditions and notification channels and how incidents open and close, including an auto-close duration that defaults to seven days when data stops arriving. Auto-close matters more than it sounds: an incident that never closes is indistinguishable from an incident nobody handled.
In campaign terms, persistence usually means two consecutive periods. One bad hour is noise. Two consecutive days below the band is a fact.
Severity routing, written down
| Signal | Severity | Route | Response time |
|---|---|---|---|
| Spend at zero on an active campaign | Critical | Phone or on-call channel | Within the hour |
| Conversion tracking flatlined | Critical | On-call channel | Within the hour |
| Spend below 40% of baseline, two days | High | Team channel, tagged owner | Same day |
| CPA above 200% of baseline, three days | High | Team channel, tagged owner | Same day |
| Disapproved ad in an active group | Medium | Daily digest | Next working day |
| Budget pacing ahead by more than 15% | Medium | Daily digest | Next working day |
| Search term volume shift | Low | Weekly report | At review |
The discipline is that the critical rows must be genuinely rare. If more than one critical alert fires per account per quarter, the row is misclassified and it will drag the whole channel down with it.
Everything medium and below goes into a digest. A digest is read once, deliberately, by someone whose job that morning is to read it. A stream of individual notifications is read by nobody and acknowledged by everyone.
The pacing row connects to a real operational question rather than a number: overdelivery has documented platform behaviour that changes what a spend spike means, and alerting on it without that context produces panic about something the platform is allowed to do.
Where the checks should run
For account-level signals, the platform's own scripting is usually the right home. Google Ads scripts run JavaScript against your account on a schedule with no infrastructure, and the published examples cover the mechanical parts, including reporting and emailing from within a script, so you are writing thresholds rather than plumbing.
For anything crossing accounts or joining to non-platform data, run the checks in the warehouse instead, on the same schedule as your loads. The rule of thumb: if the signal needs a join, it belongs downstream of the pipeline, not inside the ad platform.
Whichever you choose, the alert job needs its own scheduled trigger and its own failure alarm. A monitoring job that silently stops running is the most expensive object in this article, because it converts an unmonitored account into an account everyone believes is monitored. Scheduled runs need a defined trigger and a visible run history for exactly that reason.
Tracking checks belong in the same family and should not be a separate initiative. Automated QA for tracking asserts that the data arriving is shaped correctly; anomaly alerting asserts that the numbers within it are plausible. Both fail loudly, both have an owner.
Tune it like a system, not like a setting
Log every alert with three fields: what fired, whether it was real, and what was done. After eight weeks you will have a precision figure for each rule, and rules below roughly one in three useful should be widened or deleted.
Deleting rules is the part teams resist and the part that keeps the channel alive. A rule that has never once been actionable is not a safety net, it is noise wearing a safety net's clothes.
Review the bands quarterly against actual account seasonality. The band you set in January against a quiet baseline will be wrong in November, and the failure will present as alert fatigue rather than as a threshold problem, which is why nobody diagnoses it.
The measure of success is not alert count. It is time from a real problem starting to a human acting on it. On the self-storage programme, catching pacing and conversion breaks early is a large part of how cost per acquisition reached roughly half the corporate target and held, and the same discipline is what an ongoing Google Ads account audit should leave behind rather than a one-off list of findings.
One caution on measurement. Alerting reduces the cost of incidents rather than the hours anyone works, so do not book it as a labour saving. Counting time saved honestly keeps that distinction visible, and it is the difference between a defensible case for the work and an inflated one.