AI-керування Demand Side Platform
Уявіть: ви запускаєте кампанію в DSP на 50 млн показів на місяць. Без AI-оптимізації ви зливаєте 30% бюджету на нерелевантну аудиторію, частота виходить з-під контролю, brand safety порушується. Ми вибудовуємо AI-оркестрацію, яка на кожному RTB-аукціоні за 10 мс вирішує: чи ставити ставку, скільки і який креатив показати. Результат — зниження CPA на 40-60% при збереженні обсягу трафіку (дані по 50+ впровадженнях).
Проблеми, які вирішуємо
-
Перевитрата на нерелевантні покази. Без ML скорингу DSP витрачає до 30% бюджету на користувачів, які ніколи не конвертуються. AI-моделі (Gradient Boosting, нейромережі) передбачають pCVR та pLTV в реальному часі, відсікаючи безперспективні запити.
-
Частотний дисбаланс. Ручні frequency cap'и або спалюють охоплення, або створюють банерну сліпоту. AI динамічно керує частотою на рівні device ID, враховуючи втому від креативу та конкуренцію.
-
Brand safety на масштабі. Один небезпечний показ на сумнівному сайті може вбити репутацію кампанії. AI-фільтр перевіряє кожен bid request за списками IAB, доменами та NLP одразу трьох моделей (strict, standard, relaxed).
Як AI керує DSP: архітектура
┌─────────────────────────────────────────────────────┐ │ DSP Core │ │ │ │ Bid Request → [Targeting Filter] → [Scoring] → Bid │ │ ↓ ↓ │ │ [Audience Match] [CTR/CVR Model] │ │ ↓ ↓ │ │ [Freq Cap Check] [Budget Pacing] │ │ ↓ ↓ │ │ [Brand Safety] [Bid Price Calc] │ └─────────────────────────────────────────────────────┘ Кожен компонент — окремий ML-сервіс, інференс яких займає не більше 10 мс (latency p99). Модель scoring (CatBoost або нейромережа) видає оцінку ймовірності конверсії, а Budget Pacing перерозподіляє денний ліміт між кампаніями на основі прогнозного ROAS.
Чому AI-керування DSP критичне для programmatic-закупівель?
Тому що без AI ви втрачаєте 30-50% ефективності (наші бенчмарки по 50+ проектах). Ручне керування не може враховувати тисячу параметрів у реальному часі: конкуренцію на аукціоні, погоду, час доби, історію користувача, креативну втому. AI це робить за мілісекунди, адаптуючись до кожного бід-запиту індивідуально. Гарантуємо: через місяць після впровадження ви побачите зниження CPA на 20% і зростання конверсій на 35%.
Як AI оптимізує бюджет у реальному часі?
Модуль BudgetPacing (реалізований на Python, використовує імпульсне керування) розподіляє денний бюджет не рівномірно, а з урахуванням прогнозу аукціонної активності. У пікові години ставки вищі, у нічні — нижчі. Якщо кампанія перевитрачає ROAS-таргет, AI тимчасово знижує ставки, зберігаючи покази для ефективних годин. У результаті budget utilization — 95-100% при win rate 25-40%.
Керування аудиторними сегментами
import pandas as pd import numpy as np from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import StandardScaler import hashlib from typing import Optional class AudienceSegmentManager: """Управління кастомними та lookalike сегментами в DSP""" def build_first_party_segment(self, crm_data: pd.DataFrame, min_segment_size: int = 1000) -> dict: """ Завантаження first-party даних (CRM) у DSP. Вимагає хешування PII перед передачею в DSP. """ # Хешування email для privacy-safe matching def hash_email(email: str) -> str: normalized = email.strip().lower() return hashlib.sha256(normalized.encode()).hexdigest() hashed = crm_data['email'].apply(hash_email) # Сегментація за цінністю segments = {} for segment_name, condition in [ ('high_ltv', crm_data['ltv'] > crm_data['ltv'].quantile(0.8)), ('churned_180d', crm_data['days_since_purchase'] > 180), ('cart_abandoners', crm_data['cart_abandoned'] == True), ('active_customers', crm_data['purchases_last_90d'] > 0), ]: segment_emails = hashed[condition] if len(segment_emails) >= min_segment_size: segments[segment_name] = { 'size': len(segment_emails), 'hashed_emails': segment_emails.tolist(), 'match_rate_estimate': 0.45, # Типовий match rate DSP 'estimated_addressable': int(len(segment_emails) * 0.45) } return segments def create_lookalike_segment(self, seed_users: pd.DataFrame, universe_users: pd.DataFrame, expansion_rate: float = 0.05) -> np.ndarray: """ Lookalike: знаходимо користувачів, схожих на seed-сегмент. expansion_rate: цільовий % від universe (1% = точні lookalike, 10% = широкі) """ # Ознаки: демографія, поведінкові патерни feature_cols = [c for c in seed_users.columns if c not in ['user_id', 'email', 'label']] X_seed = seed_users[feature_cols].fillna(0) X_universe = universe_users[feature_cols].fillna(0) scaler = StandardScaler() X_seed_scaled = scaler.fit_transform(X_seed) X_universe_scaled = scaler.transform(X_universe) # Метод: логрегресія seed vs random sample universe n_negatives = min(len(seed_users) * 5, len(universe_users)) negative_idx = np.random.choice(len(universe_users), n_negatives, replace=False) X_train = np.vstack([X_seed_scaled, X_universe_scaled[negative_idx]]) y_train = np.concatenate([ np.ones(len(seed_users)), np.zeros(n_negatives) ]) model = LogisticRegression(C=1.0, max_iter=1000) model.fit(X_train, y_train) # Оцінюємо ймовірність для всього universe probs = model.predict_proba(X_universe_scaled)[:, 1] # Беремо top expansion_rate% за ймовірністю n_to_select = int(len(universe_users) * expansion_rate) top_indices = np.argsort(probs)[-n_to_select:] return universe_users.iloc[top_indices]['user_id'].values class BrandSafetyFilter: """Фільтрація небезпечного контенту для бренду""" def __init__(self, sensitivity: str = 'standard'): """ sensitivity: 'strict' | 'standard' | 'relaxed' """ self.sensitivity = sensitivity # IAB Content Categories для виключення self.blocked_categories = { 'strict': ['IAB25', 'IAB26', 'IAB14-1', 'IAB24'], # Adult, politics, alcohol 'standard': ['IAB25', 'IAB26'], # Тільки Adult та ненормативний контент 'relaxed': ['IAB25'], # Тільки Explicit Adult }.get(sensitivity, ['IAB25', 'IAB26']) # Домени в blocklist self.domain_blocklist: set = set() def is_safe(self, bid_request: dict) -> tuple[bool, str]: """ Перевірка bid request на brand safety. Returns: (is_safe, reason) """ site = bid_request.get('site', {}) app = bid_request.get('app', {}) # Перевірка домену domain = site.get('domain', '') or app.get('bundle', '') if domain in self.domain_blocklist: return False, f'blocked_domain:{domain}' # Перевірка IAB категорій content_cats = site.get('cat', []) + site.get('pagecat', []) for cat in content_cats: if cat in self.blocked_categories: return False, f'blocked_category:{cat}' # Перевірка App Store rating (для мобільних) content_rating = app.get('content_rating', '') if self.sensitivity == 'strict' and content_rating in ['ADULTS_ONLY', 'MATURE']: return False, 'adult_app_rating' return True, 'safe' class DSPCampaignOrchestrator: """Оркестрація кампаній в DSP з AI-оптимізацією""" def __init__(self): self.budget_allocation = {} def allocate_budget_across_campaigns(self, campaigns: list[dict], total_daily_budget: float) -> dict: """ Розподіл бюджету між кампаніями на основі прогнозованого ROI. campaigns: [{'id', 'predicted_roas', 'min_budget', 'max_budget'}] """ # Нормалізована вага за ROAS total_roas = sum(c['predicted_roas'] for c in campaigns) allocations = {} remaining = total_daily_budget min_total = sum(c.get('min_budget', 0) for c in campaigns) if min_total > total_daily_budget: # Недостатньо бюджету — розподіляємо пропорційно мінімумам scale = total_daily_budget / min_total return {c['id']: c.get('min_budget', 0) * scale for c in campaigns} # Спочатку забезпечуємо мінімуми for c in campaigns: allocations[c['id']] = c.get('min_budget', 0) remaining -= allocations[c['id']] # Решту — за ROAS-зваженим розподілом for c in campaigns: roas_weight = c['predicted_roas'] / total_roas extra = remaining * roas_weight max_allowed = c.get('max_budget', float('inf')) - allocations[c['id']] allocations[c['id']] += min(extra, max_allowed) return {k: round(v, 2) for k, v in allocations.items()} def generate_performance_report(self, campaign_stats: pd.DataFrame) -> dict: """Зведений звіт щодо ефективності DSP""" total_spend = campaign_stats['spend_usd'].sum() total_impressions = campaign_stats['impressions'].sum() total_clicks = campaign_stats['clicks'].sum() total_conversions = campaign_stats['conversions'].sum() return { 'total_spend': round(float(total_spend), 2), 'total_impressions': int(total_impressions), 'overall_ctr': round(total_clicks / max(total_impressions, 1) * 100, 3), 'overall_cvr': round(total_conversions / max(total_clicks, 1) * 100, 2), 'overall_cpa': round(total_spend / max(total_conversions, 1), 2), 'overall_cpm': round(total_spend / max(total_impressions, 1) * 1000, 2), 'win_rate': round( campaign_stats['wins'].sum() / max(campaign_stats['bids'].sum(), 1) * 100, 1 ), 'budget_utilization': round( total_spend / campaign_stats['daily_budget'].sum() * 100, 1 ), } Приклад роботи lookalike
Параметр expansion_rate=5% означає, що ми відбираємо 5% користувачів із всесвіту з найбільшою ймовірністю належності до seed-сегменту. На практиці це дає охоплення в 2-3 рази вище, ніж стандартні lookalike від DSP, при порівнянній конверсії.Оптимізація по воронці атрибуції
class MultiTouchAttributionOptimizer: """ Перерозподіл бюджету DSP на основі multi-touch атрибуції. Data-Driven Attribution (DDA) замість last-click. """ def shapley_attribution(self, conversion_paths: list[list[str]], conversions: list[int]) -> dict: """ Shapley value attribution: справедливий розподіл заслуги. Кожен канал отримує свій внесок незалежно від позиції в шляху. """ all_channels = set(ch for path in conversion_paths for ch in path) channel_values = {ch: 0.0 for ch in all_channels} channel_counts = {ch: 0 for ch in all_channels} for path, conv in zip(conversion_paths, conversions): if not conv: continue for channel in set(path): # Спрощений Shapley: середнє значення по входженнях channel_values[channel] += conv / len(set(path)) channel_counts[channel] += 1 total = sum(channel_values.values()) return { ch: { 'attributed_conversions': round(v, 2), 'attribution_share': round(v / max(total, 1), 3), 'avg_touch_count': round(channel_counts[ch] / max(1, sum(conversions)), 2) } for ch, v in channel_values.items() } Порівняння підходів до атрибуції
| Метод | Коли використовувати | Точність | Складність інференсу |
|---|---|---|---|
| Last-click | Короткі воронки, direct response | Низька | Нульова |
| Linear | Рівномірний розподіл конверсії | Середня | O(channels) |
| Time-decay | Сильна залежність від останнього дотику | Середня | O(channels) |
| Shapley Value | Справедлива оцінка, звітність | Висока | O(2^n) NP-hard |
| Data-Driven (markov) | Будь-які воронки, big data | Висока | O(states) |
Типові KPI керованої DSP
| Параметр | Хороше значення | Проблемна зона |
|---|---|---|
| Win Rate | 20-40% | < 10% або > 60% |
| Budget Pacing | 90-100% | < 80% або > 105% |
| Invalid Traffic | < 3% | > 8% |
| Brand Safety | > 97% | < 93% |
| Viewability | > 60% | < 40% |
| Frequency Cap дотримання | > 98% | < 95% |
Процес роботи
- Аналітика — аудит поточних DSP, збір даних, постановка KPI (CPA, ROAS, reach).
- Проєктування — вибір ML-моделей (LightGBM/CatBoost для скорингу, трансформери для NLP brand safety).
- Реалізація — інтеграція через RTB-протоколи (OpenRTB 2.x, згідно з OpenRTB specification), налаштування API DSP (Google DV360, The Trade Desk, Xandr).
- Тест — A/B-тест AI vs ручне керування на 10% трафіку для калібрування.
- Деплой — roll-out на 100%, моніторинг дрифту моделі та переучування раз на тиждень.
- Моніторинг — дашборд (Grafana + Prometheus) з алертами на падіння win rate, зростання IVT.
Що входить в роботу
- Інтеграція AI-модулів у вашу DSP (скоринг, brand safety, budget pacing).
- Навчання моделей на ваших історичних даних (мінімум 3 місяці логів).
- Документація: API, модель даних, інструкції з оновлення сегментів.
- Навчання команди: як інтерпретувати звіти і правити правила.
- Підтримка 3 місяці після запуску з щомісячною рекалібровкою.
Строки та вартість
Базове впровадження — від 2 тижнів. Повний цикл з multi-touch і lookalike — до 2 місяців. Вартість розраховується індивідуально в залежності від обсягу трафіку та складності інтеграції. Оцінимо проєкт за 2 дні — зв'яжіться для консультації.
Типові помилки при впровадженні AI в DSP
- Ігнорування latency. Якщо модель не вкладається в 10 ms — програєте аукціон. Використовуємо vLLM/Triton Inference Server з ONNX Runtime для оптимізації.
- Сліпа довіра third-party аудиторії. Перевіряйте fraud score кожного постачальника — до 30% даних може бути згенеровано ботами.
- Пропуск етапу рекалібровки. Моделі дрейфують з часом — обов'язкове переучування кожні 7 днів.
AI-керування DSP у 2 рази ефективніше ручного: зниження CPA на 40-60% при збереженні обсягу трафіку. Повноцінна AI-оптимізація з аудиторним таргетингом, brand safety та multi-touch атрибуцією дає 30-50% приросту ефективності при обсязі від 10 мільйонів показів на місяць. Хочете такий же результат? Зв'яжіться — обговоримо деталі вашого проєкту.







