spend_reach#

How far a change in spend reaches, and whether the accounting closes.

incrementality computes a difference of predictions and divides it by spend. Before it can, three facts about the fitted graph have to be established, and none of them can be assumed:

  1. How far in time a change in spend moves the evaluated nodes. The counterfactual is evaluated on a window around each period rather than on the whole date axis. A window is only valid if the perturbation’s effect dies inside it, and if each evaluated node is a causal function of date at all. Guess low and the tail falls outside the window, which returns a smaller increment with nothing to indicate anything was cut.

  2. That the evaluated nodes account for the whole move in the linear predictor. The increment is assembled from channel_contribution plus the resolved mu_effects. If spend reaches \(\mu\) by some other route, the increment reports one part of the response as though it were all of it.

  3. Whether one channel’s spend moves another channel’s contribution. A per-channel increment read off a single all-channels perturbation takes column c of channel_contribution to be a function of channel c’s spend alone. A media transform with a shared denominator makes that false for every channel at once, and neither of the other two measurements can see it.

The first two are read off one extra evaluation: perturb spend at a single interior date on the untruncated axis and compare against the baseline. The third is the same perturbation restricted to one channel, taken per channel and only when a per-channel column is going to be read. That shared measurement is why the questions live in the same module – and why they live apart from Incrementality, which owns periods, windows, spend and the link-specific reduction, and has nothing to say about any of them.

The entry points are SpendProbe.measure(), which returns a SpendReach: an evaluation-window length and whether a window is usable at all, and SpendProbe.mixes_channels(), which answers the third question.

Module Attributes

CHANNEL_CONTRIBUTION

Response variable holding the per-channel linear-predictor contribution.

LINEAR_PREDICTOR

Name the MMM gives its linear predictor, registered or not.

COMPLETENESS_ACCUMULATION_SAFETY_FACTOR

Safety factor for the float rounding accumulated across a compiled graph.

Functions

linear_predictor(model)

Find the node the increment is assembled to reproduce.

resolve_channel_dependent_effects(model)

Find the mu_effects a spend counterfactual reaches.

Classes

ChannelDependentEffect(contribution_var, ...)

A mu_effect whose contribution a spend counterfactual can reach.

SpendProbe(*, evaluator, baseline, ...)

Single-date spend perturbations, and the two facts read off them.

SpendReach(effective_l_max, requires_full_axis)

What the evaluation is allowed to assume about its window.

TemporalReach(additional_carryover_lags, ...)

How much of the date axis a change in spend moves one node over.