ds@mcpanalytics.aiEmail your data and your question and get an answer about your own data, with the method shown.Email your data and question. Get an answer.

Promotional & Discount Analysis: Measure the Real ROI of Every Promotion

By MCP Analytics Team | Published , updated

You ran a 20% off sale last month. Revenue went up. The team celebrated. But did profit actually increase, or did you just sell the same products for less money? Promotional analysis answers the question every retailer avoids: are your discounts making you richer or poorer? Upload your order history to review promo results.

Worked Example (Simulated): Was Profit per Order Higher with a Promo or at Full Price?

Question: In these made-up orders, was mean profit per order higher with a promo or at full price?

Inputs: The data are made up. The seed is 17. The script draws net profit in dollars for 12 full-price orders and 12 promo orders. It builds in a mean of $24 per full-price order and $19 per promo order, with a standard deviation of $5 in each group. That is a gap of $5 per order built in.

Method: Find the mean profit per order in each group. Subtract the full-price mean from the promo mean. The interval is a 95% interval for that gap (Welch's t interval).

import numpy as np
from scipy.stats import t

SEED = 17
rng = np.random.default_rng(SEED)

# Simulated net profit per order in dollars for two groups.
full_price = np.round(rng.normal(loc=24, scale=5, size=12), 2)
promo = np.round(rng.normal(loc=19, scale=5, size=12), 2)

full_mean = float(full_price.mean())
promo_mean = float(promo.mean())
mean_gap = promo_mean - full_mean
v_full = full_price.var(ddof=1) / len(full_price)
v_promo = promo.var(ddof=1) / len(promo)
se_gap = float(np.sqrt(v_full + v_promo))
df = se_gap**4 / (v_full**2 / (len(full_price) - 1)
                  + v_promo**2 / (len(promo) - 1))
margin = float(t.ppf(0.975, df)) * se_gap

print(f"Seed: {SEED}")
print(f"Orders per group: {len(full_price)}")
print("Built in: mean profit per order $24 at full price and $19 on promo, "
      "SD $5 in each group")
print("Full-price profit per order ($):",
      ", ".join(f"{x:.2f}" for x in full_price))
print("Promo profit per order ($):", ", ".join(f"{x:.2f}" for x in promo))
print(f"Full-price mean profit per order ($): {full_mean:.2f}")
print(f"Promo mean profit per order ($): {promo_mean:.2f}")
print(f"Promo minus full-price mean ($): {mean_gap:.2f}")
print(f"95% interval for the gap ($): {mean_gap - margin:.2f} "
      f"to {mean_gap + margin:.2f}")

Printed output:

Seed: 17
Orders per group: 12
Built in: mean profit per order $24 at full price and $19 on promo, SD $5 in each group
Full-price profit per order ($): 29.51, 25.69, 21.30, 17.70, 14.53, 24.09, 19.95, 19.64, 22.89, 23.74, 12.62, 28.63
Promo profit per order ($): 8.87, 28.30, 21.95, 16.64, 25.71, 19.10, 22.45, 19.54, 24.48, 24.31, 14.46, 15.94
Full-price mean profit per order ($): 21.69
Promo mean profit per order ($): 20.15
Promo minus full-price mean ($): -1.55
95% interval for the gap ($): -6.06 to 2.97

Result: The script builds in $5 lower profit per promo order. This draw shows $1.55 lower ($21.69 at full price against $20.15 on promo), and the 95% interval runs from -$6.06 to +$2.97. Twelve orders per group is too few to settle the gap, so this run understates the built-in gap. The example holds order counts equal, so it does not test whether extra promo orders make up the difference.

Limit: These values are made up. A group comparison can show a link in the data. This check cannot show what a real sale caused.

Sources

What Is Promotional Analysis?

Promotional analysis compares the performance of discounted orders against full-price orders to determine whether your promotions are actually working. "Working" does not just mean more orders. It means more total profit after accounting for the margin you gave away, the additional volume you attracted, and the customer behavior changes the discount triggered.

The core question is simple: when you offer 15% off, does the extra volume more than compensate for the reduced margin on every unit? The answer varies dramatically by product category, discount depth, customer segment, and timing. A 10% discount on office supplies might drive enough incremental volume to increase total profit. The same 10% on furniture might just cannibalize full-price purchases and reduce profit. Without a structured analysis, you are guessing.

This module goes beyond simple before-and-after revenue comparisons. It segments your order data by discount depth (no discount, 1-10%, 10-20%, 20-30%, and so on), breaks results down by product category, and tests whether the differences are statistically significant, not just big enough to look interesting on a dashboard. The result is a clear picture of which promotions earn their keep and which ones are burning money.

Why Most Businesses Get Promotions Wrong

The most common mistake is measuring promotion success by revenue alone. Revenue often goes up during a sale, which is usually the aim. But revenue is a vanity metric when it comes to promotions. The real question is what happened to profit, and most teams never check. A 30% off sale that doubles order volume sounds like a win until you realize each order now loses money after cost of goods and shipping.

The second mistake is treating all discounts the same. A 5% loyalty discount for returning customers is a fundamentally different lever than a 40% clearance markdown. Lumping them together in a "promoted vs. non-promoted" comparison hides the fact that shallow discounts might be highly profitable while deep discounts are destructive. This analysis breaks your orders into discount depth bins so you can see exactly where the profit breakeven point sits.

The third mistake is ignoring cannibalization. If customers were going to buy anyway and you gave them a coupon at checkout, you did not drive incremental revenue. You just reduced your margin on a sale that was already happening. This report compares order patterns, average quantities, and revenue per order across discount levels to surface cannibalization signals.

When to Use This Analysis

Run this analysis whenever you need to make a decision about promotional strategy. Common scenarios include:

Post-promotion review. You just finished a Black Friday sale, a seasonal clearance, or a coupon campaign. Before planning the next one, you need to know what actually happened to margins. Did the 20% off sale actually increase profit, or did it just shift purchases from the week before and after into the promotion window?

Discount level optimization. You are deciding between offering 10%, 15%, or 25% off. Historical data can show you the volume response curve at each discount level and identify the sweet spot where incremental volume outweighs margin loss. Some product categories are price-elastic (small discounts drive big volume increases) while others are inelastic (customers buy the same quantity regardless). This analysis tells you which is which.

Coupon effectiveness audit. You distribute coupons through email, social media, or influencer partnerships. Are these coupons reaching new customers who would not have purchased otherwise, or are they being redeemed by existing customers who would have bought at full price? The category and segment breakdowns help you answer this.

Seasonal promotion ROI. Every year you run the same holiday promotions because "we always have." This analysis lets you compare promotion periods against non-promotion periods to quantify the actual return, accounting for the margin you sacrificed.

What Data Do You Need?

You need a CSV of your order or transaction data with at least these columns: an order or transaction ID, a sales or revenue amount (numeric), and a discount percentage or amount (numeric, with 0 for orders that were not discounted). The module accepts discount as either a decimal proportion (0.2 means 20% off) or a percentage (20 means 20% off).

For the most useful results, also include product category (so the analysis can break down promotional impact by category), order date (to analyze trends over time), profit (to measure margin impact), customer ID (to analyze repeat purchase behavior), and quantity (to separate volume effects from price effects).

You need at least 50 orders, with a mix of discounted and non-discounted transactions. The more data you have, the more granular the category and discount-depth breakdowns become. The tool supports up to 5,000 rows on the free tier and 1,000,000 on business plans.

How to Read the Report

The report is organized into eight slides, each answering a specific question about your promotional performance. Here is what each one tells you and how to act on it.

Analysis Overview (Key Metrics + Data Overview)

The first slide gives you the headline numbers: total orders analyzed, the split between discounted and non-discounted orders, average discount depth, and the overall revenue impact, and profit impact when your file includes a profit or cost column. The data overview card shows the shape of your input: how many categories, the date range covered, and any data quality notes. Start here to confirm the analysis ingested your data correctly and to get the top-line story before diving into details.

Primary Results (Discount Impact Visualization)

This is the main visualization, typically a comparison of revenue and profit metrics across discount depth bins. You will see side-by-side bars or a curve showing how average order value, total revenue, and profit change as discount depth increases. The AI insights panel highlights the key finding: where the profit breakeven point is, which discount range maximizes total profit, and whether deep discounts are destroying value. This slide shows which discount level had the highest observed profit in your data. Calling that level optimal would need a suitable experiment or causal method, because a comparison of past orders cannot show what a different discount would have caused.

Distribution Analysis

The distribution slide shows how your orders spread across discount levels and categories. You might discover that 60% of your discounted orders cluster at one level (say 20% off) because that is the default coupon you distribute, meaning you have never actually tested whether 15% or 10% would work just as well with less margin sacrifice. The distribution also reveals whether certain categories are disproportionately discounted, which signals either strong promotional dependency or overuse of discounts.

Detailed Results and Summary Tables

Two side-by-side tables break down the numbers. The results table shows statistical comparisons between discounted and non-discounted orders: mean revenue, mean profit, effect size (Cohen's d), and p-values. The summary table provides category-level statistics so you can see which product lines benefit from promotions and which ones suffer. A p-value is a score from a test. If it is below 0.05, that is evidence against the null claim, the test's starting claim. The test rules must fit the data. It does not show that a discount caused a change or that the gap matters to the business. A group comparison can show a link in the data. By itself, it cannot show what buyers would have done without the offer. Look at the size of the gap and its range, not only the p-value.

Diagnostics (Assumption Checks)

The diagnostic slide shows plots that assess whether the statistical comparisons are trustworthy. This includes checks for outliers that might skew averages, distribution shapes within discount groups, and sample size adequacy per group. If any group has fewer than 10 orders, the module flags it because small samples make statistical tests unreliable.

Model Performance

This slide pairs diagnostics metrics with performance metrics. It surfaces the statistical confidence levels across comparisons, the number of categories with sufficient data for reliable breakdowns, and any warnings about data quality issues that might affect the conclusions. Think of this as the "trust score" for the rest of the report, if the performance metrics are strong, you can act on the findings with confidence.

Technical Details (Summary Stats + Methods)

The technical slide documents the methods and parameters used, including the discount bin boundaries. The summary statistics card provides secondary metrics like median order values, standard deviations, and interquartile ranges. This slide exists for reproducibility: a finance team or external auditor can verify exactly how the conclusions were reached.

Insights and Recommendations

The final slide is a plain-language interpretation generated by AI that reads the statistical output and translates it into business recommendations. It is meant to read the results from the prior slides and describe them in plain language.

What Data Sources Work?

The analysis needs a CSV with order amounts and discount information. Many store platforms let you export orders as a CSV file; check your platform's help pages. If your data has a revenue or sales column and a discount column, you have the minimum fields for a revenue and discount analysis. Profit results need a profit or cost column as well.

When to Use Something Else

If you want to measure whether a specific promotion caused a sales lift (causal inference rather than correlation), consider a Bayesian A/B test or difference-in-differences analysis. Those methods require a control group that did not receive the promotion, which this module does not assume.

If your primary question is about optimal pricing rather than promotional effectiveness, the price elasticity module is more appropriate. It models the continuous relationship between price and demand rather than comparing discrete discount levels.

If you need to analyze profitability at the product level without a focus on discounts, the product profitability module provides margin analysis, contribution analysis, and Pareto classification across your full catalog.

Your turn

Bring your own data and the question you actually need answered.

MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai