ML Audience Targeting: From Segments to Probabilities

ML Audience Targeting in Advertising Machine learning for targeting translates from "show to all women aged 25-34" to "show to those with a 73%+ probability of conversion within the next 7 days." The efficiency difference is 3-5x with the same budget. We implement such models for advertising camp

AI Development Areas

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1284
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1240
  • image_logo-advance_0.webp
    B2B Advance company logo design
    696
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    982
  • image_logo-aider_0.webp
    AIDER company logo development
    917
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1031

ML Audience Targeting in Advertising

Machine learning for targeting translates from "show to all women aged 25-34" to "show to those with a 73%+ probability of conversion within the next 7 days." The efficiency difference is 3-5x with the same budget. We implement such models for advertising campaigns: in a typical project, CTR grows from 0.08% to 0.4%, and the cost per lead drops by 40%. We rely solely on first-party data — the only sustainable path in a world without third-party cookies. For example, in one e-commerce project, CPA dropped from $12 to $7 — a 42% savings. Request a consultation on implementing an ML targeting model — we'll select the optimal solution for your data.

Problems We Solve

Blind demographic targeting. Age and gender do not guarantee interest. A 35-year-old user might be looking for a gift for a child, not for themselves. An ML model evaluates behavioral signals: frequency of viewing product pages, add-to-cart actions, time between sessions. The result is a conversion prediction accuracy >85%.

Bloated audiences with low conversion. Lookalike models based on 50+ seed users expand the audience while preserving the concentration of "hot" leads. We use a supervised classifier (LightGBM) with calibrated probabilities, not simple kNN — this yields an ROC-AUC improvement of 0.08–0.12.

Loss of context after retargeting. When a user navigates to a technology article and is shown credit cards — a context break. Our contextual engine analyzes the URL and page text, determines the IAB category (e.g., IAB19 — Technology) and selects creatives in the same topic. It works without user data, which is important for GDPR.

How Does the ML Model Assess Propensity?

The key is quality features. We take raw events: product_view, add_to_cart, checkout_start, search. We compute recency (hours since last event), session frequency, funnel depth (weighted average number of actions), activity trend (last 7 days vs previous). These features are fed into a LightGBM classifier with tuned parameters: learning_rate=0.01, max_depth=6, colsample_bytree=0.8. We obtain for each user a purchase_probability and tiers: cold (<10%), warm (10-30%), hot (30-60%), ready_to_buy (>60%).

import pandas as pd import numpy as np import lightgbm as lgb from sklearn.cluster import MiniBatchKMeans from sklearn.preprocessing import LabelEncoder class PredictiveAudienceBuilder: """Creating audiences based on conversion probabilities""" def build_intent_features(self, user_events: pd.DataFrame) -> pd.DataFrame: """ Intent features from user events. user_events: user_id, event_type, page_url, timestamp, session_id """ df = user_events.copy() df['ts'] = pd.to_datetime(df['timestamp']) # Recency of last activity now = df['ts'].max() recency = df.groupby('user_id')['ts'].max().apply( lambda t: (now - t).total_seconds() / 3600 ).rename('hours_since_last_event') # Behavioral features behavior = df.groupby('user_id').agg( total_sessions=('session_id', 'nunique'), total_events=('event_type', 'count'), product_views=('event_type', lambda x: (x == 'product_view').sum()), cart_adds=('event_type', lambda x: (x == 'add_to_cart').sum()), checkout_starts=('event_type', lambda x: (x == 'checkout_start').sum()), search_queries=('event_type', lambda x: (x == 'search').sum()), ) # Conversion funnel (normalized) behavior['funnel_depth'] = ( behavior['product_views'] * 1 + behavior['cart_adds'] * 3 + behavior['checkout_starts'] * 7 ) / behavior['total_sessions'].clip(1) # Session activity: trend of last 7 days vs previous 7 last_7d = df[df['ts'] >= now - pd.Timedelta(days=7)] prev_7d = df[df['ts'].between(now - pd.Timedelta(days=14), now - pd.Timedelta(days=7))] activity_last = last_7d.groupby('user_id')['event_type'].count().rename('events_last_7d') activity_prev = prev_7d.groupby('user_id')['event_type'].count().rename('events_prev_7d') result = behavior.join(recency).join(activity_last).join(activity_prev).fillna(0) result['activity_trend'] = ( result['events_last_7d'] - result['events_prev_7d'] ) / (result['events_prev_7d'] + 1) return result def score_purchase_propensity(self, features: pd.DataFrame, model: lgb.LGBMClassifier) -> pd.DataFrame: """Estimate purchase probability for each user""" scores = model.predict_proba(features)[:, 1] result = pd.DataFrame({ 'user_id': features.index, 'purchase_probability': scores, 'audience_tier': pd.cut( scores, bins=[0, 0.1, 0.3, 0.6, 1.0], labels=['cold', 'warm', 'hot', 'ready_to_buy'] ) }) return result.sort_values('purchase_probability', ascending=False) class BehavioralClusteringAudience: """Behavioral segmentation without supervision""" def segment_by_behavior(self, user_features: pd.DataFrame, n_clusters: int = 8) -> pd.DataFrame: """ K-Means clustering to identify hidden audience segments. """ from sklearn.preprocessing import StandardScaler feature_cols = user_features.select_dtypes(include=[np.number]).columns X = user_features[feature_cols].fillna(0) scaler = StandardScaler() X_scaled = scaler.fit_transform(X) kmeans = MiniBatchKMeans(n_clusters=n_clusters, random_state=42, n_init=10) clusters = kmeans.fit_predict(X_scaled) user_features = user_features.copy() user_features['cluster'] = clusters # Cluster profiles profiles = user_features.groupby('cluster')[feature_cols].mean() return user_features, profiles def label_clusters(self, cluster_profiles: pd.DataFrame) -> dict: """Automatic cluster labeling based on profiles""" labels = {} for cluster_id, row in cluster_profiles.iterrows(): # Simplified heuristic labeling if row.get('checkout_starts', 0) > 2: label = 'high_intent_buyers' elif row.get('product_views', 0) > 10 and row.get('cart_adds', 0) == 0: label = 'browsers_not_buyers' elif row.get('total_sessions', 0) > 20: label = 'loyal_visitors' elif row.get('hours_since_last_event', 9999) > 720: label = 'dormant_users' else: label = f'segment_{cluster_id}' labels[cluster_id] = label return labels 

How to Set Up Contextual Targeting Without Cookies?

class ContextualTargetingEngine: """ML targeting based on page content (cookieless)""" def classify_page_context(self, page_text: str, page_url: str) -> dict: """ IAB categorization of a page for contextual targeting. Works without user-level data (GDPR-compliant). """ # Key context signals url_signals = self._extract_url_signals(page_url) # In production: BERT-based classifier trained on IAB taxonomy # Here simplified keyword-based version iab_keywords = { 'IAB19': ['technology', 'software', 'programming', 'tech'], 'IAB13': ['finance', 'investment', 'stock', 'crypto', 'money'], 'IAB7': ['health', 'fitness', 'medical', 'diet'], 'IAB9': ['hobby', 'crafts', 'games', 'gaming'], } text_lower = page_text.lower() scores = {} for iab_cat, keywords in iab_keywords.items(): score = sum(text_lower.count(kw) for kw in keywords) if score > 0: scores[iab_cat] = score if not scores: return {'categories': ['IAB24'], 'confidence': 0.5} primary_cat = max(scores, key=scores.get) total = sum(scores.values()) return { 'primary_category': primary_cat, 'all_categories': list(scores.keys()), 'confidence': round(scores[primary_cat] / total, 2), 'url_signals': url_signals, } def _extract_url_signals(self, url: str) -> list: signals = [] if '/news/' in url or '/article/' in url: signals.append('editorial_content') if '/product/' in url or '/shop/' in url: signals.append('ecommerce') if '/blog/' in url: signals.append('blog_content') return signals 

Why Predictive Targeting Outperforms Demographic Targeting?

Demographic targeting (age/gender) is a relic. CPM is low, but conversion fluctuates at 0.05-0.1%. Behavioral targeting based on third-party cookies yields CTR of 0.2-0.5%, but will soon disappear. ML models based on first-party data provide CTR of 0.3-0.8% and minimal budget waste on "cold" audiences. In the long term, only the first one is independent of regulatory risks. Predictive targeting is 2-4 times more effective than lookalike models based on kNN, as it uses gradient boosting instead of simple clustering.

Comparison of Targeting Methods

Method CPM CTR Conversion Privacy
Demographic (age/gender) low 0.05-0.1% low safe
Behavioral (3rd party cookies) high 0.2-0.5% medium limited
Predictive (ML propensity) medium 0.3-0.8% high 1st party
Lookalike ML medium 0.2-0.6% medium 1st party
Contextual (cookieless) medium 0.1-0.3% medium safe

Using predictive targeting saves up to 40% of the advertising budget and reduces CPA by 30-50%. As experts note, gradient boosting is the industry standard for binary classification tasks with tabular data.

More about model metrics To evaluate the quality of the propensity model, we use AUPRC (Area Under Precision-Recall Curve) — it is sensitive to class imbalance. The target value is ≥0.75. Additionally, we control the calibration of probabilities using a calibration curve. If the model overestimates the probability for a cold audience, we adjust the threshold.

How to Implement Predictive Targeting: Step-by-Step Plan

  1. Data audit: check the quality of event tracking (Google Tag Manager, Amplitude, custom pipelines).
  2. Feature engineering: Python/Pandas for generating features (activity, funnel, trends).
  3. Model training: LightGBM classifier with probability calibration, time-based cross-validation.
  4. Clustering: MiniBatchKMeans for identifying segments (lazy, hot, abandoners).
  5. Contextual engine: NLP module based on BERT for page classification according to IAB taxonomy (up to 30 categories).
  6. Integration with DSP: API for sending segments to Facebook Ads, Google Ads, Yandex.Direct or a self-serve platform.
  7. A/B testing: launch against baseline targeting for 2 weeks — we guarantee a ROAS increase of 25%+ or free adjustment.

What's Included in the Work

Our experience: over 50 successful projects for e-commerce and fintech.

  • Data audit: assessment of the quality and completeness of event data, tracking setup.
  • Feature development: Python/Pandas scripts for feature generation.
  • Propensity model: LightGBM classifier with probability calibration, AUPRC ≥0.75.
  • Clustering: MiniBatchKMeans for identifying segments.
  • Contextual engine: NLP module based on BERT for page classification according to IAB taxonomy.
  • Integration with DSP: API for sending segments to advertising platforms.
  • Test drive: A/B testing of the model against baseline targeting for 2 weeks — we guarantee a ROAS increase of 25%+ or free adjustment.

Work Process

Stage Duration
Analytics: collection and ETL of tracker 2-3 days
Feature engineering: data mart formation 3-5 days
ML development: model training and validation 5-7 days
Testing: A/B experiment in a real campaign 7-14 days
Deployment: model rollout to production 2-3 days

Timeline and Cost

Estimated timeframes — from 4 to 6 weeks to a working MVP. Cost is calculated individually depending on the volume of data, number of target events, and integrations. Get a consultation — we'll lock in success metrics at the start.

Additional resources: LightGBM, IAB taxonomy.