Resources

Strategic Budget Optimization through Marketing Mix Modeling (MMM)

Stop guessing which channels drive growth. Join Isabella Velásquez and Daniel Chen for this end-to-end workflow demo on modeling marketing spend, building 'what-if' scenario planners in Shiny, and deploying automated Quarto reports that give non-technical stakeholders a clear, data-backed view of ROI. We will explore: 1. The Workflow Architecture: A look at the “plumbing” required to move from data to insights. 2. The Interface: Wrapping an existing model in a Shiny dashboard for real-time “what-if” scenario planning. 3. The Delivery: Automating communication via Quarto reports to keep stakeholders aligned. 4. The Deployment: Using Posit Connect to turn your code into an accessible business asset for leaders. This workflow demo grew out of the incredible energy at our recent Data Science Hangout with Ryan Timpe at LEGO. We were so inspired by the community’s interest in MMM that we decided to build this session to address your specific questions. Thank you for the great discussion. We’re excited to show you what we’ve put together! Demo References MMM Demo GitHub Repo (https://github.com/chendaniely/dashboard-mmm) MMM Demo Dashboard (https://danielchen-dashboard-mmm.share.connect.posit.cloud/) Ryan Timpe’s posit::conf(2023) talk, tidymodels: Adventures in Rewriting a Modeling Pipeline - posit::conf(2023) (https://www.youtube.com/watch?v=R7XNqcCZnLg) MMM Resources Bayesian Media Mix Modeling for Marketing Optimization, PyMC Labs (https://www.pymc-labs.com/blog-posts/bayesian-media-mix-modeling-for-marketing-optimization) Modernizing MMM: Best Practices for Marketers, IAB (https://www.iab.com/wp-content/uploads/2025/12/IAB_Modernizing_MMM_Best_Practices_for_Marketers_December_2025.pdf) The Future of Media Mix Modeling, Measured (https://info.measured.com/hubfs/Guides/Measured_Guide%20The%20Future%20of%20Media%20Mix%20Modeling.pdf?hsCtaAttrib=184767817336) Media Mix Modeling: How to Measure the Effectiveness of Advertising, Hajime Takeda, PyData (https://www.youtube.com/watch?v=u4U_PUTasPQ) An Analyst's Guide to MMM, Meta (https://facebookexperimental.github.io/Robyn/docs/analysts-guide-to-MMM/) Full Python Tutorial: Bayesian Marketing Mix Modeling (MMM) SPECIAL GUEST: PyMC Labs, Matt Dancho (https://www.youtube.com/watch?v=lJ_qq_IVUgg) Reading MMM Outputs: Dashboards and Decisions for Small Teams, SmartSMSSolutions (https://smartsmssolutions.com/resources/blog/business/reading-mmm-dashboards-article)

Feb 25, 2026
21 min

image: thumbnail.jpg

Transcript#

This transcript was generated automatically and may contain errors.

Hi everyone, I'm Isabella Velazquez, and alongside Daniel Chen, we're going to walk through a demo of a Modern Marketing Mix Modeling workflow. We'll show you how to use Posit tools to create an organized, reproducible pipeline that can help you distill your model results into clear, actionable insights that you can relate to your stakeholders.

This workflow was inspired by the fantastic discussions with Ryan Timpe and the community at a recent Data Science Hangout, so thank you to everyone who sparked these ideas.

What is Marketing Mix Modeling?

Let's first quickly introduce Marketing Mix Modeling, or MMM. Rachel Dempsey and Mark Rieke shared a great metaphor for Marketing Mix Modeling, unbaking a cake. In marketing, we're often handed the cake, or the total revenue, and asked to figure out exactly which ingredients made it taste so good, and which ones were unnecessary.

MMM does this by unbaking the cake. It identifies the impact of every ingredient—the flour, the sugar, or even the luck of the oven temperature—to answer these sorts of questions.

More concretely, MMM is an analytical approach that uses statistical techniques on marketing time series data to estimate the impact of different marketing tactics on key performance metrics.

Executing an MMM produces a sophisticated blend of technical metrics and strategic insights. On the technical side, it generates statistical outputs such as model coefficients, confidence intervals, and goodness-of-fit measures. On the strategic side, the model yields visual and actionable assets, including contribution waterfall charts, cross-channel return-on-ad-spend comparisons, and diminishing-return curves.

By reviewing these outputs, stakeholders can solve critical business uncertainties, such as attribution, how many sales did a specific channel drive over the past year, predictive forecasting, such as how would total sales shift if I invested X amount of dollars into a specific channel next year, and optimization—what is the ideal budget allocation to maximize future revenue? Ultimately, these insights allow businesses to optimize their marketing investments and turn historical data into a roadmap for future growth.

In an MMM, inputs are all marketing variables and factors, including media, like social or search, baseline factors, like seasonality or brand equity, and external factors, like the economy or even the weather. Outputs consist of business metrics and KPIs, such as sales revenue, market share, and customer acquisition. It's important to note that MMM is meant to be a holistic view. It's supposed to measure outcomes for all marketing channels together in one analysis. It uses aggregate data, not individual user information, and so is often considered a privacy-first approach.

Choosing your MMM tools

Just as there are dozens of brands of eggs, flour, and milk at the grocery store, there are many ways to bake an MMM. No two data science teams use the exact same ingredient. Within open source, there are many options. For Python, there are tools like Google's Meridian or PyMC Marketing. For R, there are tools like Meta's Robin or building custom high-flexibility workflows using tidymodels and RStandarm, as Ryan Tsingpei detailed in his Posit 2023 talk.

You also have to choose your style of baking. Are you using Bayesian methods to incorporate priors, which are marketing insights that can be included in the model, or a more traditional frequentist approach?

But the best recipes in the world don't matter if your kitchen is a mess and your oven isn't calibrated. And this is where we propose Posit tools for the process. While the MMM workflow shares many steps with traditional data science, the stakes are high since you're justifying budget and resources. Posit tools can help you develop reproducible, transparent, and defensible models for your team with a code-first integrated approach. And with that, I'll pass it to Dan to show you this workflow starting in Positron, the new data science IDE from Posit.

Data ingestion and exploration in Positron

Hi, I'm Daniel. I'm on the developer relations team here at Posit. I'm going to show you an example of creating marketing mixed models and deploying them inside a Shiny application. You can find all the code and data we'll be working with in this repository. I've opened the repository in Positron.

MMMs can and should get data from many sources. Remember, you're trying to gain holistic understanding across channels. The data may come from where you buy your data, like Google or Meta, and come in various types like databases or flat files. With R or Python, you can connect to databases, APIs, and so on in Positron, and then clean, transform, and format it to make it easier to analyze. You probably need to repeat this process consistently. And by deploying these cleaning scripts to Posit Connect, we can automate the entire process and rerun the pipeline on a schedule.

Now let's take a look at our data set that we'll be working with. This example has one row per week and one column for each marketing channel with the amount of spend in that channel for that particular week. This example is very simple, but you would have separate columns for each of your channels, such as both branded and non-branded search on Google. We also have a column for whether the week was a holiday week, and most importantly is our sales revenue number.

Using the Data Explorer, we can take a look at the distribution of each variable. But very important to MMM work is taking a very close look at variation over time. You want to look at any trends, and if you spot any irregularities and patterns, you want to be able to understand what happened. This might also prompt you to create new variables. And we'll take a look at our exploratory data analysis document to check for errors as well as stress test our assumptions. For example, if we see a massive spike in July, but no spend, we need to ask the team do we have a viral moment or PR event? And if so, we can add that into our model as a new variable.

We can click the Preview button to render this document. Here the document renders in our side panel in Positron, but we'll look at it a little bit larger in a browser.

Here's our EDA report. We can look at our sales revenue distribution across our time period. And also see the individual channel breakdowns. One of the columns we have in this particular data set is looking at whether or not a particular week is a holiday week. You can see some spike in sales on the weeks compared to non-holiday weeks. There will be some overlap since holiday aren't just individual weeks, but they might be multiple weeks or a season. And some of this is confirmed by looking at the weekly sales revenue where our highest spikes are right at the end of the year during our holiday season.

Data quality checks

You probably heard the expression garbage in, garbage out. Since MMMs deal with aggregated data, it's particularly important that the data coming from the different channels are high quality, otherwise it could put the whole model in jeopardy. You want to check things like if the activity is tracked for an entire time period or whether data is consistent over time.

For both R and Python, we can do some data quality checks with a point blank package. Here you can have this section at the top of the EDA report or as a separate script or document. In this particular case, we're checking for missingness in our variables of interest. We're also checking to see if the date in our data set is contained within a certain time span. We're also doing some checks around whether or not our sales revenue numbers are actually greater than zero.

Building the models

Now let's talk about modeling. We'll be using tidymodels for the linear regression models and rstamarm for the Bayesian model. There's also a linear regression model feature in tidymodels. This is an example script that does some basic marketing mixed modeling or MMMs. This particular modeling script is made for this demo where you can run it as a regular R script from the command line with command line arguments, and our Shiny app also will run this script.

This isn't the best way to do an official deployment, but it gives you a lot more flexibility as a demo and also lets you iterate and work on the model and dashboard simultaneously.

Now let's talk about MMMs. There's a few things that make MMMs special. There's a temporal time series component. There are carryover effects, meaning money spent now does not always mean immediate revenue, and there are diminishing returns where impact may decrease with spend. Here we'll fit two different models, a linear regression model and a weakly informative Bayesian linear regression model, and we'll fit these same models with the carryover and diminishing returns transformation for a total of four models. Because we're working in a professional IDE, we can track our experiments. If a model looks too good to be true, we can look back on the code and the parameters to see exactly why.

One of the things tidymodels gives us is the ability to split our data into training and test sets. tidymodels also has a function that splits time series data into training and testing by keeping the temporal component of the data intact. Essentially, we'll train the first 80% of the data to test on the last 20%.

Our linear regression model is using tidymodels. We set this up just like every other model in tidymodels, where we create a spec for the model, the recipe, add it to a workflow, and then we can fit our model. And then we go through this same training, testing, and look at some of our training metrics. Because this is linear regression, we can also go and extract our coefficients. These coefficients will play a role in the results for our MMM model.

We can then write a function to calculate our addStock carryover effect. And then we can also go and calculate our saturation or diminishing returns function. Next, we can use regular tidyverse functions to take our existing training data and apply these transformations to it. These transform columns is one way where we do feature engineering for our MMM models. Lastly, we want to use our transformation functions, but to prevent data leakage, we want to make sure that we're transforming and carrying over the last value from our training data set into our testing data set. And then we go and use the tidyverse functions again, but this time on our test data.

Then we go and perform our linear regression model just like before, but we use the data set with these transformations applied. Our response variable is still going to be sales revenue. For the last two models, we'll fit the same transformed and non-transformed data to a Bayesian linear regression model. Here we're using the RSTAM arm for Bayesian applied regression model via STAN. You can also look into using tidymodels for fitting linear regression models using STAN. In this example, we're only using a weekly informative prior. This is where you would provide all your actual domain knowledge and incorporate it into your model as well as any of the existing seasonality and priors from your own data.

Model diagnostics and Quarto reporting

The next step is running our model diagnostics. Model evaluation helps you figure out whether your model is capturing the right relationships and not just overfitting the data and to determine how to execute from the model insights. Our initial model parameters, our linear regression model on a transformed data has the lowest RMSE, so this might be the model we'll potentially choose to stick with our deployment. But also remember our Bayesian model only has weekly informative priors on it, and it's not including a lot of new information from our actual data.

At this point, while you can continue in a script, it might be easier to take a look at all of your diagnostics at once. So we can create a Quarto document and look at all of our models at the same time.

Using Quarto, we can generate a diagnostic brief for our models. One of the things that we do here is in our modeling step, we're saving these objects out so we can read them in other files later on without having to rerun the entire model. By combining narrative and code output, we can quickly run and document our model findings. This ensures every model we produce comes with documentation that our peers can audit and we can reference in the future. Here we see the plot output alongside our notes.

By combining narrative and code output, we can quickly run and document our model findings. This ensures every model we produce comes with documentation that our peers can audit and we can reference in the future.

Building the Shiny application

Finally, let's go past the EDA and work on presenting our results. We'll go and create a Shiny application to show some descriptive statistics, but also provide a way for users to change the transformation parameters for the model.

This model is tied to our model.r file for this demo. So our Shiny application will be loaded up with pre-compiled models, but also rerun our script as we change our transformation parameters. There are definitely more efficient ways to handle this kind of data and model changes. This demo is primarily focused on making it easier to run the model and application code separately.

Here in the application, we have a few key performance indicator cards at the top. This might be the most important set of numbers and values as you talk with stakeholders. The rest of the first page gives the data showing the current spend and revenue trend. We can also see that our EDA analysis is playing a role here in our Shiny application. Finally, the ROI values are coming from our selected model. In this case, it's our transformed linear regression model.

We can also do a bit of drill-down analysis by looking at individual channels.

Next, we can also use our model to optimize how we should allocate money to different channels. This will use the current model and some other user constraints to allocate a given mortgaging budget.

Finally, we can provide a user interface to regenerate models. In this particular example, all our models run fairly quickly, so we can get away with the current demo setup of rerunning our entire modeling script. The entire application reacts to the selected model, in this case, the transformed linear regression model. We can switch to our Bayesian model.

And you'll see how the ROI values in the overview page are reacting to the model changes.

We can also make a few what-if scenario changes to our models. Let's have a high decay rate and a low saturation shape. And then we can go and retrain our models. And now you can see our new models will react in the application.

Deploying to Posit Connect

Now let's get this application deployed. We currently have this repository on GitHub with all of the code, application, and models. We can use Posit Connect or Posit Connect Cloud to deploy our application. We'll go through a GitHub deployment for Connect Cloud. Here, after you sign in, you will click on Publish. Select Shiny. Select our repository. And point to our app.r file. Connect will read our current rm.loc file to set up our environment for the application. And finally, we can publish our application.

In this example, rsamr will take a bit of time to compile and install, and you might need a larger RAM instance. If you need to bump up the RAM instance, you may need to go on one of the paid plans. In order to bump up the RAM, if your application is failing, click on the gear. Go to Compute. And make sure that the memory dial is set to the largest that you have.

When the deployment is done, we'll have the same application we had locally. We can go and make a change to our model and retrain our models. And the application will react accordingly. We can then click the Share button, enable public access, or private link sharing.

Delivering insights to stakeholders

Now that we've finished up our data products, I'll pass it to Isabella to discuss the final steps. At this point, it's time for the team and domain experts to come together and develop a unified data-backed strategy. Because this workflow is built on code rather than a static spreadsheet, you have the agility to adjust assumptions in real-time. Junk back into the code during the meeting, tweak a parameter, and refresh the app.

The result of this huddle is a final, defensible plan. Stakeholders need clearer narratives, and we can use Quarto to bridge the gap between technical rigor and executive summary. With Quarto, the same code powering your analysis generates a polished Word doc, PDF, or even a PowerPoint. You can meet stakeholders in the format they use every day, without the risk of manual data entry errors.

IAB released an excellent report called Modernizing MMM Best Practices for Marketers. In their executive summary, they state that modern MMM should do three things well. Earn trust, balance speed and stability, and drive strategy. By building a workflow that is reproducible and version-controlled, you aren't starting from scratch every quarter. You're building an institutional asset that can be tailored to your audience. And by keeping the process transparent and defensible, you don't just build a model, you build trust.

And by keeping the process transparent and defensible, you don't just build a model, you build trust.

We want to extend a huge thank you to the subject matter experts in the POSIT community who helped us shape this workflow. Their real-side insights into MMM were instrumental in building this demo. And with that, we'll move to the Q&A. Thank you!