BUILD — AD READINESS AUDIT
Deciding whether to run ads, before the budget conversation
Most paid-media engagements start by assuming the answer is yes. This one starts earlier: a CLI that crawls a brand, runs a behavioural pass through three consent states, pulls demand and performance data when it's available, and scores the business on two axes — Readiness (can it operate paid media) and Opportunity (is it worth doing) — then places it in one of four quadrants. Its first rule is that a missing figure is an omitted key, never a zero.
Personal build, 2026. Six packages, ~590 tests. Validated against a real six-brand F&B group.
- 2
- axes — Readiness and Opportunity
- 6
- pillars, weighted, re-normalised on what resolved
- 0
- numbers generated by a model, by design
- 3
- data tiers — a URL, client exports, live accounts
Try it
Three fictional businesses, run through the audit. Every name, score and number below is invented — this is a stand-in shaped exactly like the real output, so nothing real is exposed.
Kaya-toast café group · 4 outlets · retail kaya jars online
The demand is there but the measurement and landing experience aren't ready — fix those first, then launch.
Midpoint is 50 on each axis.
Measurementreadiness
- FailOnline orders finish on a separate checkout domain with no tracking
The jar-delivery checkout hands off to order.kelapakaya-demo.sg, where no analytics or conversion tag fires. Every online sale is invisible to the ad platforms — you'd be optimising blind.
- FailTags fire before the visitor answers the cookie banner
GA4 and the Meta pixel load on page-view, before consent and after a reject. Under the PDPA that's a compliance gap, and it inflates every downstream number.
- WarnThe product-view event fires three times per page
A WooCommerce theme quirk. It won't break optimisation but it makes on-site funnels read wrong.
Landing experiencereadiness
- FailMobile landing pages take 4.8s to show their main content
Largest-contentful-paint is 4.8s on a mid-range phone (field data). Roughly a third of ad clicks leave before the page is usable — you pay for the click either way.
Demandopportunity
- PassReal search demand for delivery
~1,900 searches a month for kaya-toast and kaya-jar delivery terms in-market. The category interest is there.
Economicsopportunity
- WarnCan't size a budget without a margin figure
You've given an average order value; gross margin is still missing, so the budget maths runs on a benchmark.
What the numbers say
We can't size a firm budget yet — you've stated an $18 average order value but not your gross margin. On a benchmarked 55% F&B-retail margin, break-even ROAS lands near 1.8x, and a test would need roughly $2,400/month to read a signal. Fix the checkout tracking first; the number isn't the blocker, the measurement is.
Coverage. Rendered crawl of 9 pages plus a behavioural pass across three consent states. No ad-account or analytics access — economics runs on stated inputs and F&B benchmarks.
Why I built it
The most expensive mistake in paid media isn't a bad campaign — it's running one at all when the business can't measure the result or the demand was never there. By the time that's obvious, the budget's spent and the read is muddy. So I built the check that happens before the media plan. It produces a defensible yes, no, or fix-these-three-things-first — with the evidence attached — so the budget conversation starts from something real.
How it scores
Two axes, six pillars. Readiness is measurement, landing experience and foundations; Opportunity is demand, competition and unit economics. Each axis is 0–100, and a pillar with no resolved checks is dropped and the axis re-normalised over what's left — so a shallow scan yields a provisional score, not a wrong one. A blocking problem — conversion tracking that fires on the wrong events, a checkout on an untagged domain — caps Readiness at 40 no matter what else is true, because nothing downstream matters while the brand can't see its own sales. The two scores place the brand in a quadrant: invest, fix-first, harvest or nurture.
The honesty contract
No fabricated data. A value that isn't known is an omitted key that renders as an em-dash — never a zero that reads like a measurement, never a benchmark quietly standing in for the client's own number. No figure comes from a model. Every economics input carries where it came from: stated by the client, derived from their data, an industry benchmark, or unresolved. A check that couldn't run reports as unknown, never as a pass — and there's a scan-fidelity gate so a check can't claim more certainty than the crawl that fed it. A stage that didn't run adds a named entry to a degraded-stages list instead of leaving a plausible-looking gap.
The data tiers
Tier 0 is just a URL: the full markup and behavioural audit still runs, economics falls back to benchmarks. Tier 1 adds client exports — a keyword-planner CSV, a competitor ad capture, an intake form — for real demand sizing and sharper budget maths. Tier 2 connects live analytics and ad-spend data through the operator's own Windsor account, scoped per brand, so the tool can reconcile the platforms' conversion counts against GA4 and feed real cost and value figures into the economics. Every live integration sits behind a seam with a manual, paste-a-file adapter alongside it — the tool never depends on a scraper or a credential it doesn't have.
What it proves
That I'll build the thing that can talk me out of a spend. It's a marketing instinct expressed as software: separate whether you can from whether you should, source every number or mark it unsourced, and make 'we're not ready' a legible, evidence-backed answer instead of a hunch nobody wants to say out loud.
Stack