The Ad Runner
One intent. Three networks. Nothing spends without you.
Describe the campaign once. It compiles separately for each network against that network's own verified field set, dry-runs against the live API, and creates every object paused. Going live is a different action with a different button and a number on it.
Campaign intent
Q3 contractor range
- Objective
- Messages
- Daily budget
- $100.00
- Geography
- Kathmandu, Pokhara, Biratnagar
Written once.
Google Ads
1 campaign · 2 ad groups · 6 ads
Meta Ads
1 campaign · 2 ad sets · 4 ads
Microsoft Advertising
Built and conformance-passed
One intent, compiled three ways. Each network gets its own manifest, validated against its own API.
Early access. The builder, compiler, dry run, publish saga and previews are built and tested. Connecting a live ad account is waiting on platform credentials and app review, so campaign building is available to early-access workspaces first.
Spend
Everything lands paused. Go-live is a separate control.
There is no path in the product that publishes an active campaign in one step. The gate below is what you see before anything can spend, and it is the only thing that can turn spend on.
Q3 contractor range — 3 networks
PAUSED| Platform | Daily | Flight |
|---|---|---|
| Google Ads | $40.00 | $1,200.00 |
| Meta Ads | $35.00 | $1,050.00 |
| Microsoft Advertising | $25.00 | $750.00 |
| Projected | $100.00 | $3,000.00 |
Projected over a 30-day flight
No silent spend
Every object is created paused. Going live is a separate action that shows projected daily and total spend, per platform and per currency, before you confirm.
Dry run before create
The compiled plan is validated against each network's own API before anything is written. A campaign that would be rejected is rejected in review.
Numbers that admit what they are
Networks count conversions over different windows. A figure that would span two reporting bases is labelled non-reconciled rather than averaged.
Partial failure is recoverable
If one network accepts and another rejects, each platform can be retried on its own from the failed step, under the original idempotency root.
Reporting
Three columns that refuse to become one number
Each network counts a conversion over its own attribution window. Adding them produces a figure that is not true in any of the three, so the Ad Runner reports them separately and labels the row rather than blending it.
Google Ads
30-day click
128
conversions
$1,204.18
spend
Meta Ads
7-day click, 1-day view
96
conversions
$1,048.60
spend
Microsoft Advertising
30-day click
—
conversions
—
spend
Three attribution windows. A single figure here would be wrong in at least two of them.
Failure
Partial failure is normal, and recoverable
If two networks accept a publish and one rejects it, the two that succeeded stay published and the third retries on its own — from the failed step, under the original idempotency root, so a retry cannot create the campaign twice.
Google Ads
21 objects created · paused
Meta Ads
14 objects created · paused
Microsoft Advertising
Attempt 2 of 5 · same idempotency root
idem:5f2c…a19
- Google AdsSearch and Performance MaxEarly access
- Meta AdsFacebook, Instagram, Messenger, Audience NetworkEarly access
- Microsoft AdvertisingBing SearchIn development
- TikTok AdsIn-feed videoPlanned