Product Management Продуктовые метрики: AARRR, North Star, unit-экономика
0%

Продуктовые метрики: AARRR, North Star, unit-экономика

Продуктовые метрики: AARRR, North Star, unit-экономика

В https://courses.digitable.life/post/product-management/01-discovery-and-research/ мы выясняли, существует ли проблема. Метрики отвечают на следующий вопрос: изменилось ли что-нибудь в реальности после того, как мы что-то сделали — и стоило ли это денег, которые мы потратили.

Это не «отчётность для руководства». Метрика — инструмент принятия решений в условиях, где твоё мнение о продукте систематически ошибается примерно в 2/3 случаев (Kohavi, Tang, Xu, «Trustworthy Online Controlled Experiments», 2020). Ниже — как выбрать числа, которые действительно управляют решениями, и как не построить красивый дашборд, по которому нельзя принять ни одного решения.


1. Что такое метрика по существу

1.1. Метрика — это сжатие с потерями

Реальность продукта — это миллионы событий: клики, сессии, платежи, отвалы, жалобы. Человек не может держать это в голове. Метрика сжимает поток событий в одно число, чтобы его можно было сравнить — с прошлой неделей, с контрольной группой, с планом.

Как у любого сжатия с потерями, у метрики есть артефакты. Число конверсия = 4.2% не содержит информации о том, кто конвертировался, почему и что было с остальными 95.8%. Отсюда главное правило: метрика нужна, чтобы заметить изменение, а не чтобы его объяснить. Объясняют когорты, сегменты, качественные интервью и логи.

1.2. Критерии хорошей метрики

Алистер Кролл и Бенджамин Йосковиц в «Lean Analytics» (leananalyticsbook.com) формулируют четыре свойства:

Свойство Что значит Плохой пример Хороший пример
Сравнительная есть с чем сопоставить «12 000 регистраций» «регистраций +18% нед./нед.»
Понятная команда воспроизводит определение по памяти «engagement score 7.4» «доля пользователей, сделавших ≥3 заказа за 28 дней»
Отношение, а не счётчик нормирована на базу, устойчива к росту трафика «10 000 ошибок в день» «0.3% сессий с ошибкой»
Меняющая поведение из значения следует действие «всего просмотров» «время до первого успешного действия»

Пятый критерий добавляю от себя, и он самый недооценённый: метрика должна быть воспроизводимой без разработчика. Если её нельзя посчитать SQL-запросом или в BI за пятнадцать минут, ей не будут пользоваться — а значит, она не существует.

1.3. Vanity metrics: почему «растёт вверх» — не аргумент

Эрик Рис ввёл термин vanity metrics — метрики тщеславия. Признак: число монотонно растёт по определению, потому что это накопительный счётчик. Всего зарегистрировано, всего скачано, всего просмотров с запуска — такие числа не могут упасть, значит, не несут информации о качестве продукта.

Проверка: «если это число вырастет вдвое, что я сделаю по-другому?» Если ответа нет — это украшение дашборда, а не метрика.

Отдельный подвид — метрики, которые «растут» из-за смены знаменателя. Классика: команда чистит базу от неактивных, конверсия в платящих подскакивает с 3% до 5%, все празднуют. Абсолютное число платящих при этом не изменилось.

1.4. Закон Гудхарта

«Когда мера становится целью, она перестаёт быть хорошей мерой» — формулировка Мэрилин Стратерн по мотивам работ Чарльза Гудхарта.

Любая метрика, за которую платят премию, будет оптимизирована — включая пути, которых вы не имели в виду. Примеры из практики:

  • KPI «время ответа поддержки» → операторы отвечают шаблоном «принято в работу» за 30 секунд;
  • KPI «количество установок» → закупается мотивированный трафик, retention D7 падает вдвое;
  • KPI «DAU» → внедряются агрессивные пуши, DAU растёт неделю, отписки растут навсегда (закон паршивеющих CTR Эндрю Чена: The Law of Shitty Clickthroughs);
  • KPI «средний чек» → команда отключает дешёвый тариф, чек растёт, выручка падает.

Единственная рабочая защита — guardrail-метрики (метрики-ограничители), которые двигаться не должны, и о них ниже, в разделе 8.

1.5. Leading и lagging

  • Lagging (запаздывающие): выручка, MRR, годовой отток. Достоверны, но узнаёшь поздно — повлиять уже нельзя.
  • Leading (опережающие): активация в первую неделю, частота ключевого действия, доля пользователей, добавивших второго участника команды. Шумны, но управляемы сейчас.

Продуктовая работа живёт в leading-метриках, финансовая отчётность — в lagging. Задача продакта — доказать связь между ними (см. дерево метрик в разделе 4), иначе леденящий вопрос «а вы уверены, что это влияет на деньги?» останется без ответа.


2. AARRR: пиратские метрики

Дэйв Макклюр в 2007 году предложил разбить жизнь пользователя на пять стадий — Startup Metrics for Pirates. Ценность фреймворка не в аббревиатуре, а в дисциплине: у каждой стадии свой узкий набор метрик, свои гипотезы и своя команда. Без этого разговор «надо растить продукт» превращается в спор без предмета.

2.1. Acquisition — привлечение

Единственная метрика, которая здесь имеет смысл сама по себе, — CAC по каналу, и обязательно fully loaded: рекламный бюджет + зарплаты маркетинга и продаж + скидки и промокоды, делённые на число привлечённых клиентов того же периода.

CAC_канал = (spend + salaries + discounts) / new_customers

Типичная ошибка — считать «средний CAC по компании». Он бесполезен: органика стоит почти ноль и размывает картину платных каналов. Считайте по каналам и по когортам.

2.2. Activation — активация

Самая недооценённая стадия. Активация — это момент, когда пользователь впервые получил обещанную ценность, а не «завершил регистрацию». Формулируется как поведенческое событие:

  • Facebook: 7 друзей за 10 дней (классический кейс, много раз пересказанный в блогах роста);
  • Slack: команда обменялась 2000 сообщениями;
  • Dropbox: положил хотя бы один файл хотя бы на одно устройство.

Как найти свой aha-момент: взять пользователей, доживших до D30, и пользователей, не доживших, и искать поведение в первые дни, которое их разделяет. Дальше — обязательно проверять причинность экспериментом, потому что корреляция «активные делают X» тривиально объясняется обратным направлением: активные делают всё, включая X (см. https://courses.digitable.life/post/product-management/05-mvp-and-experiments/).

Вторая метрика стадии — TTV (time to value): медиана времени от регистрации до первого ключевого действия. Это одна из немногих метрик, где медиана и перцентили обязательны — среднее уничтожается «спящими», которые вернулись через полгода.

2.3. Retention — удержание

Retention — фундамент. Если пользователи не возвращаются, привлечение = наливать воду в дырявое ведро: каждая новая когорта вытекает, рост требует всё больше денег и останавливается, когда бюджет упирается в потолок канала. Подробный разбор — раздел 5.

2.4. Revenue — деньги

Ключевые определения, которые путают чаще всего:

ARPU   = выручка за период / ВСЕ активные пользователи
ARPPU  = выручка за период / ТОЛЬКО платящие
C1     = платящие / все пользователи          (конверсия в платящего)

следовательно:  ARPU = C1 × ARPPU

Полезно всегда держать все три: рост ARPU может быть вызван и ростом конверсии (хорошо, база расширяется), и ростом ARPPU при падающей конверсии (опасно — вы выжимаете ядро и теряете периферию).

2.5. Referral — рекомендации

k-фактор = (число приглашений на пользователя) × (конверсия приглашения в регистрацию). При k ≥ 1 рост самоподдерживающийся — на практике это крайне редко и недолго. Вторая, менее известная и более важная метрика — viral cycle time: сколько времени проходит от регистрации до приглашения. При одинаковом k продукт с циклом 2 дня растёт радикально быстрее, чем с циклом 20 дней.

2.6. Ограничения AARRR

Фреймворк линеен, а реальные продукты — нет. У маркетплейса две воронки (спрос и предложение), они связаны сетевым эффектом; у B2B-SaaS решение о покупке принимает не тот, кто пользуется; у контентного продукта Referral работает раньше Revenue. AARRR — хороший чеклист полноты («мы вообще смотрим на удержание?»), но плохая модель роста. Модель роста строится деревом метрик — раздел 4.


3. North Star: одна метрика, которая держит фокус

3.1. Зачем нужна

Организация из 200 человек не может оптимизировать 40 метрик одновременно — команды начнут тянуть в противоположные стороны (маркетинг растит регистрации, продукт растит конверсию, поддержка растит удовлетворённость, а выручка стоит). North Star Metric (NSM) — единственное число, выражающее ценность, которую продукт даёт пользователям, и через которое компания собирается зарабатывать.

Критерии из Amplitude North Star Playbook:

  1. выражает ценность для пользователя, а не удобство для компании;
  2. отражает стратегию (см. https://courses.digitable.life/post/product-management/04-strategy-and-roadmap/), а не текущий спринт;
  3. является опережающим индикатором выручки;
  4. управляема продуктовыми решениями;
  5. понятна любому сотруднику без обучения;
  6. не vanity — может упасть.

Примеры, ставшие каноном: Airbnb — забронированные ночи; Spotify — время прослушивания; WhatsApp — отправленные сообщения; Amplitude — weekly querying users. Обратите внимание: почти все NSM — это произведение охвата на интенсивность, а не просто «число пользователей».

3.2. Как её собирают правильно

Хорошая NSM почти всегда имеет форму:

NSM = (число пользователей, совершивших ключевое действие за период)
      × (интенсивность действия)
      × (качество действия)

Например, для сервиса доставки: еженедельные заказчики × заказов на заказчика × доля заказов без инцидента. Третий множитель — встроенный guardrail: нельзя вырастить NSM, разогнав заказы ценой качества.

3.3. Ограничения и честная критика

NSM — не панацея. Три реальные проблемы:

  • Инерция. NSM меняется медленно, отдельная команда за квартал сдвинет её на шум. Поэтому команды работают не с NSM, а с её драйверами (раздел 4).
  • Гудхарт в масштабе. Единственная метрика, привязанная к бонусам всей компании, — идеальный объект для оптимизации не по назначению.
  • Смена стадии. NSM ранней стадии (активация) не годится для стадии монетизации. Пересматривать её раз в год — нормально; менять каждый квартал — признак отсутствия стратегии.

4. Дерево метрик: как связать фичу с деньгами

Дерево метрик (metric tree, growth model) — декомпозиция NSM на множители, каждый из которых кому-то принадлежит. Это главный рабочий артефакт продакта: он превращает абстрактный «рост» в конечный список рычагов и делает возможной приоритизацию (см. https://courses.digitable.life/post/product-management/03-prioritization/).

4.1. Мультипликативная модель и её главный урок

Простейшая модель выручки:

Revenue = Visitors × CR_signup × CR_activation × CR_paid × ARPPU × Lifetime

Посчитаем чувствительность в коде.

from dataclasses import dataclass, replace

@dataclass(frozen=True)
class Funnel:
    visitors: int = 200_000     # визитов в месяц
    cr_signup: float = 0.08     # визит -> регистрация
    cr_activation: float = 0.45 # регистрация -> активация
    cr_paid: float = 0.06       # активация -> первая оплата
    arppu: float = 900.0        # средний чек платящего, ₽/мес
    lifetime_m: float = 7.0     # месяцев жизни платящего

    def revenue(self) -> float:
        return (self.visitors * self.cr_signup * self.cr_activation
                * self.cr_paid * self.arppu * self.lifetime_m)


def sensitivity(base: Funnel, lift: float = 0.10) -> dict[str, float]:
    """Прирост выручки при относительном улучшении каждого драйвера на lift."""
    out = {}
    r0 = base.revenue()
    for field in ("visitors", "cr_signup", "cr_activation", "cr_paid", "arppu", "lifetime_m"):
        bumped = replace(base, **{field: getattr(base, field) * (1 + lift)})
        out[field] = bumped.revenue() / r0 - 1
    return out


base = Funnel()
print(f"Выручка: {base.revenue():,.0f} ₽/мес")
for name, delta in sensitivity(base).items():
    print(f"{name:>15}: +{delta:.1%}")

Вывод одинаков для всех драйверов: +10%. Это не баг модели, а её содержательный результат: в чисто мультипликативной воронке важен не сам множитель, а достижимый относительный прирост на единицу усилий. Поднять cr_paid с 6% до 6.6% — работа на квартал; поднять visitors на 10% — вопрос бюджета. Поэтому дерево метрик не заменяет приоритизацию, а даёт ей единицу измерения: «сколько процентов выручки стоит этот рычаг».

Асимметрия появляется там, где связь нелинейна. Классический пример — retention, который входит в LTV через 1/churn:

def ltv_simple(arppu: float, gross_margin: float, monthly_churn: float) -> float:
    """Геометрическая модель: LTV = маржинальная выручка / отток."""
    return arppu * gross_margin / monthly_churn

base_ltv = ltv_simple(900, 0.80, 0.12)          # отток 12%/мес -> 6000 ₽
better   = ltv_simple(900, 0.80, 0.12 * 0.90)   # отток -10% относительно -> 6667 ₽
print(f"{base_ltv:.0f} -> {better:.0f}, прирост {better/base_ltv - 1:.1%}")  # +11.1%

При оттоке 12% улучшение на 10% даёт +11.1% LTV; при оттоке 3% то же относительное улучшение даёт те же +11.1%, но в абсолютных рублях — в четыре раза больше. Retention — единственная метрика воронки с таким рычагом, поэтому она почти всегда недоинвестирована относительно её экономической ценности.

Сложность вычислений здесь тривиальна: дерево из n узлов считается за O(n), чувствительность методом «сдвинь один драйвер» — за O(n) пересчётов дерева, то есть O(n²) в худшем случае для глубоких деревьев. Для реальных деревьев (30–80 узлов) это доли секунды, поэтому пересчёт можно делать интерактивно прямо в BI.


5. Retention: как считать и как читать

5.1. Три несовместимых определения

Прежде чем спорить о числе, договоритесь об определении. Их три, и они дают принципиально разные значения на одних данных (Mixpanel: Retention Report):

Тип Определение Когда применять
N-day (bounded) вернулся ровно на день N продукты с ежедневным ритмом: игры, соцсети
Unbounded (rolling) вернулся в день N или позже редкие сценарии: билеты, страховки, крупные покупки
Bracket (range) вернулся в интервале [N, M] SaaS и всё, что живёт неделями и месяцами

N-day для B2B-инструмента даст 4% и панику, bracket-недельный на тех же данных — 60% и спокойствие. Обе цифры «правильные». Всегда пишите определение рядом с числом.

5.2. Форма кривой важнее её уровня

Кривые удержания: выход на плато против затухания в ноль

Единственный вопрос к кривой удержания: выходит ли она на плато. Плато означает, что существует ядро пользователей, для которых продукт стал привычкой — этих людей можно масштабировать привлечением. Кривая, уходящая в ноль, означает, что каждый вложенный в маркетинг рубль сгорает, и никакой объём привлечения бизнес не спасёт.

Обратите внимание на левую часть картинки: в первую неделю обе кривые почти совпадают. Решение о жизнеспособности продукта, принятое по D1/D7, регулярно оказывается ошибочным в обе стороны. Минимальный горизонт — 8 недель, для B2B — 3–6 месяцев.

Ориентиры «что такое хорошо» сильно зависят от категории; разборы бенчмарков с реальными данными публикует Ленни Рачицкий (What is good retention?).

5.3. Жизненный цикл пользователя как автомат

Считать «активных» вообще — бессмысленно. Полезно разложить базу на состояния и смотреть на потоки между ними: именно потоки — управляемая величина.

Из этого автомата получается уравнение роста базы:

MAU(t) = MAU(t-1) + New(t) + Resurrected(t) − Churned(t)

Отношение (New + Resurrected) / Churned — это Quick Ratio (термин из портфельной аналитики Social Capital). При значении < 1 база сокращается, сколько бы вы ни привлекали. Это самая честная одноцифровая диагностика здоровья продукта.

5.4. Код: когортный retention на pandas

import pandas as pd
import numpy as np

# users:  user_id, signup_date (datetime64)
# events: user_id, event_date (datetime64) — любое «активное» действие

def weekly_retention(users: pd.DataFrame,
                     events: pd.DataFrame,
                     today: pd.Timestamp) -> pd.DataFrame:
    """Матрица удержания: строки — недельные когорты, столбцы — номер недели жизни."""
    df = events.merge(users, on="user_id", how="inner")

    # Номер недели жизни пользователя относительно его собственной регистрации.
    df["week_index"] = (df["event_date"] - df["signup_date"]).dt.days // 7
    df = df[df["week_index"] >= 0]                       # защита от событий до регистрации
    df["cohort"] = df["signup_date"].dt.to_period("W")

    active = (df.groupby(["cohort", "week_index"])["user_id"]
                .nunique()
                .unstack(fill_value=0))

    size = users.groupby(users["signup_date"].dt.to_period("W"))["user_id"].nunique()
    retention = active.div(size, axis=0)

    # КРИТИЧНО: маскируем правое цензурирование. Молодая когорта физически
    # не могла дожить до недели N — без маски она занизит средние по столбцу.
    weeks_lived = ((today - retention.index.to_timestamp()).days // 7)
    mask = np.arange(retention.shape[1])[None, :] <= np.asarray(weeks_lived)[:, None]
    return retention.where(mask)


# Пример синтетических данных
rng = np.random.default_rng(42)
n = 5_000
users = pd.DataFrame({
    "user_id": range(n),
    "signup_date": pd.Timestamp("2026-01-05") + pd.to_timedelta(rng.integers(0, 120, n), "D"),
})
rows = []
for uid, signup in zip(users.user_id, users.signup_date):
    alive_weeks = rng.geometric(p=0.25)               # у части пользователей короткая жизнь
    if rng.random() < 0.30:                            # ядро с привычкой
        alive_weeks += rng.integers(8, 30)
    for w in range(alive_weeks):
        rows.append((uid, signup + pd.Timedelta(weeks=int(w), days=int(rng.integers(0, 7)))))
events = pd.DataFrame(rows, columns=["user_id", "event_date"])

ret = weekly_retention(users, events, today=pd.Timestamp("2026-06-01"))
print((ret.iloc[:, :9] * 100).round(1))

Сложность: группировка O(E) по числу событий плюс O(C·W) на построение матрицы, где C — когорт, W — недель. Память — O(C·W), то есть матрица всегда крошечная; узкое место — исходная таблица событий, поэтому в проде агрегация делается на стороне хранилища (см. SQL ниже), а в pandas приезжает уже свёрнутый результат.

5.5. Тот же расчёт на SQL

-- Недельный bracket-retention. Работает в BigQuery / ClickHouse / Postgres
-- с минимальными правками синтаксиса date_trunc.
WITH cohorts AS (
    SELECT user_id,
           date_trunc('week', signup_at) AS cohort_week
    FROM users
),
activity AS (
    SELECT c.user_id,
           c.cohort_week,
           CAST(FLOOR(DATE_DIFF(e.event_at, c.cohort_week, DAY) / 7) AS INT64) AS week_index
    FROM events e
    JOIN cohorts c USING (user_id)
    WHERE e.event_name IN ('order_completed', 'report_created')   -- «ключевое действие»
      AND e.event_at >= c.cohort_week
),
sized AS (
    SELECT cohort_week, COUNT(*) AS cohort_size
    FROM cohorts GROUP BY cohort_week
)
SELECT a.cohort_week,
       a.week_index,
       COUNT(DISTINCT a.user_id)                          AS retained,
       s.cohort_size,
       ROUND(COUNT(DISTINCT a.user_id) / s.cohort_size, 4) AS retention
FROM activity a
JOIN sized s USING (cohort_week)
-- отсекаем незрелые точки: когорта должна прожить week_index полных недель
WHERE DATE_ADD(a.cohort_week, INTERVAL (a.week_index + 1) WEEK) <= CURRENT_DATE()
GROUP BY a.cohort_week, a.week_index, s.cohort_size
ORDER BY a.cohort_week, a.week_index;

Обратите внимание на предпоследнюю строку — это то самое отсечение правого цензурирования. Его забывают чаще всего, и в результате последние когорты выглядят «ухудшающимися», хотя они просто моложе.


6. Unit-экономика: сходится ли бизнес

6.1. Идея

Unit-экономика отвечает на вопрос: зарабатываем ли мы на одном клиенте больше, чем тратим на его привлечение и обслуживание? Если нет, рост увеличивает убыток — масштабируется не бизнес, а дыра.

Единица («юнит») выбирается по природе продукта: клиент — для SaaS, заказ — для маркетплейса, автомобиль в городе — для каршеринга. Ошибка выбора юнита обесценивает весь расчёт: считать экономику маркетплейса на клиента, а не на заказ, значит спрятать в среднем переменные затраты, которые растут с каждой транзакцией.

Водопад юнит-экономики: от выручки к прибыли с юнита

6.2. Формулы

Contribution margin (CM) на юнит = Выручка − Переменные затраты
    переменные: эквайринг, налог с оборота, хостинг/трафик на пользователя,
                стоимость поддержки, бонусы и промокоды, доставка

LTV (по когорте, дискретно) = Σ_{t=0..T} CM_t · S_t / (1 + d)^t
    S_t — доля когорты, дожившая до периода t; d — ставка дисконтирования

LTV (геометрическое приближение) = CM_месяц / churn_месяц

CAC = (маркетинг + продажи + скидки на привлечение) / число новых клиентов

Payback = число месяцев, за которое кумулятивный CM покрывает CAC

Два практических ориентира из SaaS Metrics 2.0 Дэвида Скока: LTV / CAC ≥ 3 и payback ≤ 12 месяцев. Это не законы природы, а эвристики: LTV/CAC = 3 примерно соответствует состоянию, где после переменных затрат и привлечения остаётся достаточно на R&D, админку и прибыль. LTV/CAC = 10 — не победа, а сигнал, что вы недоинвестируете в рост и оставляете рынок конкурентам.

6.3. Главная ошибка — «геометрический» LTV на реальных данных

Формула LTV = ARPU/churn предполагает постоянный отток. Реальные кривые удержания имеют падающий hazard rate: кто выжил полгода, уходит гораздо реже новичка. Средний отток по базе поэтому одновременно переоценивает жизнь новичков и недооценивает жизнь ядра.

Правильный путь — считать LTV по когортам, из фактической кривой, а хвост экстраполировать явной моделью с честно указанной неопределённостью.

import numpy as np
from scipy.optimize import curve_fit

def survival(t, plateau, decay):
    """Модель «затухание + плато»: S(t) = c + (1-c)·exp(-t/tau)."""
    return plateau + (1.0 - plateau) * np.exp(-t / decay)

# факт: доля когорты, активная в месяце t (t=0 — месяц регистрации)
t_obs = np.arange(0, 9)
s_obs = np.array([1.00, 0.62, 0.48, 0.41, 0.38, 0.36, 0.352, 0.348, 0.345])

(plateau, decay), cov = curve_fit(survival, t_obs, s_obs, p0=[0.3, 2.0],
                                  bounds=([0.0, 0.1], [0.9, 60.0]))
print(f"плато = {plateau:.3f}, tau = {decay:.2f} мес, "
      f"σ(плато) = {np.sqrt(cov[0, 0]):.3f}")

def ltv(cm_per_month: float, horizon: int, d_annual: float = 0.20) -> float:
    """Дисконтированный LTV на горизонте horizon месяцев."""
    d_m = (1 + d_annual) ** (1 / 12) - 1
    t = np.arange(horizon)
    return float(np.sum(cm_per_month * survival(t, plateau, decay) / (1 + d_m) ** t))

CM = 820.0   # маржинальная выручка на активного клиента в месяц
CAC = 600.0 * 5   # CAC когорты в расчёте на одного платящего

for h in (12, 24, 36):
    v = ltv(CM, h)
    print(f"горизонт {h:>2} мес: LTV = {v:,.0f} ₽, LTV/CAC = {v / CAC:.2f}")

# Payback: первый месяц, где кумулятивный дисконтированный CM покрывает CAC
d_m = (1 + 0.20) ** (1 / 12) - 1
cum = np.cumsum(CM * survival(np.arange(60), plateau, decay) / (1 + d_m) ** np.arange(60))
idx = np.argmax(cum >= CAC)
print(f"payback ≈ {idx + 1} мес" if cum[idx] >= CAC else "payback не достигается за 60 мес")

Три дисциплины, которые отличают взрослый расчёт от студенческого:

  1. Горизонт указывается явно. «LTV = 24 000 ₽» без горизонта — бессмысленное число. Стандарт индустрии — 12 или 24 месяца; бесконечный горизонт запрещён здравым смыслом (вы не знаете, что будет с продуктом через 5 лет).
  2. Дисконтирование. Рубль через два года дешевле рубля сегодня, а для стартапа, привлекающего капитал под 20–30%, — существенно дешевле.
  3. В LTV идёт contribution margin, а не выручка. LTV, посчитанный по валовой выручке, завышен ровно на долю переменных затрат — то есть в e-commerce вдвое-втрое.

6.4. Как это выглядит в отчёте когорты

Правильная таблица юнит-экономики — не одна строка, а когорты по месяцу привлечения:

Когорта Клиентов CAC CM накопл. M3 CM накопл. M12 Payback LTV/CAC (24 мес)
2025-09 1 240 2 800 ₽ 1 900 ₽ 4 400 ₽ 8 мес 3.1
2025-12 2 610 3 900 ₽ 1 700 ₽ прогноз 13 мес прогноз 2.2
2026-03 4 050 5 100 ₽ 1 500 ₽ прогноз 19 мес прогноз 1.5

Это самая частая история масштабирования: CAC растёт быстрее качества трафика (вычерпаны дешёвые каналы), CM когорты падает, экономика разъезжается — но по агрегату «средний LTV/CAC по компании» это видно только через год. Когортный разрез показывает разворот за квартал.


7. Модель данных: без чего метрики не существуют

Метрики — производная от событийной модели. Если события пишутся как попало, любой дашборд врёт, и это не лечится SQL-запросом.

Четыре детали, которые ломают метрики чаще всего:

  • occurred_at против received_at. Мобильный клиент офлайн отправит события через сутки. Если считать по времени приёма, вчерашний DAU «дорастёт» задним числом, и все ежедневные отчёты станут нестабильными. Считайте по occurred_at, но окно закрывайте с лагом (например, T+2).
  • Идемпотентность. Ретраи клиента — норма. Без event_id и дедупликации метрики завышены на единицы процентов, и никто этого не заметит.
  • Словарь событий (tracking plan) с владельцем и версией. Событие checkout_done, у которого разработчик поменял смысл поля amount с «до скидки» на «после», создаёт разрыв во всех исторических рядах.
  • Единый идентификатор до и после логина. Иначе воронка «аноним → регистрация» не сшивается, и конверсия считается по фантомам.

Инженерная часть этого — предмет трека data engineering; продуктовая — в https://courses.digitable.life/post/product-management/08-analytics-and-decisions/.


8. Guardrails, OEC и как не сломать продукт ростом метрики

OEC (Overall Evaluation Criterion) — термин Ронни Кохави: заранее зафиксированная формула, по которой принимается решение об успехе изменения, включающая и целевую метрику, и ограничения. Это защита от Гудхарта на уровне процесса.

Практическая конструкция для любого запуска:

Роль метрики Пример Правило
Target конверсия в оплату должна вырасти статистически значимо
Guardrail p95 времени загрузки, доля отписок, crash-free rate, тикеты в поддержку не должна ухудшиться более чем на порог
Counter-metric средний чек при росте конверсии, retention при росте DAU явно проверяем, что рост не за счёт неё
Health/data quality доля событий без user_id, SRM (перекос долей групп) нарушение = эксперимент недействителен

Пример боевого правила: «раскатываем, если конверсия +≥1.5% при p<0.05, и при этом p95 latency не выросла более чем на 50 мс, а недельный retention не упал более чем на 0.5 п.п.». Порог фиксируется до запуска, иначе он станет предметом переговоров после.

Подробности статистики — в https://courses.digitable.life/post/product-management/05-mvp-and-experiments/; книга-эталон — Kohavi, Tang, Xu, «Trustworthy Online Controlled Experiments».


9. Типичные ошибки, которые дорого стоят

1. Средние по скошенным распределениям. ARPU, время сессии, число заказов — распределения с длинным хвостом. Среднее двигают «киты». Смотрите медиану и перцентили (p50/p90/p99) и гистограмму; если среднее и медиана расходятся втрое, среднее не описывает никого.

2. Парадокс Симпсона. Метрика растёт в каждом сегменте и падает в целом (или наоборот), потому что изменились доли сегментов. Конкретно:

Сегмент Было Стало
Desktop 300/1000 = 30% 165/500 = 33%
Mobile 100/1000 = 10% 175/1500 = 11.7%
Итого 400/2000 = 20% 340/2000 = 17%

Конверсия выросла на обеих платформах, но общая упала: закупили дешёвый мобильный трафик, и доли сегментов изменились. Правило: любое изменение агрегата проверяйте разбивкой по основным измерениям (платформа, канал, страна, новизна пользователя).

3. Ошибка выжившего в когортах. Смотреть на поведение только активных пользователей и делать вывод «те, кто пользуются фичей X, дольше живут». Проверяется только экспериментом или как минимум сравнением с matched-контролем.

4. Незрелые когорты в среднем. Разобрано в 5.4/5.5 — маскируйте правое цензурирование.

5. Смена определения метрики без версии. «Активный пользователь» тихо переопределили с «открыл приложение» на «совершил действие», ряд сломался, полгода все спорят о причинах падения. Определения метрик — код: в git, с владельцем, с датой изменения и с обязательным пересчётом истории.

6. Novelty effect и сезонность. Новая фича даёт всплеск от любопытства и затухает за 2–3 недели. Одна неделя измерения — не измерение. Годовые сезонные эффекты (декабрь, каникулы) сравнивайте год к году, а не месяц к месяцу.

7. Метрика без владельца. Число, за которое не отвечает конкретный человек, не двигается. Каждый узел дерева метрик должен иметь имя рядом.

8. Слишком много метрик. Дашборд с 60 графиками не читает никто. Рабочий формат: 1 NSM + 5–7 драйверов + guardrails. Остальное — по запросу, в разрезах.


10. Как это устроено на практике

Как выглядит зрелая система метрик в компании — по нарастанию:

  1. Определения в коде. Метрики описаны в семантическом слое (dbt metrics, LookML, Cube) один раз, а не переписываются в каждом дашборде. Это устраняет ситуацию, когда у маркетинга и продукта разный «активный пользователь».
  2. Tracking plan как контракт. Схема событий валидируется в CI, событие без владельца и описания в прод не попадает.
  3. Weekly business review. Регулярная встреча, где смотрят дерево метрик сверху вниз, а не «что мы выкатили». Формат: что изменилось, почему, что делаем.
  4. Дефолтный набор к каждому запуску. Target + guardrails фиксируются в документе фичи до разработки. Через 2–4 недели после релиза — обязательный пост-анализ, и это единственный способ не стать фабрикой фич (см. https://courses.digitable.life/post/product-management/00-overview/).
  5. Экономика в разрезе когорт — часть операционного цикла, а не разовое упражнение перед раундом инвестиций.

Полезная привычка: раз в квартал брать каждую метрику на главном дашборде и задавать единственный вопрос — «какое решение мы приняли из-за неё за последние три месяца?». Метрики без ответа удаляются. Дашборд, который не худеет, всегда растёт до нечитаемости.


Мини-итог

  • Метрика — сжатие реальности ради сравнения; объясняют изменения когорты и сегменты, а не число.
  • Хорошая метрика сравнительна, понятна, является отношением и меняет поведение. Накопительные счётчики — vanity.
  • AARRR — чеклист полноты покрытия жизненного цикла, а не модель роста.
  • North Star даёт фокус; работают команды с её драйверами через дерево метрик, которое переводит фичи в проценты выручки.
  • Retention важнее уровня — важна форма кривой: есть плато или нет. Всегда указывайте тип определения (N-day / unbounded / bracket) и маскируйте незрелые когорты.
  • Unit-экономика считается на contribution margin, по когортам, с явным горизонтом и дисконтированием. LTV/CAC ≥ 3 и payback ≤ 12 мес — эвристики, а не законы.
  • Любая целевая метрика требует guardrails, зафиксированных до запуска, иначе закон Гудхарта сработает обязательно.

Источники


Что дальше

Метрики говорят, где болит, но не говорят, что делать первым. Следующий шаг — превратить дерево метрик и поток идей в упорядоченную очередь работ: Приоритизация: RICE, ICE, Kano, MoSCoW, WSJF.

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

Статья описывает общий случай. Если у вас частный — можно разобрать его отдельно, платно. А если не хватает целого материала, предложите тему: её оплачивают вскладчину, и она выходит открытой для всех.

Доска запросов