Как посчитать Last-Touch Attribution в SQL
payments(user_id) и refunds(user_id). Нужно получить пользователей, у которых был платёж, но не было ни одного возврата. Какой запрос корректнее всего описывает задачу?Содержание:
Зачем Last-Touch
Last-touch — самая распространённая модель атрибуции: вся заслуга за конверсию отдаётся последнему каналу в пути пользователя. Это дефолт в Google Ads и Яндекс Метрике, потому что модель проста, понятна бизнесу и легко считается одним запросом.
У простоты есть цена: last-touch переоценивает каналы, которые закрывают сделку (ретаргетинг, брендовый и платный поиск по бренду), и недооценивает верх воронки — SEO, органику, контент, которые вообще привели человека. Поэтому на собесе маркетинг-аналитика её любят как отправную точку, но ждут, что вы назовёте ограничения и упомянете multi-touch как более честную альтернативу.
Формула
Last-Touch: последний канал в пути пользователя получает всю заслугу за конверсиюИдея в одном предложении: берём все касания пользователя до момента конверсии, сортируем по времени и приписываем конверсию тому каналу, что был последним. Ключевое ограничение — учитывать только касания, которые произошли до конверсии.
Базовый расчёт
Исходные данные: touchpoints(user_id, channel, touched_at) — касания пользователя с каналами, и conversions(user_id, amount, converted_at) — сами конверсии с суммой.
WITH last_touch AS (
SELECT
c.user_id,
c.amount,
c.converted_at,
(
SELECT channel
FROM touchpoints t
WHERE t.user_id = c.user_id
AND t.touched_at <= c.converted_at
ORDER BY t.touched_at DESC
LIMIT 1
) AS last_channel
FROM conversions c
)
SELECT
last_channel,
COUNT(*) AS conversions,
SUM(amount) AS attributed_revenue
FROM last_touch
GROUP BY last_channel
ORDER BY attributed_revenue DESC;Здесь коррелированный подзапрос для каждой конверсии находит последнее касание до её момента (ORDER BY touched_at DESC LIMIT 1). Затем группируем по каналу и суммируем выручку, которую этот канал «закрыл».
По каналам
Тот же результат можно получить через оконную функцию — часто это читается чище и лучше оптимизируется:
WITH last_touch AS (
SELECT
c.user_id,
c.amount,
FIRST_VALUE(t.channel) OVER (
PARTITION BY c.user_id
ORDER BY t.touched_at DESC
) AS last_channel
FROM conversions c
JOIN touchpoints t ON t.user_id = c.user_id AND t.touched_at <= c.converted_at
)
SELECT
last_channel,
COUNT(DISTINCT user_id) AS conversions,
SUM(amount) AS revenue
FROM last_touch
GROUP BY last_channel
ORDER BY revenue DESC;FIRST_VALUE(...) OVER (PARTITION BY user_id ORDER BY touched_at DESC) для каждого пользователя берёт первый в порядке убывания времени канал, то есть самое позднее касание. JOIN с условием touched_at <= converted_at отсекает касания, случившиеся уже после конверсии.
Плюсы и минусы
| Плюсы | Минусы |
|---|---|
| Легко считать одним запросом | Переоценивает низ воронки |
| Дефолт в большинстве платформ | Недооценивает органику и SEO |
| Стабильный и воспроизводимый результат | Игнорирует ассистирующие касания |
| Прямая измеримость по последнему клику | Не показывает весь путь пользователя |
Частые ошибки
Учитывать касания после конверсии. В окно должны попадать только касания до момента конверсии, иначе канал, «догнавший» уже купившего пользователя, получит чужую заслугу.
Считать direct за полноценное касание. Если пользователь пришёл напрямую, это last-touch или просто узнаваемость бренда? Часто direct исключают из атрибуции — это бизнес-решение, которое нужно проговорить.
Игнорировать окно атрибуции (lookback window). Касание месячной давности и касание двухлетней давности нельзя считать одинаково значимыми — задайте разумное окно (обычно 30–90 дней) и отсекайте всё старше.
Не определиться с несколькими конверсиями. Если пользователь совершил пять покупок, засчитывать last-touch к первой конверсии или к каждой? Ответ зависит от вопроса бизнеса — важно зафиксировать логику явно.
Не сравнивать first и last. Если первое и последнее касание совпадают — это single-touch путь, когда человек пришёл и сразу купил. Доля таких путей — полезный сигнал о зрелости воронки.
Связанные темы
- Как посчитать First-Touch Attribution в SQL
- Как посчитать ROAS в SQL
- Как посчитать CAC в SQL
- Как посчитать funnel в SQL
FAQ
Last-Touch — это стандарт?
Да, это дефолтная модель в большинстве рекламных платформ (Google Ads, Яндекс Метрика). Её выбирают за простоту и понятность: легко объяснить бизнесу и легко посчитать. Но как единственную модель её лучше не использовать.
В чём главные минусы Last-Touch?
Она переоценивает каналы, закрывающие сделку — ретаргетинг, брендовый и платный поиск по бренду, — и недооценивает верх воронки: SEO, органику, контент, которые привели пользователя. То есть заслуга достаётся тому, кто «дожал», а не тому, кто привёл.
Когда Last-Touch уместна?
Для транзакционных бизнесов с коротким циклом принятия решения — e-commerce, мобильные игры, импульсные покупки. Там путь короткий, и последнее касание действительно близко к решению. Для B2B и дорогих покупок с длинным циклом last-touch сильно искажает картину.
Last-Touch или multi-touch?
Multi-touch (linear, time-decay, U-shaped) честнее: он делит заслугу между всеми касаниями. Но он сложнее в расчёте и зависит от выбранной модели. Last-touch остаётся простым baseline, с которого удобно начинать, а затем сравнивать с multi-touch.
Считать ли direct за Last-Touch?
Зависит от бизнес-логики. Часто direct исключают: пользователь вернулся напрямую, потому что бренд уже создал узнаваемость раньше, а не потому что «прямой заход» его убедил. Решение нужно зафиксировать явно и применять его последовательно.