Step 1 — Pull spend and performance from Google Ads (read-only)

For every active campaign, ad group, ad, and keyword, pull: daily spend, monthly budget, clicks, impressions, conversions, cost per acquisition (CPA), and return on ad spend (ROAS) where conversion value is tracked. Pull the trailing 30-day baseline for the same metrics.

Step 2 — Pull spend and performance from Meta Ads (read-only)

For every active campaign, ad set, and ad across Facebook and Instagram placements, pull the same fields: daily spend, budget, clicks, impressions, conversions, CPA, and ROAS, plus the trailing 30-day baseline.

Step 3 — Check budget pacing

For each campaign, compare spend-to-date against the elapsed fraction of its budget period.
Pacing signalCriteria
On paceSpend-to-date within ±15% of the expected linear pace
OverpacingSpend-to-date more than 15% ahead of expected pace — will exhaust budget early
UnderpacingSpend-to-date more than 20% behind expected pace — budget is going unused

Step 4 — Check CPA/ROAS drift

Compare each campaign's/ad's trailing 7-day CPA and ROAS against its 30-day baseline.
Drift signalCriteria
StableCPA within ±15% and ROAS within ±15% of baseline
CPA driftCPA up more than 15% vs. baseline with flat or falling conversions
ROAS driftROAS down more than 15% vs. baseline
Compounding driftCPA up AND ROAS down in the same window — flag first

Step 5 — Flag underperforming ads and keywords

Underperformer signalCriteria
Low-CTR adClick-through rate less than half the ad set's/ad group's average, with 1,000+ impressions
High-cost, no-convert keyword/adSpend above the account's median per-unit spend with zero conversions over the trailing window
Wasted-spend keywordSearch term with 3+ clicks and zero conversions over 14+ days (Google Ads search terms report)

Step 6 — Detect anomalies

Flag anything that breaks the normal pattern rather than drifting gradually:
  • A single day's spend more than 2x the campaign's trailing 7-day daily average.
  • A sudden CTR drop of more than 50% day-over-day on a previously stable ad.
  • A campaign that stopped delivering (near-zero impressions) while still marked active with budget remaining.

Step 7 — Draft the recommendation for each finding

Every finding gets exactly one concrete, human-actionable recommendation:
  • Overpacing → suggest lowering the daily budget or adding a spend cap so it doesn't exhaust the period early.
  • Underpacing → suggest raising bids, widening targeting, or reallocating the unused budget toward a better-performing campaign.
  • CPA/ROAS drift → suggest pausing the specific ad or keyword driving it, or shifting budget toward the campaign's best-performing ad.
  • Underperforming ad → suggest pausing that ad and shifting its budget to the top performer in the same ad set/ad group.
  • Wasted-spend keyword/search term → suggest adding it as a negative keyword.
  • Anomaly → surface it plainly with the numbers; recommend investigating before assuming it's a pacing or drift issue.

Step 8 — Rank and post

Sort findings highest-impact first (compounding drift and overpacing that risks exhausting budget rank above a single underperforming keyword). Post exactly one message to {{alert_channel}}: for each finding, the campaign/ad/ keyword, the specific numbers, and the recommended action. Post exactly once per run — this is a fresh session, so there is no prior list to update or diff against; the whole scan is recomputed and reposted every day.

Run your whole company from one repo you own.

Start with one job and grow from there.

Get started
Ad performance review — TaskStation Marketplace