Как посчитать Free-to-Paid в SQL

Проверь себя · 1/3разбор после ответа
Есть таблица payments(amount), в части строк amount равно NULL. Какой запрос посчитает количество всех строк в таблице, включая строки с NULL в столбце amount?

Зачем Free-to-Paid

Основа любой freemium-воронки: регистрация → бесплатное использование → конверсия в платящего. Без здоровой Free-to-Paid масштабироваться невозможно. Slack, Dropbox, Notion — все построены на этом.

Формула

Free-to-Paid = users_paid_within_X / total_signups × 100%

Окно обычно 30/60/90 дней после регистрации.

Базовый расчёт

WITH signups AS (
    SELECT user_id, signed_up_at
    FROM users
    WHERE signed_up_at BETWEEN '2026-01-01' AND '2026-02-01'
),
first_paid AS (
    SELECT
        user_id,
        MIN(created_at) AS first_payment_at
    FROM transactions
    WHERE status = 'paid'
      AND amount > 0
    GROUP BY user_id
)
SELECT
    COUNT(s.user_id) AS signups,
    COUNT(p.user_id) AS converted_to_paid,
    COUNT(p.user_id) FILTER (WHERE p.first_payment_at <= s.signed_up_at + INTERVAL '30 days') AS converted_30d,
    COUNT(p.user_id) FILTER (WHERE p.first_payment_at <= s.signed_up_at + INTERVAL '90 days') AS converted_90d,
    COUNT(p.user_id) FILTER (WHERE p.first_payment_at <= s.signed_up_at + INTERVAL '30 days')::NUMERIC * 100 / COUNT(s.user_id) AS free_to_paid_30d_pct
FROM signups s
LEFT JOIN first_paid p ON p.user_id = s.user_id;

По когортам

WITH cohort AS (
    SELECT
        DATE_TRUNC('week', signed_up_at) AS cohort_week,
        user_id
    FROM users
    WHERE signed_up_at >= CURRENT_DATE - INTERVAL '12 weeks'
),
paid AS (
    SELECT user_id, MIN(created_at) AS paid_at
    FROM transactions
    WHERE status = 'paid'
    GROUP BY user_id
)
SELECT
    c.cohort_week,
    COUNT(c.user_id) AS signups,
    COUNT(p.user_id) AS paid,
    COUNT(p.user_id)::NUMERIC * 100 / NULLIF(COUNT(c.user_id), 0) AS conversion_pct
FROM cohort c
LEFT JOIN paid p ON p.user_id = c.user_id
  AND p.paid_at - (
    SELECT signed_up_at FROM users WHERE user_id = c.user_id
  ) <= INTERVAL '30 days'
GROUP BY c.cohort_week
ORDER BY c.cohort_week;
Закрепи формулу free to paid в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать free to paid в Telegram

Время до конверсии

WITH conversions AS (
    SELECT
        u.user_id,
        u.signed_up_at,
        MIN(t.created_at) AS first_paid_at,
        EXTRACT(EPOCH FROM (MIN(t.created_at) - u.signed_up_at)) / 86400 AS days_to_pay
    FROM users u
    JOIN transactions t ON t.user_id = u.user_id
    WHERE t.status = 'paid'
      AND u.signed_up_at >= CURRENT_DATE - INTERVAL '6 months'
    GROUP BY u.user_id, u.signed_up_at
)
SELECT
    PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY days_to_pay) AS p25_days,
    PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY days_to_pay) AS median_days,
    PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY days_to_pay) AS p75_days,
    AVG(days_to_pay) AS avg_days
FROM conversions;

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

Ошибка 1. Снимок вместо когорты. «Free-to-Paid 10%» сегодня — включая тех, кто зарегистрировался 5 лет назад? Считайте по когортам.

Ошибка 2. Выбор окна. 30 и 90 дней дают очень разные цифры. Длинный хвост конверсий (оплата спустя полгода) — обычное дело.

Ошибка 3. Триал против бесплатного тарифа. Trial-to-Paid и Free-to-Paid — это разные воронки. Не путайте их.

Ошибка 4. Несколько ценовых точек. Оплатил пробную подписку за $1 — считать ли его платящим? Заранее договоритесь, что такое «платящий».

Ошибка 5. Возвраты. Оплатил, а на второй неделе вернул деньги. Отфильтруйте такие случаи.

Связанные темы

FAQ

Какой Free-to-Paid считается нормальным?

В B2C-SaaS 2-5% считается средним показателем, 5-10% — хорошим. В B2B-SaaS диапазон выше — 5-15%. У Slack конверсия доходит до ~30%, но это на уровне рабочих пространств, а не отдельных пользователей.

Окно 30 или 90 дней?

30 дней дают ранний сигнал — быстро видно, работает ли активация. 90 дней ближе к реальности для продуктов с длинным циклом принятия решения. Для оперативного мониторинга берут 30, для честной итоговой цифры — 90.

Free-to-Paid падает — что делать?

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

Считать конверсию от активированных пользователей?

Конверсия «активированный → платящий» информативнее, чем «регистрация → платящий»: она убирает из знаменателя тех, кто вообще не начал пользоваться продуктом. Отфильтруйте выборку до активированных пользователей, и цифра станет честнее.

Что делать с длинным хвостом конверсий?

В SaaS часть пользователей конвертируется спустя год и больше после регистрации. Чтобы не терять их из виду, отслеживайте полную кривую конверсии за всё время жизни когорты, а не только за первое окно.