Most organisations we work with have alerts on cloud spend. If an AWS account jumps 30% overnight, someone gets paged. The same organisation will spend a comparable amount on Google Ads and review it once a month, in a meeting, from a deck built by the agency that placed the ads.
That gap is where money disappears. A campaign gets disapproved and stops serving for eleven days before anyone notices. A bid strategy switches to maximise clicks and burns three weeks of budget on traffic that never converts. A landing page 404s after a site release and the ads keep running. None of this is exotic. It is ordinary operational drift, and it is invisible until the monthly report, by which point the money is gone.
This post is part of our Practical AI in Marketing series, and it describes a small system we build for clients: a daily automated report on Google Ads spend and performance, with anomaly alerts, and a plain-English summary that a business owner will actually read.
Why you instrument it yourself
Two things happened in the last week that make the case better than I can. On 2 September a US court declined to force Google to sell its ad tech business, accepting behavioural remedies instead, the third time in recent years that US antitrust enforcers have failed to break up a Big Tech company. The buy side and the sell side of that market stay under one roof. The day before, the FTC and 22 state attorneys general alleged that Amazon made over US$20 billion by overriding its own ad auction results with higher prices, a claim Amazon disputes.
Whatever the outcomes, the practical lesson for an Australian advertiser is the same. Auction transparency is not arriving from a regulator on a timetable that helps your budget this quarter. Newer AI-driven ad channels have their own problems; practitioners are already publicly complaining that ChatGPT ad targeting sends spend to irrelevant audiences. Pull your own spend and conversion data into a system you control, keep your own history, and reconcile platform-reported conversions against what your CRM says actually closed.
The shape of the system
- A scheduled job pulls campaign, ad group and keyword metrics from the Google Ads API each morning, read-only.
- Rows land in a database table you own, one row per entity per day, appended and never overwritten, so you keep your own history independent of platform reporting windows.
- An expectation layer computes what each campaign should have spent and returned.
- A deterministic rules engine compares actuals against expectations and raises anomalies.
- An LLM turns the day's numbers and any anomalies into six or eight sentences of plain English.
- Delivery goes to email and Slack or Teams, with the raw table available for anyone who wants to dig.
The extraction query is unremarkable:
SELECT
campaign.id,
campaign.name,
campaign.status,
metrics.cost_micros,
metrics.impressions,
metrics.clicks,
metrics.conversions,
metrics.conversions_value
FROM campaign
WHERE segments.date DURING LAST_7_DAYS
Read-only by default
The credential the reporting job uses must not be able to change anything. No write scopes, no budget edits, no pausing campaigns, even though the API would happily allow all three.
This is not a hypothetical concern. A recently merged open-source project, the KPA Traffic Stack, builds exactly this pattern for Meta and Google Ads diagnosis: read-only exports with explicit guardrails against accidental writes and credential leaks, validators that reject exports containing secret-like keys, and a flag on every export asserting that platform writes are not allowed and human approval is required. The automated code review on that pull request found a real hole in it, where one validator trusted a self-reported "no credentials" flag rather than scanning nested fields for tokens. Worth reading if you are building something similar, because the same mistake is easy to make.
Two reasons for the restriction. An agent or script with write access to a live ad account is a bad incident waiting for a bad day. And once the report can act, its findings stop being an independent record and start being a description of its own behaviour.
If you do want programmatic control of campaigns, keep it in a separate, reviewed path. The agoraform project treats Google Ads as config-as-code, covering conversion goal, budget, campaign, ad group, targeting, keywords and responsive search ads in one declarative resource graph with a validate, plan, apply lifecycle. Campaign changes then get diffed and reviewed like any infrastructure change, by a person, on a different credential.
Anomalies need an expected value, not last week's number
The weak version of this system alerts when spend moves more than some percentage against the prior period. It produces noise every Monday, every long weekend and every end of financial year.
The better version compares against a modelled expectation. The mizan target engine is a good illustration of the arithmetic: it deterministically reverse-engineers required revenue, new customers, sales, qualified calls, shows, bookings, leads and ad spend from a monthly profit or margin goal, and computes a maximum sustainable acquisition CAC, maximum media CAC and maximum cost per lead along the way. That maximum sustainable ad spend is the ceiling a runaway-spend alert should be measured against. It also fails closed: missing months stay missing rather than becoming zero, and impossible targets return an explicit unattainable result instead of a plausible-looking number.
Our rules end up looking like this:
- id: runaway_spend
window: rolling_7d
trigger: spend > 1.15 * max_sustainable_daily_spend
severity: high
- id: dead_campaign
window: rolling_3d
trigger: spend > 2 * target_cpa and conversions == 0
severity: high
- id: silent_campaign
window: rolling_2d
trigger: status == "ENABLED" and impressions == 0
severity: medium
- id: cpl_drift
window: rolling_14d
trigger: cost_per_lead > 1.3 * max_cpl and spend > 500
severity: medium
The spend floors matter. A campaign running at $30 a day will breach any ratio-based rule constantly, so suppress alerts below a dollar threshold where the money at stake is smaller than the cost of reading the email.
Where the LLM helps
The LLM does one job: it writes the summary. It receives the computed table and the list of triggered anomalies as structured input and produces a short narrative. It does no arithmetic, no ranking, no attribution reasoning. Every number in its output must appear in the input, and we validate that before sending.
The reason is boring and practical. A business owner will not open a dashboard daily, and will not read a 40-row table. They will read four paragraphs in an email that says spend was $4,180 against a $3,900 expectation, that the brand campaign is fine, and that a particular campaign has spent $612 in three days with no conversions and should be checked today. Prior to LLMs, we wrote that summary with templates, and the templates read like templates. This is the piece where the model genuinely earns its place.
Costs are small. The Google Ads API is free to use, though you need a developer token and basic access approval. Daily summarisation for a mid-sized account runs to a few thousand tokens, which is cents per day. The build is the expense: a week or two of engineering for a first version covering one account, plus a smaller amount of maintenance because Google retires API versions regularly and you will be doing an upgrade at least annually.
Honest limitations
Conversion lag is the big one. Yesterday's conversions are undercounted, so a dead-campaign rule reading a single day of data will produce false alarms. We compare on a lagged window and state the lag in the summary. Attribution is the second: Google's reported conversions and your CRM's closed deals will not agree, and the system should show both rather than pretending one is truth. Third, an alert nobody actions is worse than no alert, so cap the daily volume and give each rule an owner.
One Australian-specific note. If your campaigns use customer match or remarketing audiences, the email addresses and identifiers you upload are personal information under the Privacy Act, and the handling, consent and retention questions belong with your privacy officer before the reporting project starts, not after.
PicNet builds production AI systems for Australian organisations. Talk to us about what a first project could look like.
Originally published at picnet.com.au.
Top comments (0)