PyMC-Marketing puts Bayesian media mix modelling in a Python package
Bayesian marketing toolbox in PyMC. Media Mix (MMM), customer lifetime value (CLV), buy-till-you-die (BTYD) models and more.
At a glance
- What is it?
- PyMC-Marketing is a library of Bayesian marketing models built on PyMC, covering media mix modelling, customer lifetime value, discrete choice, Bass diffusion and predicted incrementality. Its most instructive feature is not a model but the dependency pins, which record the exact versions the sampling stack can be held to.
- Who is it for?
- PyMC-Marketing suits a data science team that has decided to model marketing effectiveness with Bayesian methods rather than with a frequentist attribution tool, and that wants the modelling choices to be inspectable Python rather than a black box service.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A marketing analytics toolbox, not one model
PyMC-Marketing is a Bayesian marketing toolbox in PyMC, and the description lists the models it covers: marketing mix modeling, customer lifetime value, buy-till-you-die models and more, with the headline of the project being Bayesian tools for marketing analytics covering MMM, CLV, customer choice, incrementality and more.
The list of methods is broader than media mix modelling. There is customer choice modelling, with discrete choice, MaxDiff and Bayesian BLP, which are the tools for asking which product attribute a customer prefers. There is Bass diffusion, which models how a new product spreads through a population. And there is predicted incrementality by experimentation, PIE, which is the part of the toolkit aimed at answering what would have happened without a campaign rather than what happened with it.
That last one is the distinction that separates this kind of tool from attribution dashboards. An attribution model tells you which channel touched the customer last. An incrementality model tries to estimate the difference between the world where you spent the money and the world where you did not, which is a much harder question and the one a marketer actually needs answered.
The audience is a data science team with a marketing budget to allocate and enough data to model it, and the readme is explicit about the commercial context: the repository is supported by PyMC Labs, which offers consulting and training for businesses integrating the tool into their operational framework, and the project is presented as empowering data-driven decisions for maximising return on investment in campaigns.
The package is on PyPI, the documentation is published, there is a journal paper for it with a DOI, and the project classifier says Production/Stable, with an intended audience of science and research.
The media mix model, and what the research it builds on does
The media mix modelling API is the centre of the package, and the readme says what it is built on: the research article by Jin, Yuxue and others on Bayesian methods for media mix modeling with carryover and shape effects from 2017, extended by integrating the expertise from the core PyMC developers.
The feature table explains the modelling choices, and each row is a decision a practitioner would otherwise have to make themselves.
Custom priors and likelihoods let you tailor the model to your business by including domain knowledge through prior distributions. Adstock transformation is about the carry-over effect in marketing channels, which is the observation that a media exposure keeps working for days or weeks afterwards rather than acting only on the day it is served. Saturation effects capture diminishing returns, the fact that the second unit of spending in a channel buys less than the first. And the adstock and saturation functions are customisable, with a selection of built-in ones and the option to implement your own, with a documentation guide for the components.
The table continues with a time-varying intercept, which is how you account for a baseline that moves over time, for example because of seasonality or a change in the market, so that the channel effects are not absorbing a drift in the response.
What this amounts to is a set of the assumptions that make attribution ambiguous, made explicit and adjustable. The carry-over and saturation functions are the two decisions that change the answer most, and a library that exposes them as a choice, with the option of writing your own, is asking the user to be responsible for them. That is the honest bargain of a modelling library rather than a reporting tool.
The rest of the toolbox, and the optional extras
Beyond media mix modelling, the package covers the other marketing questions, and the readme groups them by model family.
Customer lifetime value is the obvious second, and it comes with a plotting module of its own, which the dependency list reveals because that module imports an internal ArviZ statistics utility directly rather than relying on the ArviZ meta-package to bring it in. Customer choice modelling covers discrete choice, MaxDiff and Bayesian BLP, the three standard approaches to the question of which attribute a customer actually values, and they are different experiments with different data requirements.
Bass diffusion is the third family, and the buy-till-you-die model, named in the repository description, is a fourth: a model of how long a customer keeps buying, which is what connects a lifetime value estimate to a cash flow forecast rather than to a per-customer number.
The optional extras are worth reading because they show the edges of the package. Installing with the dag extra brings in causal identification tooling, which is the machinery for stating the assumptions that let a model produce a causal reading of its coefficients rather than only an associational one. Installing with the pie extra brings in predicted incrementality by experimentation, and the comment notes that it requires pymc-bart, so the incrementality work depends on a separate project.
That last point is the pattern to watch for in a package of this size. The core is self-contained, and the features that reach outside it do so through extras that name their extra dependencies explicitly, which is the right way to do it, because it means you only take on what you use.
Installing, and the version floors that come with it
The installation is a pip install, and the requirements are stated before the command rather than after it.
PyMC-Marketing is built on top of PyMC 6.0 or later and ArviZ 1.2 or later, with arviz-plots for visualisation, bringing the latest Bayesian sampling and plotting stack to marketing analytics, and it requires Python 3.12 or newer.
pip install pymc-marketingThe optional features are extras:
pip install pymc-marketing[dag] # causal identification tooling
pip install pymc-marketing[pie] # Predicted Incrementality by Experimentation (PIE), requires pymc-bartThere is a longer installation guide in the documentation for people who want the details, and there is a Dockerfile so the package can be reached from a Jupyter Notebook, with the specifics in the scripts/docker readme. The Docker route matters more here than in most libraries, because a Bayesian model is a thing you explore in a notebook, and a container that already has the compiled sampling stack is a reasonable way to get one.
The Python floor of 3.12 and the ArviZ 1.x requirement are both recent, and they are the visible edge of a dependency tree that has moved on. The library itself is versioned 1.2.0, with 1.0.0 on 2026-08-07, 1.1.0 on 2026-08-27 and 1.2.0 on 2026-09-29, so the 1.x line is short and recent, and the last push was on 2026-10-15.
The dependency comments are the documentation of a moving stack
The project manifest is unusually worth reading, because the dependencies carry comments explaining why they are pinned the way they are. That is a practice you rarely see, and in a package whose core dependency is a compiler-like stack it is the difference between an install that works and one that does not.
The numpy constraint has a three line explanation. Numba 0.66 or below, which is a hard requirement of pytensor 3.x, does not support numpy 2.5, and uv 0.12 or later otherwise falls back to a numba pre-release, so the bound is numpy greater than or equal to 2.0 and below 2.5. The comment adds the instruction to lift the constraint together with the next pytensor bump that allows numba 0.67 or later, which is a maintainer telling you exactly when the pin can move.
The pandas bound has a similar note. Pandas 2.2 or later is declared, but the comment says that CI runs pandas 3, so the declared floor is conservative in the other direction, the floor is lower than what is actually exercised.
The ArviZ dependencies are split for a reason. The package depends on arviz-plots with the matplotlib extra, on arviz-stats, and on arviz itself, all in the 1.2 series, and the comment explains that the customer lifetime value plotting module imports an internal statistics utility directly, so it is declared rather than left to the meta-package to pull in.
And the NetCDF stack is there for saving. The comment says that ModelIO.save writes non-Zarr paths through a data tree to NetCDF, that ArviZ 1.x made the NetCDF backends optional, and that h5netcdf does not depend on h5py, so both h5netcdf and h5py are declared explicitly.
This is a small but telling picture of the ecosystem. A library that depends on a sampling stack, a plotting stack, a dataframe stack and a compiler front end has to pin the joints, and the comments here are the notes of someone who has been the one to fix the install.
The local workflow, the docs build and the commercial context
The Makefile shows the development loop, and it is built around uv, which appears in every recipe.
The init target installs the package in editable mode with a uv sync, the test target installs the test dependencies and runs pytest, and the lint and format targets install the lint extras and run ruff and mypy, with separate check variants that do not fix anything. The format target uses ruff format, so the project has consolidated its linting and formatting on ruff, and the ruff badge in the readme is the modern one that tracks the linter's own release.
The documentation build is a target of its own, and it does something that is worth noting. The html target installs the documentation dependencies, runs a script that generates the gallery, and then runs sphinx-build over the docs directory. The comment above it says the target reproduces the GitHub Actions docs workflow locally and fails on any sphinx, myst or numydoc warning, with a keep-going flag that collects every warning before failing. So the documentation is treated as a build artefact with warnings as errors, and a developer can reproduce the CI documentation job on their machine.
The repository supports that: a docs/ directory with the source, a data/ directory, a paper/ directory, a locales/ directory for translations, a scripts/ directory, a skills/ directory, a streamlit/ directory, and both a .claude/ and a .cursor/ directory, which are the markers of a project set up for assistant tooling. There is a pre-commit configuration, a readthedocs configuration, a codecov configuration, a .test_durations file, and a uv lock file.
Two things frame the project for an adopter. The first is the commercial context: PyMC Labs maintains the repository and offers consulting and training, and the readme includes a route to a free consultation for marketing mix modelling and customer lifetime value strategy. A commercially backed open source library is a different proposition from a personal project, and the value is the availability of help when a model does not converge.
The second is the community surface: GitHub discussions, the PyMC Discourse forum, a Bayesian Discord server and the MMM Hub Slack, plus a video on Bayesian media mix models. For a model library, that support network is part of the product, because the hard problems are usually about the data rather than the code.
Editorial conclusion
PyMC-Marketing suits a data science team that has decided to model marketing effectiveness with Bayesian methods rather than with a frequentist attribution tool, and that wants the modelling choices to be inspectable Python rather than a black box service. It is the wrong choice if you need results in minutes rather than minutes of sampling, because every model here is a full probabilistic fit, and a poor match if your data is small and aggregated, since these models assume enough observations to identify channel effects. Before adopting, read the dependency comments in the manifest, because the numpy and pandas bounds there are load bearing, and plan for the sampling time in your pipeline rather than assuming a library call is cheap.
Frequently asked questions
What models does PyMC-Marketing provide?
Marketing mix modelling, customer lifetime value, customer choice with discrete choice, MaxDiff and Bayesian BLP, Bass diffusion, buy-till-you-die models, and predicted incrementality by experimentation. The media mix modelling API builds on the 2017 research on Bayesian media mix modelling with carryover and shape effects.
How do I install PyMC-Marketing?
Run pip install pymc-marketing. It requires Python 3.12 or newer, PyMC 6.0 or later and ArviZ 1.2 or later. The extras pip install pymc-marketing[dag] adds causal identification tooling, and pip install pymc-marketing[pie] adds predicted incrementality by experimentation, which requires pymc-bart.
What do the adstock and saturation options do in the PyMC-Marketing media mix model?
The adstock transformation models the carry-over effect, where a media exposure keeps working for days or weeks after it is served, and the saturation effects model diminishing returns in a channel. Both are customisable, with a selection of built-in functions and the option to implement your own, and the time-varying intercept accounts for a baseline that moves over time.
How is PyMC-Marketing developed and tested?
The Makefile drives everything through uv, with an init target that syncs the environment in editable mode, a test target that runs pytest, and lint and format targets that run ruff and mypy. The documentation build runs a gallery generation script and then sphinx-build, failing on any sphinx, myst or numydoc warning, and the same workflow runs in GitHub Actions.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pymc-labs-pymc-marketing)Was this useful?