Как посчитать K-factor в SQL

Проверь себя · 1/3разбор после ответа
Нужно пронумеровать заказы каждого пользователя по времени покупки, начиная с 1, чтобы потом найти 1-й, 2-й, 3-й заказ. Какое выражение подходит?

Зачем K-factor

K-factor — количественная мера виральности: в среднем каждый пользователь продукта приводит столько-то новых. При K ≥ 1 продукт растёт сам, без денег на маркетинг. При K < 1 вирусность играет роль «множителя» для платного привлечения, но органического взрыва не даёт.

В B2C соцсетях и B2B-инструментах (Slack, Notion, Miro и аналоги) K-factor — одна из центральных тем на собесах в growth-командах. Ошибиться в подсчёте легко: посчитать приглашения вместо фактических регистраций, забыть про cycle time, не вычесть self-invites. Ниже — формулы, SQL-запросы и самые частые грабли.

Формула

K-factor = invites_per_user × conversion_rate
  • invites_per_user — среднее число приглашений на активного пользователя.
  • conversion_rate — доля приглашений, которые стали регистрациями.

Важен не только K, но и cycle time — время от отправки приглашения до регистрации приглашённого. При одинаковом K короткий цикл даёт более быстрый рост.

Схема данных

users    (id, invited_by_user_id, signup_at)
invites  (invite_id, sender_user_id, sent_at, converted_user_id, share_channel)
events   (user_id, event_name, event_at)

1. Базовый K-factor за период

WITH sent AS (
    SELECT
        COUNT(*)                  AS total_invites,
        COUNT(converted_user_id)  AS converted_invites
    FROM invites
    WHERE sent_at >= NOW() - INTERVAL '30 days'
),
active_users AS (
    SELECT COUNT(DISTINCT user_id) AS active_cnt
    FROM events
    WHERE event_at >= NOW() - INTERVAL '30 days'
)
SELECT
    s.total_invites::NUMERIC / NULLIF(a.active_cnt, 0)       AS invites_per_user,
    s.converted_invites::NUMERIC / NULLIF(s.total_invites, 0) AS conversion_rate,
    (s.total_invites::NUMERIC / NULLIF(a.active_cnt, 0))
    * (s.converted_invites::NUMERIC / NULLIF(s.total_invites, 0)) AS k_factor
FROM sent s, active_users a;

Обычно имеет смысл считать K по активным пользователям (знаменатель active_users), а не по отправителям: иначе легко получить красивую, но малоинформативную картину, где 5% ядра приглашает много и держит среднее.

2. Invites на активного пользователя по неделям

WITH active AS (
    SELECT DISTINCT
        DATE_TRUNC('week', event_at) AS week,
        user_id
    FROM events
),
sent AS (
    SELECT
        DATE_TRUNC('week', sent_at) AS week,
        sender_user_id              AS user_id,
        COUNT(*)                    AS cnt
    FROM invites
    GROUP BY 1, 2
)
SELECT
    a.week,
    COALESCE(SUM(s.cnt), 0)::NUMERIC / COUNT(DISTINCT a.user_id) AS invites_per_active_user
FROM active a
LEFT JOIN sent s USING (week, user_id)
GROUP BY a.week
ORDER BY a.week;

3. Conversion rate приглашений

SELECT
    DATE_TRUNC('month', sent_at)::DATE AS month,
    COUNT(*)                           AS invites_sent,
    COUNT(converted_user_id)           AS conversions,
    100.0 * COUNT(converted_user_id) / NULLIF(COUNT(*), 0) AS conversion_pct
FROM invites
GROUP BY 1
ORDER BY 1;

Если conversion падает, чаще причина не в сетях и не в оформлении — а в onboarding'е после перехода.

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

4. Cycle time

SELECT
    AVG(EXTRACT(EPOCH FROM (u.signup_at - i.sent_at)) / 86400) AS avg_cycle_days,
    PERCENTILE_CONT(0.5) WITHIN GROUP (
        ORDER BY EXTRACT(EPOCH FROM (u.signup_at - i.sent_at)) / 86400
    ) AS median_cycle_days
FROM invites i
JOIN users u ON u.id = i.converted_user_id
WHERE i.converted_user_id IS NOT NULL;

Короткий цикл критичен для быстрого роста: при одном и том же K продукт с циклом «часы» растёт на порядок быстрее, чем с циклом «недели».

5. K-factor по каналам share

SELECT
    share_channel,
    COUNT(*)                           AS sent,
    COUNT(converted_user_id)           AS conversions,
    100.0 * COUNT(converted_user_id) / NULLIF(COUNT(*), 0) AS conversion_pct
FROM invites
GROUP BY share_channel
ORDER BY conversion_pct DESC;

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

6. K-factor по когортам

WITH cohorts AS (
    SELECT id AS user_id, DATE_TRUNC('month', signup_at)::DATE AS cohort
    FROM users
),
cohort_stats AS (
    SELECT
        c.cohort,
        COUNT(DISTINCT c.user_id)       AS cohort_size,
        COUNT(i.invite_id)              AS total_invites,
        COUNT(i.converted_user_id)      AS conversions
    FROM cohorts c
    LEFT JOIN invites i ON i.sender_user_id = c.user_id
    GROUP BY c.cohort
)
SELECT
    cohort,
    cohort_size,
    total_invites::NUMERIC / NULLIF(cohort_size, 0)       AS invites_per_user,
    conversions::NUMERIC  / NULLIF(total_invites, 0)      AS conversion_rate,
    (total_invites::NUMERIC / NULLIF(cohort_size, 0))
    * (conversions::NUMERIC  / NULLIF(total_invites, 0))  AS k_factor
FROM cohort_stats
ORDER BY cohort;

Когортный K-factor помогает увидеть, улучшает ли продукт виральность со временем или только раздувает общий трафик за счёт платных каналов.

7. Что означает K < 1

K = 0.5 не значит «экспоненциально растём». Это значит, что каждый пользователь приводит в среднем 0,5 нового — то есть исходный поток приглашений постепенно затухает. На практике при K < 1 виральная петля работает как мультипликатор к платному привлечению:

итоговое число пользователей ≈ paid_users × 1 / (1 − K)

Например, при K = 0.5 на каждого платного пользователя в итоге приходит ещё один органический «виральный». Это всё равно полезно — но это не «бесплатный экспоненциальный рост», которого ждут от K ≥ 1.

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

1. Считать приглашения вместо конверсий

K-factor меряется по конвертировавшимся приглашениям, а не по отправленным. Отправить ссылку дёшево, зарегистрироваться по ней — уже конверсия.

2. Игнорировать cycle time

K = 1 с циклом «30 дней» и K = 1 с циклом «сутки» — разный бизнес: второй дёт взрывной рост за недели, первый — только за месяцы.

3. Знаменатель — все пользователи, а не активные

Если делить invites на всех зарегистрировавшихся (включая «спящих»), invites_per_user систематически занижается.

4. Self-invites

Пользователи приглашают себя со второго адреса или устройства. Полезно фильтровать по IP, device_id, email-доменам или эвристикам типа «invite отправлен и конвертирован в течение 5 минут с того же устройства».

5. Чистый K без контекста

K = 0,4 в вакууме не говорит ни о чём. Разумно показывать его рядом с cycle time, invites_per_user, conversion_rate и динамикой по когортам.

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

FAQ

K > 1 вообще бывает?

Редко и обычно на коротких промежутках у продуктов с сильной утилитарной виральностью (мессенджеры на старте, кросс-платформенные соцсети в фазе взрывного роста). В устойчивом состоянии большинство успешных продуктов держат K < 1 и компенсируют платным привлечением.

K-factor важен для B2B?

Да. В B2B-продуктах виральность часто идёт через «приглашение коллег в рабочее пространство» — и это один из ключевых драйверов роста инструментов типа Slack, Miro, Notion.

Cycle time сильно важен?

Критично. При прочих равных чем короче цикл, тем быстрее растёт пул пользователей.

Как повышать K?

Два рычага: invites_per_user (больше мотивации и удобства шерить) и conversion_rate (лучший onboarding и чёткая ценность для приглашённого до регистрации).