Marketing Taxonomy and Marketing Mix Modeling
Last updated · published
Your MMM does not read utm_source. Spend comes from ad platform billing, and the outcome is a total, so the model would run happily on a taxonomy full of five spellings of Facebook.
That is exactly why taxonomy problems here are dangerous. They do not throw errors. They bias coefficients through the joins, the groupings and the control variables, and the output still looks plausible.
So the useful question is not “does MMM need clean UTMs.” It is which specific parts of the model your tagging actually controls.
TL;DR
- MMM is a regression on channel-level spend and an outcome series. It needs no cookies, click IDs or person-level data.
- Spend comes from platform billing. Your taxonomy decides how that spend is split, how outcomes are grouped, and how the two join.
- Campaign naming is the load-bearing part: splitting brand from non-brand search, flagging promotions, and separating geographies and products.
- Granularity follows a rule of thumb, roughly one variable per ten observations, so two years of weekly data supports about ten variables including controls.
- Meta’s Robyn is ridge regression with automated hyperparameter search. Google’s Meridian is Bayesian. They are not the same kind of tool.
- MMM, multi-touch attribution and platform reporting answer different questions. Shared definitions are what let you layer them.
Why MMM Came Back
The technique is decades old, and it never needed the web. What changed is that the person-level data which displaced it became unreliable.
Safari caps JavaScript-written cookies at seven days, and at 24 hours when someone arrives on a link carrying tracking parameters from a site it classifies as a tracker. Apple’s Link Tracking Protection removes known click identifiers in Mail, Messages and Private Browsing. Consent requirements removed another slice.
Chrome is the interesting case, because the story reversed. Google abandoned third-party cookie deprecation in 2024, dropped the planned user-choice prompt in 2025, and retired the Privacy Sandbox effort later that year. Third-party cookies in Chrome are staying. Everything else eroding around them is still enough to make aggregate methods attractive.
Tooling matured at the same time. Meta released Robyn in 2021, built on ridge regression with automated hyperparameter search rather than Bayesian inference. Google announced Meridian in March 2024 and opened it to everyone in January 2025, and that one is Bayesian. PyMC-Marketing covers similar ground in the PyMC ecosystem. A first build is now closer to an analyst quarter than to a six-figure engagement.
What the Model Actually Consumes
An MMM takes a weekly or daily series of spend by channel, a series for the outcome you care about, and control variables for seasonality, promotions, pricing and anything else that moves the outcome. It returns estimated contributions and response curves.
Note what is not in that list. No cookies, no click IDs, no user journeys.
Here is where your taxonomy does its work:
Splitting platform spend into model channels. The billing feed gives you spend per campaign. Turning that into “brand search” and “non-brand search” means reading campaign names, which only works if campaign names follow a pattern.
Grouping the outcome series the same way. If spend calls something Paid Social and your analytics files the same campaign under Organic Social, the two series disagree about the same reality.
Supplying control variables. Promotional periods are usually recoverable only from campaign names. A black_friday flag extracted from a naming convention is a real input to the model.
Keeping definitions stable over time. Every row for a channel has to mean the same thing in January and November. Rename a medium mid-year without mapping both forms and you have manufactured a step change the model will read as behaviour.
That is the honest list. It is narrower than “dirty UTMs break MMM” and considerably more actionable.
Pick Granularity by the Decisions You Make
The most common first-build mistake is choosing the wrong number of channels, and it fails in both directions.
Too coarse and the model cannot answer the question that prompted it. One Paid Social bucket cannot tell you whether the next dollar belongs to Meta or LinkedIn. One Paid Search bucket blends brand demand you already had with non-brand demand you bought.
Too fine and you run out of data. Here is the arithmetic, which is worth doing before anyone fits anything. Two years of weekly observations is 104 rows. A common rule of thumb allows roughly one variable per ten observations, which is about ten variables in total, and your controls (seasonality, promotions, price) are part of that budget. Feed 80 campaign-level series into 104 rows and the priors are doing the work, not the data.
So model at the level where budget decisions are made, and no finer. If Meta and TikTok have separate owners and separate budgets, they are separate channels. If they are rebalanced together, they are one.
Daily data or a longer history buys you more variables. Nothing else does.
The Taxonomy Failures That Actually Bias the Model
Six patterns, each of which looks like a modelling problem and is not.
Brand and non-brand search collapsed. Without a naming convention separating them, both land in one Paid Search channel. Brand search has high measured return because it captures intent you already had, so the blended elasticity looks strong, the model recommends more search budget, the team spends it on non-brand, and performance disappoints. This is the single most expensive taxonomy failure in MMM.
Promotions not coded as controls. Your campaign names carry black_friday_2025 and nothing extracts it. The promotional lift is absorbed by whichever channel ran heaviest that week, overstating its contribution.
Naming drift mid-window. paid-social becomes paid_social in March, and the mapping catches one. The model sees a channel that halved and another that appeared from nowhere.
Spend and outcomes grouped differently. Spend uses platform categories, outcomes use your analytics channel grouping, and someone hand-mapped them once. When either definition changes, the joint distribution is corrupted by definitions rather than by behaviour.
Direct absorbing paid. Direct shows up as a zero-spend channel that correlates with revenue, partly because it contains paid traffic that lost its parameters. The model credits it and under-credits the channels that paid for it. Thresholds for what counts as “too much direct” are rules of thumb rather than benchmarks, and the multi-touch attribution guide covers the same failure from the other side.
Untagged spend. An agency runs a podcast sponsorship nobody tagged. Spend enters the feed, no outcome maps to it, and the model assigns near-zero contribution. Note what actually happened: the channel was invisible in the outcome series, not absent from reality. The agency gets cut for a measurement failure.
Every one of these is fixed upstream, at the point where campaigns are named and links are built. Terminus, the marketing taxonomy governance platform, enforces the picklists and the campaign-name pattern when the link is created, which is what makes the mapping rules short enough to maintain.
Build the Channel Layer in Three Stages
Define the channels from the operator’s view. Sit with whoever owns the budget and list the decisions the model has to inform. That list is your channel list, subject to the variable budget above.
Write deterministic mapping rules. Every rule maps raw values to exactly one model channel, with no overlap and no gaps:
| Model channel | Rule |
|---|---|
| Paid Search Brand (Google) | source google, medium cpc, campaign matches ^brand_ |
| Paid Search Non-Brand (Google) | source google, medium cpc, campaign does not match ^brand_ |
| Paid Social (Meta) | source in (facebook, instagram), paid medium |
| Paid Social (LinkedIn) | source linkedin, paid medium |
medium email |
Two notes. Apply the same rules to spend and outcomes, ideally as one view in the warehouse that every consumer references. And notice how short the rules get when the vocabulary is controlled: one source value per platform instead of an enumeration of every spelling in use.
Validate before modelling. Two queries. What share of spend and of outcomes maps to a channel? Below roughly 95 percent, characterise the remainder before continuing. Then plot each channel weekly: a step change usually means a tagging change, and a series that vanishes for six weeks usually means a broken feed.
Skipping this stage is the most common reason a model’s second refresh disagrees with its first.
Layering, and Why It Needs Shared Definitions
MMM does not replace multi-touch attribution, and neither replaces platform reporting. They answer different questions on different horizons.
- Platform reporting answers whether the people an ad reached converted inside that platform’s window. Good for daily optimisation, self-reported by design.
- Multi-touch attribution answers which touches get credit among people you could actually track. Good for short-horizon mix decisions, limited by how much person-level data still exists.
- MMM answers what the next dollar in a channel is worth across a long window. Good for quarterly allocation, slow to notice a creative change.
- Incrementality tests answer what a channel causes. Expensive, and the closest thing to ground truth.
Most teams end up using all four, and they will disagree. Reconciling the disagreement is the job.
That only works if all four group the world the same way. When MMM defines channels one way, attribution another and the platform a third, you can never tell whether you are looking at a measurement difference or a definitional artefact. Shared taxonomy is what makes the disagreements informative.
For how taxonomy quality compounds into business value, see the ROI of marketing taxonomy governance.
FAQ
What UTM hygiene does an MMM need?
Stable channel definitions across the window, campaign names structured enough to split brand from non-brand and to flag promotions, and consistent grouping applied to both spend and outcomes. Casing consistency matters for the joins rather than for the model itself.
Does MMM need cookies or click IDs?
No. It runs on aggregate spend and outcome series, which is why it holds up as person-level data erodes.
How many channels should we model?
As many as your data supports, which is fewer than most teams expect. One variable per ten observations is the common rule of thumb, so two years of weekly data supports about ten variables including controls. Model at the level where budgets are decided.
Is Robyn Bayesian?
No. Robyn uses ridge regression with automated hyperparameter search. Meridian is the Bayesian one. The distinction matters when you are deciding how much weight your priors carry.
How does dirty taxonomy break the model if the model never reads UTMs?
Through the joins and the groupings. Spend splits on campaign names, outcomes group on source and medium, and controls are extracted from naming conventions. Those all sit upstream of the regression, and none of them fails loudly.
Should we build in-house or buy?
In-house has got easier: the open-source tools cover most of what vendors sell, and the marginal cost is closer to an analyst quarter. Buy when the team lacks modelling experience, the data engineering is too big to absorb, or a third-party stamp is what frees the budget. The taxonomy work is identical either way.
How often should we refresh?
Monthly to quarterly. The constraint is rarely the model. It is whether the input pipeline needs manual cleanup every cycle, which is a governance question.
What about B2B with long sales cycles?
Harder, because the lag runs months, weekly conversion counts are small, and the channels that matter are hard to express as spend. Model a pipeline metric rather than closed-won revenue, and widen the lag terms.
Can MMM measure AI search traffic?
Only once it is consistently identified and large enough to matter. That has got easier: GA4 now has a native AI Assistant channel and ChatGPT appends its own source parameter to citation links. Volume is usually the binding constraint rather than identification.
How should brand and non-brand search be handled?
Separately, always, and the split has to exist in your campaign names before the model can use it. Collapsing them produces a paid-search elasticity dominated by demand you already had.
Every account starts with a 21-day trial, no credit card required.