Как посчитать ROAS в SQL

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

Зачем ROAS

Маркетинг каждую неделю отчитывается: «потратили 1 млн на рекламу, принесли 4 млн revenue». Звучит хорошо. Но ROAS 4 для нового бренда — это хорошо, а для зрелого e-commerce с маржой 15% — провал (margin от 4 млн = 600 тыс., минус 1 млн на трафик = -400 тыс. убыток).

Аналитика просят: «ROAS по каналам», «ROAS Performance Max vs Search», «ROAS на 7-day vs 30-day window». В статье — SQL и нюансы (атрибуция, return-window, ROAS ≠ ROI).

Формула ROAS

ROAS = Revenue from ads / Ad spend

ROAS = 4 значит «1 рубль рекламы вернул 4 рубля выручки». ROAS = 1 — точка break-even (по выручке, не по марже).

Часто ROAS выражают коэффициентом (4.0) или процентом (400%). Это одно и то же.

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

Данные: ad_spend(date, channel, spend), attributed_revenue(date, channel, revenue).

WITH spend AS (
    SELECT channel, SUM(spend) AS total_spend
    FROM ad_spend
    WHERE DATE >= '2026-04-01' AND DATE < '2026-05-01'
    GROUP BY channel
),
revenue AS (
    SELECT channel, SUM(revenue) AS total_revenue
    FROM attributed_revenue
    WHERE DATE >= '2026-04-01' AND DATE < '2026-05-01'
    GROUP BY channel
)
SELECT
    s.channel,
    s.total_spend,
    r.total_revenue,
    r.total_revenue::NUMERIC / NULLIF(s.total_spend, 0) AS roas
FROM spend s
JOIN revenue r ON r.channel = s.channel
ORDER BY roas DESC;

Важно: агрегировать каждую сторону отдельно, потом join. JOIN до агрегации может умножить строки.

ROAS по каналам и кампаниям

WITH spend AS (
    SELECT channel, campaign, SUM(spend) AS spend_amt
    FROM ad_spend
    WHERE DATE >= CURRENT_DATE - INTERVAL '30 days'
    GROUP BY channel, campaign
),
rev AS (
    SELECT channel, campaign, SUM(revenue) AS revenue_amt
    FROM attributed_revenue
    WHERE DATE >= CURRENT_DATE - INTERVAL '30 days'
    GROUP BY channel, campaign
)
SELECT
    COALESCE(s.channel, r.channel) AS channel,
    COALESCE(s.campaign, r.campaign) AS campaign,
    s.spend_amt,
    r.revenue_amt,
    r.revenue_amt::NUMERIC / NULLIF(s.spend_amt, 0) AS roas
FROM spend s
FULL OUTER JOIN rev r
  ON r.channel = s.channel AND r.campaign = s.campaign
ORDER BY roas DESC NULLS LAST;

FULL OUTER JOIN показывает кампании с тратами но без revenue (плохие) и наоборот (атрибуционные баги).

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

Return-window и атрибуция

ROAS зависит от окна атрибуции. Купил через 2 дня после клика — это «привлёк маркетинг». Через 60 дней — спорно.

7-day attribution window

WITH ad_clicks AS (
    SELECT user_id, channel, campaign, click_date
    FROM ad_events
    WHERE event_type = 'click'
),
purchases AS (
    SELECT user_id, total, purchase_date
    FROM orders
    WHERE status = 'paid'
)
SELECT
    c.channel,
    c.campaign,
    SUM(p.total) AS attributed_revenue_7d
FROM ad_clicks c
JOIN purchases p
  ON p.user_id = c.user_id
 AND p.purchase_date >= c.click_date
 AND p.purchase_date <  c.click_date + INTERVAL '7 days'
GROUP BY c.channel, c.campaign;

Last-click vs first-click

Last-click: считаем покупку каналу последнего клика. Самая частая модель — но завышает ретаргетинг.

WITH last_click AS (
    SELECT
        user_id,
        channel,
        click_date,
        ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY click_date DESC) AS rn
    FROM ad_events
    WHERE event_type = 'click'
)
SELECT
    lc.channel,
    SUM(o.total) AS revenue
FROM orders o
JOIN last_click lc ON lc.user_id = o.user_id AND lc.rn = 1
WHERE o.status = 'paid'
GROUP BY lc.channel;

First-click оценивает «топ воронки», linear / time-decay — компромиссы.

ROAS vs ROI vs MER

Метрика Формула Что показывает
ROAS revenue / ad spend возврат выручки на каждый рубль рекламы
ROI (revenue × margin - spend) / spend прибыль на каждый рубль (с учётом маржи)
MER (Marketing Efficiency Ratio) total revenue / total marketing spend общая эффективность маркетинга

ROAS 4 при марже 20% — это ROI = (4 × 0,2 - 1) / 1 = -20%, убыток. ROAS — выручка, ROI — прибыль.

MER считает по всей выручке (включая органику), удобен для оценки всего маркетинга, а не одного канала.

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

Ошибка 1. ROAS без учёта маржи

«ROAS 4 — отлично!» Если маржа 15%, это убыток. Всегда показывайте бизнесу ROAS + margin, или конвертируйте в ROI.

Ошибка 2. JOIN до агрегации

Если у канала 100 клика и 30 покупок, и сделаешь JOIN до агрегации — получишь 100×30 = 3000 строк, SUM умножен. Сначала агрегаты, потом JOIN — см. базовый пример.

Ошибка 3. NULL revenue для каналов с тратами

Кампания запущена, потратила деньги, но ни одной покупки. INNER JOIN потеряет её. Используйте FULL OUTER JOIN + COALESCE(revenue, 0) для честного среднего.

Ошибка 4. Не учитывать return-window

Сравнение ROAS Google Ads (7d) vs Facebook (28d) — некорректно. Зафиксируйте window для всех каналов.

Ошибка 5. Дабл-каунт revenue

Если один заказ атрибутирован двум кампаниям — revenue считается дважды. Решение: дедупликация по user_id × order_id, или использование одной модели атрибуции на отчёт.

Ошибка 6. Считать ROAS = 1 как break-even

Это break-even по выручке, но не по прибыли. Для маржи 30% break-even ROAS = 1/0,3 ≈ 3,3.

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

FAQ

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

Зависит от маржи. Если маржа 20% — break-even ROAS = 5, цель ROAS 8-10. Маржа 50% — break-even ROAS = 2, цель 3-4. Просите данные о марже у финансистов.

ROAS у новых vs повторных покупателей одинаков?

Нет. Повторные — обычно сильно выше, но они и так бы купили. Считайте ROAS на новых пользователях (new customer ROAS) — это «честная» метрика рекламы.

Как мерить ROAS в B2B с долгим циклом сделки?

Стандартный ROAS не работает — клик в январе, сделка в июне. Считают pipeline ROAS (по сумме открытых сделок) или используют длинное окно (90-180 дней) с проверкой через когорты.

ROAS в реальном времени или с задержкой?

С задержкой 24-48 часов (атрибуция «дозревает» — конверсии приходят после кликов). Real-time дашборды показывают направление тренда, а не финальные числа.

Что такое target ROAS в Google Ads?

Автоматическая стратегия: алгоритм оптимизирует ставки так, чтобы среднее ROAS было ≥ заданного. Работает только при достаточном объёме конверсий (50+ в месяц по кампании).