Where this session sits
a5 ended on an honest admission: shops and games only ever infer churn from silence. This session replaces "pick a 90-day window and hope" with a model that gives every customer their own probability of still being alive. The RFM summary you built in a4 is literally the model's input, a2's counts table returns as the ground truth for LTV, and a7 will inherit the "who is worth saving" question. Work along in the companion notebook notebooks/a6_clv.ipynb.
Customers who never say goodbye 17 min live
Non-contractual settings have no churn event, so BG/NBD (Fader, Hardie and Lee, 2005) tells a story instead: while alive, each customer makes purchases at their own Poisson rate - rates vary across customers following a Gamma distribution - and after each purchase they flip a Beta-distributed coin that decides whether they silently die. Feed it three RFM summary numbers per customer - frequency (repeat purchases), recency (customer age at their LAST purchase) and T (total customer age) - and it returns P(alive) and expected future purchases. The magic intuition: high frequency + long silence = probably dead; low frequency + the same silence = probably fine, because that gap is simply their normal rhythm.
Live★ Build-along: BetaGeoFitter and per-customer P(alive)9 min▶
Two customers, the same four quiet months. The regular's silence is an anomaly against their own history; the occasional's is not - and the model prices exactly that. It needs no browsing data, no demographics: one summary row per customer, straight from the transaction log.
lifetimes library is archived - maintenance mode. We still teach with it because its API maps one-to-one onto the concepts and reads beautifully. For production, the maintained successor is PyMC-Marketing's CLV module: the same BG/NBD family, fit Bayesian, so every P(alive) comes with honest uncertainty instead of a bare point estimate. Learn here, ship there.
Where the models break 8 min live
BG/NBD is a story, and stories have fine print. Dropout is irreversible in the model - once the coin lands on death, that customer can never buy again. Real customers resurrect, binge on promo weekends, and hibernate seasonally, and every one of those behaviors violates the story. Know the four classic breaks before you present a single P(alive).
LiveThe fine print, spelled out6 min▶
- Irreversible dropout: the model has no resurrection state. Winback campaigns, seasonal shoppers and promo-spike bingers all generate purchase patterns the story says cannot happen - fit quality degrades quietly, so inspect holdout calibration, not just the fit summary.
- The one-time-buyer quirk: customers can only die immediately AFTER a purchase, so a buyer with zero repeats has never faced the coin - BG/NBD keeps their P(alive) high indefinitely. With a large one-time-buyer base (most shops), read cohort-level outputs with that skew in mind.
- Unidentifiability on short histories: when T is short relative to typical inter-purchase time, the data cannot separate "slow but alive" from "fast but dead". No fitter setting fixes missing time.
- Gamma-Gamma's independence assumption: the monetary model assumes spend per transaction is independent of frequency. Check
summary[["frequency", "monetary_value"]].corr()first; a material correlation means the CLV ranking inherits a bias.
Self-studyWhen to just use the cohort table instead3 min read▶
BTYD earns its keep when you need per-customer lifetime estimates in a non-contractual business with enough history. Skip it when:
- Small data: a few thousand customers or a short observation window - the a2 cohort table plus a5's KM curve answer the aggregate question with far fewer assumptions.
- Weekly reporting: the frozen cohort table is the reporting artifact; a probabilistic model that restates every refit has no business on a weekly dashboard.
- Contractual business: churn is observed, so you do not need to infer it - survival analysis (a5) is the right tool, not BTYD.
LTV without lying 12 min live
The formula every pitch deck loves: LTV = ARPU x margin / churn. It assumes one constant churn rate forever, and that assumption overstates - churn falls with tenure because the survivors are the durable ones (a5's lesson), so a single blended rate flatters the average customer. The honest ground truth needs no model at all: cumulative cohort gross profit over 12-36 months, read straight off a2's counts table times ARPU times margin. Against that curve, apply the classic LTV:CAC 3:1 benchmark (David Skok) - and set channel-level CAC ceilings from channel-level cohort LTV curves, not from one blended number.
Live★ Build-along: the cumulative cohort LTV curve vs the formula8 min▶
You already built the hard part in a2. The counts pivot (distinct buyers per cohort x period) becomes an LTV curve in three lines: cumulate across periods, convert to money, divide by cohort size.
- Read the curve at fixed horizons - 12, 24, 36 months - and compare like with like. "LTV" without a horizon is not a number, it is a mood.
- LTV:CAC 3:1 (Skok's classic benchmark) only means something against the honest curve at a stated horizon, with margin in the numerator.
- Cohort-informed budgeting: compute the curve per acquisition channel, and each channel gets its own CAC ceiling. A channel whose 12-month cohort LTV is half the blended average is quietly subsidized by every other channel.
How ecommerce teams actually spend winback budgets. BG/NBD plus Gamma-Gamma is the standard ranking machine: score every lapsed customer by P(alive) and expected value, then aim the winback offer at high-value customers whose P(alive) is decaying - not at the definitely-dead (wasted send) and not at the comfortably-alive (wasted discount). One caveat travels with this: a7 will show that predicting who churns is not the same as knowing who can be persuaded - hold that thought until the uplift discussion.
Try it yourself - this week ◐ 30 min total
- Fit BG/NBD on Online Retail II - after running a2's clean-up gate (drop C-invoices, drop missing CustomerID, positive quantities only). Build the summary frame with
summary_data_from_transaction_data. - Scatter P(alive) against recency. Describe the shape in one sentence: why is it not a straight line?
- Find one customer the model calls alive (P(alive) high) that your a4 RFM scoring filed under Hibernating, and explain the disagreement in plain words - whose definition of "gone" is doing the work?
- Add the cumulative cohort LTV curve for your oldest three cohorts to the running retention report - a8 will put a CAC line against it.
What this session draws on
Buy-till-you-die is one of the rare corners of retention analytics with an actual academic spine. This page teaches the working core of:
Three questions before you go 🎯 ◐ 90 seconds
1 · Two customers have both been silent for 4 months. A bought 13 times in their first 8 months; B bought 3 times in the same span. Who does BG/NBD call probably dead?
P(alive) judges silence against each customer's own purchase rate. The regular's gap is many times their usual rhythm; the occasional buyer's identical gap is unremarkable. This is the whole point of modeling heterogeneous rates.
2 · Why do one-time buyers look immortal to BG/NBD?
In the BG/NBD story a customer can only die immediately after a purchase. A buyer with no repeat purchases has never been exposed to the dropout coin, so the model holds their P(alive) high indefinitely - a quirk to keep in mind wherever one-time buyers dominate.
3 · Why does LTV = ARPU x margin / churn overstate?
The survivors are the durable ones (a5's lesson), so churn is high early and falls with tenure. Plugging one blended rate into 1/churn projects the durable minority's behavior onto every new customer. The honest check is cumulative cohort gross profit over 12-36 months.