The maths behind it all: growth marketing mathematics explained
TL;DR
Difficulty: Intermediate
Growth decisions rest on a handful of formulas, and each one answers one question.
- LTV to CAC and payback: is a customer worth what you paid, and how long until the money comes back. The usual SaaS guideline is a ratio above 3 and payback under 12 months.
- Cohorts and survival curves show what a blended average and a single churn rate hide.
- Bayesian tests and bandits give the probability that B is better and earn while they learn, but neither makes peeking free.
- Attribution, mix models and power laws: credit journeys, credit channels, and stop trusting the average customer.
- Elasticity and retention decide whether a price rise pays and why each point of retention is worth more than the last.
What to read first
This is the working toolkit behind growth decisions: ten pieces of maths, from lifetime value against acquisition cost to the retention maths that ties them together. Each comes with its formula, every symbol explained, a worked example in euro and a short piece of Python, so a newcomer can follow and a practitioner can run it.
Why growth needs maths at all
Psychology gets people interested. Data gets you funded. Every principle in this series, from scarcity to habit formation, ends up as a number someone has to measure and defend. This is the last chapter, and it is the toolkit I use every day to make decisions about acquisition, retention, pricing and experiments.
If you are new to this, every idea comes with a plain explanation and a worked example. If you know your statistics, you get the formulas, the edge cases and short Python. Every business and number in the examples is made up, so the arithmetic can be shown in full, and each formula links to its section of the Foundations page.
Lifetime value against acquisition cost tells you whether growth pays
Lifetime value (LTV) is the total gross profit a customer generates over the whole relationship. Customer acquisition cost (CAC) is what you spent to win them. A customer is worth acquiring if the first is comfortably more than the second.
Here is the lifetime value in euro, is the average revenue per user in one period (a month, say), is the gross margin as a share between 0 and 1, and is the average customer lifespan in the same periods as . Foundations: lifetime value
With a steady monthly churn rate the lifespan is one divided by churn ( months at 5%), which gives:
Here and are as before and is the churn rate per period as a share, so is the expected lifespan. It assumes the same churn every month. Foundations: lifetime value
The ratio itself:
Here is the ratio, the lifetime value and the average acquisition cost per new customer, both in euro. Foundations: ratios and rates
The common guideline comes from David Skok's SaaS metrics work: a healthy SaaS business has an LTV to CAC ratio above 3, and the best reach 7 or 8.1 He calls them guidelines, not laws. Below 1 you lose money on every customer you win.
Worked example: a rota app in Cork
Rotaglen (rotaglen.example) is an invented Cork SaaS selling rota software to cafés for €99 a month. Gross margin is 80%, monthly churn is 3%, and winning a customer costs €400.
- Lifespan: months.
- Monthly gross profit per customer: euro.
- Lifetime value: euro.
- Ratio: .
The horizontal axis is monthly churn, the vertical axis the ratio for Rotaglen. Going from 3% to 5% churn takes the ratio from 6.6 to 4.0, and from 8% it is below the guideline of 3. One or two points of churn matter more than most acquisition tweaks.
def ltv(arpu, margin, churn):
if churn <= 0:
raise ValueError("churn must be positive")
return arpu * margin / churn
cac = 400
for churn in [0.01, 0.02, 0.03, 0.05, 0.08, 0.10]:
value = ltv(99, 0.80, churn)
print(f"churn {churn:.0%}: LTV €{value:,.0f}, ratio {value / cac:.1f}")
Payback tells you whether you can afford the growth
Payback says how long you wait for the acquisition money to come back. That is a cash question: a two year payback means funding two years of acquisition before it recycles.
Here is the payback period in months, the acquisition cost, and the gross profit one customer brings in each month. Foundations: ratios and rates
For a business with €500 CAC, €100 a month ARPU and 80% gross margin:
So months. Skok's second guideline is to recover CAC in under 12 months, and he notes that many of the best SaaS businesses manage five to seven.1
Worked example: payback when some customers leave first
Take an invented business with €500 CAC, €80 a month ARPU, 75% margin and 4% monthly churn, and count the first month as always paid.
- Monthly gross profit: euro.
- Simple payback: months, so nine payments.
- Share of customers still paying in month nine: . More than a quarter leave before their own acquisition cost is recovered.
- Across the whole group, the average gross profit per acquired customer after months is . It passes €500 in month 10 (€502.75), not month nine.
Cohorts show what averages hide
A cohort is a group of customers who share a starting point, usually the month they first bought. Following each group over time shows what one blended average hides.
Worked example: two cohorts behind one average
Plassey Tea (plasseytea.example) is an invented Limerick tea subscription. Its 1,000 customers spend €50 a month on average. That looks fine. Split by cohort, 500 customers who joined in January spend €80 a month and 500 who joined in June spend €20:
The blended euro hides a problem worth chasing. Retention works the same way. Read a cohort table down a column to compare cohorts at the same age, and along a row to see one cohort decay.
| Cohort | Customers | Month 1 | Month 3 | Month 6 |
|---|---|---|---|---|
| January | 200 | 60% | 45% | 38% |
| April | 220 | 52% | 35% | 27% |
April's customers fall away faster at every age, which a blended average would show only as a gentle decline. The same grouping gives revenue, lifetime value and CAC per cohort, a single groupby in pandas.
Survival analysis models churn the way it happens
A single churn rate treats a customer of one week like one of three years. Survival analysis, borrowed from medical statistics, models how long customers last and treats those who have not left yet honestly.2 The full treatment is in survival analysis, churn and customer lifetime value.
The survival function is the probability that a customer is still with you after time :
Here is how long a customer lasts (a random variable), is a point in time such as 12 months, and is the probability that the lifetime is longer than . Foundations: probability
The hazard function is the rate of leaving at time among the customers who made it that far:
Here is the hazard at time , a small slice of time after , is the probability of leaving inside that slice given the customer was still there at , and the limit shrinks the slice towards zero. In plain words, the churn risk right now for a customer of this age. Foundations: probability
The Kaplan Meier estimator draws the survival curve from data without assuming any shape:3
Here is the estimated survival at time , are the times at which at least one customer left, is the number who left at , is the number still at risk just before , and multiplies the factors for every up to . Customers still active (censored) count as at risk until their record ends, then drop out without counting as churn. Foundations: probability
Worked example: ten customers by hand
Ten invented Rotaglen customers. Five left, at months 1, 1, 2, 4 and 6. Five are still active, watched for 3, 5, 7, 8 and 8 months.
- Month 1: 10 at risk, 2 leave. .
- Month 2: 8 at risk, 1 leaves. .
- Month 3: one record ends, nobody leaves, stays 0.70.
- Month 4: 6 at risk, 1 leaves. .
- Month 6: one more record ended at month 5, so 4 at risk, 1 leaves. .
So about 44% survive six months. A naive count (only three of ten records run past six months) would say 30%. The censored customers carry real information, and Kaplan Meier uses it.
def kaplan_meier(durations, churned):
rows = sorted(zip(durations, churned))
at_risk, s, curve = len(rows), 1.0, []
for t in sorted({d for d, c in rows if c}):
left = sum(1 for d, c in rows if d == t and c)
at_risk = sum(1 for d, _ in rows if d >= t)
s *= 1 - left / at_risk
curve.append((t, at_risk, left, round(s, 4)))
return curve
print(kaplan_meier([1, 1, 2, 3, 4, 5, 6, 7, 8, 8],
[1, 1, 1, 0, 1, 0, 1, 0, 0, 0]))
The log rank test checks whether two cohorts' curves differ by more than chance. The lifelines library implements both.3
Bayesian A/B tests answer the question you actually asked
A classical test, explained in the complete guide to digital marketing testing methods, asks how surprising the data would be if A and B were the same. A Bayesian test asks what you want to know: how likely is it that B is better? It rests on Bayes' theorem:
Here is the unknown conversion rate, is the data you observed, is the prior (what you believed before the test), is the likelihood (how probable the data is for a given rate), is the overall probability of the data, and is the posterior, your updated belief. Foundations: probability
With a Beta prior, the posterior for a conversion rate is again a Beta distribution:
Here and are the prior's parameters ( is a flat prior that treats every rate as equally likely), is the number of conversions and the number of visitors, so is the number who did not convert. Foundations: distributions
Worked example: a candle shop with modest traffic
Woodstown Candles (woodstowncandles.example) is an invented Waterford shop testing a new product page. Version A: 48 orders from 1,200 visitors (4.0%). Version B: 59 orders from 1,180 visitors (5.0%).
- Posteriors with a flat prior: A is , B is .
- Draw 400,000 samples from each and count how often B's draw beats A's: 88% of the time.
- Expected loss, the conversion rate you give up on average by picking wrong: about 0.05 percentage points if you choose B, 1.05 points if you choose A.
- The relative uplift of B has a 95% credible interval from minus 14% to plus 81%.
A classical two proportion test gives and , "not significant". Both say the evidence is thin, but the Bayesian reading is one you can act on: B is probably better and shipping it risks little.
import random
def prob_b_better(conv_a, n_a, conv_b, n_b, draws=400_000, seed=42):
rng = random.Random(seed)
wins = 0
for _ in range(draws):
a = rng.betavariate(1 + conv_a, 1 + n_a - conv_a)
b = rng.betavariate(1 + conv_b, 1 + n_b - conv_b)
wins += b > a
return wins / draws
print(prob_b_better(48, 1200, 59, 1180)) # about 0.88
Peeking is not free in either school
The original article said a Bayesian test lets you peek at any time without raising false positives. That needs correcting. For classical tests, Evan Miller shows that checking repeatedly and stopping at the first significant result can push the false positive rate to 26.1% instead of 5%.4 David Robinson's simulations show that a Bayesian test stopped once expected loss falls below a threshold is not immune either: its error rates depend on the stopping rule.5 Fix the stopping rule before the test starts, whichever school you use.
Bandits move traffic to the winner while the test runs
An A/B test splits traffic evenly to the end, so many visitors keep seeing the weaker version. A multi armed bandit shifts traffic towards the better version as evidence builds up, balancing exploration (trying versions) with exploitation (showing the best so far). The name comes from slot machines, the one armed bandits.
Thompson sampling, first described by William R. Thompson in 1933, is the standard way to do it.67 Each version keeps a Beta distribution for its rate, as in the Bayesian test. For each visitor:
Here numbers the versions, is version 's conversions plus 1, its non conversions plus 1, is one random draw from its Beta distribution, and is the version with the highest draw, which this visitor sees. After the visit, goes up by 1 on a conversion and goes up by 1 otherwise. Foundations: distributions Uncertain versions still win some draws, clearly worse ones soon stop.
Worked example: three versions, 10,000 visitors
Three invented page versions with true conversion rates of 3%, 5% and 4%, which the algorithm does not know. Each run sends 10,000 visitors, and I averaged 300 simulated runs.
- An even split earns conversions on average.
- Thompson sampling earned 470 on average, 70 more.
- On average it sent about 7,700 visitors to the 5% version, 1,720 to the 4% version and 570 to the 3% version.
The price is precision about the losers. For a clean measurement of every version, run a test. For conversions while you learn, use a bandit.
import random
def thompson(true_rates, visitors, seed=0):
rng = random.Random(seed)
k = len(true_rates)
alpha, beta, shown = [1] * k, [1] * k, [0] * k
conversions = 0
for _ in range(visitors):
draws = [rng.betavariate(alpha[i], beta[i]) for i in range(k)]
j = draws.index(max(draws))
shown[j] += 1
if rng.random() < true_rates[j]:
alpha[j] += 1
conversions += 1
else:
beta[j] += 1
return conversions, shown
print(thompson([0.03, 0.05, 0.04], 10_000))
Attribution and mix models answer different questions
Attribution asks which touchpoint gets the credit for one conversion, bottom up from tracked journeys. Marketing mix modelling (MMM) asks how much each channel added to total sales, top down with regression on weekly totals, and tracks no individuals.
Worked example: one journey, five answers
An invented customer touches Paid Search, Email, Social, Direct and Retargeting, in that order, then orders for €100.
| Model | Paid Search | Social | Direct | Retargeting | |
|---|---|---|---|---|---|
| Last click | €0 | €0 | €0 | €0 | €100 |
| First click | €100 | €0 | €0 | €0 | €0 |
| Linear | €20 | €20 | €20 | €20 | €20 |
| Time decay (halving) | €3.23 | €6.45 | €12.90 | €25.81 | €51.61 |
| Position based (40, 20, 40) | €40 | €6.67 | €6.67 | €6.67 | €40 |
Time decay here halves the weight for each step back: the weights are , which add up to 1.9375, so Retargeting gets euro. Same journey, five budgets.
Two corrections to the original article. Google no longer supports first click, linear, time decay or position based models in Google Ads, and removed them from Google Analytics 4 in November 2023, leaving data driven and last click. GA4 also gives direct visits no credit unless the whole path is direct.89 And "cookies are dying" needs care: Safari has blocked third party cookies by default since 2020,10 but Google said in April 2025 it would keep them in Chrome under user choice.11 The pressure on attribution is consent and browser privacy, not a switch off date. That is why mix models are back, with open source tools from Google (Meridian) and Meta (Robyn).1213 At its core, a mix model is a regression:
Here is revenue in week , is the base revenue you would get with no marketing, is spend on channel in week , is the revenue each euro on channel returns, is the number of channels, and is everything the model does not explain. Real models add carry over (adstock), saturation and seasonality. Foundations: regression
Worked example: reading a mix model
An invented Galway homeware retailer fits the model on two years of weekly data and gets a base of €200,000 a week and returns of €2.50 per euro on TV, €4.00 on digital, €3.00 on social and €1.50 on print. A week with €30,000 TV, €17,500 digital, €8,500 social and €4,500 print predicts:
So euro. Digital looks best, but these are average returns. The next euro may return much less, which is why real models add saturation curves. Foundations: marginal versus average
Power laws mean your average customer does not exist
Customer value is usually skewed: a few large customers bring a large share of revenue. A power law describes that, with the chance of a value above falling off as a power of :
Here is one customer's value, is a threshold in euro, is the shape (smaller means a heavier tail and more extreme customers) and means "proportional to". It shrinks far slower than a normal distribution, so very large customers are much more common than a bell curve suggests. Foundations: distributions
The Pareto distribution is the standard example:14
Here is the density at value , is the smallest possible value and the shape as before. For the mean is . Foundations: distributions
Its Lorenz curve gives the share of revenue that comes from the top share of customers:14
Here is the top share of customers (0.01 for the top 1%), is the shape from above, and is the share of total revenue they bring. Foundations: distributions
Worked example: Pareto customers with a €50 floor
Assume, for the example, customer values follow a Pareto distribution with euro and .
- Mean: euro. Median: euro. The mean is almost twice the typical customer.
- The exponent: .
- Top 1%: , so 21.5% of revenue. Top 10%: 46.4%. Top 20%: 58.5%.
- Half the revenue comes from the top of customers.
The horizontal axis is the top share of customers, the vertical axis their share of revenue. With this shape, a fifth of customers bring well over half the revenue, so that fifth deserves its own retention budget and CAC limit.
The original article said 1% of customers "often" drive 50% of revenue. I could not source that as a general rule, and the formula shows how extreme it is: it needs a shape of about 1.18. Measure your own, and estimate by maximum likelihood, not with a straight line through a log log plot, which Clauset, Shalizi and Newman show can be badly wrong.15
Price elasticity tells you whether a price rise pays
Raise the price by 10% and some customers leave. Whether it is 5% or 20% decides whether revenue rises. Price elasticity of demand puts a number on that.16 The regression side is in modelling demand and price elasticity with regression, and dynamic pricing with AI shows where it leads.
Here is the elasticity, the percentage change in quantity sold and the percentage change in price. It is usually negative. If , demand is elastic and a price rise lowers revenue. If , it is inelastic and a rise increases revenue. Foundations: elasticity
At a single point on the demand curve:
Here is the slope of the demand curve, and and are the current price and quantity. For a straight line demand curve , the slope is , so , where is the quantity at a price of zero and the units lost per euro. Foundations: elasticity
Worked example: a 10% rise for a bookkeeping app
Ledgerly (ledgerly.example) is an invented Kilkenny bookkeeping app with 1,000 customers at €99 a month. It considers €108.90, a 10% rise. Revenue changes by :
| Elasticity | Customers | Revenue |
|---|---|---|
| minus 5% | plus 4.5% | |
| minus 10% | minus 1.0% | |
| minus 15% | minus 6.5% | |
| minus 25% | minus 17.5% |
A correction to the original: at exactly revenue stays flat only for a tiny change. For a 10% step it falls 1%, because .
Now suppose Ledgerly's demand is the straight line . At €99: and . Revenue is highest where elasticity is exactly , at euro. So €99 is close to the revenue maximum, and a 10% rise would overshoot.
From elasticity to a price
The original article gave as the revenue maximising price change. That formula is wrong: with constant elasticity above 1, every price rise lowers revenue. What does hold, when you know marginal cost, is the markup rule for maximum profit, the Lerner index:17
Here is the price, the marginal cost of serving one more customer, the size of the elasticity (it must be above 1), and the profit maximising price. Foundations: marginal versus average
An example: marginal cost €20 a month and elasticity give euro. Check: .
From your own price history, elasticity is the slope of a log log regression. Foundations: logarithms
import math
def elasticity(prices, quantities):
lp = [math.log(p) for p in prices]
lq = [math.log(q) for q in quantities]
mp, mq = sum(lp) / len(lp), sum(lq) / len(lq)
num = sum((x - mp) * (y - mq) for x, y in zip(lp, lq))
den = sum((x - mp) ** 2 for x in lp)
return num / den
Asking customers instead: the Van Westendorp meter
When you have no price history, Peter van Westendorp's Price Sensitivity Meter (1976) asks four questions: at what price would it be so low you doubt the quality, a bargain, getting expensive, and too expensive to consider.18 Where the cumulative curves cross gives a range of acceptable prices: "too low" against "not a bargain" marks the bottom, "too expensive" against "not expensive" the top. It measures what people say, not what they do, so test the range. The psychology side is in pricing psychology.
Retention compounds into profit
The most quoted number in retention comes from Frederick Reichheld and Earl Sasser in 1990: across the service businesses they studied, reducing customer defections by 5% boosted profits by 25% to 85%.19 The figure later quoted from Reichheld's work at Bain is 25% to 95%.20 Their explanation: acquisition is paid once, purchases grow, operating costs fall, and loyal customers refer others (referrals are their own article).19
Two cautions. The numbers come from specific industries in 1990, so read them as "large", not as a forecast. And "5%" is ambiguous, as the example shows.
The value of better retention, with discounting:
Here is the gain in lifetime value per customer, counts periods from 0 to the horizon , is the gross profit per period (), and are the retention rates before and after, so is the chance a customer is still there in period , and is the discount rate per period. Foundations: discounting
Without discounting and with no horizon, it simplifies to:
Here is the gross profit per period and is the expected lifetime in periods for a retention rate . The original version left out the margin. Foundations: lifetime value
Worked example: why the range is so wide
An invented subscription with €100 ARPU, 80% margin, so euro a month, and €400 CAC.
- At 5% churn: euro, profit per customer .
- Churn falls by 5% of itself, to 4.75%: , profit 1,284. That is plus 7%.
- Churn falls by one point, to 4%: , profit 1,600. Plus 33%.
- Start instead at 10% churn and cut five points to 5%: goes from 800 to 1,600 and profit from 400 to 1,200. Plus 200%.
The same "5%" means plus 7% or plus 200%. The fixed CAC is the lever: LTV from €800 to €1,000 with €400 CAC takes profit from €400 to €600, plus 50% from plus 25% LTV.
The horizontal axis is monthly retention, the vertical axis undiscounted lifetime value. The takeaway is the shape: from 95% to 97% retention, lifetime value goes from €1,600 to €2,667, plus 67% for two points. Each point is worth more than the last.
Discounted at 10% a year over 60 months, the same customer is worth €1,351 at 95% retention and €1,591 at 96%. Discounting shrinks the numbers, not the shape.
Maths is not optional
LTV to CAC says whether growth pays, payback whether you can afford it. Cohorts and survival curves show what averages hide. Bayesian tests and bandits turn experiments into decisions. Attribution credits journeys, mix models credit channels. Power laws make the average customer a fiction, elasticity decides whether a price rise pays, and retention compounds.
I have applied every concept here across eCommerce, SaaS and B2B products. It is the working toolkit I use to make decisions about millions in marketing spend and product investment. Start with the one number your next decision depends on.
Footnotes
-
David Skok, SaaS Metrics 2.0: A Guide to Measuring and Improving What Matters, For Entrepreneurs, https://www.forentrepreneurs.com/saas-metrics-2/
-
Cameron Davidson-Pilon and lifelines contributors, Introduction to survival analysis (survival function, hazard function, censoring), lifelines documentation, https://lifelines.readthedocs.io/en/latest/Survival%20Analysis%20intro.html
-
Cameron Davidson-Pilon and lifelines contributors, Survival analysis with lifelines (Kaplan Meier estimate, log rank test), lifelines documentation, https://lifelines.readthedocs.io/en/latest/Survival%20analysis%20with%20lifelines.html
-
Evan Miller, How Not To Run an A/B Test, 2010, https://www.evanmiller.org/how-not-to-run-an-ab-test.html
-
David Robinson, Is Bayesian A/B Testing Immune to Peeking? Not Exactly, Variance Explained, 2015, http://varianceexplained.org/r/bayesian-ab-testing/
-
Wikipedia, Thompson sampling (history: William R. Thompson, Biometrika, 1933), https://en.wikipedia.org/wiki/Thompson_sampling
-
Daniel Russo, Benjamin Van Roy, Abbas Kazerouni, Ian Osband and Zheng Wen, A Tutorial on Thompson Sampling, Foundations and Trends in Machine Learning 11(1), 2018, https://arxiv.org/abs/1707.02038
-
Google, About attribution models, Google Ads Help, https://support.google.com/google-ads/answer/6259715
-
Google, Get started with attribution (attribution models), Google Analytics Help, https://support.google.com/analytics/answer/10596866
-
John Wilander, Full Third Party Cookie Blocking and More, WebKit blog, 24 March 2020, https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/
-
Anthony Chavez, Next steps for Privacy Sandbox and tracking protections in Chrome, Google Privacy Sandbox, 22 April 2025, https://privacysandbox.google.com/blog/privacy-sandbox-next-steps
-
Google, Meridian, an open source marketing mix model, Google for Developers, https://developers.google.com/meridian
-
Meta Marketing Science, Robyn, an open source marketing mix modelling package, https://facebookexperimental.github.io/Robyn/
-
Wikipedia, Pareto distribution (density, mean, Lorenz curve), https://en.wikipedia.org/wiki/Pareto_distribution
-
Aaron Clauset, Cosma Rohilla Shalizi and M. E. J. Newman, Power-law distributions in empirical data, SIAM Review 51(4), 2009, https://arxiv.org/abs/0706.1062
-
OpenStax, Principles of Economics 3e, 5.1 Price Elasticity of Demand and Price Elasticity of Supply, https://openstax.org/books/principles-economics-3e/pages/5-1-price-elasticity-of-demand-and-price-elasticity-of-supply
-
Wikipedia, Lerner index (Abba Lerner, 1934), https://en.wikipedia.org/wiki/Lerner_index
-
Wikipedia, Van Westendorp's Price Sensitivity Meter, https://en.wikipedia.org/wiki/Van_Westendorp%27s_Price_Sensitivity_Meter
-
Frederick F. Reichheld and W. Earl Sasser Jr., Zero Defections: Quality Comes to Services, Harvard Business Review, September to October 1990, https://hbr.org/1990/09/zero-defections-quality-comes-to-services
-
Amy Gallo, The Value of Keeping the Right Customers, Harvard Business Review, 2014, https://hbr.org/2014/10/the-value-of-keeping-the-right-customers