LTV: как считать ценность пользователя по когортам
Как считать LTV по когортам, связать его с ARPU и retention, сравнить каналы и не выдать грубую оценку за пожизненную ценность пользователя.
Содержание статьи
Команда видит, что новый канал привёл много регистраций, и сразу спрашивает: «А сколько эти пользователи принесут?» LTV — это ценность пользователя за выбранный срок: сколько дохода или маржинального вклада в среднем накопила одна когорта от начала отношений с продуктом. Простыми словами, это ответ на вопрос, сколько денег приносит один человек за время наблюдения, а не сумма одной покупки. Метрика помогает связать поведение когорты с деньгами, но только если назвать горизонт, единицу пользователя и способ учёта выручки. Один средний LTV без этих условий часто создаёт больше уверенности, чем знаний.
Коротко
LTV, или lifetime value, показывает, сколько чистой выручки в среднем приносит пользователь за выбранный горизонт жизни. Для исторического расчёта это не магическое число на всю жизнь, а накопительная выручка когорты, разделённая на размер этой когорты.
LTV_N = cumulative net revenue from cohort during N / users in cohortLTV30 и LTV90 — разные метрики. Нельзя сравнивать их как одно и то же число или выдавать LTV30 за полную ценность пользователя.
- Всегда указывайте горизонт: D30, D90, 6 месяцев или другой срок.
- Считайте одинаковые когорты: по регистрации, первой покупке или первой активации.
- Используйте net revenue, если сравниваете экономическую ценность каналов.
- Сравнивайте только зрелые когорты, которым уже исполнился выбранный горизонт.
- Для решения о закупке трафика связывайте LTV с CAC, маржой и сроком окупаемости.
LTV, ARPU и ARPPU отвечают на разные вопросы
ARPU обычно смотрит на выбранный период: месяц, неделю или день. LTV накапливает выручку одной когорты с момента старта. ARPPU исключает пользователей без платежа и поэтому описывает только платящую часть базы. Эти метрики связаны, но не заменяют друг друга.
Если ARPU вырос в июле, это ещё не значит, что июльская когорта станет более ценной. Возможно, в ней много крупных разовых платежей. LTV по когортам заставляет посмотреть, сохраняется ли разница на D30 или D90.
| Метрика | Знаменатель | Какой вопрос задаёт |
|---|---|---|
| ARPU | активные пользователи периода | Сколько в среднем принесла аудитория за этот период? |
| ARPPU | платящие пользователи периода | Сколько в среднем заплатил пользователь, который уже платит? |
| LTV30 / LTV90 | пользователи одной зрелой когорты | Сколько чистой выручки накопила когорта за 30 или 90 дней? |
Начинайте с исторического LTV по когортам
Для нового продукта лучше начать с наблюдаемого LTV, а не с модели, которая обещает точную ценность на годы вперёд. Возьмите пользователей с одинаковым стартом, посчитайте их net revenue на D1, D7, D30 и D90, а затем сравните когорты между собой.
Когорта может строиться по регистрации, первой активации, первой покупке или другому событию, которое действительно задаёт начало жизненного цикла. Выбор зависит от вопроса. Для оценки рекламного канала чаще подходит регистрация или первая активация; для повторных покупок — первая покупка.
| Параметр | Пример решения |
|---|---|
| Старт когорты | signup_at или первая успешная покупка |
| Единица | user_id, account_id или платящий workspace |
| Выручка | успешные платежи минус возвраты и скидки |
| Горизонт | D1, D7, D30, D90; только зрелые когорты |
| Разрез | канал, платформа, тариф или страна |
Кривая LTV важнее одного финального числа
Одинаковый LTV90 может складываться из разных сценариев. Одна когорта получает большую часть выручки в первый день и потом почти не растёт. Другая медленно набирает ценность за счёт повторных покупок или подписки. Для продукта это разные риски и разные решения.
На графике ниже paid social выглядит слабее уже на D7 и почти не догоняет органику к D90. Это не доказывает, что канал плохой сам по себе: нужно проверить CAC, маржу, состав кампаний и зрелость когорт. Но такой разрыв уже подсказывает, где искать причину.
Условный пример. Сравниваются зрелые когорты на одинаковых горизонтах; значения показывают net revenue на одного пользователя.
Какая выручка должна попасть в LTV
Для сравнения каналов LTV лучше считать на чистой выручке. Если один источник приводит много заказов, которые потом возвращают, его gross revenue будет выглядеть здоровее реальной экономики. То же относится к скидкам, комиссиям платёжных систем, налогам и отменённым списаниям.
В B2B-продукте важно выбрать правильную единицу. Если один аккаунт оплачивает workspace для 30 сотрудников, LTV на user_id может исказить историю. Для такого продукта полезнее считать LTV на account_id или workspace и отдельно показывать пользователей внутри аккаунта.
| Компонент | Что проверить |
|---|---|
| Платежи | учитываются только успешные операции |
| Возвраты | вычитаются из выручки в том же периоде или по согласованному правилу |
| Скидки | не теряются при переходе от gross к net revenue |
| Комиссии | понятно, считаем выручку или contribution margin |
| Валюта | все суммы приведены к одной валюте и таймзоне |
SQL для LTV30 и LTV90 по каналам
Запрос написан для учебной базы симулятора SQL-аналитика. В payments — оплаты в долларах; возвратов в этой базе нет, в рабочем запросе их вычитают из суммы. Горизонт получает число, только когда он закрыт у пришедшего в последний день месяца, поэтому свежие регистрации не занижают LTV из-за незрелого окна.
D14, D30, D60 и D90 здесь означают первые 14, 30, 60 и 90 календарных дней после регистрации; для продукта с другим жизненным циклом замените стартовое событие и границы окна. За 30 дней июньская когорта принесла 7,60 доллара на человека у рекомендаций, 7,22 у органики и 4,58 у партнёров; июльская — 7,83, 6,70, 4,78 и 2,59 у платного поиска, запущенного 1 июля. Стандартная ошибка этих чисел — 0,35–0,70 доллара: рекомендации от органики неотличимы, платный поиск ниже всех с запасом. LTV60 есть только у июня, а столбец LTV90 пуст целиком: в базе 91 день данных, и девяносто дней не прожила ни одна месячная когорта. Это правило зрелости, а не поломка: на более длинной истории тот же запрос заполнит столбец сам. Пустая клетка здесь — честный ответ, ноль был бы ошибкой.
with revenue as ( -- зерно: один пользователь
select u.user_id, u.channel,
cast(date_trunc('month', u.signup_date) as date) as cohort_month,
cast(date_trunc('month', u.signup_date) + interval '1 month' as date) - 1 as month_end,
coalesce(sum(case when p.paid_at - u.signup_date < 14 then p.amount end), 0) as rev_14,
coalesce(sum(case when p.paid_at - u.signup_date < 30 then p.amount end), 0) as rev_30,
coalesce(sum(case when p.paid_at - u.signup_date < 60 then p.amount end), 0) as rev_60,
coalesce(sum(case when p.paid_at - u.signup_date < 90 then p.amount end), 0) as rev_90
from users u
left join payments p on p.user_id = u.user_id
group by u.user_id, u.channel, u.signup_date
)
-- оплаты в базе полны по 30 августа: горизонт считаем, когда он закрыт у пришедшего последним
select cohort_month, channel,
count(*) as cohort_users,
case when month_end + 13 <= date '2026-08-30' then round(sum(rev_14) / count(*), 2) end as ltv_d14,
case when month_end + 29 <= date '2026-08-30' then round(sum(rev_30) / count(*), 2) end as ltv_d30,
case when month_end + 59 <= date '2026-08-30' then round(sum(rev_60) / count(*), 2) end as ltv_d60,
case when month_end + 89 <= date '2026-08-30' then round(sum(rev_90) / count(*), 2) end as ltv_d90
from revenue
group by cohort_month, month_end, channel
order by cohort_month, channel;LTV без CAC не отвечает на вопрос об окупаемости
Высокий LTV ещё не означает, что канал выгоден. Если привлечь пользователя стоит 300 ₽, а LTV90 равен 248 ₽, рост такой аудитории не окупается на этом горизонте. Если LTV считается по выручке, а CAC и расходы сравниваются с маржой, вывод тоже будет слишком оптимистичным.
Практическое сравнение начинайте с одной пары: зрелый LTV выбранного горизонта и CAC той же когорты. Потом добавляйте gross margin, возвраты и срок окупаемости. Не смешивайте органику с paid traffic: у них разная стоимость привлечения и разная структура аудитории.
contribution LTV_N = LTV_N × gross margin; payback when contribution LTV_N >= CACЭто рабочая проверка на выбранном горизонте, а не универсальный прогноз всей жизни пользователя.
Где LTV начинает врать
Самая опасная версия LTV — одно среднее число для всех пользователей. Оно может расти из-за нескольких крупных клиентов, изменения mix каналов или случайного исключения возвратов. Ещё одна ошибка — назвать прогнозный LTV историческим фактом и забыть, что модель строится на предположениях о будущем поведении.
- Не сравнивайте LTV30 свежей когорты с LTV90 зрелой когорты.
- Не дели выручку только на платящих, если называете результат LTV всей когорты.
- Не смешивайте user_id, account_id и workspace в одном отчёте.
- Не используйте gross revenue, если возвраты и скидки заметно меняют экономику.
- Не принимай корреляцию LTV с каналом за доказательство причинности.
- Не масштабируй канал по LTV без проверки CAC, маржи и срока окупаемости.
Исторический и прогнозный LTV — разные вещи
Исторический LTV показывает то, что уже наблюдалось: сколько net revenue накопила когорта на D30 или D90. Прогнозный LTV пытается оценить будущие платежи после этого горизонта. Для прогноза нужны предположения о возвратах, оттоке, повторных покупках, марже и насыщении. Их можно моделировать, но результат нельзя подписывать просто как LTV без горизонта и пометки «forecast».
На практике полезно держать оба слоя рядом. Историческая кривая отвечает за контроль качества каналов и продукта, а прогноз нужен для долгих решений вроде бюджета привлечения или годового контракта. Если прогноз сильно расходится с наблюдаемым D30/D90, сначала проверьте модель и определения, а не выбирайте более удобное число.
| Название | Что это означает | Для какого решения |
|---|---|---|
| LTV30 | наблюдаемая net revenue на пользователя за первые 30 дней | быстрый контроль когорты и канала |
| LTV90 | наблюдаемая накопительная выручка за 90 дней | сравнение зрелых каналов и окупаемости |
| Forecast LTV12M | модельная оценка на 12 месяцев | бюджет и долгосрочная экономика |
| Contribution LTV | выручка после маржи и согласованных переменных затрат | сопоставление с CAC |
Зрелость когорт и цензура данных
У LTV есть проблема правого края: последние когорты ещё не успели накопить платежи. Это называется right censoring. Их кривая закономерно ниже зрелых когорт, даже если будущий сценарий будет таким же. Поэтому LTV30 строится только по когортам, которым исполнилось 30 дней, а LTV90 — по тем, которым исполнилось 90. Что делать с незрелыми клетками в таблицах удержания и выручки — в статье о когортном анализе.
Не подменяй незрелое окно прогнозом без отдельной маркировки. В таблице полезно хранить cohort_start, cohort_size, observation_end и maturity_days. Тогда любой читатель может понять, почему у одной строки есть LTV90, а у другой пока только LTV7. Это также помогает не принимать свежий маркетинговый канал за худший только из-за короткого наблюдения.
- Показывайте maturity_days рядом с горизонтом LTV.
- Исключайте незрелые когорты из исторического сравнения.
- Не заменяйте missing future revenue нулём.
- Фиксируйте дату среза, чтобы отчёт был воспроизводимым.
- Сравнивайте каналы при одинаковой структуре когорт.
LTV × CAC: проверяйте срок окупаемости
Сравнение LTV и CAC одним отношением удобно для презентации, но для управления бюджетом важнее время. Канал с LTV90/CAC = 1,4 может быть полезнее канала с отношением 2,0, если он окупается на D30, а второй — только после года и зависит от слишком неопределённого прогноза. Добавьте к расчёту contribution margin и посмотрите, на каком горизонте накопленная маржа пересекает CAC.
Это не означает, что любой канал обязан окупиться за 30 дней. Допустимый срок зависит от cash flow, типа продукта и договорённостей с бизнесом. Но правило должно быть заранее известно: например, «масштабируем канал только после достижения contribution LTV90 не ниже 1,2 CAC и при приемлемом возврате». Такая рамка защищает от решений по одному красивому среднему.
payback_day = first day where cumulative contribution revenue >= CACЕсли пересечения нет на наблюдаемом горизонте, честно напишите «не окупился к D90», а не достраивайте результат до полной жизни без модели.
Payback-день когорты не читается по горизонтам D30 и D90
Возьмите органическую когорту с условного графика выше: 248 ₽ накопленной выручки на пользователя к D90. Пусть валовая маржа равна 70%, а привлечение одного такого пользователя стоило 140 ₽. Маржинальная часть кривой тогда выглядит так: 58,8 ₽ к D7, 117,6 ₽ к D30, 149,8 ₽ к D60, 173,6 ₽ к D90 — то есть 42%, 84%, 107% и 124% от CAC. Строчку «когорта окупилась» по этим четырём числам написать уже можно. Ответа на вопрос «когда» в них нет: переход через 140 ₽ случился где-то внутри тридцатидневного промежутка между D30 и D60.
Соблазн дотянуть интерполяцией понятен: 22,4 ₽ недостающей маржи при шаге 32,2 ₽ за месяц дают примерно D51. Но деньги внутри месяца приходят не ровными порциями. У подписки списание стоит на дате продления, у повторных покупок — на заказе, и если между D30 и D60 лежит одно крупное событие на D44, накопленная маржа пересекает CAC именно 44-го дня. Интерполяция ошибётся на неделю, а для месячной подписки payback по построению совпадает с датой очередного платежа, а не с серединой интервала.
Поэтому payback считают не по горизонтам отчёта, а по ежедневному накоплению: на каждый день жизни когорты — накопленная маржа на одного стартового пользователя, затем первый день, когда она дошла до CAC. CAC здесь приходит из таблицы затрат и соединяется по той же паре «неделя старта × канал»: иначе окупаемость июньской когорты будет измеряться июльским бюджетом, а при сезонной закупке это расхождение в разы.
У зрелости при этом требование слабее, чем у LTV90, и этим почти не пользуются. Когорте 45 дней: LTV90 у неё появится только через полтора месяца, но если накопленная маржа прошла 140 ₽ на 38-й день, окупаемость уже наблюдённый факт, а не прогноз. Обратную ситуацию нужно подписывать строго: у когорты, которая к своему 45-му дню до CAC не дошла, в отчёте стоит «не окупилась к D45». Пустая ячейка payback_day у свежей когорты не означает плохой канал — она означает, что наблюдение короче, чем срок возврата.
Монотонность кривой ломают возвраты. Крупный refund на D70 способен опустить накопленную маржу ниже CAC после того, как она уже его прошла, и тогда два обновления отчёта дадут разные payback_day для одной когорты. Договоритесь заранее, что считается окупаемостью — первое пересечение или устойчивое превышение на горизонте, — и храните это правило рядом с числом, как и дату среза.
Запрос ниже считает payback-день на учебной базе по месячным когортам. Расходов в ней нет, поэтому CAC задан в самом запросе и условен, как и маржа 70%: 3 доллара у платного поиска, 4 у партнёров, 5 у рекомендаций. При таком CAC июньские рекомендации окупились на 19-й день, партнёры — на 41-й; это механика расчёта, а не экономика каналов. У июльских партнёров и платного поиска payback_day пуст: за 30 наблюдённых дней маржа дошла до 3,34 и 1,81 доллара — «не окупились к D30».
| Поле | Значение | Откуда берётся |
|---|---|---|
| cohort_week | 2026-06-01 | неделя старта когорты; в запросах на учебной базе — месяц |
| cohort_users | 1 180 | знаменатель, зафиксированный на старте |
| cac | 140 ₽ | затраты канала за неделю / новые пользователи когорты |
| gross_margin | 70% | согласованное правило маржи |
| margin_d30 | 117,6 ₽ — 84% CAC | 168 × 0,7 |
| margin_d60 | 149,8 ₽ — 107% CAC | 214 × 0,7 |
| payback_day | между D31 и D60 | первый день, где накопленная маржа ≥ 140 ₽ |
| observed_days | 92 | сколько дней когорта прожила к дате среза |
with acquisition_cost (cohort_month, channel, cac) as (
-- учебная вставка: расходов на привлечение в учебной базе нет, CAC условный
values
(date '2026-06-01', 'partner', 4.00), (date '2026-06-01', 'referral', 5.00),
(date '2026-07-01', 'paid_search', 3.00), (date '2026-07-01', 'partner', 4.00),
(date '2026-07-01', 'referral', 5.00)
),
cohort as ( -- observed_days: сколько дней прожил пришедший последним
select user_id, signup_date, channel,
cast(date_trunc('month', signup_date) as date) as cohort_month,
date '2026-08-30' - (cast(date_trunc('month', signup_date) + interval '1 month' as date) - 1) as observed_days
from users
where signup_date < date '2026-08-01'
),
sizes as (
select cohort_month, channel, count(*) as cohort_users
from cohort
group by 1, 2
),
daily as ( -- зерно: когорта + канал + день жизни
select c.cohort_month, c.channel, c.observed_days,
p.paid_at - c.signup_date as day_age,
sum(p.amount) * 0.70 as contribution -- возвратов в учебной базе нет
from cohort c
join payments p
on p.user_id = c.user_id
and p.paid_at - c.signup_date <= c.observed_days
group by 1, 2, 3, 4
),
cumulative as (
select d.cohort_month, d.channel, d.observed_days, d.day_age,
sum(d.contribution) over (
partition by d.cohort_month, d.channel
order by d.day_age
) / s.cohort_users as margin_per_user
from daily d
join sizes s on s.cohort_month = d.cohort_month and s.channel = d.channel
)
select c.cohort_month, c.channel, a.cac,
min(c.day_age) filter (where c.margin_per_user >= a.cac) as payback_day,
c.observed_days,
round(max(c.margin_per_user), 2) as margin_per_user
from cumulative c
join acquisition_cost a on a.cohort_month = c.cohort_month and a.channel = c.channel
group by c.cohort_month, c.channel, a.cac, c.observed_days
order by c.cohort_month, c.channel;Как сформулировать вывод для команды
Слабый вывод звучит так: «LTV в органике выше, значит, нужно отключить paid social». Он не говорит, достаточно ли объёма органики и окупается ли платный канал после учёта CAC.
Сильнее будет так, на числах условного графика: «У зрелых июньских когорт D90 LTV organic составил 248 ₽, referral — 238 ₽, paid social — 129 ₽. Разрыв появляется уже на D7 и почти не сокращается. Следующий шаг — сравнить CAC и contribution margin по кампаниям paid social; отключать весь канал до этого сравнения рано». Такой вывод связывает цифру с решением, но не притворяется доказанной причинностью.
- Назовите горизонт и зрелость когорт.
- Покажите единицу: пользователь, аккаунт или workspace.
- Разложите LTV по каналу, тарифу или платформе.
- Сравните LTV с CAC и contribution margin.
- Зафиксируйте следующий шаг и владельца проверки.
Что почитать дальше
LTV лучше всего читать в связке с поведением и входом в продукт. Сначала проверьте, возвращаются ли пользователи, затем посмотрите, как они доходят до оплаты, и только после этого сравнивайте ценность каналов.
Материалы по теме

Когортный анализ: что это, как построить и читать таблицу
Когортный анализ простыми словами: как построить когортную таблицу в SQL, pandas и Excel, читать её по строкам, столбцам и диагоналям и что делать с незрелыми когортами.

Retention по когортам и каналам: как считать D1, D7 и D30
Как считать retention rate, D1/D7/D30 и когортную возвращаемость: выбрать return event, читать heatmap и находить слабые каналы.

ARPU и ARPPU: как считать выручку на пользователя
Как считать ARPU и ARPPU, выбрать корректный знаменатель, учитывать возвраты и скидки и не принять рост среднего чека за здоровую монетизацию.