← Гордеев Виталий · все кейсы
Кейс · 2026
Яндекс.Директ · API · РСЯ и поиск

Реклама, которую ведёт скрипт

Клуб, ресторан, гостиница, магазин цифровых товаров и студия сайтов. Кампании для них я собираю, чищу и правлю скриптами через API Директа: семантика, сотни ключей, минус-фразы, тысячи запрещённых площадок. Самое неприятное, что я тут выяснил: API молча принимает ошибки, и ловить их приходится по отчётам.

5проектов с кампаниями поиска и РСЯ
1 000запрещённых площадок в каждой из 4 кампаний РСЯ магазина
614ключей пересобрано в поиске студии за один проход
~4 сна применение списка площадок, никакой «задержки API» не было
01 · Устройство

Один помощник
на всё API

SDK не использую, к API Директа обращается одна короткая функция. Если сервер вернул ошибку HTTP, функция отдаёт её как обычные данные, и пачка из сотни операций не падает на первой же.

Семантику снимаю из Вордстата через браузерную автоматизацию на живой сессии Яндекса. Кампании, группы, объявления и ключи создают скрипты. Отчёты по поисковым запросам и кампаниям приходят асинхронно: сначала API отвечает «готовлю», и скрипт спрашивает снова, пока отчёт не будет готов.

Площадки РСЯ, которые приносят мусорные клики, раз в неделю вычищаются автоматически. Для кампаний магазина я собрал архив из 2 081 площадки без повторов и залил в каждую кампанию сколько позволяет Директ: тысячу запретов.

Картинки для объявлений рисует тот же код, что и карточки товаров для витрины ВКонтакте, поэтому выглядят они везде одинаково.

tools/direct/cd_direct.py · дословно
def call(svc, method, params):
    body = json.dumps({"method": method, "params": params}, ensure_ascii=False)
    req = urllib.request.Request(
        "https://api.direct.yandex.com/json/v5/" + svc, data=body.encode("utf-8"),
        headers={"Authorization": "Bearer " + TOK, "Accept-Language": "ru",
                 "Content-Type": "application/json; charset=utf-8"})
    try:
        return json.loads(urllib.request.urlopen(req, timeout=120).read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        return {"http_error": e.code, "body": e.read().decode("utf-8")[:400]}
PythonYandex Direct API v5Reports APIВордстатPlaywrightPillow
02 · Разбор

Пять ошибок,
которые не видно в кабинете

Во всех пяти случаях кампания выглядела рабочей, ничего не останавливалось. При этом деньги уходили не туда или не тратились вовсе.

01

259 ₽ за день на «валдбериес купить»

Симптом
Поиск студии сайтов открутился по запросам про маркетплейсы, хотя ни одного такого запроса в ключах не было.
Причина
Автотаргетинг. В каждой группе он живёт скрытой строкой среди ключей. В РСЯ его можно выключить через API, а на поиске API отвечает ошибкой 8305 и не выключает.
Проверил отчётом по поисковым запросам: в нём видно тип условия показа, и эти показы шли от автотаргетинга. Теперь перед запуском поиска первым делом смотрю автотаргетинг.
02

Ноль показов при любой ставке

Симптом
Поиск студии не показывался вообще. Три раза подряд поднимали ставку, думали, что проигрываем аукцион.
Причина
641 ключ из 650 стоял в кавычках. Кавычки включают точное соответствие, и объявление показывается, только если человек наберёт ровно эту фразу.
614 ключей без кавычек, все в статусе «допущен». Текст ключа через API поменять нельзя, так что удалял и добавлял заново, группа за группой.
03

Три месяца рекламы в Астрахани

Симптом
Группы с акциями будних дней клуба в Самаре за три месяца набрали от 40 до 114 показов и ни одного клика.
Причина
В коде по умолчанию стоял регион 37 с комментарием «37 = Самара». Только под номером 37 у Директа Астрахань, а Самара идёт под 51.
Исправил регион в двух местах кода и перевёл пять групп. Регион теперь проверяю запросом к API, комментариям в коде не верю.
04

Запрещённые площадки «не сохранялись»

Симптом
Список отправлен, ответ без ошибок, а в кампании пусто. Полдня казалось, что у API задержка.
Причина
Список надо передавать внутри поля Items, в другом формате API его молча игнорирует. К тому же обновление заменяет весь список, и старые записи пропадают.
Скрипт забирает текущий список, добавляет к нему новые площадки и записывает всё разом. Уходит на это четыре секунды.
05

Второй заголовок молча пропадал

Симптом
Объявления создавались, но без второго заголовка. Из следов было только предупреждение «поле не применено».
Причина
Лимит в 56 символов считается на оба заголовка вместе.
Пересчитал заголовки под общий лимит и встроил в скрипт проверку длины до отправки.
что я проверяю теперь перед запуском
# 1. Автотаргетинг выключен (на поиске — руками в кабинете)
# 2. Ключи без кавычек, если не нужно точное соответствие
# 3. Регион — запросом к API, не по комментарию в коде
# 4. Минус-фразы не режут собственные ключи
# 5. Title + Title2 ≤ 56 символов вместе
# 6. Минус-слова и площадки — дополнять, не перезаписывать
03 · Правила

Как не сливать бюджет

В рекламе ошибка сразу стоит денег, в остальных моих проектах так не бывает. Поэтому и правила тут строже.

01

Не верить «ошибок нет»

Если API не вернул ошибку, это ещё ничего не значит. Результат смотрю в отчёте: по каким запросам объявление правда показывалось.

02

Обученную кампанию не трогать

Кампания клуба девять месяцев училась на конверсиях, и смена стратегии обнулит обучение. Такое меняю только после прямого «да» от владельца.

03

Списки только дополнять

Минус-слова и запрещённые площадки при обновлении заменяются целиком. Поэтому сначала читаю текущий список, объединяю с новым и только потом записываю.

Реклама крутится, а заявок нет?

Проверю кампании по отчётам и найду, куда уходят деньги. Могу собрать и новые, скриптами: так меньше ошибок, чем при ручной настройке. Работаю удалённо, из Самары.

Telegram · @vitaldemort