OpenRTB 2.5 / 2.6 — Полная схема

Цепочки, schain, время жизни запроса, метрики, bid request / response

Полная цепочка OpenRTB 2.x
Представь: пользователь открывает сайт. За те 150 мс, пока страница загружается, в фоне успевает пройти целый аукцион — и на странице появляется реклама именно для этого человека. Вот кто в этом участвует и зачем.
💡 Аналогия для понимания
Представь рынок недвижимости: паблишер — владелец квартиры, SSP — агентство по аренде, Ad Exchange — аукционный дом, DSP — агент покупателя, рекламодатель — сам покупатель. Квартира (рекламное место) выставляется на аукцион каждый раз, когда новый посетитель заходит на сайт. Всё это происходит быстрее, чем ты моргаешь.
🌐
Publisher
Сайт / App / CTV
Ad Request
Ad Creative
📡
SSP
Supply-Side Platform
Bid Request
Bid Response
⚙️
Ad Exchange
Аукцион
Bid Request
Bid Response
🤖
DSP
Demand-Side Platform
Campaign
Creatives
💼
Advertiser
Рекламодатель
💡 Reselling / Daisy chaining: Между SSP и DSP может быть несколько промежуточных Ad Exchange или Trading Desk. Каждый добавляет себя в цепочку schain и берёт маржу. Чем длиннее цепочка — тем меньше денег доходит до паблишера. Смотри вкладку «Supply Chain» для деталей.

👥 Кто есть кто — подробно
Роль каждого участника, зачем он нужен, как зарабатывает и с кем взаимодействует.
🌐
Publisher
Продавец
Сайт, мобайл, CTV
SELLER

Кто это: владелец рекламного инвентаря. Новостной сайт, мобильная игра, стриминговый сервис — любая площадка, где есть рекламное место.

Задача: продать рекламное место как можно дороже, не испортив опыт пользователя. Устанавливает bidfloor — минимальную цену, ниже которой не продаст показ.

Как подключается: через JavaScript-тег или мобильный SDK на странице. Код запускается когда пользователь видит рекламный слот.

Что передаёт: размер слота (300×250, 728×90 и т.д.), URL страницы, гео пользователя, device type, user ID (cookie/IDFA). Чем больше данных — тем выше ставки от DSP.

NYT, Forbes, Яндекс Candy Crush, Spotify Hulu, Discovery+
📡
SSP
Supply-Side Platform
Агрегатор паблишера
AGGREGATOR

Кто это: платформа, которая работает на стороне паблишера и помогает ему продавать инвентарь максимально дорого. Думай о SSP как о брокере паблишера.

Что делает: получает сигнал от паблишера → упаковывает его в Bid Request по стандарту OpenRTB → рассылает этот запрос одновременно на десятки Ad Exchange и DSP → собирает все ставки → отдаёт победителя обратно паблишеру.

Как зарабатывает: берёт 10–20% от каждой транзакции (revenue share) или фиксированный fee с тысячи показов.

Зачем нужен отдельный SSP, а не напрямую к Exchange? Один паблишер не может интегрироваться с сотнями DSP/Exchange по отдельности. SSP — единая точка входа, которая уже подключена ко всем.

Pubmatic OpenX Magnite Xandr Index Exchange
⚙️
Ad Exchange
Биржа / Аукцион
Нейтральная площадка
AUCTION

Кто это: нейтральная торговая площадка. Получает Bid Request от SSP → рассылает всем подключённым DSP → собирает ставки → проводит аукцион → определяет победителя.

First Price vs Second Price:

First Price 🏆
Победитель платит свою ставку. DSP ставит $10 — платит $10. Современный стандарт (~2019+).
Second Price 📜
Победитель платит ставку второго +$0.01. DSP ставит $10, второй $7 — платит $7.01. Устаревшая модель.
Google Ad Exchange AppNexus/Xandr Rubicon
🤖
DSP
Demand-Side Platform
Мозг покупателя
BUYER

Кто это: система автоматической закупки рекламы для рекламодателей. Именно DSP за миллисекунды решает: «Нужен ли нам этот пользователь? Сколько заплатим?»

Как принимает решение за ~50ms:

1 Получает Bid Request → смотрит user ID → ищет в DMP: знаем ли мы этого пользователя?
2 Проверяет контекст: сайт не в блок-листе? IVT-риски в норме? (Pixalate API)
3 Считает bid price: сколько этот пользователь стоит для этой кампании?
4 Отвечает Bid Response или HTTP 204 No Bid — и всё это за <80ms
The Trade Desk DV360 (Google) Amazon DSP Criteo
💼
Advertiser
Рекламодатель
Тот, кто платит
CLIENT

Кто это: бренд или компания, которая хочет показать рекламу своей аудитории. Nike, Сбер, Amazon — все они покупатели. Обычно работают с DSP напрямую или через рекламное агентство.

Что настраивает в DSP: кому показывать (таргетинг по возрасту, интересам, гео, поведению), сколько платить за показ (CPM bid), дневной/суммарный бюджет, какой креатив показывать (баннер, видео, нативный формат).

Что получает обратно: отчёты о показах, кликах, конверсиях. Смотрит CTR, CPC, CPA — насколько эффективно тратится бюджет.


🔄 Header Bidding — почему это важно
До появления Header Bidding паблишер мог предложить слот только одному Exchange за раз. С HB — сразу всем одновременно.
❌ До Header Bidding (Waterfall)
Паблишер сначала предлагал слот Exchange #1. Если не купили → Exchange #2. Если не купили → Exchange #3. Это называлось «waterfall» (водопад).

Проблема: Exchange #3 мог бы заплатить больше всех, но получал запрос последним и часто с уже истёкшим таймаутом.
✅ С Header Bidding
Через Prebid.js в браузере запрос уходит ко всем Exchange/SSP параллельно и одновременно. Все возвращают ставки, паблишер выбирает лучшую.

Результат: доход паблишера растёт на 20–40%. Конкуренция честная — побеждает тот, кто реально готов платить больше.
💡 Server-side Header Bidding (Prebid Server): HB работает не в браузере пользователя, а на сервере паблишера. Это снижает нагрузку на страницу и latency. Особенно важно для CTV и мобайла, где нет JS-среды браузера.

🗄 Дополнительные участники — DMP и Trading Desk
🗄
DMP (Data Management Platform)
DATA

Хранилище аудиторных данных. DSP использует DMP чтобы понять: «Этот cookie/IDFA — молодой мужчина, интересуется авто, недавно смотрел цены на Audi». Это повышает ставку DSP для нужной аудитории.

  • 1st party data — данные самого рекламодателя (CRM)
  • 2nd party data — данные партнёров (по соглашению)
  • 3rd party data — купленные данные провайдеров
  • Примеры: Oracle BlueKai, Lotame, Nielsen
🏢
Trading Desk / Agency
INTERMEDIARY

Рекламное агентство или специализированная команда, которая управляет закупкой рекламы через DSP от имени рекламодателя. Добавляет ещё один узел в schain и берёт агентскую комиссию (обычно 10–15%).

  • Примеры: GroupM, Publicis, IPG Mediabrands
  • Работают с несколькими DSP одновременно
  • Часть цепочки: Advertiser → Agency → DSP → Exchange
📺
Ad Server
INFRASTRUCTURE

Система управления рекламными кампаниями на стороне паблишера. Решает: какой DSP/SSP вызвать, хранит прямые сделки (direct deals), считает показы и управляет частотой показа одному пользователю (frequency capping).

  • Является «диспетчером» перед HB аукционом
  • Примеры: Google Ad Manager (GAM), Kevel, Smart AdServer
  • Прямые сделки (PG/PMP) проходят через Ad Server
Время жизни запроса
Весь цикл от появления слота до показа рекламы занимает 100–300 мс. Жёсткие тайм-ауты на каждом этапе.
🏗 Co-location — почему это важно

SSP, Exchange и DSP — это физические серверы в дата-центрах. Если SSP находится в Амстердаме, а Exchange в Вирджинии — только network roundtrip добавляет 80–120ms. Это уже почти весь бюджет tmax.

Поэтому крупные игроки co-locate серверы DSP прямо в тех же дата-центрах где стоят Exchange (Equinix NY5, AMS-IX). Latency падает с 80ms до 1–3ms между узлами.

📍 Популярные точки: Equinix NY5 (Нью-Джерси), Equinix AM3 (Амстердам), Equinix LD4 (Лондон), Digital Realty SIN10 (Сингапур)

⚙️ «Ad Exchange» — не всегда биржа

В OpenRTB-цепочке на месте «Ad Exchange» может стоять разный тип участника:

SSP как Exchange — Pubmatic, OpenX сами проводят аукцион без отдельной биржи
DSP как Exchange — крупный DSP (The Trade Desk) может иметь собственный внутренний аукцион между своими seat-ами
Классический Exchange — нейтральная биржа (Google Ad Exchange, Xandr) между SSP и DSP

Вывод: «Exchange» в схеме = любой узел, проводящий аукцион. Граница между SSP/Exchange/DSP в реальности размыта.

1–3ms
SSP → Exchange (co-located, один дата-центр)
80–120ms
SSP → Exchange (разные регионы, без co-location)
5–30ms
Обработка и принятие решения в DSP
100–300ms
Полный цикл аукциона (реалистичный диапазон)
300ms
tmax для большинства Exchange (hard limit)
500ms+
Полный цикл без co-location → часто No Fill
🟢
Сценарий A: Co-located
SSP, Exchange, DSP — один дата-центр
~145ms
Страница загружается
0ms
→ SSP (browser→SSP)
+10ms
SSP → Exchange
+2ms ✓
Exchange → DSP (x10)
+3ms ✓
DSP: решение + ответ
+80ms
Аукцион + Win Notice
+10ms
Креатив → браузер
+40ms
🔴
Сценарий B: Без co-location
SSP в EU, Exchange в US, DSP в AS
450ms+
Страница загружается
0ms
→ SSP (browser→SSP)
+20ms
SSP → Exchange ⚠️
+100ms
Exchange → DSP ⚠️
+80ms
DSP: решение + ответ
+80ms
DSP → Exchange ⚠️
+80ms
Аукцион + доставка
+70ms
⚠️ Почему так важен co-location: В сценарии B network latency SSP→Exchange→DSP→Exchange = 260ms только на передачу данных, ещё до того как DSP начал думать. При tmax=300ms на Exchange это означает что у DSP остаётся лишь 40ms на весь ML-анализ — или его ставка будет отброшена. Реальные tmax у Google Ad Exchange — 120ms, у крупных SSP — 80–150ms.
⏱ Детальная временная шкала — Сценарий A (co-located, ~145ms полный цикл)
Этап
Описание
Δ время
Итого
1. Страница загружается
Браузер встречает рекламный слот. Запускается Prebid.js или тег SSP. Начало отсчёта.
0ms
0ms
2. Browser → SSP
HTTP-запрос от браузера до сервера SSP. Зависит от географии пользователя. SSP формирует OpenRTB Bid Request: imp[], site, user, device, schain, ext.
+10ms
10ms
3. SSP → Exchange
SSP рассылает Bid Request на все подключённые Exchange. Co-located: 1–3ms. Разные регионы: 80–150ms. Именно здесь теряется большинство времени без co-location.
+2ms
12ms
4. Exchange → DSP (fan-out)
Exchange одновременно рассылает Bid Request всем подключённым DSP (fan-out). Co-located DSP отвечают за 1–3ms, геораспределённые — за 50–80ms. Exchange устанавливает свой tmax.
+3ms
15ms
5. DSP: анализ + bid
DSP парсит запрос → проверяет user ID в DMP → таргетинг → Pixalate pre-bid API → считает bid price на ML-модели → формирует Bid Response. Всё это за 30–80ms. Самый долгий этап.
+80ms
95ms
6. Аукцион на Exchange
Exchange собирает все Bid Response (ждёт до tmax). Отбрасывает ставки ниже bidfloor. Проводит first/second price аукцион. Определяет победителя. Сам аукцион — 3–5ms.
+8ms
103ms
7. Win Notice → DSP
Exchange вызывает nurl победителя, подставляет ${AUCTION_PRICE}. DSP получает подтверждение и clearing price. Проигравшим — lurl с кодом причины (опционально).
+5ms
108ms
8. Креатив → браузер
SSP передаёт выигравший adm (HTML баннер или VAST URL) обратно браузеру. Браузер загружает файл с CDN и отрисовывает рекламу. Срабатывает impression pixel.
+37ms
145ms
9. Billing / async события
burl — billing event при реальном показе. Viewability pixel — MRC-стандарт. Loss notification для проигравших DSP. Всё это асинхронно, не блокирует пользователя.
async
async
⚠️ tmax — жёсткий дедлайн: Exchange устанавливает tmax (обычно 80–300ms). Bid Response от DSP, пришедший позже — игнорируется, деньги не спишутся. DSP, которые хронически опаздывают, получают меньше запросов (Exchange throttle). Именно поэтому DSP инвестируют в co-location и оптимизацию ML-инференса.
Bid Request — структура
JSON-объект, который SSP/Exchange отправляет в DSP. Содержит всё необходимое для принятия решения о ставке.
📌 Версии: Документ описывает OpenRTB 2.5 / 2.6. Ключевое отличие от 3.0: в 2.x расширения (GDPR, schain, DSA) передаются через ext объекты — они не являются нативными полями верхнего уровня. В 3.0 часть этих полей переехала в тело напрямую, но 3.0 не используется в проде.
// Bid Request — упрощённый пример { "id": "7f3b2e1d-auction-id", // уникальный ID аукциона "at": 1, // тип аукциона: 1=first price, 2=second price "tmax": 120, // таймаут ожидания ответа (мс) "imp": [{ // массив рекламных мест (impression) "id": "1", "banner": { "w": 300, "h": 250, // размер слота "btype": [4], // заблокированные типы (4=popup) "pos": 1 // позиция: 1=above the fold }, "bidfloor": 1.5, // минимальная ставка (CPM в $) "bidfloorcur": "USD", "secure": 1, // требуется HTTPS-креатив "ext": { "skadn": { ... } // SKAdNetwork (iOS) } }], "site": { // для веб (или "app" для мобайла) "id": "site123", "domain": "example.com", "cat": ["IAB1", "IAB1-7"], // IAB-категории контента "page": "https://example.com/news", "publisher": { "id": "pub456" } }, "user": { // пользователь "id": "user-uuid", // SSP user ID "buyeruid": "dsp-mapped-uid", // DSP user ID (cookie sync) "yob": 1990, // год рождения (опц.) "geo": { "country": "RU", "city": "Moscow" }, "consent": "GDPR-TCF-string" // GDPR согласие }, "device": { "ua": "Mozilla/5.0 ...", "ip": "1.2.3.4", "devicetype": 3, // 1=Mobile/Tablet, 2=PC, 3=Connected TV, 4=Phone, 5=Tablet, 6=Connected Device, 7=STB "os": "iOS", "ifa": "IDFA-device-id" // рекламный идентификатор }, "regs": { "coppa": 0, // нативное поле 2.x: 1 если аудитория — дети (COPPA) "ext": { "gdpr": 1, // IAB TCF: 1 если пользователь в зоне GDPR (через ext в 2.x) "us_privacy": "1YNN" // CCPA privacy string (4 символа) } }, "source": { // schain — цепочка поставки "ext": { "schain": { // в OpenRTB 2.x — через ext! (не нативное поле source) "complete": 1, "nodes": [ { "asi": "publisher.com", "sid": "pub-123", "hp": 1 }, { "asi": "ssp.com", "sid": "ssp-456", "hp": 1 } ] } } } }
Поле Тип Обяз. Описание
idstringreqУникальный ID аукциона. Используется для сопоставления request/response.
imp[]arrayreqМассив рекламных мест. Обычно 1, но может быть несколько (multi-format).
imp.bidfloorfloatoptМинимальная CPM-цена. Ставки ниже — отклоняются автоматически.
imp.secureintopt1 = требуется HTTPS. Важно для современных браузеров.
atintoptТип аукциона: 1=First Price, 2=Second Price + $0.01. Дефолт = 2, но рынок перешёл на 1.
tmaxintoptМаксимальное время ожидания ответа в мс. DSP должен уложиться.
site / appobjectreqКонтекст размещения. site для web, app для мобайла/CTV. Взаимоисключающие.
userobjectoptДанные о пользователе. buyeruid — результат cookie sync между SSP и DSP.
deviceobjectoptUA, IP, тип устройства, OS, рекламный ID (IDFA/GAID).
regs.coppaintoptНативное поле 2.x. 1 = аудитория дети, применяется COPPA. Ограничивает сбор данных.
regs.ext.gdprintoptВ OpenRTB 2.x GDPR флаг живёт в ext — не нативное поле. 1 = пользователь в зоне GDPR, нужна TCF-строка consent.
source.ext.schainobjectoptВ 2.x schain передаётся через source.ext.schain (расширение). Supply Chain — цепочка всех участников от паблишера до биржи.
Bid Response — структура
Ответ DSP на Bid Request. Содержит ставку, URL крeатива и метаданные для аукциона.
// Bid Response от DSP { "id": "7f3b2e1d-auction-id", // тот же ID что и в Bid Request "cur": "USD", "seatbid": [{ // ставки от DSP (группы по seat) "seat": "dsp-buyer-id", "bid": [{ "id": "bid-unique-id", "impid": "1", // ID impression из request "price": 3.75, // ставка в CPM USD "adid": "creative-123", // ID заранее одобренного крeатива "adm": "<div>...banner HTML...</div>", // HTML/VAST крeатива "nurl": "https://dsp.com/win?price=${AUCTION_PRICE}", // ^ win notification URL, вызывается при победе "burl": "https://dsp.com/billing?price=${AUCTION_PRICE}", // ^ billing URL, вызывается при фактическом показе "lurl": "https://dsp.com/loss?reason=${AUCTION_LOSS}", // ^ loss notification URL "adomain": ["advertiser.com"], // домен рекламодателя "cat": ["IAB1"], // категория крeатива "attr": [1, 2], // атрибуты (1=audio auto-play, 2=expandable) "w": 300, "h": 250, // размер крeатива "ext": { "dsa": { ... } // Digital Services Act данные (EU) } }] }] }
No Bid в OpenRTB 2.x: Если DSP не хочет участвовать — HTTP 204 No Content (пустой ответ, предпочтительно) или пустой JSON {}. Поле nbr (no bid reason) можно добавить в тело ответа, но в 2.x оно не стандартизировано так жёстко как в 3.0 — большинство exchange просто ждут 204.
🔔
nurl — Win Notice
NOTIFICATION

URL, который Exchange вызывает при победе DSP в аукционе. Содержит макрос ${AUCTION_PRICE} — реальная clearing price подставляется Exchange-ом. DSP узнаёт финальную цену.

💳
burl — Billing Event
BILLING

URL, вызываемый при фактическом показе (impression). Является финансовым событием — именно по нему DSP списывает деньги с кампании. Появился в OpenRTB 2.5 для разделения win и billing.

lurl — Loss Notice
LOSS

URL при проигрыше. Макрос ${AUCTION_LOSS} содержит код причины: 1=превышен timeout, 2=ниже bidfloor, 3=проигран аукцион, 4=отфильтрован. Используется для оптимизации ставок.

Supply Chain Object (schain)
Прозрачность пути от паблишера до покупателя. Каждый посредник добавляет себя в цепочку узлов.
⚠️ OpenRTB 2.x vs 3.0 — критическое отличие по schain: В 2.x schain живёт в source.ext.schain. В 3.0 он стал нативным полем source.schain. Если ты видишь source.schain без ext — это 3.0-спецификация, которая не используется в проде.
📖 Что такое schain? Supply Chain Object — стандарт IAB, введённый в 2019 году. Позволяет DSP видеть весь путь инвентаря: от оригинального паблишера через всех ресейлеров до Exchange. Помогает выявлять unauthorized reselling и ad fraud.
Пример реальной цепочки с 3 узлами:
NODE 0 — PUBLISHER
news-site.com
asi: news-site.com
sid: pub-001
hp: 1 (has payment)
name: News Publisher
NODE 1 — SSP
pubmatic.com
asi: pubmatic.com
sid: ssp-456
hp: 1
rid: req-uuid-xyz
NODE 2 — RESELLER
intermediary.com
asi: intermediary.com
sid: int-789
hp: 0 (no payment)
domain: news-site.com
NODE 3 — EXCHANGE
openx.com
asi: openx.com
sid: exchange-999
hp: 1
complete: 1
DSP
Видит всю
цепочку
// В OpenRTB 2.x schain передаётся через source.ext.schain "source": { "tid": "transaction-id", // нативное поле source: ID транзакции "ext": { "schain": { // через ext — стандарт для 2.x "complete": 1, // 1=полная цепочка, 0=неполная (подозрительно!) "ver": "1.0", "nodes": [ { "asi": "news-site.com", // Advertising System Identifier "sid": "pub-001", // Seller Account ID в этой системе "hp": 1, // 1=получает оплату, 0=нет "name": "News Publisher", "domain": "news-site.com" }, { "asi": "pubmatic.com", "sid": "ssp-456", "hp": 1, "rid": "request-uuid" // Request ID (для трассировки) } ] } } }
📋
Поля узла schain
FIELDS
  • asi — домен участника (должен совпадать с ads.txt/app-ads.txt)
  • sid — ID продавца в системе asi. Ключ для проверки по ads.txt
  • hp — 1 если узел участвует в расчётах. 0 у чистых посредников
  • rid — Request ID для сквозной трассировки
  • name — название компании
  • domain — домен паблишера (у ресейлеров)
📄
ads.txt / app-ads.txt
IAB STANDARD

Текстовый файл в корне сайта или приложения. Перечисляет все авторизованные системы продаж инвентаря этого паблишера. DSP проверяет — есть ли каждый узел schain в соответствующем ads.txt.

  • example.com/ads.txt — для веб-сайтов
  • example.com/app-ads.txt — для мобильных приложений (по bundle ID)
  • DIRECT — паблишер продаёт напрямую через эту платформу
  • RESELLER — через посредника (добавляет узел в schain)
  • 4-й параметр — TAG-ID сертификации (опционально)
🚨
Красные флаги schain
FRAUD SIGNALS
  • complete=0 — цепочка неполная, часть участников скрыта
  • Узел не найден в ads.txt паблишера
  • asi не существует как реальная платформа
  • Слишком длинная цепочка (5+ узлов) — перепродажа
  • Один и тот же asi несколько раз — циклический reselling

📄 ads.txt / app-ads.txt — анатомия файла
Каждая строка — одна авторизованная система продаж. Реальный пример из cas.ai/app-ads.txt:
# Формат каждой строки: # <SSP/Exchange domain>, <seller_id>, <DIRECT|RESELLER>[, <TAG-ID>] # OwnerDomain — объявляет владельца домена (важно для app-ads.txt) OwnerDomain=cas.ai # DIRECT — cas.ai сам продаёт через себя. sid=922e6092 совпадает с sellers.json cas.ai, 922e6092, DIRECT # DIRECT через Google (несколько pub-ID — разные приложения/аккаунты) google.com, pub-1022958838828668, DIRECT, f08c47fec0942fa0 google.com, pub-4382598503065232, DIRECT, f08c47fec0942fa0 # DIRECT через Facebook Audience Network facebook.com, 1210467953459280, DIRECT, c3e20eee3f780d68 # RESELLER — Pubmatic продаёт инвентарь CAS как ресейлер # DSP проверит sellers.json pubmatic.com — там должен быть seller_id=161490 pubmatic.com, 161490, RESELLER, 5d62403b186f2ace # RESELLER — Smaato, IronSource, OpenX и другие партнёры ironsrc.com, 218335, DIRECT openx.com, 537153564, RESELLER, 6a698e2ec38604c6 appnexus.com, 11826, RESELLER, f5ab79cb980f11d1
✅ DIRECT строка

google.com, pub-123, DIRECT, TAG-ID

Паблишер напрямую подключён к Google. Деньги идут от Google прямо паблишеру. В schain это будет hp=1, asi=google.com, sid=pub-123. TAG-ID — сертификат TAG (Trustworthy Accountability Group), подтверждает легитимность продавца.

🔄 RESELLER строка

pubmatic.com, 161490, RESELLER, TAG

Pubmatic продаёт инвентарь CAS как посредник. DSP при получении Bid Request с asi=pubmatic.com, sid=161490 — проверит: 1) есть ли эта строка в app-ads.txt CAS? 2) есть ли seller_id=161490 в sellers.json Pubmatic?


🗂 sellers.json — справочник SSP/Exchange
Зеркальный документ — но на стороне SSP/Exchange. Если ads.txt говорит «кто авторизован продавать», то sellers.json говорит «кто эти продавцы на самом деле». Реальный пример из cas.ai/sellers.json:
{ "contact_email": "oleh.petryshyn@cas.ai", "contact_address": "Nausis 2 Monasteraki Complex 25, 8047, Paphos, CY", "version": "1.0", // identifiers — TAG-ID сертификация платформы "identifiers": [{ "name": "TAG-ID", "value": "2115da22-275e-4892-a5a2-c5a47d50da8a" }], "sellers": [ // Тип Publisher — реальный паблишер, владелец контента { "seller_id": "922e6092", // должен совпадать с sid в schain и ads.txt "name": "cas.ai", "domain": "cas.ai", "seller_type": "Publisher" // владелец инвентаря }, { "seller_id": "b2659234", "name": "Bigo", "domain": "bigo.sg", "seller_type": "Publisher" }, // Тип Intermediary — только посредник, не владеет инвентарём { "seller_id": "4f6e3fb2", "name": "Advlion", "domain": "advlion.com", "seller_type": "Intermediary" // ресейлер без своего инвентаря }, // Тип Both — и паблишер, и ресейлер одновременно { "seller_id": "b8f36982", "name": "Luponmedia", "domain": "luponmedia.com", "seller_type": "Both" // имеет свой инвентарь + перепродаёт чужой } // ... всего 50+ записей в реальном файле ] }
🌐 Publisher

Реальный владелец инвентаря. Его контент — сайт, приложение, игра. Деньги приходят к нему как к исходному поставщику. hp=1 в schain всегда.

Пример: Bigo (bigo.sg), Truecaller, ABI Games
🔄 Intermediary

Чистый посредник-ресейлер. Не владеет инвентарём — только перепродаёт. Обязан быть указан в ads.txt паблишера как RESELLER иначе — красный флаг мошенничества.

Пример: Bidmatic, Madex, Anzu, Smaato
🔀 Both

Гибридный участник — имеет собственный инвентарь (Publisher) и одновременно перепродаёт чужой (Intermediary). Типично для мелких SSP со своими приложениями.

Пример: Luponmedia, Crackle, Omnify TV
🔍 Как DSP верифицирует цепочку: ads.txt + sellers.json + schain
Три документа работают вместе как система взаимной проверки. DSP выполняет эту проверку автоматически при каждом Bid Request.
1
Получен Bid Request: asi=pubmatic.com, sid=161490, domain=cas.ai
DSP видит в schain: Pubmatic (161490) перепродаёт инвентарь cas.ai
2
Шаг 1: Проверка app-ads.txt cas.ai
DSP смотрит cas.ai/app-ads.txt → ищет строку: pubmatic.com, 161490, RESELLER✓ найдена. Pubmatic авторизован продавать инвентарь CAS.
3
Шаг 2: Проверка sellers.json Pubmatic
DSP смотрит pubmatic.com/sellers.json → ищет seller_id=161490 → должен найти там cas.ai с типом Publisher или Both. Если не найден — потенциальный спуфинг.
4
Шаг 3: Проверка sellers.json самого cas.ai
DSP смотрит cas.ai/sellers.json → ищет seller_id=922e6092 (из первого узла schain) → находит запись: name=cas.ai, seller_type=Publisher → ✓ полная верификация цепочки.
Цепочка верифицирована — DSP делает ставку.
Если любая из проверок провалилась (нет в ads.txt, нет в sellers.json, несоответствие типов) → DSP может отклонить bid или снизить ставку как penalty за сомнительный инвентарь.
⚠️ Кэширование sellers.json: DSP не проверяют sellers.json при каждом bid — это слишком медленно. Файлы кэшируются и обновляются раз в несколько часов. Поэтому изменения в sellers.json могут проявиться с задержкой до 24 часов.
Ключевые метрики
Как работают числа в programmatic: от запроса до денег на счёте паблишера. Разбираем каждую метрику с нуля — что она значит, как считается, какое значение считать нормой и почему она падает.
🔻 Воронка одного показа
Представь: 1 000 000 пользователей зашли на сайт. Каждый визит — потенциальный показ. Вот что с ними происходит:
🌐
Bid Requests
SSP получил запрос на рекламное место и разослал его DSP-партнёрам. Это 100% всего трафика.
1 000 000
📨
Bid Responses Fill Rate = 60%
DSP ответил ставкой. Остальные 40% — No Bid: аудитория не подошла, ставка была бы ниже флора, нет бюджета или тайм-аут.
600 000
🏆
Wins (аукцион выигран) Win Rate = 30%
DSP выиграл аукцион — его ставка оказалась выше всех конкурентов и выше bidfloor паблишера. Остальные 70% — проигрыш другим DSP или отклонение из-за цены.
180 000
👁
Impressions (показ состоялся) Render Rate = 85%
Браузер пользователя загрузил и отрисовал рекламу. 15% потерь — пользователь закрыл страницу до загрузки, медленный интернет, баннер не смог загрузиться с CDN.
153 000
💰
Итог: из 1 000 000 запросов → 153 000 показов Overall = 15.3%
= fill (60%) × win (30%) × render (85%) = 15.3%. Это и есть твоя сквозная эффективность. Улучшив каждый этап на 10% — итог вырастет в разы.
153 000

📊 Каждая метрика подробно
Что значит, как считается, норма, почему падает и как починить.
Fill Rate
bid responses / bid requests
Норма: 60–80%

Что это: процент запросов, на которые DSP ответил хотя бы одной ставкой. Если fill rate = 60% — значит 40% запросов улетели в пустоту, никто не захотел покупать этот показ.

Почему падает: ставка DSP будет ниже bidfloor паблишера → No Bid. Аудитория не совпадает с таргетингом DSP. Нет бюджета у покупателя. Инвентарь заблокирован по brand safety или Pixalate IVT-флагу. DSP не успел ответить за tmax.

Кто смотрит: SSP/паблишер — низкий fill = недополученный доход. DSP — низкий fill = неэффективный байинг, нужно пересмотреть таргетинг.

Win Rate
wins / bid responses
Норма: 20–40%

Что это: из всех ставок, которые сделал DSP, сколько из них выиграли аукцион. Win Rate 30% — нормальная конкуренция. Если 5% — ты постоянно проигрываешь конкурентам, ставки слишком низкие. Если 90% — ты переплачиваешь.

Почему низкий: конкурентный инвентарь (много DSP борются за один слот), ставки ниже рынка, bidfloor паблишера выше твоей цены.

Почему высокий — тоже плохо: слишком высокий win rate (80%+) = DSP переплачивает. Правильно когда ты выигрываешь ровно те показы, которые тебе нужны, не больше.

Render Rate
impressions / wins
Норма: 80–95%

Что это: из всех выигранных аукционов, в скольких реально произошёл показ на экране пользователя. Победа в аукционе ≠ показ. Между победой и показом может произойти: пользователь закрыл вкладку, медленный CDN не отдал файл, JS-ошибка в плеере, баннер загрузился за экраном.

Почему падает: медленный CDN видеофайла (для видеорекламы критично), VAST-ошибки (ошибка 401 — файл не найден), слишком тяжёлый креатив, пользователь ушёл со страницы раньше загрузки рекламы.

Важно: низкий render rate при нормальном fill и win — это проблема на стороне паблишера или крeатива, не аукциона. Нужно смотреть VAST error codes.

CPM / eCPM
Cost per Mille
Разные точки зрения

CPM (Cost per Mille) — цена 1000 показов со стороны покупателя (DSP/рекламодателя). Это то, что DSP платит за трафик. Формула: spend / impressions × 1000.

eCPM (effective CPM) — то же самое, но со стороны паблишера/SSP. Показывает сколько паблишер реально заработал с 1000 показов. Формула: revenue / impressions × 1000.

Ключевая разница: CPM (DSP) > eCPM (паблишер), потому что между ними — маржа SSP, Exchange и других посредников. Обычно паблишер получает 60–80% от CPM байера.

Viewability
MRC Standard
Норма: 50–70%+

Что это: процент показов, которые пользователь реально мог увидеть. Показ засчитывается даже если баннер был внизу страницы вне зоны видимости — это не viewable impression.

Стандарт MRC (Media Rating Council): баннер считается видимым если ≥50% площади находилось в viewport не менее 1 секунды. Для видео: ≥50% площади + ≥2 секунды воспроизведения.

Почему важно: DSP платят премию за viewable инвентарь. Паблишеры с viewability 70%+ получают более высокие CPM. Измеряется через OMID (Open Measurement SDK) или DoubleVerify/IAS пиксели.

VCR
Video Completion Rate
Non-skip: 70–85%

Что это: процент видеообъявлений, которые пользователь досмотрел до конца. Ключевой KPI для брендинговых видеокампаний. Связан с VAST-событием complete.

Нормы: non-skippable pre-roll — 70–85%. Skippable — 30–50% (пользователи пропускают после 5с). CTV — 95%+ (нельзя скипнуть). Мобайл — ниже, чем desktop.

Связанные события VAST: start → firstQuartile (25%) → midpoint (50%) → thirdQuartile (75%) → complete (100%). Отслеживай все четыре для понимания где именно уходят зрители.


⚙️ Как bidfloor влияет на все метрики
Bidfloor — это рычаг управления. Двигая его, паблишер/SSP меняет все метрики одновременно.
Ситуация Fill Rate Win Rate DSP eCPM паблишера Объём показов Когда применять
🔼 Высокий bidfloor ↓ Низкий ↓ Ниже ↑ Высокий ↓ Мало Premium инвентарь, brand-safe контент, CTV. Хочешь дорогих байеров.
🔽 Низкий bidfloor ↑ Высокий ↑ Выше ↓ Низкий ↑ Много Long-tail трафик, наращивание охвата, performance-кампании.
🎯 Dynamic Floor ↔ Оптимально ↔ Справедливо ↑ Максимум ↔ Баланс Алгоритм SSP меняет флор в реальном времени под каждый запрос на основе ML.
🔬 Разбор кейсов из схемы
Реальные цифры с нашей схемы — разберём почему каждый кейс заканчивается именно так.
Кейс 1 — Победа в аукционе
WIN
bidfloor
$11
ставка
$15
clearing price
$14

Ставка DSP ($15) выше bidfloor ($11) → проходим фильтр. В аукционе конкурировали несколько DSP, второй ставил $13.99 → мы выиграли, платим $14.00 (second price +$0.01). Impression = 1 ✅

💡 Winning price всегда ниже твоей ставки при second price auction — это выгодно DSP.
Кейс 2 — Наш флор блокирует сделку
NO WIN
bidfloor
$11
ставка байера
$15
our price
$6

Внешний байер ставит $15, но наш внутренний "our price" — $6. Это значит что наша SSP/Exchange после всех своих корректировок и маржи выставляет внутреннюю цену $6. Это ниже нашего собственного bidfloor $11 — сделка блокируется.

⚠️ Это типичная ошибка конфигурации: несогласованность между incoming bidfloor и внутренними ценовыми корректировками.
📈
Кейс 3 — Объём vs качество
SCALE
bidfloor
$1.5
price
$2
bids
200K

Низкий флор $1.5 открывает огромный объём трафика — 200 000 ставок. eCPM $2 — невысокий, но при таком объёме суммарный доход паблишера: 200 000 / 1000 × $2 = $400 за одну рекламную сессию.

💡 Стратегия "volume play": жертвуешь eCPM, получаешь объём. Работает для паблишеров с огромным трафиком (порталы, агрегаторы).

💸 Как SSP/Exchange зарабатывают — Price Adjustment
Между ценой, которую видит DSP, и деньгами, которые получает паблишер — несколько уровней наценок. Вот как это работает на конкретных числах.
💡 Зачем это знать: если ты видишь что байер платит $10 CPM, а паблишер получает $4 — это не обман. Это fee SSP (~15%), fee Exchange (~10%), verification (~5%) и прочие операционные расходы цепочки. Нормальная доля паблишера — 55–70% от buyer CPM.
// Входящая ставка от DSP buyer_cpm = 10.00$ // Шаг 1: aggregated adjustment (Exchange берёт свою долю) // Формат: +фиксированная сумма + процент от цены exchange_fee_fixed = 0.20$ exchange_fee_pct = 25% // т.е. Exchange забирает 25% + $0.20 price_after_exchange = 10.00 - (10.00 × 0.25) - 0.20 = 7.30$ // Шаг 2: flexible adjustment (SSP берёт свою долю) ssp_fee_fixed = 1.00$ ssp_fee_pct = 30% price_after_ssp = 7.30 - (7.30 × 0.30) - 1.00 = 4.11$ // Итог: паблишер получает $4.11 при buyer CPM $10.00 // Publisher share = 41% — это низкий показатель (норма 55–70%) publisher_share = 4.11 / 10.00 = 41.1% // 💡 Если цифра ниже 50% — нужно пересматривать условия с SSP/Exchange
⚠️ Bidfloor стратегия: Слишком высокий bidfloor → падает fill rate, показов меньше, но eCPM выше. Слишком низкий → много низкокачественного трафика. Оптимум находится динамически через floor optimization — большинство современных SSP делают это автоматически на основе ML-моделей, анализируя исторические данные по каждому слоту.
Fraud Protection & Pixalate
Рекламное мошенничество — это индустрия с оборотом $100+ млрд в год. Каждый доллар, потраченный на фейковый показ, — прямой убыток рекламодателя. Здесь разбираем: что такое ad fraud, как он работает, и как Pixalate защищает от него на каждом этапе.
💡 Зачем вообще существует ad fraud?
Представь: паблишер получает деньги за каждые 1000 показов. Если сделать так, чтобы рекламу «смотрели» не люди, а боты — можно получать деньги ни за что. Мошенники создают фермы устройств, пишут скрипты, имитирующие просмотры, скрывают рекламу под другим контентом — и получают реальные деньги. DSP и рекламодатели теряют бюджеты. Pixalate — это щит между честными участниками рынка и мошенниками.

🦠 Типы Invalid Traffic (IVT) — подробно
IVT = Invalid Traffic — любой трафик, который не является реальным человеком или реальным показом рекламы. IAB делит его на два уровня.
🤖
GIVT
General Invalid Traffic
ЛЕГКО ОБНАРУЖИТЬ

Известные и легко идентифицируемые боты и скрипты. Они не скрываются — это стандартные краулеры, мониторинговые системы, технические агенты.

🕷 Поисковые краулеры
Googlebot, Bingbot сканируют страницы — они попадают на рекламный слот, но это не человек. Легко определить по User-Agent.
📊 Мониторинговые боты
Uptimerobot, Pingdom и аналоги проверяют доступность сайта — тоже попадают на рекламу. Есть в IAB/ABC International Spiders & Bots List.
🔧 Инструменты разработчиков
Автотесты, скрейперы, preview-боты соцсетей (Facebook LinkPreview, Twitter Card Validator) — не люди.
🎭
SIVT
Sophisticated Invalid Traffic
ТРУДНО ОБНАРУЖИТЬ

Сложный мошеннический трафик — специально разработан чтобы имитировать реального пользователя. Требует ML-моделей и многоуровневого анализа для обнаружения.

📱 Device Farms (фермы устройств)
Сотни реальных смартфонов в одном месте, которые роботизированно кликают рекламу 24/7. Трафик выглядит как настоящий — реальные устройства, реальный User-Agent.
👁 Hidden Ads (скрытые объявления)
Реклама размещается в 1×1 пиксель или под другим контентом — пользователь её не видит, но impression засчитывается. Технически показ произошёл.
🖥 Ad Stacking (стопка объявлений)
10–20 баннеров накладываются друг на друга в одном контейнере. Пользователь видит только верхний, но impressions считаются для всех.
🌐
Domain Spoofing
SIVT

Мошеннический сайт в Bid Request объявляет себя как «nytimes.com» или другой премиум-паблишер. DSP видит престижный домен и ставит высокую ставку — но реклама показывается на помойном сайте.

🛡 Защита: ads.txt + schain проверка. Если сайт заявляет nytimes.com, но домен не в ads.txt NYT — это спуфинг.
👆
Click Fraud
SIVT

Искусственная накрутка кликов на рекламу. Боты или наёмные люди в странах с низкой оплатой труда кликают рекламу весь день. Рекламодатель платит за клики, которые никогда не станут покупателями.

⚠️ Особенно опасно для CPC-кампаний. Признак: высокий CTR при нулевой конверсии.
🏭
MFA Sites (Made for Advertising)
BORDERLINE

Сайты, созданные исключительно ради показа рекламы. Минимальный контент низкого качества, максимум рекламных мест. Технически трафик может быть реальным, но аудитория нулевой ценности для рекламодателя.

💡 Не всегда незаконно, но всегда плохой ROI. Pixalate маркирует MFA-сайты отдельно.
🎯
Session Hijacking
SIVT

Вредоносный скрипт на устройстве пользователя перехватывает его реальную сессию и подставляет рекламу, за которую он никогда не голосовал. Пользователь реальный, но контекст фальшивый.

⚠️ Один из самых сложных для обнаружения типов SIVT — сессия выглядит полностью легитимно.

🛡 Что такое Pixalate и как он устроен
Pixalate — это независимая платформа защиты от мошенничества и compliance-аналитики. Работает на всех уровнях supply chain — от предаукционной блокировки до постфактум-анализа.
📡
Масштаб
5M+
приложений под мониторингом
80M+
доменов в базе
🔬
Детектирование
35+
типов IVT отслеживается
300M+
OTT/CTV устройств
🏢
Клиенты
LinkedIn
Yahoo
PubMatic
ByteDance
Criteo
и сотни других DSP/SSP
🚧
Pre-bid Blocking
РЕКОМЕНДУЕТСЯ
+5–15ms latency

Как работает: DSP интегрирует Pixalate API. При получении каждого Bid Request — до того как сделать ставку — он делает запрос в Pixalate: «Этот publisher/app/IP в блок-листе?». Если да — No Bid, деньги не тратятся.

Что проверяется: Publisher ID против базы известных мошенников. IP-адрес пользователя против списка дата-центров и VPN (реальные люди не сидят в AWS). Device ID против списков скомпрометированных устройств. Bundle ID приложения против базы фейковых apps.

Плюсы vs минусы:

Деньги не тратятся на фрод вообще
Списки обновляются в реальном времени
Снижает IVT% в отчётах
+5–15ms к latency DSP
Ложные срабатывания блокируют часть легитимного трафика
Не ловит 100% SIVT
🔍
Post-bid Analytics
МОНИТОРИНГ
Анализ постфактум

Как работает: После того как показ произошёл — Pixalate анализирует его по 35+ сигналам: поведение пользователя, время взаимодействия, паттерны кликов, технические аномалии. Если обнаружен фрод — показ помечается как invalid.

Зачем нужен если есть pre-bid? Pre-bid ловит известных мошенников по спискам. Post-bid анализирует поведение — ловит новых, ещё не известных мошенников и SIVT которое прошло через фильтры.

Результат: данные из post-bid анализа пополняют pre-bid блок-листы. Это обучающий цикл — система становится умнее с каждым новым типом мошенничества.

📊
MRT
Media Rating Terminal
DUE DILIGENCE
Проверка паблишеров

Что это: исследовательский инструмент для проверки паблишеров и SSP до начала работы с ними. Как кредитная история, но для рекламного инвентаря.

Когда использовать: перед добавлением нового SSP в whitelist. Перед запуском кампании на новой площадке. При подозрении на аномальные метрики в существующих интеграциях.

Что показывает MRT:

IVT % — доля невалидного трафика
Brand Safety Score — безопасность контента
schain Compliance — прозрачность цепочки
ads.txt Coverage — покрытие авторизации

🔗 Где Pixalate встроен в OpenRTB-поток
Pixalate не заменяет существующих участников — он встраивается между ними на каждом критическом этапе.
🌐
SSP / MRT Check
До интеграции: через MRT проверяется паблишер или SSP перед добавлением в whitelist. Выясняем исторический IVT%, schain compliance, наличие в ads.txt.
⚙️
Exchange / schain Check
При получении Bid Request: Exchange валидирует schain — все ли узлы есть в ads.txt, нет ли complete=0, нет ли циклического ресейлинга. Pixalate предоставляет данные для этой проверки.
🛡
Pixalate Pre-bid API
Ключевой этап
Главный блокировщик: DSP делает запрос в Pixalate API с publisher ID, IP, device ID, bundle. API возвращает risk score. Если риск высокий — DSP не делает ставку. Добавляет 5–15ms, экономит 100% денег которые ушли бы мошенникам.
🤖
DSP / Bid or No Bid
Результат проверок: если Pixalate дал зелёный свет — DSP делает ставку. Если красный — No Bid. Всё решается автоматически, без участия человека.
🔍
Post-bid Analysis
После показа: Pixalate анализирует все impressions. Обнаруженный фрод → помечается. Данные идут в clawback-процесс и обновляют pre-bid блок-листы для следующих аукционов.
🚨 Что такое Clawback (возврат денег): Если post-bid анализ обнаружил IVT после того как деньги уже уплачены, DSP инициирует возврат. Процесс: DSP формирует отчёт с invalid impressions → отправляет претензию SSP → SSP признаёт или оспаривает → вычитает из следующего платежа паблишеру. Это медленно (недели/месяцы), поэтому pre-bid всегда предпочтительнее — деньги просто не тратятся с самого начала.

📈 Publisher Trust Indexes — рейтинги паблишеров
Pixalate публикует ежеквартальные рейтинги паблишеров по уровню IVT. Это публичные данные — DSP используют их для принятия решений о whitelist/blacklist.
📱
Mobile App PTI
QUARTERLY

Рейтинг мобильных приложений по iOS и Android. Топ-приложения с наименьшим IVT%, высоким brand safety score и корректным app-ads.txt. DSP используют для автоматической оптимизации whitelist.

📺
CTV/OTT PTI
QUARTERLY

Рейтинг Connected TV приложений (Roku, FireTV, Apple TV). CTV — самый быстрорастущий и самый мошеннический сегмент: CPM высокий, контроль низкий. PTI помогает найти проверенные CTV площадки.

🖥
Desktop/Web PTI
QUARTERLY

Рейтинг веб-сайтов. Учитывает IVT%, viewability, brand safety, ads.txt compliance. Позволяет сравнить паблишеров одной вертикали между собой перед принятием решения о закупке.

VAST — Video Ad Serving Template
Стандарт IAB для доставки видеорекламы. VAST описывает что показать, где отслеживать и как управлять воспроизведением.
📌
VAST 2.0
LEGACY

Базовая версия. Линейные и нелинейные объявления, companion banners. Нет поддержки skip, ограниченный трекинг. Ещё встречается у старых игроков — избегай по возможности.

📌
VAST 3.0
УСТАРЕЛ

Добавил: AdPod (последовательность роликов), skippable ads, расширенный трекинг (progress, skip). Ещё используется, но постепенно вытесняется.

📌
VAST 4.x
АКТУАЛЕН

Текущий стандарт. Добавил: Universal Ad ID, отдельный verification блок (OMID), mezzanine файлы для перекодирования, поддержку InteractiveCreativeFile. Используй 4.2+.

🔗
VAST + VPAID → OMID
ВАЖНО

VPAID (интерактивные видео) официально deprecated. IAB заменил его связкой VAST 4 + OMID (Open Measurement SDK) для viewability и verification без исполнения произвольного кода.


Структура VAST XML
VAST — это XML-документ. Плеер паблишера парсит его и выполняет инструкции.
<VAST version="4.2"> <Ad id="ad-001" sequence="1"> <!-- InLine — весь контент здесь (не Wrapper) --> <InLine> <AdSystem>My DSP 2.0</AdSystem> <AdTitle>Summer Sale 30s</AdTitle> <!-- Universal Ad ID — уникальный ID крeатива --> <UniversalAdId idRegistry="Ad-ID">ABC123</UniversalAdId> <Creatives> <Creative id="cr-001" sequence="1"> <Linear> <!-- Длительность в формате HH:MM:SS --> <Duration>00:00:30</Duration> <!-- Кнопка Skip через 5 сек --> <SkipOffset>00:00:05</SkipOffset> <TrackingEvents> <Tracking event="start">https://dsp.com/track?e=start</Tracking> <Tracking event="firstQuartile">https://dsp.com/track?e=q1</Tracking> <Tracking event="midpoint">https://dsp.com/track?e=mid</Tracking> <Tracking event="thirdQuartile">https://dsp.com/track?e=q3</Tracking> <Tracking event="complete">https://dsp.com/track?e=complete</Tracking> <Tracking event="skip">https://dsp.com/track?e=skip</Tracking> <Tracking event="mute">https://dsp.com/track?e=mute</Tracking> <Tracking event="pause">https://dsp.com/track?e=pause</Tracking> </TrackingEvents> <!-- Impression pixel — засчитывается при старте воспроизведения --> <Impression><![CDATA[https://dsp.com/imp?id=xyz]]></Impression> <MediaFiles> <!-- Несколько форматов — плеер выберет подходящий --> <MediaFile delivery="progressive" type="video/mp4" width="1920" height="1080" bitrate="2500"> <![CDATA[https://cdn.dsp.com/video_1080p.mp4]]> </MediaFile> <MediaFile delivery="progressive" type="video/mp4" width="1280" height="720" bitrate="1200"> <![CDATA[https://cdn.dsp.com/video_720p.mp4]]> </MediaFile> <MediaFile delivery="progressive" type="video/mp4" width="640" height="360" bitrate="600"> <![CDATA[https://cdn.dsp.com/video_360p.mp4]]> </MediaFile> </MediaFiles> <!-- Клик по видео --> <VideoClicks> <ClickThrough><![CDATA[https://advertiser.com/landing]]></ClickThrough> <ClickTracking><![CDATA[https://dsp.com/click?id=xyz]]></ClickTracking> </VideoClicks> </Linear> </Creative> </Creatives> <!-- OMID verification (замена VPAID) --> <Verification vendor="doubleverify.com-omid"> <JavaScriptResource apiFramework="omid" browserOptional="true"> <![CDATA[https://cdn.doubleverify.com/omid.js]]> </JavaScriptResource> </Verification> </InLine> </Ad> </VAST>

🔗 Wrapper Chain — цепочка редиректов
Wrapper — это VAST-документ без видеофайла. Вместо файла он содержит ссылку на следующий VAST-документ. Плеер следует по этой цепочке пока не найдёт InLine с реальным видеофайлом. Каждый прыжок — отдельный HTTP-запрос с задержкой.
💡 Зачем Wrapper вообще нужен?

Каждый участник цепочки хочет добавить свои трекинг-пиксели — impression, quartile, complete. Но финальный VAST (InLine) создаёт DSP, и он не знает о трекинг-URL SSP или Exchange.

Решение: SSP возвращает Wrapper со своими трекерами + ссылкой на Wrapper Exchange, который содержит свои трекеры + ссылку на InLine DSP. Плеер разворачивает цепочку и вызывает пиксели каждого уровня.

⚠️ Почему Wrapper опасен?

Каждый Wrapper = дополнительный HTTP round-trip. При лимите tmax плеера в 5 секунд (типично для pre-roll) и задержке 300–500ms на Wrapper — уже 3 уровня могут исчерпать половину бюджета.

На CTV всё строже: плееры Roku, FireTV часто имеют лимит 3 Wrapper. Превышение → ошибка 302 Wrapper limit reached → No Fill.

Wrapper (SSP — уровень 1)
<VAST version="4.2"> <Ad id="ssp-wrapper"> <Wrapper> <AdSystem>SSP Platform</AdSystem> <!-- Ссылка на следующий уровень --> <VASTAdTagURI> <![CDATA[ https://exchange.com/vast?id=abc ]]> </VASTAdTagURI> <!-- Трекеры SSP — плеер вызовет их ПЛЮС трекеры из InLine --> <TrackingEvents> <Tracking event="impression"> https://ssp.com/imp?id=xyz </Tracking> <Tracking event="complete"> https://ssp.com/complete?id=xyz </Tracking> </TrackingEvents> <!-- Ошибки тоже на всех уровнях! --> <Error> https://ssp.com/error?c=[ERRORCODE] </Error> </Wrapper> </Ad> </VAST>
InLine (DSP — финальный уровень)
<VAST version="4.2"> <Ad id="dsp-inline"> <InLine> <AdSystem>DSP Name</AdSystem> <AdTitle>Summer Sale</AdTitle> <!-- Здесь реальные пиксели DSP --> <Impression> https://dsp.com/imp?id=abc </Impression> <Creatives> <Creative> <Linear> <Duration>00:00:30</Duration> <!-- Здесь реальный видеофайл --> <MediaFiles> <MediaFile type="video/mp4" width="1280" height="720"> https://cdn.com/video.mp4 </MediaFile> </MediaFiles> </Linear> </Creative> </Creatives> </InLine> </Ad> </VAST>
Пример цепочки 2 Wrapper + InLine (нормально) vs 5 Wrapper (проблема):
✅ Нормальная цепочка — 2 Wrapper, ~150ms total
ПЛЕЕР
Запрос VAST
0ms
+50ms
HTTP req
WRAPPER 1 — SSP
pubmatic.com
Трекеры SSP
→ exchange URL
+50ms
HTTP req
WRAPPER 2 — Exchange
openx.com
Трекеры Exchange
→ DSP VAST URL
+50ms
HTTP req
INLINE — DSP
tradedesk.com
MediaFiles + трекеры
✓ video.mp4
❌ Проблемная цепочка — 5 Wrapper, 500ms+, вероятен No Fill (ошибка 302)
ПЛЕЕР
Запрос
0ms
+100ms
W1 — SSP
Trading Desk
+100ms
W2 — Reseller
Intermediary
+100ms
W3 — SSP2
Exchange
+100ms
W4 — Ad Net
Network
+100ms
W5 — DSP
Inner SSP
+100ms
302 ERROR
Wrapper limit
No Fill ❌
💡 Как работает аккумуляция трекеров: Когда плеер разворачивает цепочку Wrapper → InLine, он объединяет TrackingEvents со всех уровней. Если в Wrapper #1 (SSP) есть complete пиксель и в InLine (DSP) тоже есть complete пиксель — плеер вызовет оба при завершении видео. Каждый участник получает свои данные независимо.
🚨 Wrapper depth limit: IAB рекомендует не более 3–4 уровней Wrapper. CTV-плееры часто ограничивают до 3. На практике у плохих паблишеров бывает 5–10 уровней из-за цепочек ресейлеров. Каждый уровень = +50–100ms. Итог: ошибка 302 и потеря показа. Единственное решение — договориться с партнёрами о сокращении цепочки или перейти на InLine VAST напрямую в adm поле Bid Response.

Все Tracking Events
Event Когда срабатывает Важность Примечание
startПервый кадр видео воспроизведёнкритичноОсновной сигнал начала показа. Используется для billing в ряде систем.
firstQuartileПросмотрено 25% длительностиважноQ1 completion. Стандартная метрика engagement.
midpointПросмотрено 50%важно50% completion rate — ключевой KPI видеокампаний.
thirdQuartileПросмотрено 75%важноQ3. Сигнал высокого интереса к ролику.
completeВидео досмотрено до концакритичноVCR (Video Completion Rate). Главный KPI для брендинга. Норма: 70–85% для non-skip.
skipНажата кнопка SkipважноДля skippable форматов. IAB: показ засчитан если смотрели ≥2с или до конца.
mute / unmuteЗвук выключен/включёнбазовоCTV и мобайл часто стартуют с muted. Важно для подсчёта реального viewability.
pause / resumeПауза / возобновлениебазовоEngagement сигнал. Паузу ставят заинтересованные зрители.
fullscreenПереход в полноэкранный режимбазовоСильный engagement сигнал, особенно на мобайле.
progressДостигнут заданный offsetдоп.VAST 3+. Можно задать произвольную точку: offset="00:00:10" или offset="50%".
impressionVAST загружен и начаткритичноНе путать с start! Impression срабатывает при старте воспроизведения — это billing event.
errorЛюбая ошибка воспроизведениякритичноURL с макросом [ERRORCODE]. Обязательно имплементировать для диагностики.
closeLinearПользователь закрыл overlayрекламудоп.Для нелинейных форматов.

VAST Error Codes
Плеер вызывает <Error> URL с макросом [ERRORCODE]. Без обработки ошибок — слепое пятно в диагностике.
<!-- В VAST-документе --> <Error><![CDATA[https://dsp.com/error?code=[ERRORCODE]&imp=xyz]]></Error> // [ERRORCODE] подставляется плеером автоматически // Пример вызова: https://dsp.com/error?code=401&imp=xyz
КодОписаниеЧастая причина
100XML parsing errorКривой XML, незакрытые теги, неэкранированные символы (& вместо &amp;)
101VAST schema validation errorНарушение структуры VAST по IAB XSD
200Trafficking errorНеправильная конфигурация на стороне сервера
201Video player received ad type not expectedПрислали Linear туда, где ожидался NonLinear
300General Wrapper errorПроблема в цепочке Wrapper
301Timeout of VAST URI⚠️ Очень частый. Wrapper не ответил вовремя. Проверь latency серверов.
302Wrapper limit reached⚠️ Превышена глубина Wrapper-цепочки (обычно лимит 3–5)
303No VAST response after redirectСервер вернул пустой ответ или ошибку HTTP
400General linear errorОшибка воспроизведения видеофайла
401File not found⚠️ Очень частый. MediaFile URL недоступен или возвращает 404
402Required media file not foundНет подходящего MediaFile для плеера (формат, размер)
403Cannot play media in sequenceПроблемы с AdPod последовательностью
405Problem displaying MediaFileMIME-тип не поддерживается, кодек несовместим
500General NonLinear errorОшибка overlay/баннера поверх видео
900Undefined errorПлеер не смог классифицировать ошибку

✅ Лучшие практики
🎞
MediaFiles — несколько форматов
DO

Всегда предоставляй минимум 3 варианта MP4: 1080p / 720p / 360p. Плеер сам выберет подходящий по разрешению и скорости соединения. Без низкого битрейта — провалишь мобайл и slow connection.

  • 1080p: 2000–4000 kbps (CTV, Desktop)
  • 720p: 1000–2000 kbps (планшеты)
  • 360p: 400–800 kbps (мобайл, слабый интернет)
  • Формат: H.264 (AVC) — универсальная поддержка
🔒
Только HTTPS
DO

Все URL в VAST — MediaFile, трекеры, ClickThrough — должны быть https://. HTTP-ресурсы блокируются браузерами в secure context. Одна HTTP-ссылка в цепочке = ошибка 401 или mixed content.

CDN для видеофайлов
DO

MediaFile URL должен отдавать файл с CDN с TTFB < 200ms. Плеер начинает буферизацию сразу. Медленный origin-сервер → ошибка 401/buffering → пользователь уходит. Используй CloudFront, Fastly, Akamai.

🧪
CDATA для URL
DO

Оборачивай все URL в <![CDATA[...]]>. Это защищает от проблем с символами &, <, > в query parameters. Без CDATA — XML сломается при наличии UTM-меток.

📏
Universal Ad ID
DO

Всегда указывай UniversalAdId в VAST 4. Это уникальный идентификатор крeатива в системах типа Ad-ID или EIDR. Позволяет трекать один и тот же ролик через разные DSP/SSP без конфликтов дедупликации.

📡
Error tracking — обязательно
DO

Имплементируй <Error> URL на всех уровнях — и в Wrapper, и в InLine. Без него ты слеп: не знаешь причину потери показов. Анализируй коды 301, 302, 401 — они самые частые.

❌ Что не делать
🚫
Глубокие Wrapper-цепочки
DON'T

Не создавай цепочки глубже 3 уровней. Каждый Wrapper — дополнительный round-trip. 5+ уровней = 500ms+ latency = ошибка 302 на большинстве плееров. Если нужны трекеры — добавляй их в один Wrapper, не плоди редиректы.

🚫
VPAID в 2024+
DON'T

VPAID официально deprecated. Исполняет произвольный JS в плеере → security risk, нестабильность, блокировка на CTV. Замени на VAST 4 + OMID для viewability и InteractiveCreativeFile для интерактивности.

🚫
Один MediaFile без fallback
DON'T

Один файл = одна точка отказа. Если он недоступен или формат не поддерживается — ошибка 401/402 и No Fill. Минимум 2–3 MediaFile разного битрейта. Для CTV добавляй HLS как отдельный MediaFile.

🚫
Спецсимволы без CDATA
DON'T

URL с &utm_source=... без CDATA сломает XML-парсер → ошибка 100. Это одна из самых частых и глупых ошибок. Правило: любой URL в VAST — только в CDATA.

🚫
Только один трекер impression
DON'T

В VAST можно указать несколько <Impression> тегов — плеер вызовет все. Используй это для независимого трекинга от разных систем (DSP + верификация + analytics), не пытайся впихнуть всё в один URL.

🚫
Не тестировать на CTV
DON'T

CTV-плееры (Roku, FireTV, Samsung Tizen) намного строже к VAST чем браузеры. Они не прощают лишние пробелы в XML, неподдерживаемые кодеки, WebM-форматы. Тестируй отдельно с помощью IAB VAST Inspector или Google Video Suite Inspector.


VAST в контексте OpenRTB
💡 В Bid Response DSP передаёт VAST либо напрямую в поле adm (inline VAST XML как строка), либо через поле adm с VAST Wrapper URL. Плеер паблишера получает его от SSP и начинает разворачивать цепочку.
// Вариант 1: VAST XML прямо в adm (inline) { "adm": "<VAST version=\"4.2\">...</VAST>", "price": 4.50 } // Вариант 2: VAST Wrapper URL в adm { "adm": "<VAST version=\"4.2\"><Ad><Wrapper><VASTAdTagURI><![CDATA[https://dsp.com/vast?id=xyz]]></VASTAdTagURI></Wrapper></Ad></VAST>", "price": 4.50 } // В imp объекте bid request для видео: "video": { "mimes": ["video/mp4"], "minduration": 5, "maxduration": 30, "protocols": [2, 3, 5, 6, 7, 8], // 2=VAST2, 3=VAST3, 5=VAST2+Wrapper, 6=VAST3+Wrapper, 7=VAST4, 8=VAST4+Wrapper "w": 1920, "h": 1080, "startdelay": 0, // 0=pre-roll, -1=mid-roll, -2=post-roll "skip": 1, // 1=skippable разрешён "skipmin": 15, // минимальная длина для skip кнопки "skipafter": 5, // через сколько секунд появляется skip "linearity": 1, // 1=linear (pre/mid/post-roll), 2=non-linear "placement": 1 // 1=in-stream, 2=in-banner, 3=in-article }
⚠️ Инструменты для диагностики VAST: Google Video Suite Inspector, IAB VAST Validator, JW Player VAST Tester. Всегда прогоняй новый VAST через валидатор перед запуском кампании — это экономит часы отладки.