Technical documentation for data scientists, analytics leads, and methodology reviewers.
This document is intended for technical evaluation of Adstock's modeling methodology. For business-level interpretation of results, see the main dashboard.
Adstock uses a frequentist Marketing Mix Modeling (MMM) framework built on Ridge regression with geometric adstock transformations. The methodology follows the same foundational econometric approach used by Google's Meridian and Meta's Robyn, adapted for speed-to-insight and accessibility.
The model ingests daily time-series data of marketing spend and revenue, applies carryover (adstock) transformations to capture lagged advertising effects, and fits a regularized linear model with non-negativity constraints to decompose revenue into channel-level contributions.
date column,
revenue (target variable), and one or more spend_<channel>
columns representing daily marketing spend per channel.spend_ columns are treated as spend features;
impr_ columns as impression features. Both are included as model predictors.is_holiday column
(0 or 1) allows the model to control for holiday-driven revenue spikes that are not
attributable to marketing spend.Deployment flexibility: Adstock can be deployed within a client's own cloud environment (Azure, GCP). Marketing data never needs to leave the client's infrastructure, satisfying enterprise security and data governance requirements.
Note: In the Adstock dashboard, adstock is referred to as “carryover” — a plain-English term for the same concept. The industry-standard term “adstock” is used throughout this methodology page for consistency with academic literature and frameworks like Google Meridian and Meta Robyn.
Advertising impact is not instantaneous. An ad exposure on day t can continue to influence consumer behavior on days t+1, t+2, ... with diminishing effect. The adstock transformation models this carryover using geometric decay:
α = 0.5.
This is equivalent to a half-life of exactly 1 day — 50% of the effect
persists after 1 day, 25% after 2 days, 12.5% after 3 days.Each adstocked column then enters the standardized feature matrix described in section 5, alongside the seasonality and trend controls described in section 4, before being passed to Ridge regression.
This is the industry-standard geometric adstock formulation used in both Google Meridian and Meta Robyn. See: Robyn Analyst's Guide, Google Meridian documentation.
Marketing spend is rarely the only driver of revenue variation. Without explicit controls for time effects, the model can misattribute trend, weekly cycles, and annual seasonality to whichever marketing channel happens to correlate with them. v2 adds four control families to the design matrix that are estimated jointly with the marketing coefficients:
0, 1, 2, …, n−1) captures gradual long-run drift in
the baseline — business growth, brand strengthening, or category-wide
tailwinds and headwinds.4
(4 sine/cosine pairs at period 365.25 days). This
captures smooth annual cycles — tax-season demand, summer slowdowns,
Q4 build-up — without requiring a calendar of named events.2
(2 sine/cosine pairs at period 7 days). This absorbs
day-of-week patterns common in DTC and retail data — weekend lifts, Monday
troughs.is_holiday binary column
retains its previous role as a step-function control for known one-day events.Fourier seasonality is the same approach used by Facebook's Prophet library and is standard practice for smooth periodic effects. Estimating these controls jointly with marketing features — rather than applying a pre-detrending step — lets the Ridge penalty arbitrate between competing explanations for any given week's revenue.
The Ridge L2 penalty λ∑jβj² treats every coefficient on the same scale. If one feature is measured in dollars (with values in the thousands) and another is a unit-bounded Fourier sine wave, the penalty effectively shrinks the dollar-scale coefficient much harder — not because that feature is less important, but because a coefficient producing the same revenue impact is much smaller in raw units. This is the classic scale-bias problem in regularized regression.
v2 corrects this by z-scoring every feature in the design matrix before fitting:
Ridge then sees features on a common scale, and the penalty is applied uniformly.
After fitting, the standardized coefficients are back-transformed
to original feature units so that contribution math
(βj × xj[t]) and ROI calculations
remain in spend dollars and revenue dollars:
The intercept absorbs the mean shift so predictions are unchanged. End users see coefficients and contributions in the same units they always did; the standardization is a numerical-stability layer that lives entirely between adstock and Ridge.
λ = 1.0 to address multicollinearity between
channels that scale spend simultaneously. The L2 penalty minimizes
∑βj², shrinking correlated coefficients toward each other
rather than allowing one to dominate arbitrarily.Marketing channels are frequently collinear — spend moves together during peak seasons, promotions, and campaign flights. Ordinary Least Squares (OLS) produces unstable, high-variance coefficient estimates in the presence of multicollinearity, often yielding negative coefficients or wildly inflated values. Ridge regularization shrinks unstable coefficients toward zero, producing more reliable and interpretable estimates.
See Google Meridian documentation and Meta Robyn Analyst's Guide for comparative discussion of regularization approaches in MMM.
The positivity constraint described in section 6 (βj ≥ 0)
is appropriate for marketing features — we don't want the model claiming that
spending money on Facebook destroyed revenue. But it is the wrong constraint for the
trend and seasonality controls: a downward trend or a negative weekend coefficient is
meaningful information that the model should be free to discover.
scikit-learn's Ridge applies positive=True to all coefficients or none.
To allow positive-only marketing coefficients alongside unconstrained controls,
v2 uses a two-stage residualized fit:
positive=True on the adstocked marketing features against this
residual, with no intercept (already absorbed in Stage 1).The two coefficient sets are then combined and back-transformed jointly to original units. This pattern — sometimes called residualization or partialling-out — is also used in Meta Robyn for the same reason.
Marketing coefficients are estimated only on the signal that survives after the controls have absorbed everything they can. If a channel's spend pattern is strongly correlated with the trend or with annual seasonality, some of its true effect will be absorbed by the control terms in Stage 1, and Stage 2 will produce a downward-biased marketing coefficient. This is a known property of two-stage approaches and the reason a fully joint Bayesian fit (planned for v3) is preferred when computational budget allows.
For each observation (day), total revenue is decomposed into the following components:
βj × hj[t], where
hj[t] = Hill(x'j[t]; Kj, Sj)
is the adstock-decayed and Hill-saturated spend feature. This isolates the non-linear
revenue attributable to each channel on each day.By explicitly framing seasonality as an exogenous structural control rather than an unexplained residual, Adstock ensures that cyclical surges (such as Q4 holiday spikes or weekend shopping lifts) are not misattributed to contemporaneous marketing spend or discarded into residual variance. The residual gap thus represents purely unmodeled variance after accounting for structural seasonality and marketing effects.
aj = xj / (1 − αj)
is the steady-state adstocked daily spend.
Kj = median(adstocked_spendj)). For S = 1.0, the
derivative simplifies directly to:
aj = Kj), this derivative evaluates to
1 / (4 · Kj). As spend scales up (aj >> Kj),
the derivative monotonically declines toward zero, modeling realistic diminishing marginal returns.
Because a marginal dollar of new spend propagates through geometric carryover as
1 + α + α² + … = 1 / (1 − α), the long-run marginal ROI
incorporates the carryover multiplier 1 / (1 − α).
d(revenue)/d(spend) = β / (1 − α)). Under constant marginal returns,
unconstrained mathematical optimization is degenerate: 100% of marginal capital collapses into whichever
single channel has the highest point estimate, regardless of market saturation, client capacity, or
estimation variance. Adstock eliminates linear attribution assumptions in favor of the active Hill
saturation formulation, ensuring that marginal returns continuously taper as spend expands.CV = σ/μ) and minimum coefficient across 5 overlapping
80% bootstrap subsample time folds:
[Lj, Uj]:
enable_saturation=False),
Adstock falls back to an excess-return weighting heuristic (Excess Returnj = max(0, mROIj − 1.0))
scaled by continuous stability shrinkage Sj. This heuristic prevents linear point estimate
collapse when running in legacy linear mode, but the non-linear Hill saturation model with SLSQP is Adstock's
primary production engine.r2_in_sample): Measures the proportion
of revenue variance explained by all inputs in the model — marketing channels
plus the v2 control terms (linear trend, Fourier yearly + weekly seasonality,
holiday flag). In Adstock's two-stage architecture, controls absorb periodic and trend
fluctuations first, allowing marketing features to compete cleanly on residual signal.
The resulting r2_in_sample directly underpins the headline Analysis Confidence tier
(High: ≥ 0.70, Medium: ≥ 0.40, Low: < 0.40).
Note: While r2_in_sample governs model evaluation thresholds,
the main dashboard abstracts raw R² values into intuitive confidence badges and MAPE-based accuracy,
ensuring executive stakeholders interpret reliability without statistical misinterpretation.
The foundational methodology — adstock transformation + regularized regression + positive constraints — is shared with Google's Meridian and Meta's Robyn, the two most widely adopted open-source MMM frameworks.
Meridian uses a Bayesian hierarchical framework with geo-level partial pooling, prior specification on parameters, and posterior sampling via MCMC. This produces credible intervals on all estimates but requires significantly more computational resources and analyst expertise. Adstock uses a frequentist approach optimized for speed-to-insight and accessibility.
Robyn uses Nevergrad for multi-objective hyperparameter optimization, evaluating thousands of model candidates across a search space of adstock parameters, saturation curves, and regularization strengths. This produces a Pareto-optimal set of models but requires significant computational time and analyst judgment to select a final model. Adstock uses a single-model specification with analyst-validated parameters.
As an independent measurement platform with no media inventory to sell, Adstock has no structural incentive to bias attribution toward any channel. This is a meaningful differentiator: Google and Meta's open-source MMM tools, while methodologically rigorous, are developed by organizations with inherent conflicts of interest as both media sellers and measurement providers.
For enterprise MMM vendors (Nielsen Marketing Cloud, Analytic Partners, Measured), engagements typically require 3–6 months and $200K–$500K+ annually. Adstock delivers comparable foundational methodology at a fraction of the cost and timeline.
Adstock translates econometrically rigorous parameter estimates into actionable, risk-managed reallocation decisions through canonical evaluation schemas and a standardized CMO confidence framework.
r2_in_sample (In-Sample Goodness-of-Fit):
Quantifies the proportion of revenue variance explained by the joint two-stage model
(controls + marketing). Instead of presenting raw decimal statistics that can confuse executive stakeholders,
Adstock directly maps r2_in_sample into three operational trust tiers:
marginal_roi (Marginal Return on Investment):
Measures the expected incremental revenue returned per additional dollar spent at current daily volume,
calculated analytically via the Hill saturation first derivative:
marginal_roi
governs forward-looking budget optimization: channels with marginal_roi > 1.00 return positive
net profit on the margin, while channels with marginal_roi < 1.00 lose money on the next dollar.
To protect client capital from noisy point estimates, Adstock evaluates parameter stability across 5 overlapping 80% bootstrap subsample time folds. The resulting stability statistics map directly to five standardized badges across the dashboard:
Methodology v2.1 | Last updated September 2026