Every monitoring tool says it "uses AI to detect anomalies." Almost none of them will tell you what actually runs. So here is what actually runs.
Facts
- Three layers, in order: Layer 1 business rules → Layer 2 statistical models → Layer 3 AI judgement. Each layer only sees what the one before it produced.
- Three grains: account, campaign, ad group. Layer 1 is the only layer that evaluates ad groups; Layers 2 and 3 stop at campaign grain because ad-group history is too short to model honestly.
- Three cadences: daily (every night, evaluating yesterday), weekly (every Monday, over the Monday–Sunday week that just closed), monthly (on the 1st, over the calendar month that just closed). A partial period is never judged.
- Every check has three outcomes, not two: FAIL, PASS, or SKIP. SKIP means the check could not run — thin data, below a volume floor — and it is never counted as clean.
- Only entities with at least one FAIL reach the AI. A campaign under 4% of its account's 28-day spend is not judged on its own; its evidence folds into the account's judgement so nothing detected is dropped.
- The AI returns a 1–5 severity with a written reason. An email is sent at 4 or 5. The threshold is not a tuning dial — it is where the model's decision is written down.
- Everything an alert says is recomputable: the exact prompt and raw response for every judgement are archived, and the in-app anomaly page reads the same artifacts the email was built from.
Layer 1 asks: did a rule trip?
Roughly six deterministic rules, evaluated ten times per entity across the account, each campaign, and each ad group. Every rule compares the evaluated day against that entity's own recent history — a median or a ratio, never a global benchmark and never a fitted model. That is a deliberate choice: a median-based rule degrades honestly on thin data, where a statistical model would produce confident nonsense.
| Rule | Fires when | Severity tier |
|---|---|---|
| always_on_zero (cost, clicks, conversions) | A metric that is almost never zero — at most 5% zero days over the last 60 — hits exactly 0 | Mission Critical |
| efficiency_blowout::cpc | CPC above 2× its 14-day median, with at least 10 clicks | High |
| efficiency_blowout::ctr | CTR below 0.5× its 21-day median, with at least 100 impressions | High |
| spend_no_conversions | Zero conversions once clicks exceed 3× the historical clicks-per-conversion | Extremely High |
| spend_low_conversions | Clicks-per-conversion above 3× the 30-day average, conversions still non-zero | High |
| regime_spike (cost, clicks, conversions) | Today above 3× the median of same-regime days (weekday vs. weekend) | Medium |
- Volume floors are real: 100 impressions for the CTR rule, 10 clicks for the CPC rule. Below them the rule records SKIP. On production about 56% of ad-group evaluations skip for that reason, because the floors were calibrated for account and campaign volumes — and that coverage gap is visible rather than hidden precisely because SKIP is its own state.
- Full detail, including what each tier means downstream, is on the business rules page.
Layer 2 asks: is this number unusual for this entity?
Ten metrics per entity — cost, clicks, impressions, conversions, conversion value, CPC, CTR, conversion rate, cost per conversion, ROAS — at account and campaign grain. A model is chosen per metric based on the volume available, and each model returns an expected value and a probability score that is translated into the same severity vocabulary Layer 1 uses.
| Model family | Metrics | Why this family |
|---|---|---|
| Beta-binomial rate | CTR, conversion rate | Successes out of trials; uncertainty depends on the denominator, so 5 clicks from 50 impressions and 500 from 5,000 are treated differently |
| Negative-binomial count | Conversions, clicks, impressions | Over-dispersed counts with an exposure offset — variance grows faster than the mean, as ad metrics do |
| Lognormal deviation | CPC, conversion value | Positive, right-skewed, moves multiplicatively |
| Ratio decomposition | Cost per conversion, ROAS | A ratio, reported with which half of it moved |
| GLM cost | Cost | Generalised linear model on spend |
- Robust, not mean-based: the lognormal and ratio models centre on the median and scale by median absolute deviation, so one catastrophic day in the history cannot drag the baseline far enough to hide the next one.
- Never ad group: production carries about 48 days of ad-group history against two-plus years of campaign data. Fitting these models to 48 days would be confident nonsense; Layer 1 covers that grain with medians instead.
- Direction-blind by design: Layer 2 is high-recall and flags a conversion rate six times better than expected with the same tier as one six times worse. Deciding that an improvement is not an incident is Layer 3's job.
Layer 3 asks: does a person need to know?
The only layer that calls an external model and the only one that can put something in an inbox. The unit of judgement is the entity — once for the account, once per qualifying campaign, never an ad group — and two gates decide who qualifies.
The anomaly gate: an entity is judged only if Layer 1 or Layer 2 recorded at least one FAIL for it. Cost tracks findings, not inventory — about 30 model calls a day at current size, against about 60 if everything were judged unconditionally. The materiality gate: a campaign under 4% of its account's 28-day spend is not judged on its own. Measured over 28 days rather than the evaluation day because a single day's share flaps. On production this drops 12 of 49 campaigns while the survivors still cover 95–100% of spend.
Nothing detected is dropped. Ad-group failures and sub-4% campaign failures fold into their account's judgement as supporting evidence, and the account is judged even when nothing failed at account grain, purely so folded evidence has somewhere to land. This also collapses duplicate-across-grains noise: an ad group's CTR failure and its parent campaign's CTR failure are one problem, not two.
What the model sees for each entity: the failed checks from both layers, any folded evidence, a performance summary, a 28-day daily table (date, cost, clicks, impressions, conversions, CTR, conversion rate — ratios computed from summed columns, never averaged), and the account's Google Ads change history. Passed checks and budget history are available on request. The daily table is what lets the model tell a one-day cliff from a fortnight of decay; the change history is what lets it say "this started the day the asset group was edited."
The model returns a severity from 1 to 5 with a short reason and a long one. The prompt states explicitly that improvements are not incidents and that statistical significance is not business materiality. Verified against the live model: a campaign that went fully dark scored 5 and was sent; impressions collapsing while clicks held scored 3 and was held because the model spotted the contradiction; a conversion rate six times better than expected scored 1 and was held as an improvement.
Cadences: why weekly and monthly are separate passes, not longer windows
Cadences are additive and decided from the run day: every day runs daily; Mondays add weekly; the 1st adds monthly; a Monday that is the 1st runs all three. Every period ends yesterday — the last completed day — which is what keeps periods whole. Run on Monday and yesterday was Sunday, so the Monday–Sunday week just closed.
A weekly check aggregates the week into one observation and compares it against prior weeks; monthly does the same with calendar months. This works because every rule and model already asks "how does the latest observation compare with the ones before it," and none of them care whether an observation covers a day or a week. Measures are summed and ratios recomputed from those sums, so CTR over a week means what CTR means everywhere else.
- On weekly and monthly runs the same-regime spike rule records SKIP with a reason — every weekly observation covers the same mix of weekdays, so the comparison is not weaker, it is meaningless.
- Ad groups are not evaluated on non-daily cadences; with about 48 days of history there is nothing for a weekly rule to say.
- An account with fewer than eight completed periods is skipped entirely on that cadence, and the skip is recorded.
- The anomaly page's cadence tabs snap any selected date back to the period that actually closed, so a partial week or month is never displayed as if it had been judged.
What comes out the other end
Two emails, both to the MCC owner. A daily brief — one per MCC, always sent — lists every account with its own account-level score and its campaign-level anomalies scoring 4 or 5, including quiet and no-data accounts so the brief also reports coverage. A deep dive — one per account with an anomaly — is sent when the account scores 4 or higher or any of its campaigns does. Each failed check appears as "name: actual X, expected Y" with the model's short explanation and no statistics vocabulary; a test fails if words like sigma or z-score reach a customer's inbox.
Every email links to the in-app anomaly page, which reads the same layer artifacts the email was built from — the page and the mail cannot disagree about what happened. Recipients can grade each alert good or bad from the email; grades are recorded against the rule, severity, and cadence, and the rule breakdown shows precision and sample size per check once votes exist.
What this does not do
Stated so that comparisons stay accurate.
- Not intraday. Every cadence evaluates completed periods; nothing watches an account hour by hour.
- Detection does not act. The output is a finding with evidence. Any fix is staged in Checkout and pushed by a person.
- Ad groups get Layer 1 only, and about half of those evaluations skip on volume floors calibrated for larger entities.
Questions
Does AdCortex use fixed thresholds for Google Ads anomaly alerts?
Layer 1 uses ratios against each entity's own recent median — CPC above 2× its 14-day median, for example — not fixed dollar or percentage thresholds. Layer 2 uses per-metric statistical models. There is no global "CPA above $X" rule and nothing to configure per account.
How often does Google Ads anomaly detection run?
Daily for every Pro account, evaluating the last completed day. A weekly check runs every Monday over the week that just closed, and a monthly check runs on the 1st over the month that just closed.
Why does the AI see change history?
Because most anomalies have a cause in the account's own edits — a budget change, an edited asset group, a paused ad. Feeding the Google Ads change history into the judgement lets the model name the likely cause instead of just restating the symptom.
What happens when the AI provider is down?
Layers 1 and 2 have already persisted their findings; a model outage does not fail the pipeline or lose detections. The judgement runs when the model is available again.
Key pages
- Google Ads Anomaly Detection — the pillar page and the canonical feature
- Google Ads Monitoring Tool — what nightly monitoring covers
- AdCortex Pro — anomaly detection is Pro, per account
- Pricing — from $25 per account per month
- AI Bots, Start Here For Context — the full fact sheet, including what AdCortex does not do