AI DSP (Demand-Side Platform) Management System

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1 servicesAll 1566 services
AI DSP (Demand-Side Platform) Management System
Complex
from 1 week to 3 months
FAQ
AI Development Areas
AI Solution Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1212
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822

AI-Management Demand Side Platform

DSPs are the operational center of programmatic buying. The goal of AI in DSPs is not simply to win auctions, but to win the right auctions at the right frequency with the right audience, without overspending or showing ads where they harm the brand. This is a multi-parameter optimization problem with strict latency constraints.

Architecture of AI DSP components

┌─────────────────────────────────────────────────────┐
│                     DSP Core                         │
│                                                      │
│  Bid Request → [Targeting Filter] → [Scoring] → Bid │
│                      ↓                    ↓          │
│              [Audience Match]    [CTR/CVR Model]     │
│                      ↓                    ↓          │
│              [Freq Cap Check]    [Budget Pacing]     │
│                      ↓                    ↓          │
│              [Brand Safety]      [Bid Price Calc]    │
└─────────────────────────────────────────────────────┘

Managing Audience Segments

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
            ),
        }

Attribution Funnel Optimization

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()
        }

Typical KPIs for a managed DSP

Parameter Good Value Problem Area
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 Compliance > 98% < 95%

Full-fledged AI-based DSP optimization with audience targeting, brand safety, and multi-touch attribution increases efficiency by 30-50% compared to manual management for volumes of 10 million impressions per month.