Акционные предложения в мобильной игре: где ломается механика
Механика офферов — это цепочка из четырёх звеньев: сервер решает, кому и когда показать предложение, клиент отрисовывает его в нужный момент, платёжный шлюз подтверждает покупку, а бэкенд начисляет товар и закрывает оффер. Разрыв любого звена не выглядит как ошибка в логах — он выглядит как недовольный игрок, который либо не увидел акцию, либо заплатил дважды, либо потерял прогресс покупки на середине.
Самая частая ошибка — неверные условия показа. Оффер привязан к триггеру (уровень, сессия, отсутствие покупок N дней), но проверка условий живёт на клиенте, а не на сервере. Игрок переводит часы на устройстве, переустанавливает приложение или заходит с другого аккаунта — и получает предложение, которое ему не положено, либо теряет то, что уже было показано. Лечится это серверным расчётом eligibility и идемпотентным ключом оффера: один игрок — один показ на кампанию, независимо от устройства.
Вторая категория — ошибки начисления покупок. Платёжный шлюз отвечает медленно, клиент повторяет запрос, а обработчик на бэкенде не проверяет уникальность транзакции. Итог — двойное начисление, которое всплывает только на сверке с магазином, когда игрок уже потратил лишнее. Решение — идемпотентная обработка по идентификатору транзакции и отдельный журнал начислений, по которому можно восстановить картину.
Третий сбой — потеря прогресса покупки при обрыве связи. Игрок оплатил, приложение закрылось, чек не дошёл до сервера. Без очереди отложенных подтверждений и фоновой до-отправки чека покупка «зависает» между магазином и игрой. Здесь помогает локальное хранилище незавершённых транзакций и повторная валидация при следующем запуске.
Все три сбоя объединяет одно: состояние оффера должно жить на сервере, а не в памяти клиента. Разбираем, как это закрывается на уровне архитектуры и какие проверки ставятся на каждом шаге.
Как работает выдача special offers: режимы, проверки, эффект
Выдача special offers — это не «показать баннер в нужный момент», а транзакционная система: сервер решает, кому и что предложить, клиент только отображает, а факт покупки подтверждается отдельно. Если решение о выдаче живёт на клиенте, любая правка локальных данных открывает доступ к акции, а повторная отправка запроса приводит к двойному списанию. Поэтому логика выдачи, лимиты акций и серверная валидация покупки держатся на бэкенде, а приложение получает уже готовый набор офферов с идентификаторами.
Режимы показа офферов
Режим определяет, когда игрок видит акцию, и напрямую влияет на нагрузку. Push-выдача по событию (вход, завершение уровня, падение ресурсов) даёт высокий отклик, но требует очереди и защиты от штормов при массовом онлайне. Pull-выдача по запросу клиента проще в эксплуатации, но добавляет задержку и лишние обращения. Гибрид — базовый набор по запросу плюс точечные события — обычно и выбирают: пиковая нагрузка сглаживается, а акция приходит вовремя.
| Вариант | Когда подходит | Ограничения |
|---|---|---|
| Push по событию | Реакция на действие игрока, ограниченные по времени акции | Нужна очередь и защита от всплесков при массовом входе |
| Pull по запросу | Простые акции, редкие события | Задержка выдачи, избыточные обращения к серверу |
| Гибрид | Основной сценарий в проде | Сложнее конфигурация и тестирование приоритетов |
Идемпотентность и лимиты
Каждая покупка несёт уникальный ключ операции: повторная отправка того же запроса возвращает результат первой, а не создаёт вторую транзакцию. Это закрывает двойные списания при обрыве связи и повторных попытках. Лимиты акций — сколько раз игрок может купить, общий объём выдачи, срок жизни — проверяются на сервере в одной транзакции с покупкой, иначе при параллельных запросах лимит обходится.
Проверки перед выдачей
Серверная валидация покупки проверяет право на акцию, остаток лимита, состояние платежа и отсутствие дубля — до начисления. Ошибка на любом шаге откатывает транзакцию целиком, поэтому игрок либо получает товар, либо не теряет ничего. Такой порядок убирает класс отказов «списали, но не начислили», самый дорогой в поддержке.
Google Play Billing и аналогичные платёжные контуры дают подтверждение чека, но не заменяют серверную валидацию: чек подтверждает оплату, а право на акцию и лимиты — только ваш бэкенд.
Этапы внедрения механики акционных предложений
Внедрение офферов начинается не с кода, а с аудита монетизации: смотрим, какие события игрока уже логируются, как устроены покупки, где теряется конверсия между показом и оплатой. Если аналитика не различает источник покупки, любая акция превращается в стрельбу вслепую — эффект не отделить от сезонного всплеска. Поэтому сначала фиксируем точки замера, потом проектируем схему выдачи акций.
- Аудит монетизации и данных. Разбираем текущие события, воронку покупок и разрезы по сегментам игроков. На выходе — карта точек, куда можно привязать триггеры офферов без доработки ядра.
- Проектирование схемы выдачи. Определяем условия срабатывания, лимиты на игрока, срок жизни предложения и правила приоритета, когда у игрока совпадают несколько акций. Схема описывается декларативно, чтобы менять параметры без релиза клиента.
- Настройка конфигурации и серверной части. Офферы выносятся в управляемый конфиг: сегмент, товар, скидка, окно показа. Сервер отдаёт предложение по запросу клиента, клиент только отображает — это снимает рассинхрон версий приложения у игроков.
- Проверка на тестовой группе игроков. Раскатываем акцию на ограниченный сегмент, сверяем конверсию, долю выкупа и нагрузку на платёжный контур. Тестовая группа отделена от общей популяции, поэтому неудачная гипотеза не портит метрики всему продукту.
- Масштабирование и мониторинг. После подтверждённого эффекта расширяем охват, ставим алерты на аномалии: всплеск отказов оплаты, просадку выкупа, рост обращений в поддержку.
- Передача конфигурации. Отдаём команде заказчика схему выдачи, набор параметров, инструкцию по запуску и остановке акции и порядок отката к предыдущему состоянию.
- Сопровождение первых кампаний. Остаёмся на связи в течение первых запусков, чтобы правки условий шли по факту данных, а не задним числом.
Такой порядок даёт предсказуемость: каждая акция запускается и выключается без релиза, а результат измеряется на ограниченной группе до того, как его увидят все игроки.
Чем серверная выдача офферов отличается от клиентской?
Клиентская выдача держит логику акции в сборке приложения: условия, состав награды и момент показа зашиты в код, а начисление происходит на устройстве. Это дёшево на старте и работает без сети — игрок видит special offers даже в метро. Плата за это — доверие к клиенту: системное время, локальное хранилище и трафик находятся под контролем игрока, поэтому защита от накрутки сводится к обфускации и проверкам на стороне сервера постфактум. Любое изменение условий требует нового релиза и прохождения проверок в магазинах, а старая версия продолжает жить у части аудитории.
Серверная выдача переносит решение на бэкенд: приложение запрашивает набор доступных акций, получает подписанный ответ с идентификатором предложения и сроком действия, а начисление подтверждает отдельным вызовом. Ключевое здесь — синхронизация состояния: сервер знает, что уже выдано, что активировано и что истекло, поэтому повторный запрос не создаёт вторую награду. Защита от накрутки строится на идемпотентности операций и привязке к аккаунту, а не к устройству, — перевод часов или переустановка приложения ничего не меняют.
Разница проявляется на отказах. При клиентской выдаче расхождение между устройством и бэкендом обнаруживается, когда игрок уже получил лишнее, и разбирать инцидент приходится по логам. При серверной состояние остаётся единственным источником правды: если ответ не дошёл, клиент повторит запрос и получит тот же результат.
На практике подходы комбинируют. Сервер решает, кому и когда показывать предложение, хранит квоты и историю активаций; клиент отвечает за отрисовку, кэш последнего ответа и офлайн-показ. Такой гибрид даёт управляемость акций без релиза и сохраняет отзывчивость интерфейса при слабой связи.
Кейс: как акционные предложения перестали терять покупки
Игра с сезонными акциями и внутриигровыми наборами приносила заметную долю выручки, но механика акционных предложений (special offers) работала нестабильно. Покупка подтверждалась на клиенте, а на сервере не проводилась: игрок видел списание, товар не приходил. Каждый такой случай — обращение в поддержку, ручной разбор логов и возврат, а часть игроков просто уходила, не дождавшись ответа.
Что было до переработки
Оффер жил на стороне клиента: таймер акции, цена и состав набора хранились в приложении и синхронизировались с сервером «когда получится». При обрыве связи в момент оплаты транзакция зависала в промежуточном состоянии, а повторная активация того же оффера создавала дубль или отказ. Доля успешных покупок держалась на уровне около 70%, обращения в поддержку по акциям шли потоком, а повторные активации были редкостью — игроки не доверяли механике.
Что изменили
Перенесли состояние оффера на сервер: клиент запрашивает актуальный набор, сервер фиксирует резерв и подтверждает выдачу только после успешной транзакции. Ввели идемпотентный ключ на каждую попытку — повторный запрос при обрыве связи не создаёт вторую покупку, а возвращает результат первой. Таймеры и условия акции стали серверными, поэтому подмена времени на устройстве больше не открывает просроченный оффер.
Отдельно переработали повторные активации: после покупки игрок получает следующий шаг цепочки офферов, а не тот же набор. Это удержало интерес к акции и снизило долю отказов на этапе подтверждения.
Что стало
| Метрика | До | После |
|---|---|---|
| Доля успешных покупок | ~70% | выше 96% |
| Обращения в поддержку по акциям | регулярный поток | снизились кратно |
| Доля повторных активаций | низкая | выросла в разы |
| Возвраты и ручные разборы | частые | единичные |
Схему подтверждения транзакций и идемпотентности строили по модели, близкой к тому, как это решено в Google Play Billing — серверное подтверждение покупки вместо доверия клиенту. Такой подход убирает целый класс отказов: зависшие транзакции, дубли и «оплатил, но не получил».
Если у вас акции теряют покупки или поддержка тонет в однотипных обращениях — опишите задачу, вернёмся с оценкой и планом переработки механики.
Сомнения перед стартом: доступы, откат, совместимость
Перед стартом заказчик обычно задаёт три вопроса: что нужно с нашей стороны, что будет при неудачном релизе и не сломает ли это текущую игру. По доступам к серверу достаточно тестового контура и учётной записи с правами на выкладку — продуктивные ключи и платежные секреты остаются у вас, мы работаем через отдельные сервисные учётки с ограниченным сроком жизни. План отката фиксируем до начала работ: конфигурация special offers выносится за пределы сборки, поэтому выключение акции — это переключение флага, а не пересборка и повторная модерация.
Совместимость с текущей игрой проверяем на вашей версии клиента и серверной логике: если баланс, инвентарь или прогресс игрока меняются по своим правилам, мы подстраиваемся под них, а не переписываем их.
Что если акция уже запущена и её нужно срочно остановить?
Конфигурация хранится отдельно от кода, поэтому остановка — это смена состояния на стороне сервера: новые выдачи прекращаются сразу, уже выданные награды остаются у игроков. Откат кода не требуется, релиз в стор не нужен.
Что если у нас своя команда и мы не хотим отдавать серверную часть? Работаем на вашей стороне: передаём спецификацию, конфигурации и тесты, ваши инженеры вносят изменения сами, мы подключаемся к приёмке.
Что если игра уже в проде и есть живые игроки? Раскатываем акцию на долю трафика, сверяем метрики выдачи и только потом включаем на всех.
На руки по итогам работ вы получаете:
- конфигурации акций с описанием параметров и условий срабатывания;
- схему взаимодействия клиента, сервера и хранилища наград;
- политику отката и порядок аварийного выключения;
- набор автотестов на выдачу, повторную выдачу и граничные условия;
- журнал событий и дашборд по метрикам акции;
- документацию по передаче: как добавить новую акцию без участия разработчика.
Опишите задачу и текущий стек — вернёмся с оценкой и планом работ.







