# Deriving the Media Mix Model

Double your ad budget. How many more sales do you get? A straight-line
regression answers with confidence: twice the spend, twice the extra sales.
The people who see the ads give a smaller answer, because the second dollar
finds fewer new people than the first, and the people it does find forget.

<figure class="mfig" id="f-hook"><div class="mfig-plot"></div><figcaption>Today's budget is the dot. Drag the new budget: the straight line promises the same return for every extra dollar, while a population of real people runs out of new ones to reach.</figcaption></figure>

**The problem.** A media mix model (MMM) estimates what advertising does from
two numbers per week: what was spent, and what was sold. Almost every MMM
uses the same recipe. An *adstock* lets an ad keep working after the week it
runs, and a *Hill curve* makes each extra dollar do a little less. The recipe
is standard, but it is rarely derived, so few people who use it can say what
it assumes about the people behind the numbers, or when those assumptions
break.

**This post builds it from the ground up**, starting from a crowd of people
who can be reached and who forget. What you will get:

- **One equation** for how a population notices ads and forgets them, from
  seven plain assumptions.
- **Where diminishing returns and carryover come from**: a pool of people you
  run out of, and a memory that fades.
- **Why a straight line fails**, measured: it credits ads with about a third
  of the sales they caused.
- **Where the standard recipe comes from**, the hidden assumption it adds,
  and the population for which it is exactly right.
- **How far to trust it**, from decades of research, and how to fit the
  equation directly as a Bayesian model.

About 25 minutes. Every simulated number is checked by
[a short Python script](../examples/mmm_dynamics.py), every figure can be
dragged, and the side calculations are folded away until you open them.

## A population that can be reached, and can forget

### Seven assumptions

An MMM never sees a person. It sees weekly spend and weekly sales. But any
curve it fits is a claim about what happened to people in between, so it pays
to write that claim down. The smallest version that produces both effects
every MMM models takes seven assumptions:

1. **A fixed pool.** The market is $N$ people, and $N$ does not change over
   the period modelled.
2. **Two states.** Each person is either *unaware* or *aware*. Aware means the
   brand is in mind and the person is in the market for it. Write
   $A(t) \in [0, 1]$ for the fraction aware.
3. **Spend buys impressions at a fixed price.** Spending $x(t)$ (in thousands
   of dollars) per week buys $x(t)/c$ impressions per week, where $c$ is the
   cost per impression.
4. **Impressions land at random.** Each impression hits a person drawn
   uniformly from the $N$, whatever their state. Nobody is targeted.
5. **One impression is enough.** An unaware person who is hit becomes aware.
   An aware person who is hit stays aware, so that impression is wasted.
6. **Forgetting is memoryless.** Each aware person becomes unaware again at a
   constant rate $\delta$ per week, however long they have been aware.
7. **Sales follow awareness.** Aware people buy at rate $p$ per week on top
   of a baseline $y_0$ that would happen without any advertising.

None of these is exactly true. Each is the simplest version of a mechanism,
and the last section returns to what changes when one fails.

### The equation

Over a short interval $dt$, spend buys $x\,dt/c$ impressions. A fraction
$1 - A$ of them land on someone unaware, and each of those moves one person,
a share $1/N$ of the population, into the aware state. Meanwhile a share
$\delta\,dt$ of the aware forget. So

<div class="aeq" data-id="ode"></div>

Here $r$ is reach per dollar: the share of the population one dollar would
reach if nobody were ever hit twice. Weekly sales are

$$
y_t \;=\; y_0 \;+\; \beta\,A_t \;+\; \varepsilon_t, \qquad \beta = pN.
$$

This has the form of the Vidale–Wolfe model of sales response (1957), written
for awareness rather than sales, and its linear part is the goodwill stock of
Nerlove and Arrow (1962). It has exactly two mechanisms. The factor $1 - A$
is **depletion**: the pool of people not yet reached shrinks as you reach
into it. The term $-\delta A$ is **forgetting**. Saturation comes from the
first, and adstock from the second.

## Saturation is depletion

### Each impression finds fewer strangers

Switch forgetting off and deliver $I$ impressions in one burst. The share
reached is

$$
A(I) \;=\; 1 - e^{-I/N},
$$

the negative-exponential reach curve of media planning. The first impression
is never wasted, but once one impression per person has been delivered only
37% of the next ones find a stranger, and after three only 5%.

<figure class="mfig" id="f-pool"><div class="mfig-plot"></div><figcaption>Four hundred people, and impressions landing on them at random. Drag along the curve: up to one impression per person, the gap between the dashed line and the curve is impressions that hit someone already reached.</figcaption></figure>

<details class="more"><summary>Derivation: the reach curve</summary>

Measured in impressions rather than time, the equation without forgetting is
$dA/dI = (1 - A)/N$, which integrates to $1 - e^{-I/N}$. For a finite pool
the exact expectation is $1 - (1 - 1/N)^I$, which the exponential matches to
within a fraction of a percent once $N$ is more than a few hundred. The
$j$-th impression finds someone new with probability $e^{-j/N}$.

</details>

Nothing psychological is happening here: no fatigue, no wear-out.
Diminishing returns are the arithmetic of sampling with replacement from a
finite pool. That is one thing a saturation curve can mean: there is a pool,
and you are running out of it. The section on the standard recipe shows the
other.

### Where reaching balances forgetting

Now switch forgetting back on and hold spend constant at $x$. Awareness
climbs until the people reached each week equal the people who forget:

$$
r\,x\,(1 - A^{*}) \;=\; \delta\,A^{*}
\quad\Longrightarrow\quad
A^{*}(x) \;=\; \frac{x}{x + \kappa},
\qquad \kappa = \frac{\delta}{r}.
$$

<figure class="mfig" id="f-balance"><div class="mfig-plot"></div><figcaption>Left: people gained and lost per week, as functions of the share already aware. They cross at the steady state, which the right panel traces against spend; drag the spend.</figcaption></figure>

The steady state is a Hill curve, $x^s/(x^s + \kappa^s)$, with shape $s = 1$.
Its half-saturation point $\kappa$ is no longer a free constant fitted to
make a curve bend. It is $\delta/r$: the weekly spend at which, with half the
pool aware, reach and forgetting cancel. Forget twice as fast and you need
twice the spend to hold the same awareness; pay twice as much per
impression, and the same.

The same equation says something a curve cannot. The speed at which
awareness settles is not fixed: near the steady state it moves at rate
$r x + \delta$, so heavy spend settles faster, because it turns the pool over
faster. A fixed adstock cannot do that, and the section on the standard
recipe shows what it costs.

<details class="more"><summary>Derivation: the marginal return</summary>

$$
\frac{d}{dx}\,\beta A^{*}(x) \;=\; \frac{\beta\,\kappa}{(x + \kappa)^2},
$$

so the return on the next dollar falls as $1/(x + \kappa)^2$: at
$x = \kappa$ it is a quarter of the first dollar's. Linearising the equation
around $A^{*}$ gives the settling rate $r x + \delta$.

</details>

### Thresholds bend the curve into an S

Hill curves with $s > 1$ are S-shaped: flat, then steep, then saturating.
Assumption 5 rules that out. Relax it as Krugman (1972) argued: suppose a
person must see the ad $k$ times in a week before it moves them. With random
delivery, the impressions a person gets are Poisson with mean $\mu = r x$,
and the share moved is $\Pr[\mathrm{Poisson}(\mu) \ge k]$. For $k = 1$ the
curve is concave; for $k \ge 2$ it bends into an S, with an inflection at
$\mu = k - 1$.

<figure class="mfig" id="f-threshold"><div class="mfig-plot"></div><figcaption>Bottom: how many impressions each person got this week, at the spend marked above. A person moved by one impression counts in every coloured bar; one who needs three counts only in the dark bars.</figcaption></figure>

So $s > 1$ needs a second mechanism, repetition, on top of the pool, and the
pool alone gives $s = 1$.

<details class="more"><summary>How close these curves are to Hill curves</summary>

None of them is exactly a Hill curve. Fitted for $\mu$ from 0 to 8, the best
Hill shape grows with the threshold: $s \approx 1.75$, $2.45$ and $2.9$ for
$k = 1, 2, 3$. Even $k = 1$ prefers $s > 1$ over this range, because
$1 - e^{-\mu}$ approaches 1 faster than any $s = 1$ Hill curve can. People
with different thresholds produce the same qualitative shape.

</details>

## Adstock is forgetting

### From the equation to the recursion

When awareness is small next to 1, which is the regime of spend well below
$\kappa$, the depletion factor is close to 1 and the equation is linear:
$dA/dt \approx r\,x(t) - \delta A$. Its solution is a convolution: each
week's spend leaves its own echo, decaying by the same factor every week,
and the echoes add.

<figure class="mfig" id="f-echo"><div class="mfig-plot"></div><figcaption>Each week of spend leaves a fading echo, and the adstock, awareness measured in spend units, is their sum. Drag the half-life marker on the first echo; the dots are the weekly adstock recursion, which lands exactly on the curve.</figcaption></figure>

With spend constant within each week, the linear equation can be integrated
across a week exactly. Measured in spend units, $a_t = (\delta / r)\,A_t$,
it is the normalised geometric adstock:

$$
a_t \;=\; \lambda\,a_{t-1} \;+\; (1 - \lambda)\,x_t,
\qquad \lambda = e^{-\delta}.
$$

So the decay rate in every MMM is not a convention about "the share of this
week's effect that carries to the next". It is $e^{-\delta}$, the share of
aware people still aware a week later. A $\lambda$ of 0.71 is a two-week
half-life. This is Broadbent's adstock (1979), and Koyck's geometric lag
(1954) before it.

<details class="more"><summary>Derivation: the convolution and the weekly step</summary>

The linear equation has the solution

$$
A(t) \;=\; r \int_{-\infty}^{t} e^{-\delta (t - u)}\, x(u)\, du.
$$

With $x$ fixed over one week, integrating across it gives
$A_t = \lambda A_{t-1} + (1 - \lambda)(r/\delta)\,x_t$. Rescaling by
$\delta / r$ gives the recursion above. The factor $1 - \lambda$ makes the
adstock of constant spend equal to that spend, so $\kappa$ keeps its units
of dollars per week when the two transforms are composed; Broadbent's
original version is not normalised. The half-life is
$\ln 2 / \delta = -\ln 2 / \ln \lambda$ weeks.

</details>

### Delayed peaks: more than one stage

A geometric kernel peaks the week the money is spent; television often
peaks later. Add a stage: an impression first moves a person into
*considering*, from which they become aware at rate $\rho$. The response to
a pulse then rises before it falls, peaking at
$t^{*} = \ln(\rho/\delta)/(\rho - \delta)$: 1.6 weeks after the spend for
$\rho = 1$ per week and a two-week half-life.

<figure class="mfig" id="f-stages"><div class="mfig-plot"></div><figcaption>The same pulse of spend, through one stage and through two. Both forget at the same rate, but the second stage holds people back before they count.</figcaption></figure>

A chain of stages with equal rates gives a gamma-shaped kernel. The delayed
adstock of Jin et al. (2017) and the Weibull adstock are flexible stand-ins
for this family.

## Why a straight line is not enough

The simplest model regresses this week's sales on this week's spend,
$y_t = \beta_0 + \beta x_t + \varepsilon_t$. In the population's terms it
claims two things: that $\beta$ is constant, an inexhaustible pool; and that
this week's spend has no effect next week, instant forgetting. The
population model contains the line only in that double limit.

To see what the line does with a real population, simulate one. Two years of
weekly spend, flighted the way media plans are: bursts of two to five weeks
at between \$8k and \$120k, with one to four dark weeks between them. The
population has $\kappa$ = \$40k per week, a two-week half-life, $\beta = 1000$,
a baseline of 200 and noise $\sigma = 15$.

<figure class="mfig" id="f-line"><div class="mfig-plot"></div><figcaption>Each dot is one week of the simulation: its spend against its sales. Drag the memory to zero and the dots fall onto the true curve, which the line still misses; give the population memory and the dark weeks rise off the floor.</figcaption></figure>

The figure shows the two failures. With no memory, the weeks lie on the
steady-state curve, and a straight line through a concave curve is too high
at the ends and too low in the middle. With memory, the dark weeks after a
burst sit far above the true baseline, and the line can only absorb them in
its intercept. At a two-week half-life the fit is $y = 454 + 4.25\,x$.

Its slope is close to the truth near a typical week: 4.25 sales per \$1k,
against a true marginal return of 4.37 at the median active spend of \$55.6k.
Everything else is wrong:

- **Counterfactuals.** Doubling weekly spend to \$111k, and keeping it there,
  truly adds 154 sales a week. The line says 236, 54% too many, because it
  has no depletion.
- **Attribution.** Over two years, advertising caused 40,700 sales. The line
  credits it with 14,200, 35%. The rest went into the intercept, 454 instead
  of 200, because carryover arrives in weeks the line sees as unrelated to
  spend.
- **Uncertainty.** Its residuals are the echoes of past bursts, with a lag-1
  autocorrelation of 0.65, so its standard errors are wrong too.

## What the standard recipe adds

### The recipe on the same data

The standard MMM response for one channel puts both transforms in:

$$
y_t \;=\; \beta_0 \;+\; \beta\,\mathrm{Hill}\big(\mathrm{Adstock}_\lambda(x)_t;\ \kappa\big).
$$

Fitted to the same two years (a grid over $\lambda$ and $\kappa$, with
$\beta_0$ and $\beta$ by least squares), it brings the RMSE from 101.7 down
to 18.7, near the noise floor of 13.8. The marginal return is 5.02 per \$1k
(15% high), sustained doubling is predicted to add 189 sales a week against
a true 154, and media is credited with 36,100 of the true 40,700. But the
fitted memory is $\hat\lambda = 0.54$, a 1.1-week half-life, against a true
two weeks, and $\hat\kappa = 60$ against 40. The model fits well with the
wrong parameters. (Adding memory alone, without saturation, is worse: it
halves the misfit but almost doubles the marginal return, to 8.07 per \$1k
against a true 4.37.)

<figure class="mfig" id="f-ladder"><div class="mfig-plot"></div><figcaption>The same 104 weeks fitted three ways: a straight line, the standard recipe, and the exact population model. The number on each row is the RMSE; the noise floor is 13.8.</figcaption></figure>

### The exact weekly update

The reason is in the population equation itself. With spend constant inside
each week, the full nonlinear equation, not only its linear part, can be
integrated across a week exactly:

<div class="aeq" data-id="update"></div>

Read it as an adstock whose input has already been saturated, and whose
retention falls in heavy weeks because the pool turns over faster. It
contains the steady-state Hill curve and reduces to the geometric adstock at
low spend, but it is neither $\mathrm{Hill} \circ \mathrm{Adstock}$ nor
$\mathrm{Adstock} \circ \mathrm{Hill}$.

```python
import math

def population_weekly(x, kappa, half_life):
    """Exact weekly solution of dA/dt = r x (1 - A) - delta A,
    spend constant within each week."""
    delta = math.log(2) / half_life
    r = delta / kappa
    a, out = 0.0, []
    for xt in x:
        lam = math.exp(-(r * xt + delta))        # retention falls in heavy weeks
        a = lam * a + (1 - lam) * xt / (xt + kappa)
        out.append(a)
    return out

def hill_of_adstock(x, kappa, lam):
    """The standard composition: carry spend over, then saturate the stock."""
    s, out = 0.0, []
    for xt in x:
        s = lam * s + (1 - lam) * xt             # normalised geometric adstock
        out.append(s / (s + kappa))              # Hill, shape 1
    return out
```

> Both functions agree for constant spend: the normalised adstock of constant spend is that spend, so the composition lands on $x/(x+\kappa)$, the population's steady state. They disagree during and after a burst. `examples/mmm_dynamics.py` checks both claims and fits every model in the main text.

<figure class="mfig" id="f-order"><div class="mfig-plot"></div><figcaption>A four-week burst, through the population and through the standard composition with the same true parameters. Drag the burst's size: the two agree for small bursts and part ways for large ones.</figcaption></figure>

Fitted with the exact update, a grid over half-life and $\kappa$ recovers a
half-life of 2.0 weeks and $\kappa = 38$, with an RMSE of 13.7, at the noise
floor. The other order, saturating each week and then carrying it over, does
worse (RMSE 34.6), because its retention is fixed as well.

### Where the recipe is exact, and what it adds

The population produces the recipe in two regimes, and only there:

| Regime | What the population gives | Standard-form piece | Exact? |
| --- | --- | --- | --- |
| Constant spend | $A^{*} = x / (x + \kappa)$, $\kappa = \delta / r$, which is also $\mathrm{Hill}(\mathrm{Adstock}(x))$ | Hill with $s = 1$, and Hill ∘ Adstock | Yes |
| Low spend | $a_t = \lambda a_{t-1} + (1 - \lambda) x_t$, $\lambda = e^{-\delta}$ | Geometric adstock | Yes, in the limit $A \to 0$ |
| Bursts at high spend | The exact weekly update above | — | No |

Both halves of the recipe are derived, each in its own limit. Gluing them
together adds four assumptions the population does not make, two of them
hidden:

1. **Memory does not depend on spend** (hidden). The population's retention,
   $e^{-(r x_t + \delta)}$, falls in heavy weeks; the recipe holds $\lambda$
   fixed. This is why it read the memory as 1.1 weeks instead of 2.
2. **Saturation acts on the accumulated stock** (hidden). The population
   saturates *new reach*, week by week; the recipe saturates the sum of past
   weeks, so after a large burst it stays near the top while the population
   is already forgetting, and on the way up it is too slow.
3. **The shape $s$ comes from somewhere else.** The pool gives $s = 1$; an
   S-curve needs thresholds or another mechanism.
4. **Channels add.** A sum over channels means each channel has its own
   pool. Channels whose audiences overlap share their saturation:
   $dA/dt = (\sum_m r_m x_m)(1 - A) - \delta A$.

### The population for which it is exact

Ask the question in reverse: what population would make
$\beta\,\mathrm{Hill}(\mathrm{Adstock}(x))$ exact? A *dose-response*
population: everyone sees the same stock of advertising, and people differ
in how much of it they need.

1. **One shared stock.** Everyone carries the same memory of the brand, a
   stock that grows with spend and decays at rate $\delta$. An impression
   adds to it however large it already is, so nothing is used up. In weeks,
   the stock is exactly the normalised adstock.
2. **Different thresholds.** Person $i$ buys once the stock passes a
   personal threshold $\theta_i$.
3. **Log-logistic thresholds.** If the thresholds follow a log-logistic
   distribution with scale $\kappa$ and shape $s$, the share of people past
   their threshold is exactly $\mathrm{Hill}(\mathrm{Adstock}(x); \kappa, s)$,
   for every $s$.

So the recipe is the right model for a population that shares one memory and
differs in how much it needs, the reasoning that makes the Hill curve the
standard dose-response curve in pharmacology. Its $s$ measures how alike
people are.

<details class="more"><summary>Derivation: why log-logistic thresholds give Hill exactly</summary>

Write the stock as $\dot S = \delta\,(x - S)$, Nerlove and Arrow's goodwill
in spend units; integrated across weeks, $S_t$ is the normalised adstock. If
$\theta_i$ is log-logistic with scale $\kappa$ and shape $s$, its CDF is

$$
\Pr\big(\theta_i \le S_t\big) \;=\; \frac{S_t^{\,s}}{S_t^{\,s} + \kappa^{s}} \;=\; \mathrm{Hill}\big(\mathrm{Adstock}(x)_t;\ \kappa, s\big).
$$

The other order has its own population too.
$\mathrm{Adstock}(\mathrm{Hill}(x))$ is exact when the pool refills every
week and people differ in how reachable they are: with exponentially
distributed reachability, the share reached in a week with $\mu$ impressions
per person is exactly $\mu/(1 + \mu)$, a Hill curve. The people reached then
buy over the following weeks with a geometric delay. `examples/mmm_dynamics.py`
checks both results by simulation.

</details>

<figure class="mfig" id="f-mechanisms"><div class="mfig-plot"></div><figcaption>The same four-week burst through both populations, with matching κ and half-life. Drag the week: the pool forgets from the first dark week, while the shared stock stays above most thresholds for weeks.</figcaption></figure>

The two populations agree at steady state and disagree after a burst, which
makes the choice testable. In the first dark week after a large burst, the
pool keeps a share $\lambda = e^{-\delta}$ of its awareness, 71% here,
whatever the burst; the dose population keeps 92%, then speeds up towards a
geometric decay. Decay at a constant rate from the first dark week points to
a pool; a slow start that speeds up points to a dose. Real channels are
likely mixtures, but the recipe commits to the dose story, and fitting it to
a pool biases it in a predictable direction: memory too short, saturation
too late.

<details class="more"><summary>The dose population's retention</summary>

Its week-on-week retention, $\lambda (S + \kappa)/(\lambda S + \kappa)$, is
always above $\lambda$ and only approaches it as the stock runs down. Only
the pool predicts that awareness settles faster in heavy weeks, and a brand
tracker that follows the same people can tell them apart: under a pool, who
is aware churns from wave to wave; under a dose, the same people stay aware
and the boundary moves.

</details>

## How far to trust it

### What each term assumes

With several channels, a smooth baseline $\tau_t$ (trend and season) and
controls $z_t$ such as price, the recipe becomes the standard MMM:

<div class="aeq" data-id="standard"></div>

with $\lambda_m = e^{-\delta_m}$, $\kappa_m = \delta_m / r_m$,
$\beta_m = p_m N_m$, and $s_m = 1$ for a pool. Every parameter that was a
fitting constant is a property of channel $m$'s audience, and every term
carries one of the seven assumptions:

| Term | Population quantity | Assumption | What breaks it |
| --- | --- | --- | --- |
| $\lambda_m$ | $e^{-\delta_m}$, weekly retention | Forgetting is memoryless (6) | Multi-stage journeys: a delayed peak, not a geometric decay |
| $\kappa_m$ | $\delta_m / r_m$, spend where reach balances forgetting | Random delivery to one fixed pool (1, 4) | Targeting and frequency caps reshape the reach curve; a growing market moves $N$ |
| $s_m$ | How much repetition the population needs | $s_m = 1$ is the pool's steady state (5) | Thresholds above one exposure give an S, $s_m > 1$ |
| $\beta_m$ | $p_m N_m$, sales if the whole pool were aware | Sales are linear in awareness (7) | Purchase cycles, stock-outs, price responses |
| $\sum_m$ | Separate pools per channel | Channels reach disjoint audiences | Overlapping audiences make saturation shared |
| $\mathrm{Hill} \circ \mathrm{Adstock}$ | The exact weekly update, approximately | Exact only at steady state | Large bursts, where the pool turns over faster |
| $x_{m,t}$ as a regressor | Spend set independently of demand | — | Budgets that follow forecasts |

A Hill curve fitted to aggregate data says you are running out of something:
unreached people, or thresholds left to cross. It does not say which. The
same curve arises from depletion, from thresholds and from heterogeneity,
and which one is true changes what a new creative, a new audience or a
frequency cap will do.

### What the evidence says

As a skeleton, the model is well supported; carryover and diminishing
returns are among the most replicated findings in marketing science. As a
literal description it is wrong in ways that matter.

- **Carryover is real, and modest.** Sethuraman, Tellis and Briesch (2011)
  pool 751 short-term and 402 long-term elasticity estimates from 56 studies:
  0.12 short-term and 0.24 long-term on average. A long-run effect twice the
  short-run one is consistent with geometric carryover, which gives a ratio
  of $1/(1 - \lambda)$, so $\lambda \approx 0.5$ per data period.
- **Concave response is the norm.** Simon and Arndt (1980) found response
  concave, without an S. Vakratsas, Feinberg, Bass and Kalyanaram (2004)
  note that threshold effects "are rarely encountered in practice", because
  budgets settle by trial and error where advertising already works; with a
  model built to find them, they do, in evolving durable categories (SUVs and
  minivans) but not in a mature one (liquid detergent). So $s = 1$ is a sound
  default for an established brand.
- **Weight is not the main lever.** In 389 split-cable television tests,
  Lodish et al. (1995) found that more advertising weight does not, in
  general, increase sales. Weight increases did work in a sizeable minority
  of tests, but the circumstances, such as a new brand or a new message,
  mattered more. The population model has no term for the message.
- **Ads wear out, and some effects persist.** Naik, Mantrala and Sawyer
  (1998) let ad quality decay with repetition and find that pulsed schedules
  can then beat continuous ones. Dekimpe and Hanssens (1995) find that some
  advertising has trend-setting effects that a model in which everything
  decays can understate.
- **The clock matters.** Clarke (1976) showed that carryover estimated from
  annual data implies effects lasting far too long, the *data interval bias*.
  The weekly update here is honest about its interval; monthly data would
  need $\lambda = e^{-4.35\,\delta}$.

So the population model is best used as the minimal mechanistic prior for an
MMM, the structure you depart from with evidence, rather than as the truth.

### Fitting the equation as a Bayesian model

The equation can be the model directly. The likelihood is the ODE's solution
read through the sales equation:

$$
\begin{gathered}
y_t \sim \mathcal{N}\big(y_0 + \beta\,A_t(\delta, \kappa),\ \sigma^2\big),\\[4pt]
A_t = \lambda_t A_{t-1} + (1 - \lambda_t)\frac{x_t}{x_t + \kappa},
\qquad \lambda_t = e^{-(\delta x_t / \kappa + \delta)}.
\end{gathered}
$$

$A_t$ is a deterministic, differentiable recursion, so Hamiltonian Monte
Carlo in Stan, PyMC or NumPyro samples it as written. What the population
reading adds is priors in measurable units:

- **Half-life** from how fast brand recall decays in tracking studies.
- **Half-saturation** $\kappa = \delta / r$, with $r = 1/(cN)$ from the
  channel's cost per impression and audience size.
- **Scale** $\beta = pN$, bounded by the category's purchase rate.
- **Awareness itself**, if the brand runs a tracking survey: $m_t$ aware out
  of $n_t$ asked is a second likelihood,
  $m_t \sim \mathrm{Binomial}(n_t, A_t)$. Sales alone trade $\kappa$ against
  $\beta$; the survey fixes the scale of $A_t$ and breaks that trade.

<figure class="mfig" id="f-bayes"><div class="mfig-plot"></div><figcaption>The model as a Bayesian network. Shaded nodes are observed; the double circle is computed from its parents by the weekly update; dashed arrows are evidence from outside the sales data.</figcaption></figure>

<figure class="mfig" id="f-posterior"><div class="mfig-plot"></div><figcaption>Exact posteriors over half-life and κ on the simulated two years: 90% and 50% regions, with the truth marked. The standard form is confident and wrong; the ODE is confident and right, and a survey of 400 people every fourth week tightens it further.</figcaption></figure>

Computed exactly on a grid, with flat priors and the linear coefficients
integrated out, the standard form puts the half-life at 1.14 weeks (90%
interval 1.10 to 1.18) and $\kappa$ at 60 (53 to 68): both exclude the truth,
2 weeks and 40. The ODE gives 2.00 (1.93 to 2.08) and 38.9 (36 to 43), and
adding the survey narrows $\kappa$ to 40 to 42.

Bayesian inference propagates uncertainty within a model; it does not repair
a wrong one. A misspecified likelihood yields a narrow posterior around the
wrong answer, and the narrowness looks like evidence. On real data, fit the
standard form and the population model side by side and compare them on
held-out weeks, for instance with leave-future-out cross-validation, before
trusting either one's intervals.

<details class="more"><summary>Tooling: when there is no closed form</summary>

The core model has an exact weekly update, so no numerical solver is needed.
Extensions without one put a solver inside the likelihood: Stan's `ode_rk45`
and `ode_bdf`, PyMC's ODE module, or diffrax under NumPyro.

</details>

## Further reading

- M. L. Vidale and H. B. Wolfe, "An operations-research study of sales
  response to advertising," *Operations Research* 5(3), 1957. The equation
  this essay starts from.
- M. Nerlove and K. J. Arrow, "Optimal advertising policy under dynamic
  conditions," *Economica* 29(114), 1962. Advertising as a depreciating
  stock of goodwill.
- L. M. Koyck, *Distributed Lags and Investment Analysis*, North-Holland,
  1954. The geometric lag.
- S. Broadbent, "One way TV advertisements work," *Journal of the Market
  Research Society* 21(3), 1979. Adstock.
- H. E. Krugman, "Why three exposures may be enough," *Journal of
  Advertising Research* 12(6), 1972. Effective frequency.
- J. D. C. Little, "Aggregate advertising models: the state of the art,"
  *Operations Research* 27(4), 1979. A survey of response models, including
  the ones above.
- Y. Jin, Y. Wang, Y. Sun, D. Chan and J. Koehler, "Bayesian methods for
  media mix modeling with carryover and shape effects," Google, 2017.
  Delayed adstock and Hill saturation in the modern Bayesian MMM.
- D. G. Clarke, "Econometric measurement of the duration of advertising
  effect on sales," *Journal of Marketing Research* 13(4), 1976. The data
  interval bias.
- J. L. Simon and J. Arndt, "The shape of the advertising response
  function," *Journal of Advertising Research* 20(4), 1980.
- L. M. Lodish et al., "How T.V. advertising works: a meta-analysis of 389
  real world split cable T.V. advertising experiments," *Journal of
  Marketing Research* 32(2), 1995.
- M. G. Dekimpe and D. M. Hanssens, "The persistence of marketing effects on
  sales," *Marketing Science* 14(1), 1995.
- P. A. Naik, M. K. Mantrala and A. G. Sawyer, "Planning media schedules in
  the presence of dynamic advertising quality," *Marketing Science* 17(3),
  1998. Wear-out and Kalman-filter estimation.
- D. Vakratsas, F. M. Feinberg, F. M. Bass and G. Kalyanaram, "The shape of
  advertising response functions revisited: a model of dynamic
  probabilistic thresholds," *Marketing Science* 23(1), 2004.
- R. Sethuraman, G. J. Tellis and R. A. Briesch, "How well does advertising
  work? Generalizations from meta-analysis of brand advertising
  elasticities," *Journal of Marketing Research* 48(3), 2011.
