MMMM Studio

The headline, in one sentence

Media produced about $131.6M of your $476.6M — roughly 28 cents in every dollar. Of your six channels, one has clearly paid for itself and five genuinely cannot be called yet.

That second half is not a hedge and it is not a fault in the model. Three years of weekly history is simply not enough evidence to separate six channels that mostly ran at the same time. Below, the channels are sorted by how much we actually know about them — not by how good their number looks.

Three years of revenue, and where it came from

Each band is one channel's contribution, stacked on the business you'd have had without any media at all. The white line is what you actually sold.

$476.6M

actually sold

$5.2M/WK202220232024

The pale mass underneath is the business you’d have had anyway: $345.0M, three quarters of everything.

Paid Search18.0%
Paid Social4.1%
TV — Broadcast2.8%
Programmatic Display1.5%
Affiliate0.8%
Retail Media0.5%
Everything else72.4%
±media total 14.6%–39.9%
How do I read this?
The one thing we're sure of

Paid Search paid for itself several times over, and it is the only channel we can say that about.

Every $1 came back as somewhere between $3.80 and $23.27, best guess $13.69. Even the pessimistic end of that range is profitable — that is what makes it the only settled answer on the screen. It contributed about $85.9M, more than the other five channels combined.

The range is enormous, and that is the honest part. Paid Search overlapped the others too closely for the data to say by how much it won — only that it did. The evidence tab shows why, and this is the one number on the page you should not put in a spreadsheet as a point estimate.

What each dollar came back as

Sorted by how much your data actually pinned down. The dotted line is break-even — a band crossing it means we can't tell you whether it won or lost.

Paid SearchPaid off$13.69

$3.80 to $23.27 · whole range is above break-even

TV — BroadcastCan't call it$1.14

$0.51 to $2.34 · best-measured channel you have, and it still straddles break-even

Programmatic DisplayCan't call it$1.25

$0.30 to $4.77

AffiliateCan't call it$1.22

$0.25 to $4.80

Retail MediaCan't call it$1.12

$0.25 to $5.30 · widest range on the screen relative to its size

Paid SocialCan't call it$1.79

$0.32 to $7.60

How do I read this?

Do this first

Don't cut Paid Search. Test whether it can take more.

It is the only channel with a proven return, and at current spend the next dollar still comes back as about $7.49 rather than $1. That headroom is on the channel screen, and the budget plan already leans on it.

Do this next

Run one lift test on a Paid Social burst. It is worth more than another year of data.

Paid Social and Paid Search each switch on once across the whole window, and that is all the model has to learn from. One deliberate on/off test would narrow both faster than waiting.

Don't do this

Don't rank the five uncertain channels against each other.

Their ranges overlap almost completely. Any ordering you read off the medians is noise, and it will reverse itself next quarter. If someone asks for a ranking, show them this panel.

Eight things would make next quarter’s answer sharper. Four of them are ours.

Everything the run flagged, in one place and sorted by who actually does the work. Nothing in the first two columns is generic — each item is the engine’s own words about a specific finding in your data. The third column is opinion, and is drawn so you can tell at a glance.

Email this list

Your media team

changes to how you buy, not to the data

Severe variance inflation

Usually the same cause as near-duplicate channels: this one is reconstructable from the others. Combine it with whichever channel it shadows, or drop a control that is standing in for it. A channel that launched partway through the window hits this too, because the baseline absorbs the period it was dark.

It does. Your data removed only 10% of the uncertainty you started with on Retail Media. The condition in that remedy is met, so treat its individual number as unreliable.

FROM · vif · Retail Media · 34.01 vs 10

Two channels move closely together

Vary their budgets independently for a quarter if you can. Until then, trust the pair’s combined return more than either individual number.

FROM · collinearity · 0.817 vs 0.8

Affiliate spend barely varies

Nothing can be recovered from a flat budget — the model needs the spend to move to see what moves with it. Either vary the budget deliberately for a quarter, or accept that this channel’s number is your assumption reflected back.

FROM · flat_spend · Affiliate · 0.0119 vs 0.05

Retail Media ran for only part of the window

Nothing to fix in the data — this is what the buy looked like. Treat the channel's return as provisional until it has a full year, and be especially wary of scaling its budget on this fit.

FROM · partial_history · Retail Media · 0.372 vs 0.5

Us

nothing for you to do — one click and we rerun

WarningBulk effective sample size

Lowest bulk ESS 185 at baseline_knots. Under 400 the point estimates carry visible Monte Carlo error.

FROM · scorecard · ess_bulk · 184.71 vs 400

WarningTail effective sample size

Lowest tail ESS 250 at roi. Under 400 the interval endpoints carry visible Monte Carlo error.

FROM · scorecard · ess_tail · 249.99 vs 400

WarningDivergent transitions

3 divergences in 1000 draws (0.30%). Divergences mean the sampler could not follow the posterior's curvature, so the region it failed in is under-represented. Raise target_accept_prob (spec section 6) before trusting the numbers.

FROM · scorecard · divergences · 0.003 vs 0.001

Runs the same fit with twice the draws (500 → 1000), and a more careful search (target_accept_prob 0.9 → 0.95). Nothing else moves — same data, same priors, same holdout — so the two are comparable. If the answer shifts, that shift is itself the finding.

WarningIn-sample accuracy

MAPE 6.1% (target <10%), R-squared 0.895 (target >0.9). In-sample fit is necessary, not sufficient — a model with enough knots fits anything.

FROM · scorecard · in_sample · 6.09 vs 10

Failed checkVariance inflation (post-transform)

Highest VIF 34.0 on Retail Media (warn 5, hard 10), measured after adstock and saturation because that is what the model sees.

FROM · scorecard · vif · 34.01 vs 5

WarningNo prior/data conflict

Outside the prior's 1st-99th percentile: Paid Search (13.66 vs [0.15, 9.91]). Either the prior is wrong or the data are being over-read; the fit is a compromise between two claims that disagree.

FROM · scorecard · prior_conflict · 1 vs 0

Those are a property of the data and the priors rather than of the search, so running it again will not move them. Listed here so nobody goes looking for a fix that does not exist.

Nothing to fix in your file

No extreme weeks, no gaps in what you sold, no column that is really an outcome rather than a cause, and a measure of underlying demand is present. Those are the four things that would have landed here, and all four came back clean.

General advice — not from your data

true of most MMMs, not measured on this one

Keep a channel dark somewhere, on purpose

The single cheapest thing you can do for next year's model is leave one region or one fortnight without a channel that normally runs everywhere. Continuous channels are the hardest to measure precisely because they never stop.

Record promotions and price changes weekly

A column of promotion weeks and a column of average price cost nothing to keep, and their absence is the usual reason media ends up with the credit for a price cut. Most uploads arrive without them.

This column is separated on purpose. Everything in the other two is traceable to a finding in your run; nothing in this one is.

Stamped so this can be reproduced

Every fit is written to disk with the data it read and the version that read it, so a number in last quarter’s deck can be traced to the run that produced it — and that run can be produced again. Nothing on these pages is computed when you open them.

run
20260802-123752-c3cdc0
data
c725e113668a
engine
0.1.0
holdout
0 periods
dataset
messy_upload
fitted
2 Aug 2026
took
1 min
name
unnamed

Past runs

Every fit is kept, with its verdict and its date, so a number in last quarter’s deck can always be traced back to the run that produced it.

This is the only fit on record. The second one is where this list starts earning its space.

How do I read this?