MMMM Studio
  1. 01 Map
  2. 02 Check
  3. 03 Expect
  4. 04 Fit
  5. 05 Test
  6. 06 Plan

Step two · before any modelling

Can this data answer the question at all?

A fit takes minutes and hands back confident-looking numbers whether or not the design could ever have identified them. So we ask whether it could first, and it costs a second. Nothing here has been modelled — this is arithmetic on your file.

The verdict

No-go

The model will still run — it never refuses — but this data cannot tell your channels apart. Read the total, not the split, and fix the columns named below before you quote any single channel.

The problem is with the shape of the data itself, not with one channel.Two channels are near-duplicatesIll-conditioned design matrixNothing you do to a single column fixes that.

How this verdict is decided

NO-GOsomething is broken that isn't about one named channel — or every channel is blocked
CAUTIONone or two named channels are blocked, and the rest are fine
GOnothing blocked — cautions on named channels travel with those channels instead

There is no score to improve and no percentage to argue with. A caution about one channel never demotes the whole dataset, because it has somewhere better to live: that channel’s own row, and its trust grade after the fit.

Set my expectations anyway →

Takes about two minutes, and it is the step that catches impossible assumptions before they become results.

Five questions we ask of every dataset

History
Is there enough data to work out this many things at once?

2.74 · line at 4.00

across the whole dataset

Separability
Can the channels be told apart from each other, and from ordinary demand?

13 channels flagged

Two channels are near-duplicates, Two channels are near-duplicates, Two channels are near-duplicates, Two channels are near-duplicates, Two channels are near-duplicates, Two channels are near-duplicates, Two channels are near-duplicates, Two channels are near-duplicates, Two channels are near-duplicates, Two channels are near-duplicates, Two channels are near-duplicates, TV — Cable and Ill-conditioned design matrix

Variation
Does each channel's spend move enough for its effect to be visible?

3 channels flagged

TV — Broadcast, TV — Cable and Out of Home

Demand control
Is there a column for the demand that prompted the spend? Whether it is a good one can't be established from this data — only that it is there.

Present

a demand control is mapped

Sales series
Is the sales line itself clean enough to model?

No extreme weeks

nothing the outlier check flagged

Where channels moved together

  • TV — Broadcast moved with TV — Cable (r=1.00)
  • Social — Meta moved with Social — TikTok (r=1.00)
  • Social — Meta moved with Search — Brand (r=0.96)
  • Social — Meta moved with Search — Non-brand (r=0.96)
  • Social — Meta moved with Programmatic Display (r=0.96)
  • Social — TikTok moved with Search — Brand (r=0.96)
  • Social — TikTok moved with Search — Non-brand (r=0.96)
  • Social — TikTok moved with Programmatic Display (r=0.95)
  • Search — Brand moved with Search — Non-brand (r=1.00)
  • Search — Brand moved with Programmatic Display (r=0.93)
  • Search — Non-brand moved with Programmatic Display (r=0.93)

17 things to know, each with what to do about it

BlockingTwo channels are near-duplicates1.000 measured · 0.90 threshold

TV — Broadcast and TV — Cable correlate at r=1.00 after transformation. No model can attribute between them; combine them or run an experiment.

What to do: These two were bought as one thing, so model them as one thing: combine the columns. If you need them split, the only way to get there is an experiment that moves one without the other.

Two channels are near-duplicates0.998 measured · 0.90 thresholdOpen

Social — Meta and Social — TikTok correlate at r=1.00 after transformation. No model can attribute between them; combine them or run an experiment.

What to do: These two were bought as one thing, so model them as one thing: combine the columns. If you need them split, the only way to get there is an experiment that moves one without the other.

Two channels are near-duplicates0.959 measured · 0.90 thresholdOpen

Social — Meta and Search — Brand correlate at r=0.96 after transformation. No model can attribute between them; combine them or run an experiment.

What to do: These two were bought as one thing, so model them as one thing: combine the columns. If you need them split, the only way to get there is an experiment that moves one without the other.

Two channels are near-duplicates0.960 measured · 0.90 thresholdOpen

Social — Meta and Search — Non-brand correlate at r=0.96 after transformation. No model can attribute between them; combine them or run an experiment.

What to do: These two were bought as one thing, so model them as one thing: combine the columns. If you need them split, the only way to get there is an experiment that moves one without the other.

Two channels are near-duplicates0.958 measured · 0.90 thresholdOpen

Social — Meta and Programmatic Display correlate at r=0.96 after transformation. No model can attribute between them; combine them or run an experiment.

What to do: These two were bought as one thing, so model them as one thing: combine the columns. If you need them split, the only way to get there is an experiment that moves one without the other.

Two channels are near-duplicates0.959 measured · 0.90 thresholdOpen

Social — TikTok and Search — Brand correlate at r=0.96 after transformation. No model can attribute between them; combine them or run an experiment.

What to do: These two were bought as one thing, so model them as one thing: combine the columns. If you need them split, the only way to get there is an experiment that moves one without the other.

Two channels are near-duplicates0.960 measured · 0.90 thresholdOpen

Social — TikTok and Search — Non-brand correlate at r=0.96 after transformation. No model can attribute between them; combine them or run an experiment.

What to do: These two were bought as one thing, so model them as one thing: combine the columns. If you need them split, the only way to get there is an experiment that moves one without the other.

Two channels are near-duplicates0.955 measured · 0.90 thresholdOpen

Social — TikTok and Programmatic Display correlate at r=0.95 after transformation. No model can attribute between them; combine them or run an experiment.

What to do: These two were bought as one thing, so model them as one thing: combine the columns. If you need them split, the only way to get there is an experiment that moves one without the other.

Two channels are near-duplicates0.998 measured · 0.90 thresholdOpen

Search — Brand and Search — Non-brand correlate at r=1.00 after transformation. No model can attribute between them; combine them or run an experiment.

What to do: These two were bought as one thing, so model them as one thing: combine the columns. If you need them split, the only way to get there is an experiment that moves one without the other.

Two channels are near-duplicates0.929 measured · 0.90 thresholdOpen

Search — Brand and Programmatic Display correlate at r=0.93 after transformation. No model can attribute between them; combine them or run an experiment.

What to do: These two were bought as one thing, so model them as one thing: combine the columns. If you need them split, the only way to get there is an experiment that moves one without the other.

Two channels are near-duplicates0.929 measured · 0.90 thresholdOpen

Search — Non-brand and Programmatic Display correlate at r=0.93 after transformation. No model can attribute between them; combine them or run an experiment.

What to do: These two were bought as one thing, so model them as one thing: combine the columns. If you need them split, the only way to get there is an experiment that moves one without the other.

BlockingSevere variance inflation5171 measured · 10 threshold

TV — Cable has VIF 5170.9 after transformation; it is nearly a linear combination of the other regressors.

What to do: 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.

BlockingIll-conditioned design matrix216 measured · 30 threshold

Condition number 216 means the design is close to singular.

What to do: The design as a whole is near-singular, so no single column is to blame. Simplify: fewer channels, fewer controls, or a longer window.

Worth watchingThin degrees-of-freedom budget2.737 measured · 4.00 threshold

104 observations against 38 parameters is 2.7x, under the 4x rule of thumb. Expect wide intervals.

What to do: Merging two closely related channels would buy back headroom. Otherwise expect wide intervals and treat them as the honest answer rather than a defect.

Worth watchingTV — Broadcast is off air most weeks0.567 measured · 0.50 threshold

It runs in 39% of weeks, in bursts rather than at the start or end of the window. The effect is identified from the handful of on/off transitions rather than from the whole period, so its interval comes back wide even when the fit itself is sound.

What to do: Nothing to fix in the data — this is a media plan, not a defect. Expect a wide range on this channel and weight it accordingly; a lift test on a single burst would pin it faster than more history would.

TV — Cable is off air most weeks0.567 measured · 0.50 thresholdOpen

It runs in 39% of weeks, in bursts rather than at the start or end of the window. The effect is identified from the handful of on/off transitions rather than from the whole period, so its interval comes back wide even when the fit itself is sound.

What to do: Nothing to fix in the data — this is a media plan, not a defect. Expect a wide range on this channel and weight it accordingly; a lift test on a single burst would pin it faster than more history would.

Out of Home is off air most weeks0.596 measured · 0.50 thresholdOpen

It runs in 40% of weeks, in bursts rather than at the start or end of the window. The effect is identified from the handful of on/off transitions rather than from the whole period, so its interval comes back wide even when the fit itself is sound.

What to do: Nothing to fix in the data — this is a media plan, not a defect. Expect a wide range on this channel and weight it accordingly; a lift test on a single burst would pin it faster than more history would.

What we will do about it

Findings can change the model, never your numbers — we never impute, winsorise or drop a row. A change a finding calls for is only a candidate until a full fit has tested it on your own spend, and every entry says what it would cost you.

A full fit will test these on your own data before choosing

None of these is a change yet. Before fitting, a full fit hides returns we chose in copies of your own spend and tries setups built from these changes on them, side by side with your model exactly as you specified it. It uses a change only if its setup does better, and holds back from the budget plan any channel whose return it cannot find. A quick preview tests nothing and uses none of them.

  • One combined return for two channels bought together

    To be testedraised by two channels bought together
    for each ofTV — Broadcast + TV — CableSearch — Brand + Search — Non-brandSocial — Meta + Social — TikTok

    These two channels were bought so closely together that the data cannot tell their effects apart, so any split between them would be a guess. We estimate one return for the pair from their combined spend, starting from an assumption that blends the two channels' own, weighted by how much each spent.

    What it would cost you, if a full fit uses it

    You get one number for the pair and no split within it. If you need each channel's own return, only an experiment that moves one without the other can give it to you.

  • One carryover shared by every channel

    To be testedraised by a short history for everything the model estimates

    Your history is short for everything the model has to estimate. Instead of learning separately how long each channel's ads keep working after they run, we estimate one carryover for all of them, which leaves more of your data for the returns themselves.

    What it would cost you, if a full fit uses it

    Channels that genuinely differ in how long their ads keep working are treated alike, so each channel's timing is assumed rather than measured.

  • A firmer starting assumption for a channel the data barely sees

    To be testedraised by spend that runs in short bursts
    Out of Home

    This channel's spend barely moves, runs in short bursts or covers only part of the window, so your data holds little evidence about what it returned. We narrow its starting assumption, so a few weeks of noise cannot hand it credit that belongs to the baseline or to another channel.

    What it would cost you, if a full fit uses it

    This channel's number leans on the starting assumption more than on your data. Read it as an informed default, not a measurement.

  • A shared starting assumption for two channels bought together

    To be testedraised by two channels bought together
    for each ofTV — Broadcast + TV — CableSearch — Brand + Search — Non-brandSocial — Meta + Social — TikTok

    These two channels were bought so closely together that the data struggles to tell their effects apart. Each keeps its own return, but both start from the assumption that they return about the same, so the split between them leans on that rather than on noise.

    What it would cost you, if a full fit uses it

    The two returns are pulled toward each other. If one channel genuinely returns far more than the other, this setting narrows the gap between them.

  • A smoother baseline with fewer bends

    To be testedraised by a short history for everything the model estimates

    Your history is short for everything the model has to estimate. We let the baseline — the sales you would have had without media — change direction at fewer points in time, which leaves more of your data for the channel returns.

    What it would cost you, if a full fit uses it

    A slow shift in underlying demand that the smoother baseline cannot follow may be credited to media instead.

  • An assumed diminishing-returns curve for a channel the data barely sees

    To be testedraised by spend that runs in short bursts
    Out of Home

    This channel's spend barely moves, runs in short bursts or covers only part of the window, so your data cannot trace how its returns fall off as spend rises. We fix that curve at the starting assumption — half its full effect at about its typical weekly spend — and estimate only how much the channel returned.

    What it would cost you, if a full fit uses it

    How fast this channel runs into diminishing returns is assumed, not measured, so its number, and any budget advice built on its curve, leans on the starting assumption.

How much each channel's spend moves about

Ups and downs are what let the model see what a channel does. Spend the same amount every week and there is nothing to learn from — the return comes back as whatever we assumed going in, however large the budget.

ChannelSpend shareVariationOverlap costWeeks with nothing spent
TV — Broadcast22.6%1.345169.361% of weeks had no spend
TV — Cable12.3%1.345170.961% of weeks had no spend
Social — Meta15.5%0.25311.4spent every week
Social — TikTok8.2%0.25310.4spent every week
Search — Brand7.4%0.45505.1spent every week
Search — Non-brand11.1%0.42486.9spent every week
Programmatic Display7.9%0.1915.6spent every week
Video — CTV9.4%0.609.1spent every week
Out of Home5.6%1.231.260% of weeks had no spend

How closely your channels move together

Read a cell as: when this channel went up, did that one go up too? 1.00 means always, 0.00 means never. Anything above 0.80 and your data cannot tell the two apart. Measured after allowing for advertising that keeps working once it stops running and for the tenth million doing less than the first — checking raw spend instead is the usual reason a tool declares your data fine and then fails to separate anything.

TV — Broadcast1.001.000.180.190.210.200.14-0.020.08
TV — Cable1.001.000.180.180.210.200.14-0.020.08
Social — Meta0.180.181.001.000.960.960.960.240.05
Social — TikTok0.190.181.001.000.960.960.950.240.07
Search — Brand0.210.210.960.961.001.000.930.230.07
Search — Non-brand0.200.200.960.961.001.000.930.230.08
Programmatic Display0.140.140.960.950.930.931.000.190.02
Video — CTV-0.02-0.020.240.240.230.230.191.00-0.04
Out of Home0.080.080.050.070.070.080.02-0.041.00
TV — BroadcastTV — CableSocial — MetaSocial — TikTokSearch — BrandSearch — Non-brandProgrammatic DisplayVideo — CTVOut of Home
How do I read this?