Product A/B & Funnel Analytics — конверсия против удержания
Ситуация
Подписочный B2C-сервис тратит бюджет на привлечение, но выручка упирается в узкое место. Данные лежат на трёх grain’ах — пользователь, событие, транзакция, — а из 12 000 зарегистрировавшихся 8 616 не платят ни разу. Любая денежная метрика обязана явно объявить знаменатель, иначе числа между разрезами расходятся в разы.
Продуктовая команда тестирует новый онбординг-флоу. Управленческий вопрос звучит не «работает ли вариант», а «стоит ли раскатывать и какой рычаг — конверсия или удержание — даёт больший прирост выручки».
Задача
Нужно было закрыть одним разбором три вопроса: даёт ли вариант статистически значимый прирост целевой конверсии без нарушения ratio групп и guardrails; где воронка теряет пользователей и какой шаг держит основную убыль; что сильнее двигает выручку — uplift конверсии или удержание — и каков итог ship / extend / stop. Сравнение рычагов требовало одного масштаба шага, иначе вывод получался из сравнения величин разного размера.
Действия
Воронка на пользовательском grain
Воронка signup → activation → paid_subscription считается в DuckDB по уникальным пользователям: MIN(ts) по каждому шагу, затем COUNT(*) FILTER, с правилом порядка t_k >= t_(k-1). Наивный COUNT(*) по событиям раздувает шаги, поэтому grain зафиксирован как пользователь. Дополнительно считаются вариант с renew и сегментные срезы по каналу, платформе и стране.
A/B-анализ
Когорта эксперимента — 2 552 пользователя (control 1 271 / treatment 1 281). Первая проверка — SRM по χ²; без неё последующие p-value недействительны. Целевая метрика — paid given activated: знаменатель это активировавшиеся, а не вся группа, потому что решение инвестируется именно в этот шаг. Для бинарной метрики считаются абсолютный и относительный lift, 95% CI, z-статистика и p-value.
Guardrails и устойчивость
Вторичная метрика — activation rate. Guardrails — доля возвратов и доля отмен среди плательщиков. Чтобы снять риск обусловливания на post-treatment активации, та же гипотеза проверена ITT-аналогом paid per signup на всей группе. Мощность и MDE считаются при наблюдённом эффекте.
Сравнение рычагов на равном шаге
Юнит-экономика на 12 месяцев даёт LTV на привлечённого. Затем два рычага двигаются на один и тот же шаг +10% относительно: конверсия и удержание. Это сравнение заменило прежнюю формулировку, где lift конверсии сопоставлялся со сдвигом кривой удержания иной величины.
Воспроизводимость
Аналитические ядра вендорены в репозиторий, поэтому чистый клон запускается без внешних зависимостей. Данные синтетические, seed 42, сырые CSV закоммичены. Набор pytest — 16 тестов в 5 файлах — держит ядра, golden-воронку и согласованность SQL с артефактами.
Результат
Воронка: основной провал — перед оплатой
| Шаг | Пользователей | step_conversion, % | overall_conversion, % | Потеря |
|---|---|---|---|---|
| signup | 12 000 | 100.00 | 100.00 | — |
| activation | 9 623 | 80.19 | 80.19 | 2 377 |
| paid_subscription | 3 384 | 35.17 | 28.20 | 6 239 |
Шаг activation → paid забирает 6 239 из 8 616 потерь — 72% убыли. Вход теряет 2 377 пользователей (19.81%). В расширенной воронке renew given paid = 76.48% (2 588 пользователей), то есть после оплаты утечка в 7.8 раза меньше. По каналам разрыв почти целиком на оплате: referral 33.65% overall против paid_search 25.79%; на платформах разрыв создаёт активация (ios 85.41% против web 72.59%).
A/B: целевая метрика значима, guardrails не ухудшились
| Проверка | control | treatment | Эффект | p |
|---|---|---|---|---|
| SRM (χ²) | 1 271 | 1 281 | χ²=0.0392 | 0.843 |
| paid given activated | 36.11% (381/1 055) | 43.19% (447/1 035) | +7.07 п.п. / +19.59% | 0.000946 |
| paid per signup (ITT) | 29.98% (381/1 271) | 34.89% (447/1 281) | +16.41% | 0.007967 |
| activation rate | 83.01% | 80.80% | −2.66% | 0.147 |
| возвраты (refunds / charges) | 3.39% | 3.20% | −0.19 п.п. | — |
| отмены среди плательщиков | 48.82% | 46.53% | −2.29 п.п. | — |
95% CI относительного lift целевой метрики — [+8.00%; +31.18%], достигнутая мощность 0.911, MDE 16.30% относительно. Наблюдённые +19.59% лежат выше порога детекции, нижняя граница CI положительна. ITT-аналог даёт тот же знак и порядок величины, поэтому вывод не зависит от выбора знаменателя.
Рычаги: при равном шаге +10% они сопоставимы
| Рычаг | LTV на привлечённого, ₽ | Прирост к базе 1 594.59 ₽ |
|---|---|---|
| конверсия, +10% | 1 754.05 | +10.00% |
| удержание, +10% | 1 732.45 | +8.65% |
Отношение — примерно 1.2×, а не «в разы». Измеренный эффект варианта на ITT-базе даёт LTV 1 856.27 ₽; условный lift на активировавшихся, экстраполированный на всех, — 1 906.97 ₽, но это верхняя граница, потому что активация в treatment ниже. Вывод: раскатывать — не потому, что конверсия радикально сильнее, а потому, что её эффект измерен и значим, тогда как у удержания нет ни эксперимента, ни оценки эффекта.
Отличие от volta
Форма та же, что у volta (воронка → A/B → ship), но вклад этого кейса — измеренное сравнение конверсионного и удержанческого рычагов на одном шаге. Именно оно превращает «ship, потому что p-value» в решение с ценой альтернативы.
Вердикт: SHIP
SRM нет, целевая метрика значима, эффект выше MDE, направление устойчиво к выбору знаменателя, guardrails не деградировали. В пост-релизном мониторинге держатся activation rate, cancel rate среди плательщиков и paid given activated.
Ограничения
Данные полностью синтетические: эффект варианта, форма кривой удержания и воронка заложены генератором (seed 42), поэтому значимый результат ожидаем по построению и не является свидетельством о реальном продукте. Целевая метрика обусловлена на активации — post-treatment переменной; ITT-проверка снижает, но не устраняет этот риск.
У удержания нет эксперимента: сравнение рычагов — модель на равном шаге, а не измеренный эффект. LTV-оценки ограничены 12-месячным окном, поздние когорты цензурированы справа. Тест был рассчитан на эффекты от 16.30% относительно и выше — меньший эффект этот дизайн бы не отличил от нуля.
Документация
- GitHub → product-ab-funnel-analytics
- README с вердиктом и сравнением рычагов
- Инсайт по воронке
- Инсайт по A/B-эксперименту
- Инсайт по LTV и рычагам
Частые вопросы
Почему вердикт SHIP, если активация в варианте ниже?
Падение активации незначимо (−2.66%, p=0.147), а эффект на оплату значим и подкреплён ITT-проверкой paid per signup (+16.41%, p=0.007967). Падение не заложено в генератор и трактуется как шум.
Почему метрика считается среди активировавшихся, а не по всей группе?
Целевой шаг — paid given activated: именно он держит 72% потерь воронки. Риск обусловливания на post-treatment переменной снят ITT-аналогом, который даёт тот же знак и порядок величины.
Какой рычаг сильнее — конверсия или удержание?
При равном шаге +10% конверсия добавляет к LTV +10.00%, удержание +8.65% — примерно в 1.2 раза меньше. Измерен и значим только конверсионный рычаг.
Можно ли считать результат свидетельством о реальном продукте?
Нет: данные синтетические (seed 42), эффект варианта заложен генератором. Кейс показывает методику и вывод, а не свойство реального сервиса.