Echo/Docs

CLI command

mmm anomalies

Ad spend anomalies: watch a campaign's daily spend or cost per conversion against the band of its own history, alert once per day outside it and, where allowed, pause the campaign above it.

Invocation#

Shell
echo-cli mmm anomalies list
echo-cli mmm anomalies watch --campaign <campaign-id> --metric <metric> --history-days <n> --sigmas <n> --auto-pause <true|false> --by <who>
echo-cli mmm anomalies unwatch --id <watch-id>
echo-cli mmm anomalies check

Inputs and output#

list writes watches (id, campaign_id, metric, history_days, sigmas, auto_pause, declared_by, declared_at) and alerts, newest day first (id, watch_id, day, value, low, high, paused, pause_error, pending_action_id, raised_at). watch writes the stored watch; unwatch the watch it removed. check writes checks: per watch, watch_id, campaign_id, metric, day, outcome (within, alerted, already_alerted or unmeasured), reason (why it is unmeasured, or why a pause failed), value, low, high and the alert.

State effect#

The verbs call Echo Web's authenticated /api/analytics/mmm/anomalies (GET, PUT, DELETE and POST) with ECHO_INTERNAL_BEARER at ECHO_WEB_BASE_URL; the Ad spend anomalies section of the tracking screen and of Echo Desktop's GEO screen do the same, echo-mcp runs them as echo_ad_anomaly_watches, echo_ad_anomaly_watch, echo_ad_anomaly_unwatch and echo_ad_anomaly_check, and /api/cron/ad-anomalies runs check daily at 06:41 UTC, after the paid-ads sync. A check reads the last whole day (UTC) and the --history-days days before it from ad_campaign_metrics; --metric spend reads the day's spend and cost_per_conversion its spend over its conversions. The band is the history's mean plus or minus --sigmas sample standard deviations. A day outside it is stored once in ad_anomaly_alerts, with an ad_anomaly pending action for the ad account's user; a day above it on a watch with --auto-pause true also pauses the campaign on Meta or Apple Ads through Stado's paid-ads integration and records PAUSED on ad_campaigns, or records why it could not. A day the sync did not report, or reported without the metric, leaves the watch unmeasured with that reason.

Refusals#

  • A wrong invocation is refused before anything is sent: "mmm anomalies takes …; got <word>", "mmm anomalies <verb> does not take <flag>; …", "<flag> needs a value", "mmm anomalies <verb> needs <flag>" and "--auto-pause must be true or false; got <word>".
  • Echo Web answers a bad request with "campaign_id is required: the synced ad campaign to watch, as echo-cli mmm library lists it", "metric must be one of spend, cost_per_conversion; got <metric>", "history_days must be a whole number above 1: the days before the checked day that make the band, since one day has no spread; got <value>", "sigmas must be a positive number: how many standard deviations either side of the mean the band spans; got <value>", "auto_pause must be true or false: whether a day above the band pauses the campaign on its platform", "declared_by is required: who declares the watch" or "id is required: the watch to remove, as echo-cli mmm anomalies list shows it"; not found with "no synced ad campaign has id <id>; echo-cli mmm library lists them" or "no anomaly watch has id <id>"; and a conflict with "campaign <id> already has a <metric> watch (<watch>), declared by <who>; remove it first". The command prints Echo Web's sentence and exits 1.
  • With an approval policy on change_ad_campaign (echo-cli approvals policy set --action change_ad_campaign), an auto_pause watch does not pause the campaign: the alert's pause_error reads "the pause waits as approval request <id> (<policy reason>) until echo-cli approvals approve <id> makes it", and the pause is made once a reviewer approves it.