AI-мультиканальная атрибуция (Multi-Touch Attribution)
Мультиканальная атрибуция решает вопрос: какой маркетинговый канал заслуживает кредит за конверсию? От примитивного last-click до data-driven ML-атрибуции — разница в десятках процентов по оценке ROI канала и, соответственно, в миллионах бюджетных решений.
Модели атрибуции — от простых к сложным
Правиловые модели:
attribution_models = {
'last_click': 'вся ценность → последний touchpoint',
'first_click': 'вся ценность → первый touchpoint',
'linear': 'равномерное распределение между всеми touchpoints',
'time_decay': 'экспоненциально больше → ближе к конверсии',
'position_based': '40% первый + 40% последний + 20% на середину'
}
def time_decay_attribution(touchpoints, half_life_days=7):
"""
Вес ∝ exp(-decay × days_before_conversion)
"""
weights = []
for tp in touchpoints:
days_before = (conversion_date - tp['timestamp']).days
weight = np.exp(-np.log(2) / half_life_days * days_before)
weights.append(weight)
total = sum(weights)
return [w / total for w in weights]
Ограничения правиловых моделей: Arbitrary выбор правила без данных. Last-click переоценивает intent каналы (direct, brand search), недооценивает awareness (programmatic, YouTube).
Data-Driven Attribution
Shapley Value Attribution:
from itertools import combinations
def shapley_attribution(channels, conversion_rate_by_combination):
"""
Shapley value: маржинальный вклад канала усреднённый по всем коалициям
Аксиоматически справедливое распределение кредита
"""
n = len(channels)
shapley_values = {ch: 0 for ch in channels}
for ch in channels:
for r in range(n):
# Все подмножества без текущего канала размером r
others = [c for c in channels if c != ch]
for subset in combinations(others, r):
subset_without = frozenset(subset)
subset_with = frozenset(subset | {ch})
# Маржинальный вклад
marginal = (conversion_rate_by_combination.get(subset_with, 0) -
conversion_rate_by_combination.get(subset_without, 0))
# Вес коалиции
weight = (factorial(r) * factorial(n-r-1)) / factorial(n)
shapley_values[ch] += weight * marginal
return shapley_values
from math import factorial
Проблема Shapley для больших n: 2^n комбинаций — экспоненциальный взрыв. При > 15 каналах нужна аппроксимация (Monte Carlo Shapley sampling).
Markov Chain Attribution
import pandas as pd
import numpy as np
def markov_chain_attribution(paths_df):
"""
Пути: 'organic → email → paid_search → conversion'
Состояния Маркова: каждый канал + conversion + null (уход без конверсии)
Removal effect: насколько снизится CR без данного канала?
"""
# Строим матрицу переходов из путей
transition_matrix = build_transition_matrix(paths_df)
# Absorption probability для каждого начального состояния
# (вероятность достичь conversion, а не null)
absorption_probs = compute_absorption_probs(transition_matrix)
# Removal Effect: removal_effect[ch] = (base_CR - CR_without_ch) / base_CR
removal_effects = {}
base_cr = absorption_probs['conversion']
for channel in channels:
modified_matrix = remove_channel(transition_matrix, channel)
cr_without = compute_absorption_probs(modified_matrix)['conversion']
removal_effects[channel] = (base_cr - cr_without) / base_cr
# Нормализованный вклад
total_effect = sum(removal_effects.values())
attribution = {ch: re / total_effect for ch, re in removal_effects.items()}
return attribution
Cookieless Attribution
Privacy-safe методы после GDPR и Chrome без cookie:
Aggregated Measurement (Google Privacy Sandbox):
- Attribution Reports API: браузер сам агрегирует, передаёт с differential privacy noise
- Event-level reports с ограниченным битрейтом
MMM + MTA конвергенция: Комбинированный подход:
- MMM (Media Mix Modeling): верхний уровень — вклад каналов без user-level data
- MTA (Multi-Touch): lower-funnel, где data доступна (logged-in users, first-party)
- Калибровка MTA по MMM: согласование оценок
def calibrate_mta_with_mmm(mta_attribution, mmm_attribution):
"""
MTA может быть смещена из-за selection bias (logged-in users ≠ все)
MMM даёт "истинный" incremental lift
Используем MMM как prior для байесовской коррекции MTA
"""
calibration_factor = {
ch: mmm_attribution[ch] / mta_attribution.get(ch, 0.01)
for ch in mmm_attribution
}
calibrated_mta = {
ch: mta_attribution[ch] * calibration_factor.get(ch, 1.0)
for ch in mta_attribution
}
return calibrated_mta
Incrementality Testing
Geo-holdout эксперименты: Лучшая валидация атрибуции — эксперимент:
- Включаем/выключаем канал в одном регионе
- Сравниваем конверсии с control-регионом (DID, разность-в-разностях)
- Измеренный incremental effect → калибровка модели
def difference_in_differences(treatment_region, control_region, pre_period, post_period):
"""
DiD: (treatment_post - treatment_pre) - (control_post - control_pre)
"""
did = (
(treatment_region[post_period].mean() - treatment_region[pre_period].mean()) -
(control_region[post_period].mean() - control_region[pre_period].mean())
)
return did # incremental conversions due to intervention
Ghost Ads (Meta, Google): Показываем рекламу только части аудитории, другим показываем "заглушку" → истинный incremental lift.
Операционализация
Attribution Pipeline:
Raw event data (CDP / warehouse)
→ Path stitching (cross-device, cross-session)
→ Attribution model
→ Channel credit allocation
→ Reporting: attributed revenue per channel
→ Budget recommendations
Cross-device: Пользователь: телефон → ноутбук → покупка. Matching по logged-in ID или probabilistic device graph (IP + fingerprint).
Отчётность: Сравнение: last-click vs. data-driven. Обычно: upper-funnel каналы (display, YouTube, organic social) получают +20-50% вклада при переходе к data-driven.
Сроки: path stitching + Markov Chain attribution + базовые правиловые модели — 3-4 недели. Shapley Value, incrementality testing framework, MMM калибровка, cookieless-адаптация — 2-3 месяца.







