Крупний iGaming-оператор з базою 2 млн гравців втрачав 30% прибуткових клієнтів у перші 90 днів. Масові бонуси приваблювали мисливців, ROI кампаній коливався близько 80% — кожен рубль бонусу приносив 80 копійок повернення. Після впровадження нашої системи оператор скоротив збитки: зниження бонусного бюджету на $200,000 на рік та збільшення LTV на 20%, що принесло додатково $1.5 млн.
Ми розробили AI-систему CRM-аналітики на основі ансамблю GradientBoosting (Gradient boosting) та KMeans-сегментації. За 6 тижнів впровадження оператор отримав ROI 250%, знизив бонусний бюджет на 20% і скоротив churn rate на 18%. Ключова зміна — перехід від універсальних RFM до GGR-сегментації, що враховує реальну прибутковість гравця.
Система включає пайплайни на Airflow, сховище ClickHouse та дашборди Metabase. Для кожного сегменту (champion, at_risk_highvalue, loyal_lowvalue, dormant) підбирається індивідуальна бонусна механіка з різним вейджером. Вбудовані RG-перевірки блокують бонуси для гравців з високим ризиком проблемної поведінки. Система щотижня оновлює сегменти та моделі, адаптуючись до змін поведінки гравців.
Проблеми, які вирішуємо
- Churn prediction: стандартні RFM-моделі не враховують тренди. Ми будуємо фічі: зміна сесій за 7/30 днів, тренд GGR, скарги в підтримку. GradientBoosting дає AUC 0.87 — на 12% краще логістичної регресії.
- Bonus abuse: масові бонуси приваблюють мисливців. Сегментація виділяє 4 групи: champion (5–10% бази, 50–70% GGR), at_risk_highvalue, loyal_lowvalue, dormant. Для кожної — свій тип бонусу з різним вейджером.
- RG compliance: вбудовані перевірки блокують бонуси для гравців з високим RG-ризиком. Це знижує претензії регуляторів.
Як передбачити відтік гравців за 30 днів?
Використовуємо ансамбль GradientBoosting з параметрами: n_estimators=200, learning_rate=0.05, max_depth=4. Навчаємо на даних за 6 місяців. Фічі включають days_since_last_session, sessions_trend, ggr_trend, bonus_expiry_ignored. Модель видає ймовірність churn і розбиває на tier: low, medium, high, critical. Для critical tier автоматично запускається реактиваційна кампанія з кешбеком.
Чому сегментація за GGR ефективніша за RFM?
RFM враховує лише давність, частоту та суму. GGR = депозити – виведення – бонуси. Він точніше відображає реальну цінність гравця. Наприклад, гравець з високим RFM, але частими виведеннями та бонусами — збитковий. GGR-сегментація виділяє 'champion' (високий GGR + активність) і 'at_risk_highvalue' (високий GGR, низька активність) — саме на них потрібно фокусувати ресурси.
Як ми це робимо
Стек: Python, scikit-learn, PyTorch, Hugging Face (для NLP аналізу чатів підтримки), ClickHouse (аналітика в реальному часі), Airflow (пайплайни), Metabase/Tableau (дашборди). Розгортання в Docker/Kubernetes.
Приклад коду сегментації:
import pandas as pd
import numpy as np
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.cluster import KMeans
class iGamingPlayerSegmentor:
"""Сегментація за GGR та поведінкою"""
def compute_player_value(self, player_data: pd.DataFrame) -> pd.DataFrame:
"""
GGR (Gross Gaming Revenue) та LTV розрахунок.
GGR = deposits - withdrawals - bonuses_paid
"""
df = player_data.copy()
df['ggr'] = df['total_deposits'] - df['total_withdrawals'] - df['bonuses_paid']
df['ggr_per_month'] = df['ggr'] / df['months_active'].clip(1)
df['deposit_frequency'] = df['deposit_count'] / df['months_active'].clip(1)
df['withdrawal_ratio'] = df['total_withdrawals'] / df['total_deposits'].clip(1)
# LTV прогноз: проста лінійна проекція
df['predicted_ltv_12m'] = df['ggr_per_month'] * 12 * (
1 - df['churn_probability_30d'].fillna(0.3)
)
return df
def segment_players(self, player_value: pd.DataFrame) -> pd.DataFrame:
"""Сегментація за value та активністю"""
df = player_value.copy()
ggr_median = df['ggr'].median()
activity_median = df['sessions_last_30d'].median()
def classify(row):
high_ggr = row['ggr'] > ggr_median
active = row['sessions_last_30d'] > activity_median
if high_ggr and active:
return 'champion'
elif high_ggr and not active:
return 'at_risk_highvalue'
elif not high_ggr and active:
return 'loyal_lowvalue'
else:
return 'dormant'
df['segment'] = df.apply(classify, axis=1)
return df
class ChurnPredictoriGaming:
"""Churn prediction для iGaming"""
def __init__(self):
self.model = GradientBoostingClassifier(
n_estimators=200, learning_rate=0.05, max_depth=4, random_state=42
)
def build_features(self, players: pd.DataFrame) -> pd.DataFrame:
return pd.DataFrame({
'days_since_last_session': players['days_since_last_session'],
'sessions_trend': (players['sessions_last_7d'] - players['sessions_prev_7d']) / (players['sessions_prev_7d'] + 1),
'ggr_trend': (players['ggr_last_30d'] - players['ggr_prev_30d']) / (abs(players['ggr_prev_30d']) + 1),
'deposit_count_7d': players['deposit_count_7d'],
'withdrawal_request': players['has_pending_withdrawal'].astype(int),
'bonus_expiry_ignored': players['bonus_expiry_ignored'].astype(int),
'support_complaint': players['has_support_complaint'].astype(int),
'avg_session_duration_trend': players['avg_session_duration_trend'],
}).fillna(0)
def predict(self, players: pd.DataFrame) -> pd.DataFrame:
X = self.build_features(players)
probs = self.model.predict_proba(X)[:, 1]
result = players[['player_id']].copy() if 'player_id' in players.columns else pd.DataFrame(index=players.index)
result['churn_prob_30d'] = probs
result['churn_tier'] = pd.cut(probs, bins=[0, 0.2, 0.5, 0.75, 1.0],
labels=['low', 'medium', 'high', 'critical'])
return result
class BonusCampaignOptimizer:
"""Оптимізація бонусних кампаній"""
def design_retention_campaign(self, player_segment: str,
player_stats: dict,
budget_per_player: float) -> dict:
"""Бонусна пропозиція під сегмент та бюджет"""
campaigns = {
'champion': {
'bonus_type': 'cashback_vip',
'value': min(player_stats.get('avg_weekly_ggr', 50) * 0.15, budget_per_player),
'wagering_req': 1, # Мінімальний вейджер для VIP
'message': 'Ексклюзивний кешбек для наших найкращих гравців'
},
'at_risk_highvalue': {
'bonus_type': 'targeted_reload',
'value': min(player_stats.get('avg_deposit', 100) * 0.25, budget_per_player),
'wagering_req': 3,
'message': 'Спеціальна пропозиція — поверніться до нас'
},
'loyal_lowvalue': {
'bonus_type': 'free_spins',
'value': 20, # 20 free spins ~ $5-10 value
'wagering_req': 5,
'message': 'Бонус за лояльність'
},
'dormant': {
'bonus_type': 'reactivation_bonus',
'value': min(20, budget_per_player),
'wagering_req': 5,
'message': 'Ми сумували! Ось бонус за повернення'
}
}
campaign = campaigns.get(player_segment, campaigns['loyal_lowvalue'])
# RG перевірка: не видаємо бонуси гравцям з високим RG-ризиком
if player_stats.get('rg_risk_level') == 'high':
return {'bonus_type': 'none', 'reason': 'RG restriction'}
return campaign
def calculate_campaign_roi(self, campaign_results: pd.DataFrame) -> dict:
"""ROI бонусної кампанії"""
total_bonus_cost = campaign_results['bonus_value'].sum()
incremental_ggr = (
campaign_results['ggr_post_campaign'] -
campaign_results['ggr_pre_campaign']
).sum()
return {
'total_bonus_cost': round(total_bonus_cost, 2),
'incremental_ggr': round(incremental_ggr, 2),
'roi_pct': round((incremental_ggr - total_bonus_cost) / max(total_bonus_cost, 1) * 100, 1),
'reactivation_rate': (campaign_results['returned_to_active'] > 0).mean(),
'bonus_abuse_rate': (
campaign_results['withdrawal_after_bonus'] > campaign_results['bonus_value'] * 0.9
).mean()
}
Процес роботи
- Аналітика: аудит поточної CRM, збір даних (DWH, ClickHouse), виділення сегментів.
- Проектування: визначення метрик (GGR, LTV, churn rate), вибір моделей.
- Реалізація: пайплайни на Airflow, навчання моделей, інтеграція з бонусною системою.
- Тестування: A/B тест на 10% трафіку, порівняння ROI.
- Деплой: розгортання в продакшн, дашборди, документація.
Що входить у роботу
- Аудит поточної CRM та даних
- Наповнення DWH (ClickHouse, PostgreSQL)
- ML-моделі сегментації, churn prediction, оптимізації бонусів
- Інтеграція з бонусною системою (REST API)
- Дашборди в Metabase/Tableau
- Навчання команди (2 воркшопи)
- Технічна підтримка 1 місяць
Орієнтовні строки
| Етап | Строк |
|---|---|
| Аналітика | 1-2 тижні |
| Проектування | 1 тиждень |
| Реалізація | 3-4 тижні |
| Тестування | 1 тиждень |
| Деплой та навчання | 1-2 тижні |
| Разом | 4-8 тижнів |
Порівняння метрик сегментації
| Сегмент | Частка бази | Частка GGR | Churn ризик | Рекомендований бонус |
|---|---|---|---|---|
| Champion | 5–10% | 50–70% | Низький | Кешбек з вейджером 1 |
| At-risk high value | 10–15% | 20–30% | Середній | Релоад з вейджером 3 |
| Loyal low value | 30–40% | 10–15% | Середній | Фріспіни з вейджером 5 |
| Dormant | 40–50% | 5–10% | Високий | Реактиваційний бонус |
Деталі моделі GradientBoosting
Оптимальні гіперпараметри: n_estimators=200, learning_rate=0.05, max_depth=4, subsample=0.8. Важливість фіч: days_since_last_session (0.25), ggr_trend (0.20), sessions_trend (0.18). Оцінка AUC на відкладеній вибірці — 0.87.
Типові помилки
- Ігнорування RG: без вбудованих RG-перевірок бонуси можуть стимулювати проблемних гравців, що призведе до штрафів.
- Pure RFM: RFM не враховує GGR та тренди, дає хибні пріоритети.
- Масові бонуси: без сегментації бонусний бюджет витрачається на мисливців, ROI падає нижче 100%.
- Слабка інфраструктура: без DWH та пайплайнів дані застарівають, моделі працюють некоректно.
Гарантуємо підвищення ROI бонусних кампаній мінімум на 30% за результатами A/B тесту. Зв'яжіться з нами для консультації — оцінимо ваш проект за 2 дні. Замовте впровадження системи та отримайте перші результати вже через 4 тижні.







