Prooflytics + Criteo: атрибуция ретаргетинга до закрытой B2B-сделки

Criteo - крупнейшая платформа ретаргетинга и performance рекламы. B2B SaaS компании используют Criteo для возврата посетителей сайта, которые не конвертировались при первом визите. Стандартная метрика Criteo - конверсии и ROAS. Проблема: Criteo считает конверсией любое целевое действие на сайте (заполнение формы, регистрация), но не закрытую B2B-сделку. Реальный вопрос - сколько CLOSED DEALS принесла кампания Criteo и каков CAC. Prooflytics замыкает этот разрыв.

Criteo работает по модели first-party data: браузерный скрипт Criteo (OneTag) собирает события, Criteo Shopper Graph строит аудитории для ретаргетинга. В B2B ретаргетинг наиболее эффективен когда посетитель изучал pricing или features - это High Intent сигнал. Но даже при правильных аудиториях без замыкания на CRM-сделку невозможно понять, какие кампании реально конвертируются в revenue.

Criteo Events API (Server-side) - позволяет отправлять конверсионные события напрямую с сервера, минуя ad-blocker. Complementary к OneTag (браузерный скрипт).

Механизм атрибуции Criteo

Criteo использует cookie criteo_write и click ID в параметре cto_bundle (или gclid-подобный параметр cto_pld). При клике на объявление:

  1. Criteo устанавливает cookie с информацией о клике
  2. В URL landing page добавляется параметр (в зависимости от настройки)

gum_caller_id - Criteo’s Universal Matching - более надёжный механизм: пользователь идентифицируется через email hash (User ID matching), не только по cookie.

Архитектура Prooflytics + Criteo

Клиент кликает на Criteo рекламу
  -> Landing page: OneTag (браузерный) фиксирует клик
  -> Prooflytics JS фиксирует Criteo click cookie + email при регистрации

Prooflytics backend
  -> Сохранить attribution: {email -> criteo_click_data, timestamp}

Когда лид регистрируется в CRM (HubSpot/Kommo)
  -> Prooflytics обогащает лид атрибуцией Criteo

Когда сделка закрыта (CRM webhook: closed_won)
  -> Prooflytics отправляет конверсию в Criteo Events API
  -> Рассчитывает CAC: Criteo spend / closed deals

Реализация: захват Criteo атрибуции на стороне клиента

Prooflytics JS (встраивается на сайт рядом с Criteo OneTag):

(function() {
  var PROOFLYTICS_KEY = 'YOUR_PROOFLYTICS_KEY';
  var API_BASE = 'https://api.prooflytics.io/v1';

  // Получить Criteo user ID из cookie criteo_write или URL параметра
  function getCriteoData() {
    var criteoId = null;

    // Метод 1: из URL параметра cto_pld (click payload)
    var urlParams = new URLSearchParams(window.location.search);
    var ctoPld = urlParams.get('cto_pld');
    if (ctoPld) {
      criteoId = ctoPld;
      sessionStorage.setItem('prooflytics_criteo_id', ctoPld);
      sessionStorage.setItem('prooflytics_criteo_ts', Date.now().toString());
    }

    // Метод 2: из sessionStorage (если пользователь уже кликнул в этой сессии)
    if (!criteoId) {
      criteoId = sessionStorage.getItem('prooflytics_criteo_id');
    }

    return criteoId;
  }

  // При успешной регистрации/входе - отправить attribution
  window.prooflyticsTrackCriteo = function(email) {
    var criteoId = getCriteoData();
    if (!criteoId || !email) return;

    var payload = {
      email:      email,
      criteo_id:  criteoId,
      page_url:   window.location.href,
      referrer:   document.referrer,
    };

    navigator.sendBeacon(
      API_BASE + '/attribution/criteo',
      JSON.stringify(Object.assign({}, payload, {api_key: PROOFLYTICS_KEY}))
    );
  };
})();

Вызывать window.prooflyticsTrackCriteo(email) после успешной регистрации/входа пользователя.

Реализация: сервер Prooflytics - получение и хранение атрибуции

import requests, time, os
from flask import Flask, request, jsonify

app = Flask(__name__)
CRITEO_PARTNER_ID    = os.environ["CRITEO_PARTNER_ID"]
CRITEO_CLIENT_ID     = os.environ["CRITEO_CLIENT_ID"]
CRITEO_CLIENT_SECRET = os.environ["CRITEO_CLIENT_SECRET"]

@app.route("/v1/attribution/criteo", methods=["POST"])
def receive_criteo_attribution():
    data     = request.json or {}
    email    = data.get("email", "")
    criteo_id = data.get("criteo_id", "")

    if not email or not criteo_id:
        return jsonify({"error": "missing fields"}), 400

    # Сохранить атрибуцию: email -> criteo_id
    record = {
        "email":      email,
        "criteo_id":  criteo_id,
        "page_url":   data.get("page_url", ""),
        "received_at": int(time.time()),
    }
    db.upsert("criteo_attribution", record, key="email")
    return jsonify({"status": "ok"}), 200

Реализация: отправка конверсии в Criteo Events API при закрытии сделки

def get_criteo_token() -> str:
    r = requests.post(
        "https://api.criteo.com/oauth2/token",
        json={
            "client_id":     CRITEO_CLIENT_ID,
            "client_secret": CRITEO_CLIENT_SECRET,
            "grant_type":    "client_credentials",
        }
    )
    return r.json()["access_token"]

def send_criteo_conversion(email: str, deal_value: float, deal_id: str):
    attr = db.get("criteo_attribution", email=email)
    if not attr:
        return  # нет атрибуции Criteo для этого пользователя

    token = get_criteo_token()

    event = {
        "id":           deal_id,
        "channel":      "web",
        "timestamp":    time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
        "eventType":    "transactionConfirmation",
        "currency":     "USD",
        "products":     [{"id": "b2b_deal", "price": deal_value, "quantity": 1}],
        "user": {
            "email": email,
        },
    }

    requests.post(
        "https://api.criteo.com/2024-07/events/confirm",
        headers={
            "Authorization": f"Bearer {token}",
            "Content-Type":  "application/json",
            "Criteo-Partner-Id": str(CRITEO_PARTNER_ID),
        },
        json={"events": [event]},
        timeout=10,
    )

# CRM webhook handler: deal closed_won
@app.route("/crm/deal-won", methods=["POST"])
def deal_won():
    data     = request.json or {}
    email    = data.get("contact_email", "")
    deal_id  = data.get("deal_id", "")
    value    = float(data.get("deal_value", 0))

    if email:
        send_criteo_conversion(email, value, deal_id)
    return jsonify({"status": "ok"}), 200

Что видит маркетолог в Prooflytics

После настройки в дашборде Prooflytics:

  • Criteo кампании по CAC: кампания ретаргетинга pricing -> $1 240 CAC, кампания ретаргетинга features -> $890 CAC
  • Assist attribution: Criteo часто участвует как assist (не first touch, не last touch) в пути клиента
  • Funnel: click -> registration -> qualified lead -> closed deal по каждой кампании
  • ROAS реальный: выручка из закрытых сделок / Criteo spend

Реальный кейс

B2B SaaS, бюджет $8 000/месяц на Criteo ретаргетинг. Criteo Dashboard показывал ROAS 4.2x (по атрибуции конверсий на сайте). После интеграции с Prooflytics выяснилось: из 340 form-fills только 18 стали платящими клиентами. Реальный ROAS - 1.8x. Перераспределили бюджет: увеличили targeting на High Intent сегмент (посещение pricing), уменьшили на broad ретаргетинг.

Для кого актуально

B2B SaaS компании с бюджетом от $5 000/месяц на Criteo ретаргетинг и длинным циклом продаж (30+ дней). Особенно если между кликом на ретаргетинг и закрытием сделки проходят недели - стандартный 30-дневный атрибуционный window Criteo не захватывает такие конверсии.

Аналогичный подход описан для Prooflytics + Google Ads и Prooflytics + Meta Ads.

Часто задаваемые вопросы

Нужен ли OneTag Criteo если используется только Events API?

OneTag (браузерный скрипт) нужен для аудиторий ретаргетинга - без него Criteo не знает кого ретаргетировать. Events API используется только для конверсий (post-click). Оба нужны: OneTag для построения аудиторий, Events API для атрибуции конверсий с сервера (обходит ad blocker).

Как работает атрибуция если клиент использует несколько устройств?

Criteo Universal Match использует email hash для cross-device атрибуции. Если при отправке конверсии передать email, Criteo сможет сматчить конверсию с кликом на другом устройстве. Именно поэтому в Prooflytics собирается email при регистрации и передаётся в Events API при конверсии.

Criteo Events API имеет ограничения на частоту запросов?

Да: 1 000 событий за запрос, 100 запросов в минуту. Для большинства B2B SaaS с десятками закрытых сделок в месяц это несущественно. При больших объёмах батчируйте события.

Итог

Prooflytics + Criteo - реальный CAC из ретаргетинга:

  • JS: захват cto_pld cookie/параметра + email при регистрации -> Prooflytics API
  • При closed_won в CRM: Criteo Events API с email-based атрибуцией
  • OAuth 2.0 Client Credentials для авторизации в Criteo API
  • Дашборд: campaign CAC = Criteo spend / closed deals, реальный ROAS

Если хотите видеть реальный ROI ретаргетинговых кампаний до закрытой сделки - обратитесь в команду Prooflytics.

Ещё статьи

Все →