Exit-интервью на LLM у пейволла: как я узнаю, почему не платят

Отдельный чат-интервьюер с другим тоном, чем игровой бот
Отдельный чат-интервьюер с другим тоном, чем игровой бот

Когда игрок в моей онлайн-игре закрывает окно оплаты, с ним заговаривает отдельный LLM-бот — короткое custdev-интервью по правилам книги «Спроси маму», максимум пять реплик. За две недели я провёл 59 сессий, 20 человек ответили — это 34% отклика. Главная находка: заметная доля пришла из поиска по слову «бесплатно» из-за формулировки в моём же title. Ниже — архитектура, промпты, грабли и каркас, который можно перенести в любой продукт с моментом отказа.

Exit-интервью — это разговор с пользователем в горячий момент, когда он уже отказался от оплаты, но ещё на странице. В отличие от email-опроса «почему не купили?» здесь причина свежая, а порог входа ниже: не анкета с галочками, а короткий чат с другим тоном и другой ролью.

Я делаю онлайн-версию «Лилы» — настольной игры самопознания с ИИ-ведущим. Игрок формулирует личный запрос, бросает кубик, ИИ ведёт партию по полю и задаёт вопросы. Фаза формулировки запроса бесплатная; дальше игра просит оплату. Классический freemium с пейволлом — на его месте у вас может быть корзина, тариф или подписка, схема от этого не меняется.

Почему момент закрытия пейволла — золото для custdev

Пользователь дошёл до пейволла и закрыл его. В аналитике это событие paywall_dismissed. Причин там нет — только факт отказа.

Опросник в этот момент у меня не работал: человек раздражён, галочки «дорого / не сейчас» ставит не глядя. Письма «почему вы не купили?» собирали почти ноль ответов. А человек ещё на странице — и у него есть причина прямо сейчас, пока эмоция горячая.

Я сделал так: закрыл модалку — открывается отдельный чат. Не игровой. Другой визуальный стиль, другая роль: не как ведущий игры, а «просто интересно, что сейчас произошло?». Отвечают 34%. Для custdev-канала с нулевой стоимостью привлечения респондента это сильный результат.

Схема бэкенда: отдельные таблицы, кап реплик и второй вызов LLM для заметки
Схема бэкенда: отдельные таблицы, кап реплик и второй вызов LLM для заметки

Как я перенёс «Спроси маму» в системный промпт

Роб Фитцпатрик в «The Mom Test» формулирует простую мысль: мнения бесполезны, факты бесценны. Пять правил из книги я перенёс прямо в системный промпт бота-интервьюера.

Спрашивать о случившемся, не о будущем. «Что произошло, когда открылось окно?» — да. «Купили бы вы, если…» — мусор: о будущем люди врут, не со зла.

«Не сейчас» — вежливое «нет». В заметке для меня это не «тёплый лид», а честный отказ.

За «нет денег» копать жизнь, а не защищать цену. Что человек уже делал со своей темой? Платил психологу? Покупал курсы? Это данные о рынке, а не повод спорить с ценником.

Комплимент — форма отказа. «Всё понравилось» — одно тёплое слово и назад к фактам.

Не вести клиента. Не пересказывать ответы «правильными словами». Моя догадка — не факт.

Шестое правило я выстрадал сам. В первой версии бот начинал с «я ничего не продаю и не уговариваю». Убрал: фраза «я не продаю» звучит ровно наоборот — как продажа. Рамку задаёт первый вопрос. После правки доля ответивших не изменилась, а тон ответов стал спокойнее.

Финальный вопрос каждого интервью, тоже из книги: «О чём мне стоило спросить, но я не спросил?» Он приносит непрошеное. Одна из игравших ответила: «Вы рано про оплату спрашиваете — технически можно позже, когда человек уже много выложит о себе». Готовая продуктовая гипотеза.

Архитектура: поток, таблицы и защита от гонок

Поток простой: закрыл пейволл → панель ResearchChat → POST /api/games/:id/research с действиями start (создать или возобновить сессию, стрим первого вопроса), message (реплика игрока, кап пять) и end (завершение → LLM-заметка + транскрипт → мне в Telegram).

Exit-интервью на LLM у пейволла: как я узнаю, почему не платят

Решения, которые потом спасли:

Отдельные таблицы и отдельный эндпоинт. Research-диалог не пишется в игровой корпус сообщений и не трогает freemium-гейт. Данные интервью не загрязняют данные продукта.

Одна сессия на объект, idempotent. INSERT … ON CONFLICT DO NOTHING по subject_id (у меня это id игры). Повторное закрытие модалки возобновляет тот же диалог.

Кап реплик — в транзакции. Инкремент счётчика с гардом user_replies < 5 и вставка реплики в одной транзакции. Row lock закрывает гонку параллельных отправок; без него потолок пробивается, а при падении вставки теряется последняя реплика, хотя счётчик уже съеден.

Никакого крона. Брошенные сессии закрывает попутный sweep: любой research-запрос fire-and-forget добивает чужие диалоги, где 30 минут тишины. У меня процесс долгоживущий (Docker), поэтому fire-and-forget живёт спокойно. В serverless заворачивайте вызов в waitUntil — там он умирает вместе с воркером.

Заметка — вторым LLM-вызовом. По завершении сессии транскрипт прогоняется через промпт-аналитик. На выходе JSON: summary, signal (причина не-оплаты одним словом), payment_tech_issue, emotion, tried_before, quotes (только дословные цитаты), insight.

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

Пересылка — с атомарным клеймом. forwarded_at IS NULL → NOW() перед отправкой; при фейле клейм снимается. Дублей нет, «типа отправленных» нет.

Минимальный каркас, который переносится куда угодно: TypeScript + Postgres + LLM с fallback. Две таблицы — research_sessions и research_messages, один эндпоинт, кап пять реплик в транзакции. Системный промпт — шаблон с тремя дырками: голос продукта, момент отказа, контекст сцены (не вся история — боту хватит последних реплик). Промпт заметки — второй вызов, вход равен транскрипту; на выходе структурированный JSON для вебхука в Telegram или Slack.

Шаблон системного промпта я оставляю открытым: в фигурных скобках подставляете голос своего продукта (у меня — ведущий игры, у вас — ассистент магазина или поддержка сервиса), момент отказа (закрыл пейволл, бросил корзину, отменил подписку) и короткий контекст сцены — карточка товара, состав корзины, тариф. Боту не нужна вся переписка: достаточно последних двух-трёх реплик, иначе он начнёт пересказывать историю вместо того, чтобы слушать.

Промпт аналитика на выходе требует честности: нет причины — так и пиши. «Подумаю» равно вежливому «нет», не интерес. Сигналы вроде price, timing, got_enough, trust, tech_payment помогают быстро сортировать ленту заметок и не тонуть в свободном тексте.

Грабли, которые я принял как цену формата

Злость на бота. «Зачем я с роботами начала общение — позорно». Человек пришёл играть, наткнулся на пейволл, а тут ещё разговоры. Это честная цена формата. Ответ архитектурный: жёсткий кап, завершение после двух односложных ответов, ноль попыток удержать или допродать. И кризис-протокол: если в ответах тяжёлое — бот бросает исследование и ведёт к живой помощи.

Бот-интервьюер не универсален. Части людей проще выдать боту больше, чем человеку: ниже порог стыда. Часть принципиально не разговаривает с «роботами». 34% — те, кому формат подошёл. Остальные 66% мне ничего не должны.

Про данные: диалог уходит в LLM-провайдера и в Telegram без имени, почты и идентификаторов — только текст реплик и номер сессии. В публичных цитатах я дополнительно меняю формулировки до неузнаваемости конкретного человека — смысл не трогаю.

Что дали 20 ответов за две недели

Заметка exit-ресёрча: сигнал, инсайт и цитата игрока в Telegram
Заметка exit-ресёрча: сигнал, инсайт и цитата игрока в Telegram

Раскладка причин по 20 ответившим:

«Ожидал бесплатно» — 7. Доминанта с отрывом. Ещё в одном ответе та же нота: злость, «что ничего не бывает бесплатно».

Нет денег — 3. Ценность не успела раскрыться до пейволла — 3. Техфейл оплаты — 1. Философское «за деньги это не купишь» — 2. Прочее — единицы. И одна обратная: «Почему так дёшево. Ценность игры выше».

20 интервью — это уже сигнал, не статистика. Гипотезы отсюда проверяются метриками. Теперь главное: откуда «бесплатно»? Смотрю атрибуцию — все 59 сессий из поиска и прямых заходов, ни одной с моих лендингов. Иду в git своей посадочной — и вот оно: SEO-проход добавил в title главной «играть бесплатно». Запрос частотный, CTR вырос. Поиск приводил людей на обещание, которое продукт выполняет только наполовину: бесплатна первая фаза, дальше пейволл.

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

Что я сделал: title переписан — теперь обещает ровно то, что есть. Проверяю метрикой: доля сигнала «ожидал бесплатно» в новых exit-интервью ушла. Я строил инструмент, чтобы понять чужие возражения. Первым делом он вскрыл мою собственную ошибку. Лучшее доказательство, что это работает.

Отдельно отмечу тех, кто не ответил: 66% молчат — и это нормально. Exit-интервью не заменяет количественные эксперименты, но даёт качественные гипотезы, которые потом проверяются A/B-тестами, воронкой и атрибуцией. Без горячих цитат я бы ещё долго крутил «низкую конверсию органики», не видя очевидного несоответствия между SEO-обещанием и продуктом.

Когда exit-интервью на LLM стоит внедрять

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

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

Себестоимость: час вайбкода, две таблицы, один эндпоинт, два промпта, вебхук. Данные бесценны — особенно когда одна цитата экономит недели слепого A/B-тестирования заголовков.

Я делаю онлайн-версию игры «Лила» с ИИ-ведущим — quantumgame.love. Пейволл, о котором речь выше, оттуда.

Частые вопросы про exit-интервью у пейволла

Сколько реплик достаточно? У меня кап пять — этого хватает, чтобы дойти до факта, не утомив человека после отказа.

Нужен ли отдельный UI? Да. Другой тон и роль снижают сопротивление: это не продажа и не продолжение игры, а короткий разговор «что случилось».

Как не смешать данные интервью с продуктом? Отдельные таблицы, отдельный эндпоинт, idempotent-сессия на объект отказа.

Что делать с техническими сбоями оплаты? Выделять payment_tech_issue в отдельный срочный алерт — это не «возражение», а потерянная выручка.

Как измерить успех канала? Смотрю на долю ответивших (у меня 34%), распределение сигналов по неделям и скорость реакции на техфейлы. Если сигнал «ожидал бесплатно» падает после правки посадочной — инструмент сработал как датчик, а не как декорация.

1