Skip to content
PПромтбук
RUEN
05OKR и метрики

Дизайн когортного дашборда 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
CollaborationSent ≥ 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 channelOrganic vs paid retention сильно различаются
Plan tierFree vs Pro retention — две разные истории
Use case / personaЕсли product поддерживает несколько jobs
GeoРегион может скрывать новый product-market fit
Onboarding variantA/B вариант — критично сравнить именно cohort-wise

Запрети «overall retention» как единственное число — всегда показывай рядом segment cuts.

5. Что алёртить

СигналThresholdAction
Wk1 drop > 5pp от baselineЛюбая когорта подрядInvestigate — onboarding regression?
Wk4 drop > 10pp в одном segmentОдна когортаСегмент-specific event
Wk8+ начала падать stable retention2 когорты подрядДеградация 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
  • План пересмотра определений (раз в полгода)
К подразделу «OKR и метрики»
Похожие промты