Commit Graph

5 Commits

Author SHA1 Message Date
Дмитрий f2bfe3f1da fix реклама Яндекса: пять поломок, которые вскрыл первый живой запуск связки портал-робот-кабинет
Ни одну нельзя было увидеть без настоящего прогона: часть закрыта песочницей Яндекса,
часть — швами между кусками, которые по отдельности покрыты тестами.

1. Слепок креативов уходил с SelectionCriteria пустым МАССИВОМ. Живой Яндекс отвечает
   отказом 8000 «SelectionCriteria cannot contain an array», портал не может снять слепок,
   задание роботу не выдаётся, клиент видит вечное «готовим картинки». В JSON нужен пустой
   ОБЪЕКТ. Песочница до этой проверки не доходила — отвергала запрос раньше, на входе.

2. Отказы Яндекса ПО ПОЗИЦИИ внутри ответа глотались молча. Запрос успешен, а нужного Id
   в позиции нет — вместо него Errors с человеческим объяснением. Портал падал ошибкой PHP
   «Undefined array key Id», ни клиенту, ни в журнал не попадало ни слова из ответа Яндекса.
   Теперь слова Яндекса выходят наружу — именно это и позволило найти пункт 3.

3. В условии ретаргетинга не передавался MembershipLifeSpan — срок хранения человека
   в сегменте. Живой Яндекс отказывает «Required field: Not specified time for goal or
   segment», и следом «Object not found»: довод негоден целиком, запуск встаёт. Берём
   audience_days кампании, границы Яндекса 1..540.

4. Робот не отдавал набор Яндексу: заливал файлы, нажимал «Создать» и уходил. Оказалось,
   «набор» в кабинете и «креатив» в creatives.get — разные вещи: пока набор не отмечен
   галочкой и не нажато «Добавить выбранные», Яндекс креативы не регистрирует. Замер:
   14 залитых картинок были невидимы для creatives.get, после добавления в ЧЕРНОВИК формы
   счётчик прыгнул 18 -> 32 в ту же секунду. Объявление при этом не сохраняется,
   «Сохранить изменения» робот по-прежнему не трогает никогда.

5. Гонка при заливке. Три живых прогона подряд из 15 картинок доносили 14, и каждый раз
   пропадала ДРУГАЯ: 480x320, потом 300x600, потом 336x280. Замер объяснил: кнопка
   «Создать» разблокируется на 4-й секунде, когда принято 11 файлов из 15, остальные
   дозагружаются к 7-й. Робот жал сразу по разблокировке. Ждём теперь по строкам принятых
   файлов и по исчезновению слова «Загружается».

   Первая попытка этой починки НЕ РАБОТАЛА и выглядела рабочей: сторож считал размеры
   в окне, не заметив постоянного фильтра из тех же 15 размеров вверху. Поймано по тому,
   что прогон занял ровно столько же секунд, сколько до починки. Отсюда тире в признаке
   приёма — фильтр его не содержит.

Каждая починка закрыта тестом, который сначала падал на своей поломке. Прежние тесты
проверяли разбор ОТВЕТОВ и путь ДО «Создать» — форму запросов и то, что после, не смотрел
никто. Робот 84 из 84, реклама портала 42 из 42.

Проверено живьём на боевом: задание роботу отработало со статусом done, опознано
15 креативов из 15.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 07:14:33 +03:00
Дмитрий abb3941ec0 feat реклама за показы: удаление отклонённых объявлений в кабинете Яндекса 2026-07-28 11:10:54 +03:00
Дмитрий 0548fc0d8f fix реклама за показы: слепок креативов при выдаче, сверка размера перед объявлением, один баннер на слот
Хвосты портала П1-П8 из приёмочного листа v12.

П1 обрыв постановки задания больше не даёт клиенту голый 500 — 503 с человеческим
текстом и записью в журнал. Таймаут у HTTP-клиента Laravel уже был, эта половина
находки не подтвердилась.

П2 и П6 роботу отдаются только баннеры без номера креатива — тот же список
сопоставляется при отчёте. Раньше стороны расходились и опознание падало на
безупречной работе робота, плодя дубли в кабинете. Плюс постраничный обход описи
креативов: слепок обрывался на первой странице.

П3 слепок «до» снимается при выдаче задания, а не при постановке, и в той же
транзакции, что и перевод в работу. Два задания в очереди получали одинаковый
слепок, второе падало всегда. Постановка перестала зависеть от живости Яндекса.

П4 перед созданием объявлений сверяется настоящий размер каждого креатива одним
запросом. Не сошлось или креатива нет — запуск не идёт.

П5 уникальный индекс uq_ad_campaign_banner_slot, запись v9.09 в CHANGELOG схемы,
rls-reviewer GO.

П7 замок на правку расширен на сегмент Аудиторий — он создаётся раньше кампании.
Смежная находка: перезаливка картинки теперь обнуляет номер креатива.

П8 и Р-х5 файл отдаётся под настоящим расширением и типом содержимого, имя от
номера баннера; робот берёт расширение из ответа портала.

Портал 287/287, робот 43/43. Денежных выходов снятия заморозки по-прежнему четыре.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 05:37:56 +03:00
Дмитрий c9406533bf feat реклама показы: ядро переведено на набор креативов вместо одного адаптивного
Конструктор креативов Яндекса закрыт 01.06.2026 — адаптивного креатива на все
размеры не существует. Медийная кампания состоит из объявления на каждый размер
блока со своим креативом, поэтому строка баннера стала единицей
размер плюс файл плюс креатив плюс объявление.

Что сделано:
- у баннера появились номер креатива, номер объявления и статус модерации
- кап веса баннера поднят со 150 КБ до предела Яндекса 512 КБ
- слепок картиночных креативов аккаунта через creatives.get
- опознание своих креативов разницей слепков до и после загрузки по размеру
- запуск заводит объявление на каждый включённый баннер
- модерация считается по каждому объявлению: кампания работает, если принято
  хотя бы одно, а деньги возвращаются только когда отклонены все

Заморозка и возврат денег не тронуты, денежных выходов по-прежнему четыре.

После выката на прод ПЕРЕзапустить db/03_service_bypass_policies.sql, иначе
джоб модерации молча увидит ноль баннеров.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 14:33:02 +03:00
Дмитрий 12ef186a43 feat(реклама): показы — медийные методы клиента Директа для запуска за показы
Аддитивно в YandexDirectClient пять методов под медийную кампанию, старый клик-путь не тронут:
- addCpmBannerCampaign — CpmBannerCampaign, стратегия CP_MAXIMUM_IMPRESSIONS, FrequencyCap, суммы в микросах
- addCpmBannerAdGroup — пустая группа CpmBannerKeywordsAdGroup как JSON-объект {}, регионы
- addMediaAudienceTarget — привязка сегмента к группе без клик-ставки ContextBid
- addCpmBannerAd — объявление CpmBannerAdBuilderAd по номеру готового креатива + href
- getCreativePreview — превью креатива для показа клиенту, null если не найден

Всё за рубильником, к реальному Яндексу не обращается. Тесты Http::fake 7/7 зелёные,
весь реклама-модуль 186/186 не сломан. Контракт — findings 2026-07-26-direct-media-api-contract.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-26 23:53:31 +03:00