Как посчитать Multi-Touch Attribution в SQL

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

Зачем Multi-Touch

Last-touch overweights closing channels. First-touch overweights top-of-funnel. Multi-touch — все touchpoints получают часть credit, более fair.

Модели

Модель Credit
First-touch 100% первому
Last-touch 100% последнему
Linear равный для всех touches
U-shaped 40% first + 40% last + 20% middle
Time-decay exponential, recent > old
Data-driven (ML) Algorithmic — Shapley values

Linear Attribution

WITH user_touches AS (
    SELECT
        c.user_id,
        c.amount AS conversion_value,
        t.channel,
        COUNT(*) OVER (PARTITION BY c.user_id) AS total_touches
    FROM conversions c
    JOIN touchpoints t ON t.user_id = c.user_id AND t.touched_at <= c.converted_at
)
SELECT
    channel,
    SUM(conversion_value::NUMERIC / total_touches) AS attributed_revenue
FROM user_touches
GROUP BY channel
ORDER BY attributed_revenue DESC;

Каждый touch получает conversion_value / num_touches.

U-shaped

40% first + 40% last + 20% distributed middle:

WITH ranked AS (
    SELECT
        c.user_id,
        c.amount,
        t.channel,
        t.touched_at,
        ROW_NUMBER() OVER (PARTITION BY c.user_id ORDER BY t.touched_at) AS rn,
        COUNT(*) OVER (PARTITION BY c.user_id) AS total
    FROM conversions c
    JOIN touchpoints t ON t.user_id = c.user_id AND t.touched_at <= c.converted_at
),
weighted AS (
    SELECT
        user_id,
        channel,
        amount,
        rn,
        total,
        CASE
            WHEN total = 1 THEN amount
            WHEN total = 2 AND rn = 1 THEN amount * 0.5
            WHEN total = 2 AND rn = 2 THEN amount * 0.5
            WHEN rn = 1 THEN amount * 0.4
            WHEN rn = total THEN amount * 0.4
            ELSE amount * 0.2 / NULLIF(total - 2, 0)
        END AS attributed
    FROM ranked
)
SELECT channel, SUM(attributed) AS attributed_revenue
FROM weighted
GROUP BY channel
ORDER BY attributed_revenue DESC;
Закрепи формулу multi touch attribution в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать multi touch attribution в Telegram

Time-decay

Exponential, recent touches более weight:

WITH weights AS (
    SELECT
        c.user_id,
        c.amount,
        t.channel,
        c.converted_at,
        t.touched_at,
        EXP(-0.5 * EXTRACT(EPOCH FROM (c.converted_at - t.touched_at)) / 86400 / 7) AS weight
    FROM conversions c
    JOIN touchpoints t ON t.user_id = c.user_id AND t.touched_at <= c.converted_at
),
normalized AS (
    SELECT
        user_id,
        channel,
        amount,
        weight,
        weight / SUM(weight) OVER (PARTITION BY user_id) AS normalized_weight
    FROM weights
)
SELECT channel, SUM(amount * normalized_weight) AS attributed_revenue
FROM normalized
GROUP BY channel
ORDER BY attributed_revenue DESC;

EXP(-0.5 × days/7) — half-life 7 days (approximate).

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

Ошибка 1. Без lookback window. Touch 2 года назад — не influence. Cap window 30-180 days.

Ошибка 2. Same model for all conversions. B2C — time-decay. B2B — U-shaped (long cycle).

Ошибка 3. Direct excluded. Direct туч — это re-engagement или part of journey? Decision.

Ошибка 4. Не валидировать. ML-driven attribution требует validation against incrementality tests.

Ошибка 5. Compare models without context. Linear vs U-shaped give different numbers — both correct в своих assumptions.

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

FAQ

Какая модель лучше?

Зависит от business. B2C — time-decay. B2B — U-shaped (long cycle). Data-driven (ML) — most accurate but complex.

Multi-touch обязательно?

Для maturity yes. Стартап — start with first / last, потом graduate.

Lookback window?

B2C: 30-90 days. B2B: 90-365 days.

Shapley values?

Game-theory: each touchpoint's contribution based on все возможные коалиции. ML-grade.

Direct counts?

В большинстве моделей yes, но often filtered (re-engagement).