A/B двух заголовков попапа без второго скрипта: как я сделала это на одном embed

В прошлой статье разбирала, почему «один промпт — и готовый попап» разваливается, и как устроен пайплайн из парсера и трёх вызовов Yandex GPT. В конце обещала отдельно рассказать про A/B двух заголовков на одном embed. Дошла.

A/B двух заголовков попапа без второго скрипта: как я сделала это на одном embed

Сервис тот же — ИИ-conversion. Текст снова не про «купите», а про инженерную задачу: как сравнить два оффера на живом трафике, не вешая на сайт второй счётчик, второй виджет и вторую админку.

Зачем вообще A/B, если ИИ уже «придумал хороший текст»

Генерация убирает чистый лист. Она не говорит, какой заголовок реально соберёт заявки.

Типичная развилка после генерации:

  • вариант A: «Рассчитать стоимость за 2 минуты»
  • вариант B: «Бесплатный расчёт — без предоплаты»

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

Классический путь маркетолога: Google Optimize / свой AB-сервис / два разных скрипта / UTM на две страницы. Для владельца сайта на Tilda это часто «потом». Я хотела, чтобы тест запускался из того же кабинета, куда уже вставили одну строку кода.

A/B двух заголовков попапа без второго скрипта: как я сделала это на одном embed

Что нельзя было ломать

Ограничения были жёсткие:

  • Один script на сайт. Клиент уже поставил виджет — не просим «ещё один для эксперимента».
  • Один посетитель = один вариант. Иначе человек видит то A, то B, а в статистике каша.
  • Метрики те же, что и без теста: показ, клик, заявка. Без отдельной «магии A/B».
  • Победитель выключается одной кнопкой: проигравший перестаёт показываться, скрипт пересобирается.

Если решение усложняет онбординг — оно проиграет даже самому умному сплиту.

Модель данных проще, чем кажется

Не стала городить «варианты внутри одного попапа» с ветвлением полей. Сделала иначе:

  • два обычных попапа на одном домене (два заголовка, можно разные буллиты и CTA);
  • сущность experiment: ссылки на A и B, доля трафика на A (split_a, по умолчанию 50), статус running / completed;
  • на сайте по-прежнему один embed, внутри которого живут оба варианта.

Плюс: редактирование как у обычного попапа. Минус: нельзя случайно завести два теста на одном сайте или кинуть в тест колесо фортуны — на это стоят проверки.

Как виджет решает, что показать

В JS уходит компактный конфиг: id эксперимента, id варианта A, id варианта B, split_a.

Перед показом виджет смотрит в localStorage по ключу эксперимента. Если вариант уже выбран — показывает его. Если нет — бросает монетку по split_a, сохраняет выбор и показывает только «свой» попап. Второй в бандле молчит.

Почему localStorage, а не cookie на бэкенде:

  • нет лишнего round-trip до первого показа;
  • конфиг уже в скрипте, не нужно ждать API;
  • sticky на устройстве без серверной сессии.

Минусы честно: инкогнито и смена устройства = новый бросок монетки. Для сравнения заголовков на лендинге этого обычно достаточно. Для кросс-девайс атрибуции — нет; у меня задача другая.

Один скрипт, два попапа — как это не конфликтует

Самый скользкий момент: на сайте один файл, а вариантов два.

Решение: при старте и остановке теста оба виджета пересобираются. В payload активного теста попадает один и тот же ab_experiment. Оба скрипта «знают» про сплит, но на экране оказывается только тот, чей id вытянул выбор.

Когда тест завершают и выбирают победителя:

  • статус становится completed;
  • проигравший попап деактивируется;
  • оба скрипта пересобираются уже без конфига эксперимента.

Клиенту не нужно трогать код на сайте. Это было важным условием: иначе тест «запустили» и забыли навсегда с двумя конфликтующими окнами.

На какие цифры смотрю в тесте

В кабинете по каждому варианту: показы, клики, заявки, CTR и доля заявок от показов.

Подсказка «кто лидирует» — сначала по заявкам, при равенстве по CTR. Это не p-value и не байесовский калькулятор. Для трафика малого бизнеса важнее не «статзначимость на 10 тысяч», а не оставить слабый оффер на месяцы, когда разница уже видна по заявкам.

Ошибка, которую видела у себя и у клиентов: останавливать тест на 30 показах, потому что «B впереди на 2%». Шум. Я для себя держу правило: не трогать, пока по каждому варианту не набралось осмысленное число заявок для ниши. На B2B-лендинге это может быть долго — тогда лучше сузить гипотезу, а не крутить спиннер.

Какие гипотезы тестировать имеет смысл

Бессмысленно A/B «синий фон vs зелёный», пока не закрыт оффер. Имеет смысл менять одно:

  • Формулировка выгоды: срок vs цена vs «без обязательств».
  • Сила CTA: «Оставить заявку» vs «Получить расчёт».
  • Один буллит с доказательством: цифра со страницы vs снятие риска.

Плохая практика — одновременно новый заголовок, другая картинка и exit-intent вместо таймера. Потом непонятно, что сработало. ИИ как раз провоцирует «перегенерировать всё»; для теста я копирую попап и меняю одно поле.

Что ломалось

Два активных теста на одном домене. Посетитель мог попасть в логический тупик. Запретила на уровне API: один running-experiment на сайт.

Варианты с разных сайтов. Казалось бы, «ну почти тот же лендинг». Нет: разный трафик = бессмысленное сравнение. Оба попапа должны совпадать по нормализованному домену.

Забыли выключить проигравшего. Люди оставляли оба активными «на всякий случай». При завершении теста проигравший гасится автоматически — иначе снова два окна.

Ожидание, что A/B починит слабый продукт. Если на странице нет ответа «зачем мне оставлять телефон за 5 секунд», победит лишь менее раздражающий заголовок. Об этом писала в первой заметке

Что бы повторила

1. Варианты = полноценные сущности, не JSON-ветки внутри одной записи.

2. Sticky assignment на клиенте, конфиг — в том же embed.

3. Пересборка виджетов при старте и финише теста — без ручного «обновите код на сайте».

4. Метрики теста = обычные события продукта, без второй аналитики.

5. Одна гипотеза за раз — даже если генератор умеет написать пять текстов подряд.

A/B здесь не про «научный маркетинг ради науки». Про то, чтобы после генерации не спорить вкусом, а дать трафику один голос.

Если интересно — в следующий раз могу разобрать few-shot по нишам: почему два примера из той же отрасли бьют temperature, и как я храню примеры, чтобы модель не утаскивала чужие цифры в чужой попап.

А вы гоняете заголовки попапов в тесте или выбираете «на глаз»? Напишите в комментариях, сколько показов обычно ждёте перед решением — сравним подходы.

P.S. A/B — часть ИИ-conversion ; живой виджет можно посмотреть на glm-dev.ru. Пишу по опыту разработки, это не пресс-релиз.