Почему проиграл аукцион RTB: коды loss reason и min_to_win
Аукцион проигрывают по трем группам причин: ставка оказалась ниже конкурента или флора (цена), ответ не прошел проверки биржи (креатив, формат, блокировки) либо не уложился во время (таймаут, техническая ошибка). Биржа сообщает причину через уведомление о проигрыше lurl и макрос ${AUCTION_LOSS}, а при ценовом проигрыше может подсказать, сколько не хватило, — макросом ${AUCTION_MIN_TO_WIN}.
Как биржа сообщает о проигрыше: lurl и макросы
В OpenRTB DSP сама задает адреса уведомлений в каждой ставке. Для выигрыша это nurl (см. win notice) и burl, для проигрыша — lurl. Спецификация определяет lurl как адрес, который биржа вызывает, когда известно, что ставка проиграла. Поле появилось в версии 2.5 вместе с макросом ${AUCTION_LOSS}; макрос ${AUCTION_MIN_TO_WIN} добавлен в 2.6.
{
"id": "resp-1",
"seatbid": [{
"bid": [{
"id": "b-1",
"impid": "1",
"price": 120.0,
"crid": "cr-42",
"nurl": "https://dsp.example/win?a=${AUCTION_ID}&p=${AUCTION_PRICE}",
"burl": "https://dsp.example/bill?a=${AUCTION_ID}&p=${AUCTION_PRICE}",
"lurl": "https://dsp.example/loss?a=${AUCTION_ID}&l=${AUCTION_LOSS}&m=${AUCTION_MIN_TO_WIN}"
}]
}],
"cur": "RUB"
}
Перед вызовом биржа ищет в URL макросы и подставляет значения. Если значения нет (например, цена выигрыша не раскрывается), макрос заменяется пустой строкой — обработчик на стороне DSP должен это переживать.
| Макрос | Что подставляется | С какой версии |
|---|---|---|
${AUCTION_LOSS} |
Код причины проигрыша из списка Loss Reason Codes | 2.5 |
${AUCTION_MIN_TO_WIN} |
Минимальная ставка, нужная для выигрыша, в валюте и единицах ставки | 2.6 |
${AUCTION_PRICE} |
Цена клиринга; при проигрыше обычно пустая | ранние версии |
${AUCTION_ID} |
BidRequest.id — ключ для склейки с логом ставки |
ранние версии |
Важно. Поддержка
lurl— политика конкретной биржи. Спецификация прямо допускает, что биржа не шлет уведомления о проигрыше или не раскрывает цены. Отсутствиеlurlне значит, что вы все выиграли.
Коды причин проигрыша: что означает каждый
Список Loss Reason Codes впервые появился в OpenRTB 2.5 (раздел 5.25), в версии 2.6 перечисления вынесены в справочник AdCOM, а описание макроса ${AUCTION_LOSS} ссылается на список из OpenRTB 3.0. Коды сгруппированы по сотням.
| Код | Название | Группа | Что это значит на практике |
|---|---|---|---|
| 0 | Bid Won | — | Ставка выиграла (служебный код) |
| 1 | Internal Error | Техническая | Ошибка на стороне биржи |
| 2 | Impression Opportunity Expired | Техническая | Ответ опоздал, показ уже ушел |
| 3 | Invalid Bid Response | Техническая | Ответ не разобрался или не прошел валидацию |
| 4 | Invalid Deal ID | Техническая | Ставка с dealid, которого нет в запросе |
| 5 | Invalid Auction ID | Техническая | Ответ не соответствует запросу |
| 6 | Invalid Advertiser Domain | Техническая | Нет или неверен adomain |
| 7 | Missing Markup | Техническая | Нет adm и нет способа получить разметку |
| 8 | Missing Creative ID | Техническая | Нет crid |
| 9 | Missing Bid Price | Техническая | Нет цены |
| 10 | Missing Minimum Creative Approval Data | Техническая | Не хватает данных для модерации креатива |
| 100 | Bid was Below Auction Floor | Ценовая | Ставка ниже флора площадки |
| 101 | Bid was Below Deal Floor | Ценовая | Ставка ниже флора сделки |
| 102 | Lost to Higher Bid | Ценовая | Кто-то предложил больше |
| 103 | Lost to a Bid for a Deal | Ценовая | Приоритет отдан ставке по сделке |
| 104 | Buyer Seat Blocked | Блокировка | Место покупателя заблокировано |
| 200–215 | Creative Filtered — … | Креатив | Креатив отфильтрован: модерация, размер, формат, категория, атрибуты, язык, рекламодатель, приложение |
| 500+ | — | Своя у биржи | Значения конкретной биржи, их описание должно быть передано покупателю заранее |
Внутри группы 200 полезно различать: 201 — креатив еще на модерации или перекодировании, 202 — отклонен биржей, 203 — размер не разрешен, 204 — неверный формат, 205 — исключения по рекламодателю, 206 и 215 — исключения по магазину или bundle ID приложения, 207 — небезопасный (не HTTPS) креатив, 209 — исключенная категория, 210 — запрещенные атрибуты, 213 — креатив не разрешен в сделке.
min_to_win: сколько не хватило
${AUCTION_MIN_TO_WIN} отвечает на главный вопрос медиабайера: «на сколько надо было поднять ставку». Спецификация 2.6 описывает три случая:
- ставка проиграла другой ставке — подставляется минимальная цена, при которой вы сравнялись бы с победителем;
- ставка выиграла — минимальная цена, чтобы сравняться со следующей по величине ставкой или с флором, если ставка была одна;
- биржа не хочет или не может раскрыть цену — пустая строка.
Пустое значение допустимо, когда ставку не пустили на торги (блокировки места или рекламодателя), когда по коду проигрыша цена не была решающей или когда так требуют правила приватности.
Пример: одна и та же тройка ставок в двух типах аукциона
Флор 50 ₽ за тысячу показов, три конкурирующие ставки — 80, 72 и 60 ₽. Для наглядности считаем, что во второй цене клиринг равен второй ставке плюс 0,01 ₽.
| Ставка, ₽ CPM | Первая цена: AUCTION_PRICE |
Первая цена: MIN_TO_WIN |
Вторая цена: AUCTION_PRICE |
Вторая цена: MIN_TO_WIN |
|---|---|---|---|---|
| 80 | 80 | 72 | 72,01 | 72 |
| 72 | пусто | 80 | пусто | 72,01 |
| 60 | пусто | 80 | пусто | 72,01 |
В первой цене проигравшему с 72 ₽ сообщают 80 ₽: чтобы выиграть, нужно было сравняться с победителем. Во второй цене иллюстрация спецификации дает проигравшим цену клиринга. Победитель в первой цене узнает, что переплатил: хватило бы 72 ₽. Этот сигнал — сырье для bid shading.
Флоры: проигрыш еще до сравнения ставок
Коды 100 и 101 значат, что ставка не дотянула до минимальной цены. Флор приходит в запросе: imp.bidfloor и imp.bidfloorcur для открытого аукциона, deal.bidfloor для сделки (см. что такое bidfloor). Для видео и аудио OpenRTB 2.6 добавил флоры за секунду (mincpmpersec) и по длительности (durfloors).
Типичные ошибки, которые дают код 100 без видимой причины:
- Валюта.
bidfloorcurпо умолчанию — USD. Если биржа прислала флор в одной валюте, а DSP ставит в другой без пересчета, ставка «проваливается». - Единицы.
priceиbidfloor— это CPM, цена за тысячу. Ставка «за показ» вместо CPM в тысячу раз ниже. - Флор сделки. Для ставки с
dealidдействуетdeal.bidfloor, а не флор показа — проигрыш будет с кодом 101.
Если ставка выше флора из запроса, а код 100 все равно приходит, значит, у площадки есть правила, которых нет в запросе. Это вопрос к SSP, а не к стратегии.
Таймауты и технические причины
Код 2 — ответ пришел, когда показ уже разыгран. Бюджет времени задает поле tmax: максимальное время в миллисекундах, за которое биржа ждет ставки, включая сетевую задержку. Опоздавший ответ биржа может вообще не учесть, и тогда lurl не придет — смотрите собственные метрики таймаутов. Подробно — в статье «tmax и задержки в RTB».
Коды 3–10 — ошибки в ответе: нет adm, crid, adomain, неверный dealid. Они чинятся один раз в коде и обычно дают резкий скачок win rate без изменения ставок.
Фильтрация креатива (200–215)
Это самая «дешевая» потеря: деньги не тратятся, но показ не случается. Частые сценарии:
- креатив новый и еще на модерации у биржи (201) — проигрыши уйдут сами;
- креатив отклонен (202) — нужно запросить причину у SSP;
- размер не совпадает с
banner.formatв запросе (203) — проверьте, что вы отвечаете на размер из запроса; - креатив по HTTP при требовании HTTPS (207);
- категория или атрибуты креатива в списках
bcatиbattrзапроса (209, 210) — DSP должна фильтровать такие запросы до ставки; - рекламодатель в
badvили приложение вbapp(205, 206, 215).
Как превращать loss reason в действия
| Доминирующая причина | Действие | Чего не делать |
|---|---|---|
| 102 — проиграли более высокой ставке | Смотреть распределение min_to_win, повышать ставку там, где отрыв мал |
Повышать ставку на всех площадках разом |
| 100/101 — ниже флора | Сверить валюту и единицы; отключить площадки, где флор выше ценности показа | Поднимать ставку до флора, не считая окупаемость |
| 103 — проиграли сделке | Принять как данность или договариваться о сделке | Пытаться перебить сделку ценой |
| 2 — опоздали | Профилировать задержку, урезать работу на горячем пути | Игнорировать: это платный трафик, который вы уже обработали |
| 3–10 — невалидный ответ | Исправить формирование ответа | Ждать, что пройдет само |
| 200–215 — креатив отфильтрован | Модерация, размеры, HTTPS, учет bcat/battr/badv/bapp |
Поднимать ставку |
Пример разбора
Допустим, за сутки DSP сделала 10 000 ставок на одном слоте, выиграла 1 800 и получила 7 400 уведомлений о проигрыше (на остальные 800 ставок уведомления нет). Разбивка: 102 — 5 200, 100 — 1 300, 2 — 600, 202 — 300. Выводы:
- 300 проигрышей с кодом 202 — один отклоненный креатив, исправляется без денег;
- 600 таймаутов — 6 % ставок, работа для инженеров;
- 1 300 проигрышей по флору — проверить валюту; если все верно, флор слота выше вашей оценки показа;
- по 5 200 ценовым проигрышам смотрим
min_to_win: если медиана на 5 % выше ваших ставок, точечный подъем даст больше выигрышей, чем общий.
Цифры здесь условные — важен порядок разбора: сначала бесплатные причины, потом цена.
Почему уведомления приходят не всегда
- Биржа не поддерживает
lurlили шлет его только части покупателей. - Ставку отсеяли до аукциона, и биржа считает, что «проигрыша» не было.
- Уведомление — обычный HTTP-запрос по открытой сети: часть теряется, часть может прийти повторно. Обработчик должен быть идемпотентным, а склейка с логом ставок — идти по
${AUCTION_ID}и id ставки. - Цена не раскрывается:
${AUCTION_PRICE}и${AUCTION_MIN_TO_WIN}пустые по политике площадки.
Поэтому win rate считают от числа ставок, а не от суммы «выигрыши + проигрыши из lurl».
Причины проигрыша в отчетах Ibiza
DSP Ibiza в каждой ставке указывает lurl с макросами ${AUCTION_LOSS}, ${AUCTION_MIN_TO_WIN}, ${AUCTION_PRICE} и ${AUCTION_ID} и записывает пришедшие уведомления отдельно от выигрышей. На бюджеты и лимиты проигрыш не влияет — он нужен для аналитики. В расчет снижения ставки идут только ценовые проигрыши с кодом 102 и непустым min_to_win: bid shading считает по ним квантили для пары «объявление × слот» и добавляет маржу, а автобид калибрует ставку под целевой win rate. Какие макросы подставлять в трекеры, описано в документации: макросы и трекеры, снижение ставки (bid shading).
Частые вопросы
Что такое lurl в OpenRTB?
Это поле bid.lurl в ответе DSP: адрес, который биржа вызывает, когда точно известно, что ставка проиграла. Поле появилось в OpenRTB 2.5, в URL можно подставить макросы ${AUCTION_LOSS} и ${AUCTION_MIN_TO_WIN}.
Что означает код проигрыша 102?
Lost to Higher Bid — ставка прошла все проверки, но другой покупатель предложил больше. Это единственная причина, которую лечат именно ценой.
Почему ${AUCTION_MIN_TO_WIN} приходит пустым?
Спецификация разрешает бирже не раскрывать значение: если ставку не допустили к торгам, если цена не была причиной проигрыша или так требуют правила приватности площадки.
Можно ли выигрывать чаще, не поднимая ставку?
Да, если проигрыши не ценовые: отклоненный креатив, неверный размер, таймаут или блокировки рекламодателя лечатся исправлением креатива и интеграции, а не деньгами.