LTV, CAC, ROI, ROMI и CPL в Битрикс24: формулы и SQL-примеры

LTV, CAC, ROI, ROMI и CPL в Битрикс24: формулы и SQL-примеры

Обновлено 3 сентября 2026 года.

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

Главная задача — согласовать определения. Лид, успешная сделка, новый покупатель и платёж — разные события. Если считать их взаимозаменяемыми, даже технически корректный SQL выдаст неверную бизнес-метрику.

Что означают LTV, CAC, ROI, ROMI и CPL

Метрика Базовый расчёт Что нужно определить
CPL Затраты на получение лидов / число лидов Что считается лидом, исключаются ли спам и дубли, какой состав затрат
CAC Затраты на привлечение / число новых клиентов Первое приобретение, полная стоимость маркетинга и продаж, временное соответствие
LTV Ценность отношений с клиентом на выбранной основе Выручка или маржа, наблюдаемый горизонт или прогноз, единица клиента
ROI Чистый результат инвестиции / затраты на инвестицию Какие результаты и затраты относятся к проекту и за какой срок
ROMI (Маржинальный результат маркетинга до его затрат − маркетинговые затраты) / маркетинговые затраты Состав маржи, атрибуция или дополнительный эффект, состав бюджета

Проценты получают умножением коэффициента на 100. Если знаменатель равен нулю или данных о нём нет, показатель не определён. Это следует показывать отдельно, а не заменять нулём или «бесконечной эффективностью».

Какие данные взять из Битрикс24

У CRM есть несколько интерфейсов доступа: REST API, наборы BI Конструктора и физическая база коробочной версии. Их таблицы и поля не являются одной схемой. Название b_crm_deal относится к физической базе; crm_deal в документации BI — аналитический набор. SQL для подготовленной PostgreSQL-витрины не обязательно выполнится в BI Конструкторе.

Справочники полей своего портала можно получить через crm.deal.fields и crm.lead.fields либо соответствующий интерфейс выбранного способа выгрузки. В примерах ниже используются собственные учебные таблицы.

Данные Для чего нужны Что легко перепутать
Лид: ID, дата, источник, статус Объём и качество обращений Конвертация лида не подтверждает получение денег
Сделка: ID, стадия, воронка, сумма, валюта Результат продаж по правилам CRM OPPORTUNITY — сумма карточки, а не гарантированная учётная выручка
Контакт или компания Канонический ключ бизнес-клиента Контактное лицо и организация могут относиться к одной покупке
История стадий Момент перехода, повторное открытие, длительность обработки Текущая стадия не описывает всю прошлую историю
Оплаты, возвраты, признанная выручка Финансовый результат выбранного типа Платёж и выручка могут относиться к разным датам
Маркетинговые и коммерческие затраты CPL, CAC и окупаемость Расход рекламного кабинета не охватывает все затраты привлечения

Коды успешных стадий зависят от воронки. Универсальное условие STAGE_ID = ‘WON’ пропустит часть сделок. В наборе BI crm_deal доступен STAGE_SEMANTIC_ID: S — успех, F — неуспех, P — работа. Для другого интерфейса получите его справочник и соответствие стадий. У лида есть собственная семантика статусов; её нельзя подменять стадиями сделки.

Особенно важно поле CLOSEDATE. В документации наборов сделок оно описано как планируемая дата закрытия. Фактический переход на стадию отражает DATE_CREATE записи истории crm_deal_stage_history. START_DATE и END_DATE там связаны с датами сделки и не являются универсальными фактическими границами пребывания на стадии. Для периода оплат используйте дату финансовой операции, для закрытий — выбранное событие истории.

Не объединяйте все записи без клиента в одного «клиента NULL». Для B2B чаще выбирают компанию, для B2C — контакт или ID покупателя в учётной системе. Это бизнес-правило, а не простая замена одного столбца другим. Если сделка связана с несколькими контактами, её сумму нельзя целиком начислить каждому контакту.

Источник WEB в CRM не означает органический поиск: это может быть общее обращение с сайта. Связь с рекламными кампаниями требует отдельного сопоставления источников, UTM и идентификаторов кабинета. Зафиксируйте модель атрибуции и сохраните категорию обращений без определённого канала.

CPL: сначала бюджет, затем деление на лиды

Для CPL нужно одинаково считать обращения в числителе и знаменателе отчёта. Например, рекламные расходы можно делить на все принятые лиды либо только на квалифицированные; во втором случае показатель следует назвать стоимостью квалифицированного лида. Спам и технические повторы обрабатывают по единому правилу.

Пример: 12 000 ₽ расходов и 24 принятых лида дают CPL 500 ₽. Если 8 из них квалифицированы, стоимость квалифицированного лида — 1 500 ₽. Оба расчёта верны, но отвечают на разные вопросы.

При JOIN бюджета к каждому лиду одна сумма повторяется. Для бюджета 900 ₽ и трёх лидов SUM(cost) / COUNT(*) после такого соединения даст 900 ₽ вместо правильных 300 ₽. Сначала агрегируйте расходы и лиды отдельно до одного и того же разреза, затем делите суммы.

CAC: новые покупатели по всей доступной истории

CAC включает согласованные затраты на маркетинг и продажи, связанные с привлечением новых клиентов. Помимо рекламы это могут быть производство контента, агентские услуги, зарплаты и комиссии соответствующей команды, инструменты привлечения. Распределение общих затрат по каналам должно быть явным. Такой подход описан, например, в руководстве Stripe по CAC.

Новым клиентом не следует автоматически считать новый контакт, новый лид или каждую выигранную сделку. Сначала определите первую покупку клиента по всей доступной истории. Затем выберите тех, у кого она попала в период. Если сначала отфильтровать сделки за август, июньский покупатель с повторным августовским заказом ошибочно станет «новым».

Читай также:  Битрикс24 «Невесомость»: интерфейс «Зефир» и проверенный обзор релиза 2025 года

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

Месячный CAC по затратам и первым покупкам этого месяца — операционный показатель периода. При длинном цикле продаж он не равен окупаемости рекламной когорты: часть расходов текущего месяца даст клиентов позже. Для когортного расчёта связывают расходы с привлечёнными обращениями и наблюдают их результат на одинаковом горизонте.

Рабочий SQL-пример CPL и CAC

Ниже самостоятельный пример PostgreSQL на вымышленных данных. purchases — уже проверенные покупки, а не строки сырых платежей или любые сделки. Одна покупка входит один раз; source первой покупки содержит заранее определённый канал привлечения. Все суммы — рубли, часовой пояс периода — UTC+3. Расходы содержат распределённые затраты маркетинга и продаж, относящиеся к привлечению.

Запрос ищет первую покупку до фильтра по месяцу, агрегирует каждый набор отдельно и сохраняет все каналы через общее множество. Отсутствующий расход остаётся NULL; явно записанный нулевой расход остаётся нулём.

WITH bounds AS (
  SELECT TIMESTAMPTZ '2026-08-01 00:00+03' AS date_from,
         TIMESTAMPTZ '2026-09-01 00:00+03' AS date_to
), costs(day, source, marketing_cost, sales_cost) AS (
  VALUES
    (DATE '2026-08-01', 'yandex', 500::numeric, 100::numeric),
    (DATE '2026-08-10', 'yandex', 400, 200),
    (DATE '2026-08-01', 'organic', 200, 100),
    (DATE '2026-08-01', 'email', 0, 100),
    (DATE '2026-08-01', 'display', 300, 0)
), leads(id, source, created_at) AS (
  VALUES
    (1, 'yandex', TIMESTAMPTZ '2026-08-01 10:00+03'),
    (2, 'yandex', TIMESTAMPTZ '2026-08-02 10:00+03'),
    (3, 'yandex', TIMESTAMPTZ '2026-08-03 10:00+03'),
    (4, 'organic', TIMESTAMPTZ '2026-08-05 10:00+03'),
    (5, 'email', TIMESTAMPTZ '2026-08-20 10:00+03'),
    (6, 'email', TIMESTAMPTZ '2026-08-31 23:59+03'),
    (7, 'yandex', TIMESTAMPTZ '2026-07-31 23:59+03'),
    (8, 'yandex', TIMESTAMPTZ '2026-09-01 00:00+03'),
    (9, 'affiliate', TIMESTAMPTZ '2026-08-15 10:00+03')
), purchases(id, customer_id, source, paid_at) AS (
  VALUES
    (1, 1, 'yandex', TIMESTAMPTZ '2026-06-15 10:00+03'),
    (2, 1, 'yandex', TIMESTAMPTZ '2026-08-05 10:00+03'),
    (3, 2, 'yandex', TIMESTAMPTZ '2026-08-04 10:00+03'),
    (4, 2, 'yandex', TIMESTAMPTZ '2026-08-06 10:00+03'),
    (5, 3, 'organic', TIMESTAMPTZ '2026-08-10 10:00+03'),
    (6, 4, 'email', TIMESTAMPTZ '2026-08-20 10:00+03'),
    (7, 5, 'yandex', TIMESTAMPTZ '2026-09-01 10:00+03'),
    (8, 6, 'yandex', TIMESTAMPTZ '2026-07-31 23:30+03'),
    (9, 7, 'email', TIMESTAMPTZ '2026-08-31 23:59+03'),
    (10, NULL, 'yandex', TIMESTAMPTZ '2026-08-15 10:00+03'),
    (11, 8, 'affiliate', TIMESTAMPTZ '2026-08-15 10:00+03')
), first_purchase AS (
  SELECT DISTINCT ON (customer_id)
         customer_id, source, paid_at
  FROM purchases
  WHERE customer_id IS NOT NULL
  ORDER BY customer_id, paid_at, id
), cost_totals AS (
  SELECT source, SUM(marketing_cost) AS marketing_cost,
         SUM(sales_cost) AS sales_cost
  FROM costs
  WHERE day >= DATE '2026-08-01' AND day < DATE '2026-09-01'
  GROUP BY source
), lead_totals AS (
  SELECT source, COUNT(*) AS leads
  FROM leads CROSS JOIN bounds
  WHERE created_at >= date_from AND created_at < date_to
  GROUP BY source
), customer_totals AS (
  SELECT source, COUNT(*) AS new_customers
  FROM first_purchase CROSS JOIN bounds
  WHERE paid_at >= date_from AND paid_at < date_to
  GROUP BY source
), channels AS (
  SELECT source FROM cost_totals
  UNION SELECT source FROM lead_totals
  UNION SELECT source FROM customer_totals
)
SELECT c.source, ct.marketing_cost, ct.sales_cost,
       COALESCE(lt.leads, 0) AS leads,
       COALESCE(nt.new_customers, 0) AS new_customers,
       ROUND(ct.marketing_cost / NULLIF(lt.leads, 0), 2) AS cpl,
       ROUND((ct.marketing_cost + ct.sales_cost)
             / NULLIF(nt.new_customers, 0), 2) AS cac
FROM channels c
LEFT JOIN cost_totals ct USING (source)
LEFT JOIN lead_totals lt USING (source)
LEFT JOIN customer_totals nt USING (source)
ORDER BY c.source;
Канал Маркетинг Продажи Лиды Новые клиенты CPL CAC
affiliate Нет данных Нет данных 1 1 Не определён Не определён
display 300 0 0 0 Не определён Не определён
email 0 100 2 2 0 50
organic 200 100 1 1 200 300
yandex 900 300 3 1 300 1 200

У yandex есть повторная покупка прежнего клиента и две покупки одного нового клиента, но новый клиент считается один раз. Августовские границы включают 31 августа целиком и исключают 1 сентября. Запись без customer_id не участвует в числе новых клиентов и должна попасть в контроль качества.

Результат проверен выполнением этого SQL на учебных VALUES. Для рабочей выгрузки нужны ещё уникальные ключи, полный список источников, контроль полноты расходов и дедупликация. Пример не обращается к физическим таблицам Битрикс24 и не заменяет подготовку данных.

LTV: разделите наблюдаемый результат и прогноз

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

Для начала удобно считать наблюдаемый результат за фиксированное время после первой покупки. Например: «маржинальный доход на клиента за 90 дней». Суммируйте результат каждого клиента за его первые 90 дней, затем разделите на всех клиентов подходящей когорты. Включайте и тех, кто больше не покупал; иначе среднее будет завышено.

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

Учебный пример: три клиента полностью наблюдались 90 дней. Их выручка после возвратов — 10 000, 6 000 и 0 ₽; маржинальный доход до привлечения — 4 000, 2 000 и 0 ₽. Средняя выручка за этот горизонт — 5 333,33 ₽, средний маржинальный доход — 2 000 ₽. Это два разных показателя.

Читай также:  BI Data 2.0.4: архивный анонс обновления коннектора

Если CAC этой когорты равен 2 500 ₽, выручка выше CAC ещё не доказывает окупаемость. За наблюдаемые 90 дней маржинальный доход не покрыл привлечение. Возможно, клиент принесёт доход позже, но это прогноз, для которого нужны основания.

Для LTV/CAC используйте сопоставимые величины. Если LTV уже рассчитан после вычета CAC, повторное сравнение или вычитание может учесть привлечение дважды. Укажите, что именно включено. Отношение 3:1 может быть рабочим ориентиром конкретного бизнеса, но не гарантирует прибыль, ликвидность и приемлемый срок возврата затрат.

Возвраты и отмены нужно относить по согласованному правилу. Частичный возврат не означает, что следует удалить всю покупку. Полный возврат также может оставить расходы на обработку и доставку. Не подменяйте отсутствующую себестоимость произвольной «средней маржой 50%», если это не явно подписанный сценарный расчёт.

ROI, ROMI и ROAS: разные числители и знаменатели

Для ROI важно определить инвестицию и её чистый результат. Если затраты проекта составили 100 000 ₽, а поступивший результат до вычета этих затрат — 250 000 ₽, чистый результат равен 150 000 ₽, ROI — 150%. Это не 50%: на вложенный рубль получено 1,5 рубля результата сверх возврата самого рубля.

В рекламной аналитике нельзя считать чистой прибылью всю сумму сделок минус рекламный бюджет. Нужно учесть расходы, относящиеся к продажам и проекту. Например, пояснение ROI в Google Ads показывает расчёт с учётом производства и рекламы.

Для сравнения маркетинга здесь используем управленческую формулу ROMI: из маржинального результата до маркетинга вычитаем маркетинговые затраты и делим на них. Состав маржи фиксируется отдельно. Если результат лишь приписан каналу моделью атрибуции, называйте его атрибутированным: это не доказанный прирост, вызванный рекламой.

Учебные данные Канал A Канал B
Выручка 500 000 ₽ 150 000 ₽
Затраты на выполнение продаж 300 000 ₽ 90 000 ₽
Маржинальный результат до маркетинга 200 000 ₽ 60 000 ₽
Маркетинговые затраты 100 000 ₽ 200 000 ₽
ROMI (200 000 − 100 000) / 100 000 = 100% (60 000 − 200 000) / 200 000 = −70%
Выручка / маркетинговые затраты 5 0,75

Последнюю строку можно назвать ROAS, если в знаменателе именно рекламные затраты. Если туда включены все расходы маркетинга, подпишите более широкий состав. ROAS показывает отношение выручки к расходу, но не прибыль.

Для формулы (результат − затраты) / затраты точка окупаемости — 0%. Положительные 50% не являются убытком из-за того, что они меньше 100%. Отдельно учитывайте постоянные расходы, налоги и другие статьи, если выбранная маржа их не включает: положительный ROMI не тождественен чистой прибыли всей компании.

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

Как не исказить показатели в BI

  • Суммируйте числители и знаменатели отдельно. Общий CPL — общие затраты / общее число лидов, а не среднее CPL каналов. Для 100 ₽ и 2 лидов, 900 ₽ и 3 лидов общий CPL равен 200 ₽; среднее двух CPL дало бы неверные 175 ₽.
  • Отделяйте отсутствие данных от нуля. Пропущенный бюджет не означает бесплатный канал. Нулевые продажи при полном учёте — другое состояние.
  • Не размножайте суммы соединениями. Товарные строки, контакты, платежи и рекламные расходы могут образовать связь многие-ко-многим. До объединения определите детализацию каждого набора.
  • Не смешивайте даты. Создание лида, фактическая стадия, оплата и признание выручки формируют разные периоды отчёта.
  • Пересчитывайте отношение после фильтров. Фильтр по каналу должен одинаково ограничивать соответствующие факты затрат и результата.
  • Показывайте свежесть и полноту. Обновление страницы дашборда не загружает автоматически недостающие CRM-данные или расходы.

Для руководителя достаточно начать с таблицы по каналам: затраты, лиды, квалифицированные лиды, новые клиенты, результат за горизонт, CPL, CAC и окупаемость с точным названием. Рядом укажите период, модель атрибуции и долю записей без клиента или источника.

Проверка перед использованием для бюджета

  1. Сверьте число исходных объектов и операций с выбранным интерфейсом CRM и учётной системой.
  2. Проверьте несколько клиентов с повторными покупками, несколькими контактами, возвратами и объединёнными дублями.
  3. Убедитесь, что расходы после всех соединений совпадают с исходными суммами и что их состав явно указан.
  4. Проверьте последний день периода, часовой пояс и будущие операции.
  5. Сохраните каналы без продаж и записи без сопоставления; объясните причины NULL.
  6. Зафиксируйте формулы и владельца показателей, чтобы следующая выгрузка считалась по тем же правилам.

Метрики помогают выбрать, что исследовать дальше. Высокий CAC может сопровождаться долгим циклом сделки или более дорогим сегментом; низкий LTV — коротким наблюдением; высокий ROMI — небольшой выборкой. Решение об изменении бюджета должно учитывать эти условия и возможность воспроизвести результат при увеличении расходов.