Customer lifetime value with transparent assumptions
In this article (6 sections)
Customer lifetime value is a model of future customer value under stated assumptions. It is not a directly observed fact about a newly acquired customer. A useful calculation separates contribution from revenue, specifies when cash or contribution arrives, and exposes how retention assumptions change the answer.
Start with a finite horizon that you can explain. An impressive lifetime estimate based on an unexplained infinite tail can be less useful than a modest twelve-month scenario with visible inputs.
Define a teaching scenario
Suppose an acquired customer generates ₹100 of monthly contribution while active. This fictional amount is revenue less the variable costs included in our definition; it is not a NeuraPath price or observed business result.
Assume the customer is active in month one, survives into each subsequent month with probability 90%, and receives no reactivation treatment. Contribution arrives at each month end. Use a hypothetical monthly discount rate of 1%, a twelve-month horizon and acquisition cost of ₹500 paid now.
These are modeling assumptions, not recommended market rates or forecasts. Constant retention also assumes that tenure, channel and calendar conditions do not change survival probabilities.
Calculate expected discounted contribution
For month m, expected contribution is 100 × 0.9^(m−1). Discount it by 1.01^m. Sum months one through twelve, then show acquisition cost separately.
from math import isclose
def contribution_value(monthly, retention, discount, months):
if monthly < 0 or not 0 <= retention <= 1 or discount <= -1:
raise ValueError('invalid scenario assumptions')
if not isinstance(months, int) or months < 1:
raise ValueError('months must be a positive integer')
return sum(monthly * retention**(m-1) / (1+discount)**m
for m in range(1, months+1))
value = contribution_value(100, .90, .01, 12)
net = value - 500
assert isclose(contribution_value(100, 0, .01, 12), 100/1.01)
assert isclose(contribution_value(100, 1, 0, 12), 1200)
assert contribution_value(100, .80, .01, 12) < value
assert value < contribution_value(100, .95, .01, 12)
assert value > 500
print({'12_month_contribution_value_INR': round(value, 2),
'less_acquisition_cost_INR': 500,
'net_scenario_value_INR': round(net, 2)})
for retention in (.80, .90, .95):
print(retention, round(contribution_value(100, retention, .01, 12), 2))The boundary tests are meaningful: zero continuation leaves only month one; perfect retention and zero discount produce twelve full contributions. They catch an easy off-by-one mistake that incorrectly subjects the first month's contribution to a retention loss.
The ₹500 acquisition cost is not hidden inside contribution and then subtracted again. If your chosen contribution definition already contains acquisition spending, revise the bridge to avoid double counting.
Reproduce the calculation in a spreadsheet
Create twelve rows with month, survival probability, expected contribution, discount factor and present value. Sum the final column. With equally spaced month-end contributions, Excel's NPV function documentation explains its timing convention; a time-zero acquisition cost belongs outside the future-payment sequence.
An explicit row-by-row model is easier to inspect when retention varies with tenure. Replace the constant survival power with the product of the applicable monthly continuation probabilities. Do not mix annual discount rates with monthly periods without an explicit conversion.
Keep observations separate from the tail
For a mature cohort, report observed contribution to date alongside modeled future contribution. A six-month-old cohort has no observed twelve-month outcome. Filling its future months with zero understates value; treating a fitted forecast as observed overstates certainty.
Retained customers may also spend differently from customers who leave. A model using one average contribution and one retention rate can miss that dependence. Segmenting may help, but small groups can make estimates unstable. Use holdout cohorts and compare predicted cumulative contribution with subsequently observed results.
Turn the estimate into a decision range
The sensitivity loop shows what happens when monthly retention changes while other inputs stay fixed. That is a scenario comparison, not a confidence interval. A probabilistic interval requires a defensible uncertainty model and data supporting its parameters.
A higher modeled value does not automatically justify a higher acquisition bid. Capacity, cash timing, channel incrementality, adverse selection and measurement error can all matter. Keep the business recommendation conditional on those facts.
Exercise: add a one-time onboarding cost and a contribution increase beginning in month four. Write the timing assumptions, update the month table and verify that the original scenario remains reproducible when both additions are zero.
NeuraPath's Data Analytics with Generative AI course connects spreadsheet and Python analysis with business interpretation. A defensible value model makes its assumptions easier to challenge than its headline number.
Continue learning
This article is part of the Customer and product analytics sequence. Use the neighbouring tasks when you need the prerequisite or the next application.
- Review the prerequisite or neighbouring task in Retention curves: distinguish acquisition and calendar views.
- Continue with Churn rate: choose the population at risk.
Pankit Kumar has 10 years in Data Science & AI, building and shipping production systems in regulated pharma and clinical environments. He is a freelance trainer at Boston Institute of Analytics, AnalytixLabs and Scaler, and has taught this material to thousands of working professionals.
This article is part of our Data Analytics with Generative AI programme — 3–4 months. The full analyst stack — Excel, SQL, Power BI and Python pipelines — then a generative-AI layer you can prove is right.
Explore Data Analytics with Generative AI