You are thinking about raising prices on a few products, or running a 20% off sale on your best sellers. But how much will demand actually change? Price elasticity is one number for that: if you raise prices 10% and sales drop 15%, elasticity is -1.5: elastic demand, meaning customers are price-sensitive and volume falls faster than price rises. Upload your Shopify orders CSV, and this analysis estimates one elasticity across the rows you give it, with an interval around it.
Worked Example (Simulated): A Log-Log Fit of Units on Price
Question: In this made-up sample, how do units sold move with price?
Inputs: Simulated data, seed 23. The script makes 36 price and unit rows, with prices from $20 to $40, and needs numpy and scipy. Unit counts come from a set log-log rule with random noise. The script sets the elasticity at -1.4. Prices are assigned at random in the simulation, so the slope has a causal reading here and not in a shop's real order data. No Shopify data is used.
Method: Fit an ordinary least squares line to log units and log price. The slope is the fitted elasticity. The interval and p-value use the usual least squares errors.
import numpy as np
from scipy import stats
seed = 23
rng = np.random.default_rng(seed)
n = 36
price = np.tile(np.array([20., 24., 28., 32., 36., 40.]), 6)
rng.shuffle(price)
log_price = np.log(price / 30.0)
log_units = np.log(120.0) - 1.4 * log_price + rng.normal(0, 0.12, size=n)
units = np.exp(log_units)
x = np.column_stack([np.ones(n), log_price])
beta = np.linalg.lstsq(x, log_units, rcond=None)[0]
resid = log_units - x @ beta
df = n - x.shape[1]
s2 = (resid @ resid) / df
cov = s2 * np.linalg.inv(x.T @ x)
se = np.sqrt(np.diag(cov))[1]
t_value = beta[1] / se
p_value = 2 * stats.t.sf(abs(t_value), df)
crit = stats.t.ppf(0.975, df)
lo, hi = beta[1] - crit * se, beta[1] + crit * se
dev = log_units - log_units.mean()
r_squared = 1 - (resid @ resid) / (dev @ dev)
change = (1.10 ** beta[1] - 1) * 100
print(f"Simulated data, seed {seed}")
print(f"rows={n}; prices=${price.min():.0f}-${price.max():.0f}; "
"units generated from a log-log relation with random noise")
print(f"OLS slope={beta[1]:.3f}; 95% CI=[{lo:.3f}, {hi:.3f}]; "
f"p={p_value:.2e}; R-squared={r_squared:.3f}")
print(f"fitted association for a 10% price rise: {change:.1f}% units")
Printed output:
Simulated data, seed 23
rows=36; prices=$20-$40; units generated from a log-log relation with random noise
OLS slope=-1.340; 95% CI=[-1.543, -1.137]; p=3.88e-15; R-squared=0.841
fitted association for a 10% price rise: -12.0% units
Result: The fit recovers -1.340, with a 95% interval from -1.543 to -1.137, which contains the set value of -1.4. The p-value is 3.88e-15, small because the link was built in. In this sample, a 10% price rise goes with 12.0% fewer units. This is a sample result, not a forecast for a shop.
Decision: Treat a result like this as a cue to test a price change with a small, planned test, then check units and margin. Do not use this made-up result to set a real price.
Limit: The data follow a set rule, so they do not show how real buyers react. In real sales, other changes can affect both price and demand.
What Is Price Elasticity Analysis?
Price elasticity of demand measures how sensitive your customers are to price changes. The core idea is simple: when you change the price, how much does the quantity sold change? The answer is a single number, the elasticity coefficient.
To see how much your own demand drops when the price rises, try the free price elasticity tool.
Here is how to read it. An elasticity of -1.5 means a 10% price increase goes with a 15% drop in units sold. An elasticity of -0.3 means a 10% price increase goes with a 3% drop. The sign is usually negative (higher prices tend to mean fewer sales), so what matters is the magnitude. If the absolute value is greater than 1, demand is elastic: customers are price-sensitive, and a price hike will cost you more in lost volume than it gains in per-unit revenue. If the absolute value is less than 1, demand is inelastic: the volume drop is small relative to the price increase, so total revenue goes up.
This analysis uses log-log regression. By taking the natural log of both price and quantity, the slope of the regression line equals the elasticity coefficient. A log-log fit is a linear regression on logged values. It assumes a constant elasticity across the price range. The free tool fits one regression to all the rows you upload and reports one elasticity with a 95% interval. It says whether demand looks elastic or inelastic, and gives the direction revenue would move, read as an association because prices were not randomly assigned.
When to Use Price Elasticity Analysis
The most common use case is planning a price increase. You have rising costs (shipping, materials, supplier prices) and you need to pass some of that along. The fitted slope gives a rough sense of how sensitive demand is across your catalog. It does not give a separate answer for each product, so use it to choose questions for further study.
Discount planning is the flip side. As arithmetic only: if the elasticity were -0.4, a 20% discount would raise units sold by about 8%, which gives away margin for little volume. If it were -2.0, the same discount would raise units by about 40%. Which case you are in is what the estimate helps you judge.
For new product pricing, you can compare against existing items in your catalog. A new athletic shoe priced at $140 could be compared with other shoes in the $120-160 range, but that comparison does not show how demand for the new shoe will respond to its own price.
What Data Do You Need?
You need a Shopify orders export CSV with a product name, the price the customer paid per unit, and the quantity bought. To export this from Shopify, go to Orders > Export, and select the line-item level export. The key fields are "Lineitem name", "Lineitem price" and "Lineitem quantity". If you use a different naming convention, the tool lets you map columns when you upload.
The tool needs at least 30 usable rows and at least 3 distinct prices to run. The regression needs price variation to estimate elasticity. If all your products sell at $29.99, there is no price variation and no elasticity to measure. Very thin data produces wide intervals.
One important nuance: rows pooled across products give a catalog-level slope, not each product's own. It compares how demand differs across products at different price levels. This is distinct from within-product elasticity, which measures how one product's demand changes when its own price changes over time. For that you need history showing the same product at different prices.
How to Read the Report
The report has these cards: Analysis Overview, Data Quality, Executive Summary, Demand Curve, Elasticity Estimates, and Fit and Classification.
Analysis Overview and Data Quality describe the run and the rows it used. Check them first, so you know what the estimate rests on.
Executive Summary gives the headline: the elasticity, whether demand looks elastic or inelastic, and the direction revenue would move.
The Demand Curve is the log-log scatter with the fitted line. Its slope is the elasticity coefficient. A steep downward slope means more elastic demand and a flatter slope means less elastic demand. Points far from the line are worth a look on their own.
Elasticity Estimates shows the elasticity with its 95% interval. If the interval spans -1.0, you cannot tell from these data whether demand is elastic or inelastic.
Fit and Classification shows how well price alone explains the variation in sales volume (R-squared), the p-value, and the elastic, inelastic or unit-elastic class. A low p-value is evidence against a zero slope under the model's assumptions. Read it with the coefficient interval and the limits of the data; it does not confirm that price caused the change in demand.
When to Use Something Else
If you want to measure the causal effect of a specific price change on a specific product, a designed price test is the cleaner way. Show half your visitors one price and half another, then compare conversion rates. Price elasticity analysis from observational data (like order history) measures association: other factors like seasonality, marketing spend, and product quality also affect demand.
If you have historical data where a product's price changed over time and you want to model that relationship, regression on price vs. quantity over time (a time-series approach) may be more appropriate. You can include controls for seasonality, marketing campaigns, and competitor actions.
For new products where you have no sales data at all, conjoint analysis (survey-based) estimates willingness to pay by showing potential customers different product configurations at different prices.
If your goal is simply to understand discount effectiveness without the full elasticity framework, the promotional analysis module compares revenue, volume, and margin during promotional vs. non-promotional periods. And if you are looking at overall Shopify order patterns rather than pricing specifically, the AOV analysis module breaks down average order value trends and drivers.
The R Code Behind the Analysis
Every report names its method and includes the R code that produced it, so you can reproduce, audit and cite it. The method code is fixed, not rewritten for each run, so the same data gives the same analysis every time.
The analysis uses lm() from base R to fit the log-log regression model, lm(log(quantity) ~ log(price)), where the coefficient on log(price) is the price elasticity of demand. The elastic or inelastic class comes from the fitted slope and its interval.
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