Как посчитать time to value в SQL

Закрепи формулу time to value в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать time to value в Telegram

Что такое TTV

Time to Value (TTV) — время от регистрации до первого получения ценности от продукта. Чем короче TTV, тем сильнее retention. Это одна из главных метрик активации.

В Slack — время до первого отправленного сообщения в команду. В Notion — до первой созданной страницы. В банковском приложении — до первого перевода.

Не путать с активацией: активация — доля юзеров, дошедших до value. TTV — время, за которое они доходят.

Выбор события «value»

Это самая важная часть. Хорошее value-событие:

  • Связано с core ценностью продукта, не вторичным действием
  • Сильно коррелирует с D7-retention (как и активация)
  • Происходит у большинства активных юзеров (иначе нет данных для медианы)

Например, для маркетплейса доставки:

  • Плохой выбор: «открыл каталог» (происходит у всех, не отражает ценности)
  • Хороший: «получил первый заказ»
  • Отличный: «получил первый заказ и оценил его на 4-5 звёзд»

SQL: общий TTV

Допустим, у вас есть users(user_id, signup_at) и events(user_id, event_type, created_at):

WITH first_value AS (
  SELECT
    u.user_id,
    u.signup_at,
    MIN(e.created_at) AS first_value_at
  FROM users u
  LEFT JOIN events e
    ON e.user_id = u.user_id
    AND e.event_type = 'first_order_completed'
    AND e.created_at >= u.signup_at
  WHERE u.signup_at >= '2026-01-01'
  GROUP BY u.user_id, u.signup_at
)
SELECT
  COUNT(*) AS total_users,
  COUNT(first_value_at) AS reached_value,
  ROUND(COUNT(first_value_at)::NUMERIC / COUNT(*), 3) AS share_reached,
  EXTRACT(EPOCH FROM AVG(first_value_at - signup_at)) / 3600 AS avg_ttv_hours,
  EXTRACT(EPOCH FROM PERCENTILE_CONT(0.5)
    WITHIN GROUP (ORDER BY first_value_at - signup_at)) / 3600 AS median_ttv_hours
FROM first_value
WHERE first_value_at IS NOT NULL;

Медиана почти всегда полезнее среднего — TTV имеет длинный хвост (некоторые юзеры активируются через месяц, тянут среднее).

Закрепи формулу time to value в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать time to value в Telegram

SQL: TTV по когортам

Чтобы видеть, как TTV меняется со временем (после релизов, изменений onboarding):

WITH first_value AS (
  SELECT
    u.user_id,
    DATE_TRUNC('week', u.signup_at)::DATE AS cohort_week,
    u.signup_at,
    MIN(e.created_at) AS first_value_at
  FROM users u
  LEFT JOIN events e
    ON e.user_id = u.user_id
    AND e.event_type = 'first_order_completed'
    AND e.created_at >= u.signup_at
  GROUP BY u.user_id, cohort_week, u.signup_at
)
SELECT
  cohort_week,
  COUNT(*) AS users,
  ROUND(EXTRACT(EPOCH FROM PERCENTILE_CONT(0.5)
    WITHIN GROUP (ORDER BY first_value_at - signup_at)) / 3600, 1) AS median_ttv_hours,
  ROUND(EXTRACT(EPOCH FROM PERCENTILE_CONT(0.9)
    WITHIN GROUP (ORDER BY first_value_at - signup_at)) / 3600, 1) AS p90_ttv_hours
FROM first_value
WHERE first_value_at IS NOT NULL
GROUP BY cohort_week
ORDER BY cohort_week;

Связь с retention

Чем короче TTV, тем выше retention. Это можно проверить SQL'ем:

WITH ttv AS (
  SELECT
    u.user_id,
    EXTRACT(EPOCH FROM (MIN(e.created_at) - u.signup_at)) / 3600 AS ttv_hours
  FROM users u
  JOIN events e
    ON e.user_id = u.user_id
    AND e.event_type = 'first_order_completed'
  GROUP BY u.user_id, u.signup_at
),
ttv_buckets AS (
  SELECT
    user_id,
    CASE
      WHEN ttv_hours <= 1 THEN '<1 hour'
      WHEN ttv_hours <= 24 THEN '1-24 hours'
      WHEN ttv_hours <= 168 THEN '1-7 days'
      ELSE '>7 days'
    END AS ttv_bucket
  FROM ttv
),
d30_retention AS (
  SELECT
    user_id,
    EXISTS (
      SELECT 1 FROM events
      WHERE user_id = user_id
        AND created_at >= NOW() - INTERVAL '30 days'
    ) AS retained_d30
  FROM users
)
SELECT
  tb.ttv_bucket,
  COUNT(*) AS users,
  ROUND(AVG(CASE WHEN dr.retained_d30 THEN 1.0 ELSE 0 END), 3) AS d30_retention
FROM ttv_buckets tb
JOIN d30_retention dr USING (user_id)
GROUP BY tb.ttv_bucket
ORDER BY tb.ttv_bucket;

Ожидаем: чем меньше TTV, тем выше D30-retention. Если связь обратная — value-событие выбрано неправильно.

Частые ошибки

Среднее вместо медианы. TTV имеет длинный хвост. Один юзер с TTV 30 дней тянет среднее. Используйте медиану.

Игнорировать тех, кто не достиг value. Если 70% не активировались — медиана TTV считается только по 30%. Это смещение. Считайте отдельно median TTV и share who reached value.

Использовать timezone сервера. Юзер из UTC+3 регистрируется в 23:00 UTC, value совершает в 02:00 UTC — TTV считается «3 часа», но фактически было 23:30 локального → 5:30 локального = 6 часов. Используйте локальное время.

Не учитывать новые когорты. Юзер, зарегистрированный 2 дня назад, не имел шанса достичь value за 7 дней. Считайте только когорты, где окно прошло.

Брать «слабое» value-событие. «Открыл приложение второй раз» — слабое value. Не предсказывает retention. Берите событие, которое реально отражает core ценность.

FAQ

Какой TTV считается хорошим?

Зависит от продукта. Соцсеть — минуты. Маркетплейс доставки — часы. SaaS B2B — дни. Главное — снижать TTV для своей категории.

Как использовать TTV в работе?

A/B-тесты onboarding меняют TTV. Если новый онбординг сократил median TTV с 24 до 6 часов — это сильный сигнал, что и retention вырастет.

Это официальная информация?

Нет. Статья основана на индустриальных практиках.