Реализация акционных предложений (Special Offers) мобильной игры
Special Offers — ограниченные по времени предложения с высокой ценностью, которые показываются в правильный момент правильному игроку. Это не «скидка 20% на все товары», это таргетированный оффер: новичку на 3-й день — starter pack, игроку застрявшему на уровне 15 — нужный ему бустер, churning-пользователю перед удалением — winback оффер с 50% скидкой.
Разница в конверсии между «показать всем» и «показать нужному сегменту в нужный момент» — 3–5x.
Архитектура системы офферов
Серверная конфигурация. Все офферы — на сервере. Клиент запрашивает «активные офферы для этого игрока» при входе и при открытии магазина. Сервер возвращает только те, которые подходят по условиям:
{
"offerId": "starter_pack_d3",
"title": "Стартовый набор",
"products": [
{"type": "gems", "amount": 500},
{"type": "chest", "itemId": "epic_chest", "amount": 3},
{"type": "resource", "itemId": "gold", "amount": 10000}
],
"iapProductId": "com.mygame.starter_pack_d3",
"originalPrice": 9.99,
"discountPercent": 70,
"validUntil": "2025-03-28T23:59:59Z",
"triggerConditions": {
"daysSinceInstall": {"min": 2, "max": 4},
"hasNeverPurchased": true,
"minLevel": 5
},
"maxPurchases": 1
}
triggerConditions проверяются на сервере — клиент не видит логику сегментации, только готовый список офферов.
Триггеры показа
Оффер не просто висит в магазине — он всплывает в контексте. Триггеры:
Contextual trigger. Игрок проиграл уровень 3 раза подряд — показываем оффер с бустером именно для этого уровня. Сервер знает текущий уровень игрока и его попытки.
Time trigger. День 3 после установки — лучший момент для starter pack: игрок уже вложился, понял механику, готов потратить первый доллар.
Re-engagement trigger. Игрок не заходил 5 дней — при возврате показываем winback оффер. Реализуется через push-уведомление с deeplink на экран оффера.
Achievement trigger. Игрок только что прошёл крутой уровень или открыл новый контент — эмоциональный пик, лучший момент для предложения.
Таймер и urgency
struct OfferTimerView: View {
let expiresAt: Date
@State private var timeRemaining: String = ""
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
Text("Осталось: \(timeRemaining)")
.onReceive(timer) { _ in
let remaining = expiresAt.timeIntervalSinceNow
if remaining > 0 {
timeRemaining = formatDuration(remaining)
} else {
// Оффер истёк — скрываем
NotificationCenter.default.post(name: .offerExpired, object: nil)
}
}
}
}
Время истечения проверяется на сервере при клике «Купить» — таймер на клиенте только для UI. Нельзя купить просроченный оффер, даже если клиент не обновил состояние.
A/B-тестирование офферов
Firebase Remote Config позволяет тестировать разные варианты оффера:
- Группа A: 500 gems + 3 chest за $1.99
- Группа B: 300 gems + 5 chest + 1 skin за $1.99
Метрика: conversion rate (купили / увидели). Тест на 1000+ игроков на каждую группу, статистическая значимость >95%.
Для более сложной персонализации используем Firebase ML или собственную recommendation-систему на основе сегментов: новички, mid-spenders, whales, churning users.
Ограничение покупок и anti-abuse
maxPurchases: 1 на уровне сервера — оффер можно купить только один раз. Проверка: перед покупкой сервер смотрит purchase_history по offerId + userId.
Некоторые офферы «one-time-ever» (стартовый пакет — никогда больше не показываем), другие — повторяются с ограничением по времени (flash sale раз в неделю). Логика хранится в конфиге оффера, не в клиенте.
Интеграция с IAP
Special Offer — это отдельный продукт в App Store/Google Play с уникальным productId. Нельзя динамически менять цену существующего IAP-продукта — это ограничение платформ. Поэтому каждый ценовой тир оффера = отдельный registered product.
Apple позволяет Promotional Offers (скидка на subscription или non-consumable для существующих покупателей) и Introductory Offers (скидка для новых подписчиков) — это встроенные механизмы, которые не требуют отдельных product ID.
Сроки: базовая система с 3–5 типами офферов, серверной конфигурацией и таймером — 2–3 дня. Полная система с персонализацией, A/B-тестами, contextual triggers и аналитикой — 1–1.5 недели. Стоимость рассчитывается индивидуально.







