Перейти к основному содержимому
megapromotingДавайте обсудим

Экспертиза · Маркетинговые автоматизации

Рабочая среда, в которой агент, который занимается вашими кампаниями Google Ads и Meta, читает отчёты, предлагает изменение с записанной причиной и выполняет только в пределах, которые вы ему задали.

Сервис — это предложение, а не реализация, и мы говорим это первыми: сегодня у нас нет системы, которая меняет бюджеты или ставки в Google Ads или Meta. У нас построены и запущены части, из которых такая система делается — отправка сигнала о реальной конверсии в Google, движок, который покупает платное продвижение с dry-run, включённым по умолчанию, реестр, который записывает каждое действие, которое стоит денег, и выключатель, который останавливает orchestrator без обходного пути.

Предложение с условиями«offer», а не «delivered», и причину можно проверить за несколько секунд. Мы искали в более чем 150 собственных репозиториях поля, через которые рекламные API двигают деньги: `budget_micros`, `campaignBudget`, `target_cpa`, `target_roas`, `bid_strategy` — и они нигде не встречаются, ни у Google, ни у Meta. Сегодня мы не управляем рекламными бюджетами. Что есть, и что можно открыть файл за файлом, — это детали, которые отделяют автоматизацию от аварии: отправка офлайн-конверсий в Google через Data Manager API, 264 строки в нашем production-проекте; движок платного продвижения, который покупает boostere, etichete и pachete при включённом по умолчанию dry-run; байесовский A/B-тестер, который отказывается объявлять победителя при менее чем 100 показах на вариант, и оркестратор кампаний в MEGA CRM с выключателем без `--force`. Сервис описан этими деталями. Не панелью, которой не существует.

Агент, который занимается кампаниями, — это не кнопка с надписью «optimizează». Это программа, которой разрешено читать определённые отчёты, разрешено писать определённые поля и больше ничего. Сложная часть не в том, чтобы предложить изменение — модели делают это хорошо и быстро. Сложная часть в том, чтобы написать, где оно останавливается, как оно доказывает, что сделало, и что происходит, когда оно ошибается. Об этом работа, и с этого мы начинаем обсуждение.

Мы с самого начала говорим, чего у нас нет, чтобы вы не узнали это от кого-то другого. Сегодня у нас не работает система, которая поднимает бюджет в Google Ads или меняет ставку в Meta. Что работает, и что можно показать строка за строкой, — это механизмы безопасности, которые мы написали для других автоматизаций, которые тратят реальные деньги: dry-run, включённый по умолчанию, счётчик на каждое платное действие, задержка при ошибке, чтобы ошибка не повторялась в цикле, порог доказательства перед решением, и выключатель, который отказывается запускать оркестратор.

Часть, которая у нас уже собрана, — это не изменение бюджета, а сигнал, и именно с него мы предлагаем начать. Google учится на том, что вы называете конверсией. Если вы говорите ему «форма отправлена», он будет искать людей, которые отправляют формы. Мы написали интеграцию, которая говорит ему «запрос реально дошёл до системы клиента», с идентификатором клика и с идентификаторами пользователя, переданными через SHA-256, через Data Manager API. С этого можно начинать сразу, потому что это существующий код, а не обещание.

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

Что входит

Работа, по составляющим

Читайте отчёты, а не панель

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

Предлагайте изменение с записанным рядом мотивом

Предложение — это не цифра. Это поле, которое меняется, старое значение, новое значение, окно данных, по которому было принято решение, и почему. Предложения собираются в отчёт, который читает человек, в форме «я бы поднял дневной бюджет кампании X с A до B, потому что за последние N дней она была ограничена бюджетом в M% аукционов, при стоимости привлечения ниже согласованного порога». Если причину нельзя записать, предложение не делается.

Три порога: что делает сам, что требует человека, чего не делает никогда

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

Dry-run включён по умолчанию — шаблон, который мы приносим с собой

В нашем двигателе платного продвижения на 999.md функция, которая решает, тратить ли деньги, написана наоборот по сравнению с обычным способом: dry-run активен, если переменная среды не имеет точно значения `false`. Не задана, пустая, `true`, записана с ошибкой — всё это оставляет dry-run включённым. Это осознанный выбор: ошибка в настройке не может открыть кран, она может только оставить его закрытым. Та же функция есть в двух независимых местах — в двигателе продвижения и в исполнителе перепубликации.

Каждое действие, которое стоит денег, записывается в журнал

В системе продвижения любое выполнение попадает в таблицу `agent_costs` с объявлением, пользователем, типом действия, суммой в леях, признаком успешности, сырым ответом поставщика и меткой `dry_run`. Запись делается в той же транзакции, что и обновление расписания, поэтому не может существовать расхода без следа или следа без расхода. Когда это dry-run, записанная сумма равна нулю, но строка существует — видно точно, что бы произошло.

Сигнал реальной конверсии — элемент, который уже существует

Когда кто-то приходит из платного клика и отправляет запрос, сигнал уходит в Google только после того, как запрос попадает в систему клиента, а не при нажатии кнопки. Интеграция использует `https://datamanager.googleapis.com/v1/events:ingest`, передаёт идентификатор клика, момент времени, значение и валюту, а также идентификаторы пользователя, пропущенные через SHA-256 — нормализованный адрес в нижнем регистре, телефон, приведённый к международному формату. Без идентификатора клика отправка останавливается сама и помечается как пропущенная, потому что она не была бы атрибутируемой.

Согласие ставится до тегов, а не после

Consent Mode v2 инициализируется со всеми целями маркетинга и аналитики в состоянии `denied` до запуска какого-либо скрипта Google, с окном ожидания 500 ms для обновления. Оно переводится в `granted` только при взаимодействии человека с баннером, без перезагрузки страницы. Функциональное и защитное хранилище остаются включёнными, потому что без них страница не работает. Это написано один раз и работает при каждом визите.

Решение между двумя вариантами принимается на основе доказательств, а не впечатления

Созданный нами A/B-тестер моделирует каждый вариант как Beta-Binomial с равномерным prior и оценивает вероятность того, что один лучше другого, по 10.000 выборкам Monte Carlo. Он не объявляет победителя при менее чем 100 показах на вариант и при вероятности ниже 0,95. Если через 168 часов решение не принято, он закрывает эксперимент и сообщает, что срок истёк, вместо того чтобы называть победителем то, что не может обосновать.

Переключатель, который нельзя обойти

Оркестратор кампаний в нашей внутренней системе проверяет переменную среды перед чем-либо. Если она задана, он отказывается запускаться — нет `--force`, нет аргумента, который мог бы это обойти. Он был добавлен после реального инцидента с дублирующими отправками, а не для вида. Здесь используется тот же шаблон: переключатель на уровне аккаунта, который останавливает все записи, оставляя чтение и отчётность продолжать работу.

Как это выглядит

Путь, шаг за шагом.

01

Инвентаризация аккаунтов и прав

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

02

Слой чтения, запускаемый сам

Чтение подключается через API с аккаунтом, который не имеет права записи, и запускается ежедневный отчёт. На этом этапе в аккаунтах ничего не меняется — видно только то, что видит агент. Именно тогда выявляются конверсии, которые считали неправильно, кампании, ограниченные бюджетом без ведома кого-либо, и пересекающиеся аудитории. Мы поставляем: ежедневный отчёт и список того, что мы нашли при чтении.

03

Сигнал реальной конверсии

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

04

Слой предложений, без исполнения

Агент начинает писать предложения: поле, старое значение, новое значение, причина, окно данных. Ничего не выполняется. Это запускается так, пока предложения не станут скучными — то есть пока читающий их человек и так нажал бы «да» почти на все. Мы поставляем: поток предложений, со всем, что было предложено, и что вы одобрили или отклонили, чтобы было видно, где он ошибается.

05

Запуск исполнения, поле за полем

Исполнение открывается для первого поля из списка «один», с dry-run, включенным по умолчанию, и с дневным лимитом. В реестре проверяется, что записанное — это то, что было предложено. Затем второе поле. Мы поставляем: журнал действий, переключатель, который останавливает все записи, оставляя чтение включенным, и письменную процедуру на случай, когда агент ошибся.

Маршрут решения1citire prin API cuаккаунт без права наscriere2предложение с полем,valoare veche,новое значение и причина3filtrul celor treiliste (singur / cuодобрение / никогда)4выполнение с dry-runзапущен по умолчанию иplafon zilnic5строка в реестрезатраты, написано вта же транзакцияКоммутатор отключения прерывает выполнение и оставляет чтение включенным.
Маршрут решения

Данные

К чему прикасаемся, где оно лежит и сколько остаётся

Вопросы, которые задаёт всякий, у кого есть ответственный за защиту данных, — заданы здесь раньше, чем их задаст он.

Какие данные затрагивает
Отчеты по кампании, группе объявлений и ключевому слову, читаемые через API. Идентификатор клика объявления, захваченный из адреса целевой страницы и сохраненный в запросе клиента. События конверсии с моментом, значением и валютой. По явному запросу, адрес электронной почты и телефон конвертировавшего человека, но только в виде криптографического резюме.
Что уходит в Google и в каком виде
Идентификатор клика уходит в открытом виде — это и есть идентификатор клика. Email и телефон уходят только как SHA-256, вычисленный локально перед отправкой: email очищается от пробелов и переводится в нижний регистр, телефон приводится к международному формату. Почтовый адрес вообще не отправляется, потому что схема Google требует его полностью с почтовым индексом и кодом региона, а почтовый индекс непоследователен в реальных данных — причина записана в коде, а не предполагается.
Где они хранятся и кто их видит
Данные кампании и события хранятся в базе вашего проекта, на согласованной инфраструктуре. Учетные данные рекламных аккаунтов хранятся в файле окружения, читаемом системным сервисом, а не в коде и не в репозитории исходников. Токен доступа хранится в памяти не более 55 минут, хотя провайдер выдает его действительным на 3.600 секунд — запас намеренный, чтобы никогда не использовать просроченный.
Сколько времени событие еще может быть отправлено
Практическое окно — 90 дней с момента конверсии — именно это Google принимает для офлайн-конверсий. Повторная попытка для неудачных отправок работает точно в этом окне, пакетами, с максимум пятью попытками на запрос. После пяти попыток запрос оставляется в покое и остается помеченным как неотправленный, вместо того чтобы повторяться бесконечно.
Что мы не делаем с данными
Мы не строим публично из ваших списков клиентов без письменного правового основания и без того, чтобы это было указано в уведомлении, которое видит человек. Мы не передаем данные между аккаунтами двух разных клиентов. Мы не храним копии отчетов по кампании вне согласованной системы. Реестр обработок заполняется до первой отправки, а не после.

Случай

Кампания, которая платила за формы, а не за запросы

Ситуация

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

Что мы построили

Я перенёс момент конверсии дальше по цепочке. Идентификатор клика захватывается на посадочной странице и сохраняется в запросе. Запрос уходит дальше в нижестоящую систему; если она возвращает собственный идентификатор — то есть вход действительно произошёл — только тогда событие уходит в Google через Data Manager API, со временем, значением, валютой и идентификаторами пользователей, переданными через SHA-256. Без идентификатора клика отправка сама останавливается и помечается как пропущенная. Я добавил job повторных попыток, который ищет запросы с идентификатором клика и без отметки об отправке, за последние 90 дней, пакетами по 50, максимум с пятью попытками.

Что получилось

Сигнал, который получает рекламная платформа, теперь описывает запросы, которые доходят до назначения, а не нажатия кнопки. Все операции неактивны, если интеграция не настроена или отключена — функция проверяет все семь credentials перед чем-либо и возвращает «пропущено», если одного не хватает. Ошибки журналируются, но не распространяются: если Google не отвечает, запрос клиента проходит дальше без изменений.

Чего этот случай не говорит

Это интеграция сигнала, а не управления кампанией. Она не меняет ни бюджет, ни ставку. Влияние на cost per acquisition нами не измерялось, и мы его не публикуем — в коде есть записанное ожидание автора, а не измерение, и между ними вся разница.

Вопросы

О чём нас спрашивают перед тем, как позвонить

Кто несёт ответственность, когда агент увеличивает бюджет и расход растёт?

Вы. И именно поэтому среда построена так, чтобы вы могли нести ответственность осознанно, а не чтобы вас застать врасплох. Конкретно: у агента нет ни одного permission на запись, который ему не дали бы по имени, письменно, поле за полем; у каждого открытого поля есть предел, после которого предложение идёт на human approval; каждое выполненное действие записывается в register со старым значением, новым значением и причиной, в той же transaction, что и execution; и есть переключатель, который останавливает все записи, не останавливая чтение. Мы отвечаем за то, что построили — что лимиты, которые вы написали, соблюдаются кодом, что register полон, что остановка работает. Мы не отвечаем за коммерческий результат изменения, которое вы одобрили, как не отвечает и agency, которая нажимает кнопку вручную. Если кто-то обещает вам иное, спросите его, что написано в contract в разделе ограничения ответственности.

У вас сегодня есть система, которая управляет кампаниями Google Ads или Meta?

Нет. Нигде в нашем коде нет какого-либо поля, через которое меняется бюджет, аукцион или стратегия назначения ставок в Google или Meta. Мы проверили это, ища именно эти названия полей во всех репозиториях. Что у нас есть — это отправка конверсий в Google, движок, который покупает платное продвижение на другой платформе, и механизмы безопасности вокруг них. Сервис строится, начиная оттуда, и отмечен как предложение именно для того, чтобы не было путаницы.

Тогда что именно вы уже построили и что тратит реальные деньги?

Наш двигатель paid promotion на платформе classified ads в Молдове. Он ставит paid tags, запускает boosters с daily limit и cost per click, активирует packages и republish-ит объявления через интервал, рассчитанный по реальной скорости категории. Он отказывается запускать booster, у которого daily limit не больше, чем cost per click — небольшая проверка, но именно тот тип проверки, которого обычно не хватает. Каждое действие проходит проверку dry-run перед любым costful call.

Что может менять само и что требует approval?

Это решается вместе, заранее, и фиксируется письменно. Наша отправная точка в обсуждении: само — корректировки ниже согласованного процента от daily budget, в пределах абсолютного daily cap, по кампаниям, которые вы отметили как open; с approval — любое превышение cap, новые кампании, новые audiences, любое изменение bids; никогда — остановка кампаний, запущенных кем-то другим, payment methods, billing accounts. Если вы хотите всё на approval в начале, это valid choice, и мы его предпочитаем.

Откуда агент знает, что конверсия настоящая, а не пустая форма?

Потому что сигнал не уходит по нажатию кнопки. Он уходит только тогда, когда запрос подтверждён downstream, в системе, которая для вас важна — идентификатор запроса, полученный обратно от CRM или партнёра. До того ничего, что стоило бы назвать конверсией, не произошло. Разница не косметическая: алгоритм ставок Google учится на том, что вы ему отправляете, так что если вы отправляете формы, он будет приводить вам людей, которые заполняют формы.

Что происходит с персональными данными тех, кто конвертируется?

Email и телефон уходят только как SHA-256 cryptographic summary, вычисленный локально перед отправкой, с нормализацией — email без пробелов и в нижнем регистре, телефон приведён к международному формату. Почтовый адрес не отправляется вообще. Ничто не уходит до того, как человек примет цель marketing в banner, потому что Consent Mode изначально полностью на `denied`. Legal basis и информирование пишутся до первой отправки, а не после первого вопроса кого-либо.

Что происходит, если вызов к рекламной платформе прерывается на середине?

Сбой записывается с сырым ответом, а действие откладывается — в нашем исполнительном модуле перепубликации, максимум из настроенной паузы и пяти минут, явно чтобы ошибка не превратилась в цикл вызовов. Неудачные отправки конверсионных запросов повторяются через отдельный job, партиями по 50, с не более чем пятью попытками на запрос, в окне 90 дней. После пятой попытки всё останавливается и остаётся помеченным как неотправленное, чтобы это было видно, а не исчезало.

Как мне отключить это полностью и быстро?

Переключатель записи. Чтение и отчётность продолжаются, выполнение останавливается. В наших существующих системах это реализовано двумя способами, оба проверяемые: переменная среды, которая должна иметь точно значение `false`, чтобы тратить деньги — всё остальное держит кран закрытым — и выключатель на оркестраторе кампаний, который отказывает в запуске и не имеет `--force`. Мы не зависим от кнопки в интерфейсе, которая может не загрузиться.

Вы гарантируете снижение стоимости за приобретение?

Нет, и стоит объяснить почему, потому что в нашем коде есть ровно такая цифра. В комментарии в начале интеграции конверсий написано ожидание — насколько могла бы снизиться стоимость за приобретение и насколько могла бы вырасти доля показов. Это ожидание написано тем, кто это сделал, а не измерение, и поэтому вы не найдёте его нигде на этом сайте как результат. Что мы можем пообещать — это то, что измерение можно будет сделать: с конверсиями, которые что-то значат, и с журналом каждого изменения сравнение до и после становится возможным. Без них — нет.

На чём основаны утверждения выше (20 источников)

20 из них — код и файлы из наших репозиториев. Мы не публикуем их название и строку: вместе, на одной странице, они слишком точно описали бы, как устроены системы, которые принадлежат не только нам. Мы разбираем их вместе с тобой, в репозитории, по запросу — проверка остаётся возможной, просто она проходит в разговоре.

Что вы хотели бы наладить?

Расскажите о своём процессе. Вместе определим, что стоит построить, что можно подключить и как проверим результат.

Давайте обсудим