5 Marketing Mix Modeling

Marketing mix modeling (MMM) relates an aggregate business outcome over time to media activity and other drivers. It is useful when user-level paths are incomplete and when online and offline channels must be considered together.

5.1 The modeling target

A simplified model is:

\[ Y_t = \alpha + f_1(X_{1t}) + \cdots + f_k(X_{kt}) + \gamma^T Z_t + s(t) + \epsilon_t \]

where \(Y_t\) is a KPI, \(X_{jt}\) is media activity for channel \(j\), \(Z_t\) contains controls such as price or distribution, and \(s(t)\) captures trend and seasonality.

MMM does not become causal merely because it includes many variables. Media spend is often selected in response to expected demand, promotions, or prior performance. Omitted drivers and weak variation can make contributions non-identifiable.

5.2 Carryover and saturation

Advertising can affect later periods. A geometric adstock transformation is:

\[ A_t = X_t + \lambda A_{t-1}, \qquad 0 \leq \lambda < 1 \]

The same additional dollar may also have less effect at high spend. Saturating response functions represent diminishing marginal returns. A log transform is not a universal solution: it imposes a particular shape and has problems at zero. Modern MMMs estimate or constrain channel-specific carryover and saturation.

5.3 Synthetic illustration

This example demonstrates transformations and time-based validation. It is not a production MMM and its coefficients should not be interpreted as causal ROI.

set.seed(42)
n <- 120
week <- seq_len(n)

adstock <- function(x, decay) {
  out <- numeric(length(x))
  for (i in seq_along(x)) {
    out[i] <- x[i] + if (i == 1) 0 else decay * out[i - 1]
  }
  out
}

saturate <- function(x, half_saturation) {
  x / (x + half_saturation)
}

tv_spend <- rgamma(n, shape = 4, scale = 18)
search_spend <- rgamma(n, shape = 6, scale = 10)
promotion <- rbinom(n, size = 1, prob = 0.20)
season <- sin(2 * pi * week / 52)

tv_signal <- saturate(adstock(tv_spend, 0.60), 160)
search_signal <- saturate(adstock(search_spend, 0.20), 110)

sales <- 500 + 150 * tv_signal + 110 * search_signal +
  70 * promotion + 35 * season + rnorm(n, sd = 20)

mmm_data <- data.frame(
  week, sales, tv_signal, search_signal, promotion, season
)

train <- mmm_data$week <= 96
fit <- lm(
  sales ~ tv_signal + search_signal + promotion + season,
  data = mmm_data,
  subset = train
)

prediction <- predict(fit, newdata = mmm_data[!train, ])
holdout_rmse <- sqrt(mean((mmm_data$sales[!train] - prediction)^2))

coef(fit)
##   (Intercept)     tv_signal search_signal     promotion        season 
##      501.9040      134.7286      114.8832       72.8880       34.8016
holdout_rmse
## [1] 16.17024

The data-generating process is known here. Real data does not reveal the true decay, saturation, or omitted variables, so uncertainty is much larger.

5.4 Data design

Collect a consistent time series with:

  • a business outcome aligned to the decision;
  • media spend, impressions, reach, or frequency by channel;
  • price, promotions, distribution, product availability, and major events;
  • calendar, trend, and seasonality features; and
  • documented changes in definitions and tracking.

More rows do not guarantee identification. A channel with nearly constant spend or spend synchronized with another channel provides little independent signal. Geographic variation can help when markets are comparable and modeled appropriately.

5.5 Controls require causal reasoning

Include variables that affect both spend and the outcome when they block confounding. Do not automatically control for variables caused by advertising, such as branded search or site visits, because they may mediate the effect being estimated. Conditioning on colliders can create bias.

5.6 Validation

Evaluate more than in-sample fit:

  • use rolling or future holdouts;
  • inspect residual autocorrelation and systematic error;
  • test sensitivity to priors, transformations, controls, and time windows;
  • check whether response curves are plausible in observed spend ranges;
  • report intervals for contribution, ROI, and optimized budgets; and
  • calibrate with credible incrementality experiments when possible.

Budget optimization extrapolates a fitted response surface. Constrain proposed spend to operationally realistic ranges and validate reallocations gradually.

5.7 Current open-source tools

  • Google Meridian provides a Bayesian MMM workflow with model diagnostics, response curves, and budget optimization.
  • Meta Robyn combines ridge regression, media transformations, hyperparameter search, and calibration options.
  • PyMC-Marketing provides Bayesian MMM and customer-value components in Python.

Tool output is not self-validating. Analysts remain responsible for data quality, assumptions, calibration, uncertainty, and business interpretation.

5.8 Interview checkpoints

  • Why is an MMM not automatically causal?
  • How do adstock and saturation represent different behaviors?
  • What happens when two channels always change spend together?
  • Why should budget recommendations remain near observed support?