Product Management Ценообразование, монетизация и рост
0%

Ценообразование, монетизация и рост

Ценообразование, монетизация и рост

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

Классическая оценка из McKinsey (Marn & Rosiello, «Managing Price, Gaining Profit», Harvard Business Review, 1992): для типичной компании из S&P 1500 улучшение цены на 1% при неизменном объёме даёт около 11% роста операционной прибыли. Тот же 1% улучшения переменных издержек даёт ~7%, объёма — ~3%. Цена — самый чувствительный рычаг в модели, и при этом самый недоинвестированный: исследование ProfitWell/Paddle на выборке SaaS-компаний показывает, что медианная команда тратит на ценообразование менее 10 часов за всё время существования продукта.

Эта статья — про то, как перестать назначать цену «как у конкурента минус 10%» и начать проектировать монетизацию как часть продукта. Во второй половине — про рост: почему воронка как ментальная модель исчерпала себя и что такое growth loops.

Предполагается, что вы уже знакомы с базовой unit-экономикой из https://courses.digitable.life/post/product-management/02-metrics/ — LTV, CAC, contribution margin здесь используются как известные понятия.


1. Что такое цена по существу

1.1. Value stick: цена не создаёт ценность, она её делит

Самая полезная модель — value stick из работ Гарвардской школы бизнеса (Felix Oberholzer-Gee, «Better, Simpler Strategy», 2021). Представьте вертикальную «палку» с четырьмя отметками:

Value stick: WTP, цена, себестоимость и распределение созданной ценности

  • WTP (willingness to pay) — максимум, который клиент готов отдать. Выше него сделки нет.
  • Цена — то, что он реально платит.
  • Себестоимость (COGS) — что стоит обслужить его: инфраструктура, поддержка, эквайринг.
  • Резервная цена поставщиков — минимум, за который согласны работать сотрудники и вендоры.

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

  1. Созданная ценность = WTP − резервная цена поставщиков. Это длина всей палки. Цена её не удлиняет — она лишь ставит отметку, где кончается доля клиента и начинается ваша.
  2. Клиент покупает только если WTP > цены. Разница — потребительский излишек, и он не «упущенная выручка», а причина, по которой клиент вообще нажал «оплатить», не ушёл к конкуренту и рекомендовал продукт другому. Излишек, стремящийся к нулю, — это продукт без сарафанного радио и с высоким оттоком.
  3. Единственный устойчивый способ зарабатывать больше — растянуть палку: поднять WTP продуктом (не риторикой) или опустить издержки. Всё остальное — перетягивание одеяла.

1.2. Три способа назначить цену и почему два из них плохие

Подход Как считают Что не так
Cost-plus себестоимость + желаемая маржа Клиенту безразличны ваши затраты. В софте предельная себестоимость близка к нулю → цена уезжает в ноль.
Competitor-based «как у X, минус 10%» Вы наследуете чужую бизнес-модель и чужие ошибки. Скидка к конкуренту — это заявление «мы хуже».
Value-based доля от измеримой ценности для клиента Требует понимать экономику клиента. Дорого, медленно, единственный работающий.

Value-based на практике означает: у вас есть числовая гипотеза о ценности. Не «мы экономим время», а «команда из 12 аналитиков тратила 6 часов в неделю на ручную выгрузку; при ставке 3 500 ₽/час это 1.1 млн ₽ в год; мы забираем 15–25% этой экономии → 165–275 тыс. ₽/год». Такую гипотезу можно проверить в интервью (см. https://courses.digitable.life/post/product-management/01-discovery-and-research/), и от неё есть куда двигаться.

1.3. Value metric — сердце монетизации

Value metric — единица, за которую вы берёте деньги. Это решение важнее, чем сама цифра цены: цифру легко поменять, метрику — почти невозможно.

Хорошая value metric удовлетворяет трём условиям:

  1. Растёт вместе с ценностью для клиента. Клиент, получающий вдвое больше пользы, платит примерно вдвое больше — и не считает это несправедливым.
  2. Понятна до покупки. Клиент может прикинуть свой счёт заранее. «За активного пользователя» — понятно. «За compute unit» — нет.
  3. Не наказывает за правильное поведение. Плата за хранение логов заставляет клиента логировать меньше — то есть использовать продукт хуже.
Продукт Value metric Почему работает
Slack активный пользователь в месяц ценность = коммуникация команды ∝ размер команды; неактивных не считают
Stripe % от объёма платежей выручка клиента напрямую = ценность
Twilio сообщение / минута атомарная единица пользы
AWS S3 ГБ × месяц + запросы издержки и ценность коррелируют
Figma редактор (не зритель) зрители бесплатны → вирусность внутри компании
HubSpot контакт в базе база растёт → растёт и ценность CRM

Типичная ошибка: брать деньги за «место» (seat) там, где ценность не в людях. Продукт мониторинга, продающийся по seat, получает ситуацию, когда клиент экономит, покупая три лицензии на отдел из тридцати — и продукт не проникает в компанию. Переход Datadog на host-based pricing и Snowflake на consumption — примеры смены value metric ради снятия этого потолка.


2. Как измерить готовность платить

WTP не спрашивают в лоб («сколько бы вы заплатили?») — ответ систематически смещён: люди занижают, чтобы не показаться расточительными, и завышают, чтобы поддержать приятного интервьюера. Есть три рабочих инструмента.

2.1. Van Westendorp Price Sensitivity Meter

Метод 1976 года (оригинальная статья, ESOMAR) обходит смещение, задавая четыре косвенных вопроса:

  1. При какой цене продукт покажется вам слишком дешёвым (усомнитесь в качестве)?
  2. При какой цене он покажется вам выгодной покупкой?
  3. При какой цене он покажется дорогим, но вы бы ещё подумали?
  4. При какой цене он слишком дорог, чтобы вообще рассматривать?

Дальше строятся кумулятивные кривые и ищутся их пересечения.

"""Van Westendorp PSM: диапазон приемлемых цен из четырёх вопросов.

Сложность: O(n log n) на сортировку ответов + O(g) на проход по сетке цен,
где n — число респондентов, g — число точек сетки. Память O(n + g).
"""
from dataclasses import dataclass


@dataclass
class Answer:
    too_cheap: float      # «слишком дёшево, подозрительно»
    cheap: float          # «выгодно»
    expensive: float      # «дорого, но подумаю»
    too_expensive: float  # «неприемлемо дорого»


def _share(values: list[float], price: float, direction: str) -> float:
    """Доля респондентов, для которых порог сработал на данной цене."""
    if direction == "at_or_below":   # убывающая кривая: «дёшево» при p <= порога
        return sum(1 for v in values if v >= price) / len(values)
    return sum(1 for v in values if v <= price) / len(values)  # возрастающая


def psm(answers: list[Answer], grid: list[float]) -> dict[str, float]:
    tc = [a.too_cheap for a in answers]
    ch = [a.cheap for a in answers]
    ex = [a.expensive for a in answers]
    te = [a.too_expensive for a in answers]

    curves = {
        "too_cheap":     [_share(tc, p, "at_or_below") for p in grid],
        "cheap":         [_share(ch, p, "at_or_below") for p in grid],
        "expensive":     [_share(ex, p, "at_or_above") for p in grid],
        "too_expensive": [_share(te, p, "at_or_above") for p in grid],
    }

    def cross(a: str, b: str) -> float:
        """Первая точка сетки, где кривая a перестаёт быть выше b (линейная интерполяция)."""
        ya, yb = curves[a], curves[b]
        for i in range(1, len(grid)):
            d0, d1 = ya[i - 1] - yb[i - 1], ya[i] - yb[i]
            if d0 > 0 >= d1:                       # смена знака разности
                t = d0 / (d0 - d1)                 # доля отрезка до пересечения
                return grid[i - 1] + t * (grid[i] - grid[i - 1])
        return float("nan")

    return {
        # нижняя граница: дешевле — начнут сомневаться в качестве
        "point_of_marginal_cheapness": cross("too_cheap", "expensive"),
        # «безразличие»: одинаково много считают дорогим и выгодным ≈ цена лидера рынка
        "indifference_price": cross("cheap", "expensive"),
        # оптимум: минимум суммарного отказа по обеим крайностям
        "optimal_price_point": cross("too_cheap", "too_expensive"),
        # верхняя граница: дороже — отвал ускоряется нелинейно
        "point_of_marginal_expensiveness": cross("cheap", "too_expensive"),
    }


if __name__ == "__main__":
    import random
    random.seed(42)
    # У каждого респондента свой «якорь» a — его личный масштаб цен.
    # Четыре ответа привязаны к нему, поэтому по выборке распределения перекрываются,
    # и кривые действительно пересекаются (на несвязанных диапазонах метод вырождается).
    data = []
    for _ in range(300):
        a = random.uniform(800, 3000)
        data.append(Answer(
            too_cheap=a * random.uniform(0.20, 0.40),
            cheap=a * random.uniform(0.50, 0.75),
            expensive=a * random.uniform(1.00, 1.30),
            too_expensive=a * random.uniform(1.60, 2.10),
        ))
    grid = [100 * i for i in range(1, 71)]  # 100…7000 ₽
    for k, v in psm(data, grid).items():
        print(f"{k:34s} {v:8.0f} ₽")

Что метод даёт и чего не даёт. Даёт диапазон, в котором цена не вызывает рефлекторного отторжения — это полезная рамка для стартовой точки. Не даёт спроса: респондент не берёт на себя обязательства платить. Van Westendorp систематически смещён вниз для новых категорий (людям не с чем сравнить) и вверх для статусных товаров. Использовать как первый фильтр, не как решение.

2.2. Gabor-Granger: ближе к спросу

Респонденту называют конкретную цену и спрашивают «купите?». При «да» цену поднимают, при «нет» — опускают. На выходе — кривая доли покупателей от цены, то есть эмпирическая кривая спроса, из которой сразу считается выручка. Метод честнее PSM, но требует готового описания продукта и обычно завышает намерение примерно вдвое — классическая проблема разрыва «intention–behaviour».

2.3. Conjoint / MaxDiff: цена как одна из характеристик

Самый строгий подход. Респонденту показывают наборы «продукт = набор характеристик + цена» и просят выбрать. Из выборов методом дискретного выбора (multinomial logit) оценивается частичная полезность каждой характеристики, включая цену. Дальше можно симулировать долю рынка для любой комбинации фич и цены и найти оптимальную упаковку тарифов.

Conjoint отвечает на вопрос, который PSM не берёт: что положить в какой тариф. Практический разбор — у Sawtooth Software и в книге Мадхавана Рамануджама и Георга Таке «Monetizing Innovation», 2016 — это, пожалуй, лучшая практическая книга о ценообразовании продукта.

Главный тезис «Monetizing Innovation»: разговор о цене должен быть первым разговором о продукте, а не последним. 72% провалившихся инноваций в их выборке провалились не из-за качества, а из-за несоответствия продукта и модели монетизации.


3. Эластичность: математика оптимума

3.1. Определение

Ценовая эластичность спроса — на сколько процентов изменится спрос при изменении цены на 1%:

$$E = \frac{\Delta q / q}{\Delta p / p}$$

E всегда отрицательна (спрос падает при росте цены), поэтому говорят о модуле. При |E| < 1 спрос неэластичен: подъём цены увеличивает выручку. При |E| > 1 — эластичен, подъём цены выручку снижает. Максимум выручки — ровно в точке |E| = 1.

Кривая выручки от цены: неэластичная и эластичная зоны

3.2. Оптимальная цена при постоянной эластичности

Если спрос описывается степенной моделью $q(p) = A p^{-e}$ (постоянная эластичность $e$), то прибыль $\Pi(p) = (p - c) \cdot A p^{-e}$. Приравняв производную к нулю, получаем классическую формулу наценки:

$$p^\ast = c \cdot \frac{e}{e - 1}, \quad e > 1$$

Читается так: чем менее эластичен спрос (e ближе к 1), тем выше наценка. При e → ∞ (идеальная конкуренция) цена стремится к себестоимости.

"""Оценка эластичности по двум точкам и оптимум прибыли.

Сложность: O(1) по обеим формулам; сеточный поиск ниже — O(g).
"""


def arc_elasticity(p0: float, q0: float, p1: float, q1: float) -> float:
    """Дуговая (midpoint) эластичность — симметрична к направлению изменения."""
    dq = (q1 - q0) / ((q1 + q0) / 2)
    dp = (p1 - p0) / ((p1 + p0) / 2)
    return dq / dp


def optimal_price_constant_elasticity(cost: float, elasticity: float) -> float:
    e = abs(elasticity)
    if e <= 1:
        raise ValueError("при |E| <= 1 оптимума нет: выручка растёт с ценой без предела — "
                         "модель неприменима, ограничение лежит вне неё (конкуренты, регуляторы, справедливость)")
    return cost * e / (e - 1)


def subscription_value(p: float, cost: float, elasticity: float, base_churn: float,
                       churn_elasticity: float, p_ref: float, q_ref: float) -> float:
    """Целевая функция подписки: (число купивших) × LTV каждого.

    Цена бьёт дважды. Спрос:  q(p) = q_ref · (p/p_ref)^(-e).
    Отток: churn(p) = c0 · (p/p_ref)^s — мультипликативная модель, отток
    не может уйти в ноль или в минус, в отличие от линейной поправки.
    """
    q = q_ref * (p / p_ref) ** (-abs(elasticity))
    churn = base_churn * (p / p_ref) ** churn_elasticity
    return q * (p - cost) / churn


def subscription_ltv_optimum(cost: float, elasticity: float, base_churn: float,
                             churn_elasticity: float, grid: list[float]) -> float:
    """Сеточный поиск максимума. Сложность O(g)."""
    p_ref, q_ref = grid[len(grid) // 2], 1000.0
    return max(grid, key=lambda p: subscription_value(
        p, cost, elasticity, base_churn, churn_elasticity, p_ref, q_ref))


def subscription_optimum_closed_form(cost: float, elasticity: float,
                                     churn_elasticity: float) -> float:
    """Для степенных q и churn целевая функция ∝ p^-(e+s)·(p−c),
    и оптимум берётся аналитически: p* = c·(e+s)/(e+s−1) при e+s > 1.
    Полезно как проверка сеточного поиска — и как объяснение, почему
    чувствительность оттока к цене работает ровно как добавка к эластичности."""
    k = abs(elasticity) + churn_elasticity
    if k <= 1:
        raise ValueError("e + s <= 1: внутреннего оптимума нет")
    return cost * k / (k - 1)


if __name__ == "__main__":
    e = arc_elasticity(p0=990, q0=1200, p1=1490, q1=700)
    print(f"эластичность: {e:.2f}")
    print(f"оптимум разовой продажи:  {optimal_price_constant_elasticity(300, e):7.0f} ₽")

    s = 0.6  # рост цены на 1% увеличивает отток на 0.6%
    grid = [50 * i for i in range(4, 60)]  # 200…2950 ₽ с шагом 50
    print(f"оптимум подписки (сетка):  {subscription_ltv_optimum(300, e, 0.04, s, grid):7.0f} ₽")
    print(f"оптимум подписки (формула):{subscription_optimum_closed_form(300, e, s):7.0f} ₽")
    print("→ учёт оттока сдвигает оптимум ВНИЗ: чувствительность оттока "
          "складывается с эластичностью спроса")

3.3. Три поправки, без которых формула вредна

  1. Максимум выручки ≠ максимум прибыли. При ненулевой себестоимости оптимум прибыли всегда правее оптимума выручки: последний клиент, привлечённый снижением цены, может быть убыточным. Для SaaS с высокой валовой маржой разница мала, для маркетплейсов с большими переменными затратами — велика.
  2. В подписке цена влияет на отток. Разовая покупка оптимизирует один платёж, подписка — поток. Поднятая на 20% цена, увеличившая месячный отток с 3% до 4.5%, снижает LTV: было 0.8·p/0.03 = 26.7p, стало 0.8·1.2p/0.045 = 21.3p.
  3. Эластичность неоднородна по сегментам. Средняя эластичность — такая же фикция, как средняя температура по палате. Enterprise-сегмент может быть почти неэластичен (|E| ≈ 0.3), а самозанятые — крайне эластичны (|E| ≈ 2.5). Отсюда вся идея сегментированных тарифов.

4. Модели монетизации

4.1. Выбор модели: что определяет ответ

  • Как выглядит потребление ценности. Равномерное во времени → подписка. Пиковое и непредсказуемое → потребление. Событийное → транзакции.
  • Какова предельная себестоимость. Близка к нулю → freemium возможен. Заметна (LLM-инференс, видеотранскод, доставка) → freemium превращается в машину сжигания денег, нужен гибрид с жёстким лимитом.
  • Кто принимает решение о покупке. Если решает не пользователь, а бюджетодержатель, вам нужны предсказуемость счёта и годовой контракт — usage-based pricing проваливает бюджетное согласование именно из-за непредсказуемости.

4.2. Гибрид как современный дефолт

Чистые модели почти исчезли. Актуальный дефолт для B2B SaaS — **платформенная база

  • потребление сверху**: фиксированная плата за доступ, предсказуемая для финансов клиента, плюс переменная часть, которая растёт вместе с ценностью. Так устроены Twilio, Snowflake, современный Datadog, большинство AI-продуктов (подписка + токены/кредиты).

Для AI-продуктов есть отдельная ловушка: предельная себестоимость больше не нулевая. Безлимитный тариф на инференс — это опцион, который выпишут против вас 2% самых тяжёлых пользователей. Практическое решение: гибрид «включённые кредиты + прозрачный overage» плюс жёсткие rate limits как продуктовая, а не техническая мера.

4.3. Упаковка: тарифная линейка как инструмент сегментации

Три тарифа — не эстетика, а механизм самоотбора. Клиент сам сообщает вам свою готовность платить, выбирая тариф. Чтобы это работало, между тарифами нужны fences — барьеры, привязанные к признаку сегмента, а не к произвольной фиче:

Тип барьера Пример Кого отсекает
Объём 3 проекта / 10 000 событий мелких от крупных
Роли и доступы SSO, аудит-лог, RBAC стартапы от enterprise
Совместная работа гости, шаринг, комментарии одиночек от команд
Интеграции и API вебхуки, лимит API ручной труд от автоматизации
SLA и поддержка 24/7, выделенный менеджер тех, для кого простой стоит денег

Два эффекта из поведенческой экономики, которые здесь работают всегда:

  • Якорение (anchoring). Самый дорогой тариф слева/справа задаёт систему отсчёта, и средний перестаёт выглядеть дорогим. Enterprise-тариф «по запросу» продаётся редко, но исправно поднимает конверсию в Pro.
  • Приманка (decoy / asymmetric dominance). Третий вариант, доминируемый одним из двух, сдвигает выбор в сторону доминирующего — знаменитый эксперимент с подпиской The Economist, разобранный у Дэна Ариели, «Predictably Irrational».

Граница, которую переходить нельзя: fence должен быть объяснимым. Если клиент не понимает, почему функция в верхнем тарифе, он читает это как вымогательство, и вы платите оттоком. Хороший fence звучит как «это нужно только компаниям вашего размера», плохой — «мы отключили кнопку, пока вы не заплатите».

4.4. Когда freemium вообще имеет смысл

Freemium оправдан, когда выполняется хотя бы одно: бесплатный пользователь приводит платных (вирусность, публичный контент, шаринг), бесплатный пользователь улучшает продукт (данные, контент, ликвидность маркетплейса), или он почти ничего не стоит и служит дешёвым верхом воронки. Если ни одного — это не freemium, а благотворительность; берите бесплатный триал с ограничением по времени: он даёт тот же опыт продукта без бесконечного хвоста издержек.

Ориентир по конверсии: медиана free→paid в B2B SaaS находится в районе 2–5%; у продуктов с сильной вирусностью — до 10%. Значения ниже 1% почти всегда означают, что бесплатный тариф решает задачу целиком.


5. Жизненный цикл платящего и expansion revenue

Две дуги на этой схеме — там, где лежат деньги, о которых обычно забывают.

Дуга «Платящий → Расширенный». Расширение выручки в существующей базе стоит кратно дешевле привлечения: у вас уже есть контакт, доверие и данные о потреблении. Компании с net revenue retention выше 120% растут вдвое, даже полностью остановив привлечение. Именно это отличает «дорого расти» от «растём сами».

Дуга «Просрочен → Платящий». Involuntary churn — отток из-за технического сбоя платежа (истёк срок карты, лимит, 3-D Secure) — составляет обычно 20–40% всего оттока в подписных продуктах. Это самая дешёвая выручка на свете: грамотный dunning (умные ретраи по расписанию, предварительное уведомление об истечении карты, account updater у эквайера) возвращает половину. Продакты почти никогда об этом не думают, потому что это выглядит «биллинговой инженерией», а не продуктом.

5.1. GRR и NRR: как считать честно

  • GRR (gross revenue retention) — сколько выручки удержали без учёта расширения. Не может быть выше 100%. Показывает, дырявое ли ведро.
  • NRR (net revenue retention) — с учётом расширения. Может быть выше 100%. Показывает, компенсирует ли рост базы её потери.
-- NRR/GRR по когорте: сравниваем MRR одних и тех же клиентов через 12 месяцев.
-- Ключевая деталь: знаменатель — MRR ТОЛЬКО тех клиентов, что были в базовом месяце.
-- Новые клиенты в расчёт не входят, иначе метрика превращается в рост выручки.
WITH base AS (
    SELECT customer_id, mrr AS mrr_start
    FROM monthly_recurring_revenue
    WHERE month = DATE '2025-07-01' AND mrr > 0
),
later AS (
    SELECT customer_id, mrr AS mrr_end
    FROM monthly_recurring_revenue
    WHERE month = DATE '2026-07-01'
)
SELECT
    SUM(b.mrr_start)                                          AS mrr_base,
    SUM(COALESCE(l.mrr_end, 0))                               AS mrr_now,
    -- NRR: всё, что осталось, включая рост у выживших
    ROUND(SUM(COALESCE(l.mrr_end, 0)) / SUM(b.mrr_start), 3)  AS nrr,
    -- GRR: расширение обрезаем потолком базового MRR
    ROUND(SUM(LEAST(COALESCE(l.mrr_end, 0), b.mrr_start))
          / SUM(b.mrr_start), 3)                              AS grr,
    -- разложение изменения на составляющие
    SUM(GREATEST(COALESCE(l.mrr_end, 0) - b.mrr_start, 0))    AS expansion,
    SUM(GREATEST(b.mrr_start - COALESCE(l.mrr_end, 0), 0))
      FILTER (WHERE COALESCE(l.mrr_end, 0) > 0)               AS contraction,
    SUM(b.mrr_start) FILTER (WHERE COALESCE(l.mrr_end, 0) = 0) AS churned
FROM base b
LEFT JOIN later l USING (customer_id);

Ориентиры для B2B SaaS: GRR ≥ 85% и NRR ≥ 110% считаются здоровыми, NRR ≥ 130% — выдающимися (характерно для usage-based моделей, где счёт растёт сам).

5.2. LTV с расширением и дисконтированием

Простая формула LTV = маржа / отток игнорирует две вещи: деньги завтра дешевле денег сегодня, и у выживших клиентов чек растёт.

"""LTV в замкнутой форме и численно, с расширением и дисконтом.

Замкнутая форма: LTV = m / (c + d - g), где
  m — месячная валовая маржа с клиента,
  c — месячный отток (доля), d — месячная ставка дисконтирования, g — месячный рост чека.
Условие сходимости: c + d > g. Иначе ряд расходится, и модель говорит
«клиент бесконечно ценен» — верный признак, что параметры оценены неверно.

Численный вариант: O(h) по времени, O(1) по памяти, где h — горизонт в месяцах.
"""


def ltv_closed_form(margin: float, churn: float, discount: float, growth: float) -> float:
    denom = churn + discount - growth
    if denom <= 0:
        raise ValueError("c + d <= g: ряд расходится, проверьте оценки оттока и роста чека")
    return margin / denom


def ltv_numeric(margin: float, churn: float, discount: float,
                growth: float, horizon: int = 60) -> float:
    """Горизонт обязателен: LTV на бесконечности — красивая, но неуправляемая цифра.
    Практика — считать LTV на 24 или 36 месяцев, это и есть срок планирования."""
    total, alive, m = 0.0, 1.0, margin
    for t in range(1, horizon + 1):
        total += alive * m / (1 + discount) ** t   # дисконт компаундируется по месяцам
        alive *= (1 - churn)                       # доля выживших к следующему месяцу
        m *= (1 + growth)                          # чек выживших растёт
    return total


def payback_months(cac: float, margin: float, growth: float = 0.0) -> float:
    """Через сколько месяцев маржа отбивает стоимость привлечения."""
    acc, m, months = 0.0, margin, 0
    while acc < cac and months < 240:
        acc += m
        m *= (1 + growth)
        months += 1
    return months if acc >= cac else float("inf")


if __name__ == "__main__":
    print(f"LTV (закрытая форма): {ltv_closed_form(1200, 0.03, 0.01, 0.008):,.0f} ₽")
    print(f"LTV (36 мес, численно): {ltv_numeric(1200, 0.03, 0.01, 0.008, 36):,.0f} ₽")
    print(f"Payback при CAC 18 000 ₽: {payback_months(18000, 1200, 0.008)} мес.")

Практическое правило: для здорового бизнеса LTV/CAC ≥ 3 и payback ≤ 12 месяцев (для SMB — ≤ 6). Второй критерий важнее первого: LTV — оценка будущего с широким доверительным интервалом, а payback — почти наблюдаемая величина, определяющая, сколько оборотного капитала съест рост.


6. Как менять цену в проде

Изменение цены — это не деплой, а операция с юридическими, продуктовыми и коммуникационными последствиями. Ниже — последовательность, по которой это делают компании, для которых цена не разовое событие.

6.1. Почему A/B-тест цены — особый случай

Обычный A/B (см. https://courses.digitable.life/post/product-management/05-mvp-and-experiments/) здесь ломается о три вещи:

  1. Утечка информации. Пользователи видят разные цены и обсуждают это публично. Ущерб репутации может превысить ценность знания. Amazon поймали на этом ещё в 2000 году, и с тех пор это хрестоматийный кейс.
  2. Нарушение SUTVA. Пользователь в контроле может узнать про цену из теста и изменить поведение — независимость наблюдений исчезает.
  3. Долгий отклик. Настоящий эффект цены проявляется в оттоке через 3–6 месяцев, а не в конверсии за неделю. Тест, остановленный по конверсии, систематически выбирает низкую цену.

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

6.2. Скидки: самая дорогая привычка

Скидка бьёт напрямую по contribution margin: при валовой марже 80% скидка 20% съедает 25% прибыли. Хуже другое — скидка необратимо переопределяет якорь: клиент, однажды купивший за 70%, больше никогда не считает 100% справедливой ценой, и каждое продление превращается в переговоры.

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


7. Рост: от воронок к циклам

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

Воронка AARRR (см. https://courses.digitable.life/post/product-management/02-metrics/) — линейная модель: сверху заливаем трафик, снизу капают деньги. У неё встроенный дефект: выход не связан со входом. Чтобы получить вдвое больше клиентов, нужно вдвое больше трафика, а трафик дорожает по мере исчерпания канала. Рост через воронку всегда упирается в CAC.

Growth loop — модель, в которой выход цикла становится его же входом (Brian Balfour, Reforge, «Growth Loops are the New Funnels»). Тогда рост компаундируется, а не линейно масштабируется с бюджетом.

У любого цикла три параметра, и все три — рычаги для продакта:

  • Коэффициент k — сколько новых входов даёт один прошедший цикл. При k ≥ 1 рост экспоненциальный, при k < 1 — затухающий, но всё равно умножающий приток.
  • Время цикла T — от входа до порождённого им входа. Сокращение T часто мощнее, чем рост k: оно повышает частоту компаундирования.
  • Утечки — на каждом переходе цикла есть конверсия, и именно они, а не сам k, обычно определяют результат.

7.2. Математика цикла

"""Вирусный цикл: усиление притока и чувствительность к k и времени цикла.

При k < 1 суммарное число пользователей, порождённых одной начальной когортой,
равно сумме геометрической прогрессии: N_total = N0 / (1 - k) — «вирусный множитель».
Симуляция ниже: O(периодов) по времени, O(1) по памяти.
"""


def viral_multiplier(k: float) -> float:
    if k >= 1:
        return float("inf")  # формально бесконечность; практически k>=1 не держится долго
    return 1 / (1 - k)


def simulate(seed: int, k: float, cycle_days: int, horizon_days: int) -> list[float]:
    """Возвращает накопленную базу по дням при постоянном k."""
    cohort, total, series = float(seed), float(seed), []
    for day in range(horizon_days + 1):
        if day > 0 and day % cycle_days == 0:
            cohort = cohort * k     # каждый цикл когорта порождает новую
            total += cohort
        series.append(total)
    return series


if __name__ == "__main__":
    print(f"k=0.5  → множитель {viral_multiplier(0.5):.2f}×")
    print(f"k=0.8  → множитель {viral_multiplier(0.8):.2f}×")
    print(f"k=0.95 → множитель {viral_multiplier(0.95):.2f}×")

    base = simulate(seed=1000, k=0.8, cycle_days=14, horizon_days=90)
    fast = simulate(seed=1000, k=0.8, cycle_days=7,  horizon_days=90)
    print(f"\nЗа 90 дней при одинаковом k=0.8 (потолок обоих — 5 000):")
    print(f"  цикл 14 дней: {base[-1]:,.0f}")
    print(f"  цикл  7 дней: {fast[-1]:,.0f}  ← та же вирусность, вдвое быстрее выбирается потолок")

Обратите внимание на нелинейность: рост k с 0.5 до 0.8 даёт множитель 2× → 5×, а с 0.8 до 0.95 — 5× → 20×. Вблизи единицы каждая сотая доля k стоит очень дорого, поэтому продукты с k ≈ 0.9 выглядят как «магия», хотя отличаются от k ≈ 0.6 всего лишь парой процентных пунктов конверсии на каждом шаге цикла.

7.3. Growth accounting: откуда на самом деле берётся рост

Агрегированный рост MRR скрывает всё интересное. Разложение (Jonathan Hsu, Social Capital, «Diligence at Social Capital: Accounting for Revenue Growth») раскладывает изменение на пять потоков и даёт quick ratio — насколько приобретение опережает потери.

"""Growth accounting по MRR: new / expansion / resurrection / contraction / churn.

Сложность: O(n) по числу клиентов в объединении двух периодов, O(n) памяти.
Инвариант, который стоит проверять в тестах:
    mrr_end - mrr_start == new + expansion + resurrection - contraction - churn
"""
from dataclasses import dataclass


@dataclass
class GrowthAccounting:
    new: float
    expansion: float
    resurrection: float
    contraction: float
    churn: float

    @property
    def net(self) -> float:
        return self.new + self.expansion + self.resurrection - self.contraction - self.churn

    @property
    def quick_ratio(self) -> float:
        """(приобретённое) / (потерянное). Ориентир для SaaS ранней стадии: >= 4."""
        lost = self.contraction + self.churn
        return float("inf") if lost == 0 else (self.new + self.expansion + self.resurrection) / lost


def growth_accounting(prev: dict[str, float], curr: dict[str, float],
                      ever_paid: set[str]) -> GrowthAccounting:
    """prev/curr — MRR по клиенту за два соседних месяца (нулевые записи опускаем).
    ever_paid — множество клиентов, плативших когда-либо ДО prev (для resurrection)."""
    acc = GrowthAccounting(0, 0, 0, 0, 0)
    for cid in prev.keys() | curr.keys():
        a, b = prev.get(cid, 0.0), curr.get(cid, 0.0)
        if a == 0 and b > 0:
            if cid in ever_paid:
                acc.resurrection += b      # вернулся после паузы
            else:
                acc.new += b               # действительно новый
        elif a > 0 and b == 0:
            acc.churn += a
        elif b > a:
            acc.expansion += b - a
        elif b < a:
            acc.contraction += a - b
    return acc


if __name__ == "__main__":
    prev = {"a": 1000, "b": 500, "c": 2000, "d": 300}
    curr = {"a": 1500, "b": 500, "e": 800, "d": 100, "f": 400}
    acc = growth_accounting(prev, curr, ever_paid={"f"})
    print(acc, f"\nnet={acc.net:+.0f}  quick_ratio={acc.quick_ratio:.2f}")

Как читать результат: quick ratio 4 означает, что на каждый потерянный рубль вы приобретаете четыре. Значение около 1 — вы бегаете на месте, независимо от того, что показывает график MRR. Ниже 1 — база сжимается, и любые инвестиции в привлечение льются в дырявое ведро; правильное действие — идти в удержание, а не в маркетинг.

7.4. PLG и product-qualified leads

Product-led growth — модель, где продукт сам выполняет функции маркетинга и продаж: пользователь получает ценность до разговора с человеком. Ключевой объект здесь — PQL (product-qualified lead): не «скачал whitepaper», а «выполнил в продукте действия, статистически предсказывающие покупку».

PQL строится эмпирически: берём исторические данные, находим поведенческие признаки, разделяющие купивших и не купивших (логистическая регрессия или просто анализ пороговых значений), и получаем правило вида «команда ≥ 3 человек И ≥ 2 интеграции И ≥ 5 активных дней за 14 дней». Такое правило поднимает конверсию контакта продавца в разы по сравнению с обзвоном всех регистраций — техника оценки таких моделей разбирается в https://courses.digitable.life/post/product-management/08-analytics-and-decisions/.

Ключевое ограничение PLG: он не отменяет продажи, а меняет их момент. Сделки выше ~25 $–50k ARR практически всегда требуют человека — из-за закупочных процедур, безопасности и юристов на стороне клиента. Работающая конфигурация — PLG для входа и самообслуживания, sales-assist для расширения внутри уже проникшего аккаунта.


8. Типичные ошибки

  1. Цена назначена один раз при запуске и не пересматривалась. Продукт с тех пор вырос вдвое по ценности. Регулярный пересмотр (раз в 6–12 месяцев) — норма, а не событие.
  2. Оптимизация конверсии вместо выручки. Снижение цены всегда повышает конверсию. Метрика решения — выручка на посетителя (RPV), а лучше — контрибуция на когорту с горизонтом.
  3. Value metric выбрана из удобства учёта, а не из ценности. Считать seats проще, чем результат — и именно поэтому ставится потолок роста аккаунта.
  4. Freemium без модели окупаемости бесплатного. Бесплатный тариф должен иметь назначение: вирусность, данные, контент или канал. «Чтобы попробовали» — не назначение.
  5. Скидки как инструмент закрытия квартала. Разрушают якорь, обучают клиентов ждать конца квартала и портят предсказуемость выручки.
  6. Игнорирование involuntary churn. 20–40% оттока лечится настройкой ретраев и уведомлений об истекающих картах — работа на две недели с окупаемостью в разы.
  7. Одна цена на все сегменты. Enterprise переплатил бы, SMB не может себе позволить — вы теряете деньги на обоих концах распределения.
  8. A/B-тест цены с решением по недельной конверсии. Эффект цены живёт в оттоке на горизонте кварталов; недельный тест систематически выбирает более дешёвый вариант.
  9. Growth-хаки без цикла. Разовый всплеск регистраций, не замыкающийся в цикл, — это разовый всплеск регистраций. Проверьте: приводит ли новый пользователь следующего?
  10. Рост при quick ratio < 1. Заливать трафик в продукт, теряющий базу, — самый дорогой способ ничего не изменить.

9. Как это выглядит в проде

Прайс-план — сущность, а не поле. Цена никогда не хранится как колонка в subscriptions.price. Это отдельная версионированная сущность price_plan с датой начала действия, а подписка ссылается на конкретную версию. Иначе грандфазеринг невозможен, а любой пересчёт истории даёт неверные цифры. Такова модель у Stripe (Products and Prices API) — и она хороша именно тем, что цена иммутабельна: изменение = создание новой цены.

Каталог фич отделён от тарифов. Право доступа выражается как entitlement («может создать N проектов», «имеет SSO»), а тариф — это набор entitlements. Тогда упаковку можно менять без релиза, а исключения для конкретного клиента — без ветвлений в коде.

Витрина цен под контролем аналитики. Прайсинг-страница — часть продукта: она инструментирована событиями (просмотр тарифа, наведение на фичу, клик по «сравнить»), её конверсию считают в разрезе источника и сегмента, и на ней регулярно идут тесты формулировок и упаковки (но не самой цифры — см. §6.1).

Обязательный дашборд монетизации. Минимальный набор, который должен существовать до любых экспериментов с ценой: MRR с разложением на growth accounting, NRR/GRR по когортам, ARPU по тарифам и сегментам, распределение потребления value metric (именно распределение, а не среднее — оно почти всегда с тяжёлым хвостом), доля involuntary churn, payback по каналам.

Кто владеет ценой. В зрелых компаниях — не продакт единолично, а треугольник «продукт + финансы + продажи», с продактом как ответственным за модель и упаковку. Это медленнее, но каждое изменение цены имеет юридические и договорные последствия, которые продакт в одиночку не удержит.


10. Мини-итог

  • Цена делит созданную ценность, но не создаёт её. Растягивать «палку» можно только продуктом.
  • Value metric важнее цифры цены: цифру меняют за день, метрику — почти никогда.
  • WTP измеряют косвенно: Van Westendorp даёт диапазон, Gabor-Granger — спрос, conjoint — упаковку. Ни один метод не заменяет наблюдение за реальными платежами.
  • Максимум выручки — там, где |E| = 1; максимум прибыли — правее; в подписке оба смещаются оттоком, который цена сама же и меняет.
  • Тарифная линейка — механизм самоотбора; барьеры между тарифами обязаны быть объяснимыми.
  • Расширение выручки и лечение involuntary churn — самая дешёвая выручка в продукте.
  • Воронка масштабируется бюджетом, цикл компаундируется. Ищите, где выход становится входом.
  • Growth accounting и quick ratio показывают правду, которую агрегированный MRR прячет.

Источники


Что дальше

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

Продуктовая аналитика и принятие решений на данных

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

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

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

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