Дизайн когортного дашборда retention
Когорты × возраст, heatmap, drilldown по сегментам, алёрты на просадку Wk1 — как читать и не врать себе.
Спроектируй когортный дашборд retention для {{product}} в {{stack}}.
Что такое cohort retention
Cohort retention отвечает на один вопрос: «из юзеров, пришедших в неделю X, какой % остался активен через N недель?». Не путать с aggregate retention (% активных от total) — там просадки маскируются ростом.
1. Оси и единицы
Y-ось: acquisition cohort (когда юзер пришёл)
- неделя для consumer/SMB
- месяц для enterprise (медленный sales cycle)
X-ось: age (сколько прошло с acquisition)
- Wk0, Wk1, Wk2 ... Wk12
- или D1, D7, D14, D28, D60, D90 — для frequency
Cell: % cohort, активный в этот период
«Активный» — единое определение для всех когорт. Если меняешь — backfill.
2. Что считать «активным»
Не event «opened app» — это бесполезно. Используй value moment:
| Тип продукта | Активный = |
|---|---|
| SaaS workflow | Завершил core action ≥ 1 раз за период |
| Marketplace | Завершил transaction (любая сторона) |
| Content | Потребил ≥ N минут или N items |
| Collaboration | Sent ≥ 1 message ИЛИ shared ≥ 1 doc |
Зафиксируй определение в шапке дашборда — без него любые числа спорные.
3. Heatmap-визуализация
Cohort | Wk0 | Wk1 | Wk2 | Wk4 | Wk8 |
---------|-----|-----|-----|-----|-----|
2026-01 | 100%| 62% | 48% | 41% | 38% |
2026-02 | 100%| 60% | 47% | 40% | 37% |
2026-03 | 100%| 55% | 41% | 33% | 29% | <- алёрт
2026-04 | 100%| 58% | 44% | 36% | - |
2026-05 | 100%| 53% | 39% | - | - | <- алёрт
- Цвет от красного к зелёному по threshold-ам
- Вертикальная читалка: одна когорта во времени
- Горизонтальная: один age — как меняется поколение к поколению
4. Drilldown по сегментам
Один retention curve бесполезен. Раскладывай по:
| Cut | Зачем |
|---|---|
| Acquisition channel | Organic vs paid retention сильно различаются |
| Plan tier | Free vs Pro retention — две разные истории |
| Use case / persona | Если product поддерживает несколько jobs |
| Geo | Регион может скрывать новый product-market fit |
| Onboarding variant | A/B вариант — критично сравнить именно cohort-wise |
Запрети «overall retention» как единственное число — всегда показывай рядом segment cuts.
5. Что алёртить
| Сигнал | Threshold | Action |
|---|---|---|
| Wk1 drop > 5pp от baseline | Любая когорта подряд | Investigate — onboarding regression? |
| Wk4 drop > 10pp в одном segment | Одна когорта | Сегмент-specific event |
| Wk8+ начала падать stable retention | 2 когорты подряд | Деградация product value |
| Activation (Wk0 → Wk1) flat 3 когорты | — | Activation potential исчерпан, нужен новый experiment |
| Cohort size падает 3 когорты | — | Acquisition issue, не retention — алёрт другой команде |
Wk1 — самый важный leading indicator. Onboarding ломается там.
6. Frequency vs depth retention
Бинарное «активен / нет» теряет информацию. Дополни:
- L7/L28: сколько из 7/28 дней юзер был активен (среднее по cohort)
- Power user curve: распределение по частоте — bimodal или smooth?
- Action count per active user: глубина использования
Если retention плоский, но L7 растёт — продукт становится глубже даже без роста ширины.
7. Survivor bias — главная ловушка
Считая только «выживших» через 8 недель, получаешь optimistic-bias картину. Counter:
- Показывай также mortality curve (cumulative % churned)
- Не cherry-pick «лучшие» когорты для презентаций
8. Реализация в {{stack}}
Mixpanel
Retention Report → Cohorts. Кастомизация: define «active» событием value moment, не «session start».
Amplitude
Cohort Analysis chart. Создай computed event «valuable_action» и используй как retention event.
In-house (Metabase / Looker)
WITH cohorts AS (
SELECT user_id, DATE_TRUNC('week', first_seen) AS cohort_week
FROM users
),
activity AS (
SELECT user_id, DATE_TRUNC('week', event_at) AS active_week
FROM events WHERE event_name = 'valuable_action'
GROUP BY 1, 2
)
SELECT
c.cohort_week,
DATE_DIFF('week', c.cohort_week, a.active_week) AS week_age,
COUNT(DISTINCT c.user_id) AS active_users,
COUNT(DISTINCT c.user_id) * 1.0
/ FIRST_VALUE(COUNT(DISTINCT c.user_id)) OVER (PARTITION BY c.cohort_week ORDER BY DATE_DIFF('week', c.cohort_week, a.active_week)) AS retention
FROM cohorts c
JOIN activity a USING (user_id)
GROUP BY 1, 2
Анти-паттерны
- ❌ Aggregate retention вместо cohort — рост маскирует churn
- ❌ «Active = opened app» — бесполезное определение
- ❌ Менять определение active без backfill — все исторические когорты невалидны
- ❌ Показывать только средние — outlier-cohort легко теряется
- ❌ Игнорировать survivor bias — особенно при cherry-pick «good cohorts»
- ❌ Алёрт на overall retention, а не по segment — поздно реагируешь
В конце
- Mockup дашборда (heatmap + segment cuts + frequency)
- Определение «active» и rationale
- SQL/спека для каждого графика
- Алёрт-таблица: метрика → threshold → owner → action
- План пересмотра определений (раз в полгода)
Измерение воронок: настройка
Какие воронки строить, как считать, на каких сегментах смотреть.
North-Star метрика и input-метрики
Одна главная метрика которая отражает успех продукта + 3-5 драйверов под неё.
Reactivation flow для dormant пользователей
Email-флоу возврата уснувших пользователей: сегментация, темы, тайминг, метрики. Не «вернись, мы скучаем», а конкретный crm-конвейер.