מיקוד קהלים עם ML בפרסום
למידת מכונה למיקוד מתרגמת מ"הצגה לכל הנשים בגילאי 25-34" ל"הצגה לאלה עם הסתברות של 73%+ להמרה בתוך 7 הימים הקרובים." הפרש היעילות הוא פי 3-5 עם אותו תקציב. אנו מיישמים מודלים כאלה לקמפיינים פרסומיים: בפרויקט טיפוסי, CTR עולה מ-0.08% ל-0.4%, והעלות לליד יורדת ב-40%. אנו מסתמכים אך ורק על נתוני צד ראשון — הדרך הברת-קיימא היחידה בעולם ללא עוגיות צד שלישי. לדוגמה, בפרויקט מסחר אלקטרוני אחד, CPA ירד מ-$12 ל-$7 — חיסכון של 42%. בקשו ייעוץ ליישום מודל מיקוד ML — נבחר את הפתרון האופטימלי עבור הנתונים שלכם.
בעיות שאנו פותרים
מיקוד דמוגרפי עיוור. גיל ומגדר אינם מבטיחים עניין. משתמש בן 35 עשוי לחפש מתנה לילד, לא לעצמו. מודל ML מעריך אותות התנהגותיים: תדירות צפייה בדפי מוצר, פעולות הוספה לסל, זמן בין מפגשים. התוצאה היא דיוק חיזוי המרה >85%.
קהלים מנופחים עם המרה נמוכה. מודלי Lookalike המבוססים על 50+ משתמשי בסיס מרחיבים את הקהל תוך שמירה על ריכוז הלידים "החמים". אנו משתמשים במסווג מפוקח (LightGBM) עם הסתברויות מכוילות, לא kNN פשוט — זה מניב שיפור ROC-AUC של 0.08–0.12.
אובדן הקשר לאחר ריטרגטינג. כאשר משתמש מנווט למאמר טכנולוגי ומוצגים לו כרטיסי אשראי — שבירת הקשר. המנוע הקונטקסטואלי שלנו מנתח את ה-URL וטקסט הדף, קובע את הקטגוריה של IAB (לדוגמה, IAB19 — טכנולוגיה) ובוחר קריאייטיבים באותו נושא. זה עובד ללא נתוני משתמש, מה שחשוב ל-GDPR.
כיצד מודל ה-ML מעריך נטייה?
המפתח הוא תכונות איכותיות. אנו לוקחים אירועים גולמיים: product_view, add_to_cart, checkout_start, search. אנו מחשבים רעננות (שעות מאז האירוע האחרון), תדירות מפגשים, עומק משפך (ממוצע משוקלל של פעולות), מגמת פעילות (7 ימים אחרונים לעומת קודמים). תכונות אלה מוזנות למסווג LightGBM עם פרמטרים מכוונים: learning_rate=0.01, max_depth=6, colsample_bytree=0.8. אנו מקבלים עבור כל משתמש purchase_probability ורמות: קר (<10%), חם (10-30%), חם מאוד (30-60%), מוכן לקנייה (>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:
"""Создание аудиторий на основе вероятностей конверсии"""
def build_intent_features(self, user_events: pd.DataFrame) -> pd.DataFrame:
"""
Признаки намерения из событий пользователя.
user_events: user_id, event_type, page_url, timestamp, session_id
"""
df = user_events.copy()
df['ts'] = pd.to_datetime(df['timestamp'])
# Рекентность последней активности
now = df['ts'].max()
recency = df.groupby('user_id')['ts'].max().apply(
lambda t: (now - t).total_seconds() / 3600
).rename('hours_since_last_event')
# Поведенческие признаки
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()),
)
# Конверсионная воронка (нормализованная)
behavior['funnel_depth'] = (
behavior['product_views'] * 1 +
behavior['cart_adds'] * 3 +
behavior['checkout_starts'] * 7
) / behavior['total_sessions'].clip(1)
# Сессионная активность: тренд последних 7 дней vs предыдущие 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:
"""Оценка вероятности покупки для каждого пользователя"""
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:
"""Поведенческая сегментация без supervision"""
def segment_by_behavior(self, user_features: pd.DataFrame, n_clusters: int = 8) -> pd.DataFrame:
"""
K-Means кластеризация для выявления скрытых аудиторных сегментов.
"""
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
# Профили кластеров
profiles = user_features.groupby('cluster')[feature_cols].mean()
return user_features, profiles
def label_clusters(self, cluster_profiles: pd.DataFrame) -> dict:
"""Автоматическая маркировка кластеров по профилям"""
labels = {}
for cluster_id, row in cluster_profiles.iterrows():
# Упрощённая эвристическая маркировка
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
כיצד להגדיר מיקוד קונטקסטואלי ללא עוגיות?
class ContextualTargetingEngine:
"""ML-таргетинг на основе контента страницы (cookieless)"""
def classify_page_context(self, page_text: str, page_url: str) -> dict:
"""
IAB категоризация страницы для контекстуального таргетинга.
Работает без user-level data (GDPR-compliant).
"""
# Ключевые сигналы контекста
url_signals = self._extract_url_signals(page_url)
# В production: BERT-based classifier, обученный на IAB taxonomy
# Здесь упрощённая keyword-based версия
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
מדוע מיקוד חיזוי עולה על מיקוד דמוגרפי?
מיקוד דמוגרפי (גיל/מגדר) הוא שריד. CPM נמוך, אך ההמרה נעה ב-0.05-0.1%. מיקוד התנהגותי המבוסס על עוגיות צד שלישי מניב CTR של 0.2-0.5%, אך ייעלם בקרוב. מודלי ML המבוססים על נתוני צד ראשון מספקים CTR של 0.3-0.8% ובזבוז תקציב מינימלי על קהלים "קרים". בטווח הארוך, רק הראשון אינו תלוי בסיכונים רגולטוריים. מיקוד חיזוי יעיל פי 2-4 ממודלי Lookalike המבוססים על kNN, מכיוון שהוא משתמש בהגברת גרדיאנט במקום באשכולות פשוטים.
השוואת שיטות מיקוד
| שיטה | CPM | CTR | המרה | פרטיות |
|---|---|---|---|---|
| דמוגרפי (גיל/מגדר) | נמוך | 0.05-0.1% | נמוכה | בטוח |
| התנהגותי (עוגיות צד שלישי) | גבוה | 0.2-0.5% | בינונית | מוגבל |
| חיזוי (נטיית ML) | בינוני | 0.3-0.8% | גבוהה | צד ראשון |
| Lookalike ML | בינוני | 0.2-0.6% | בינונית | צד ראשון |
| קונטקסטואלי (ללא עוגיות) | בינוני | 0.1-0.3% | בינונית | בטוח |
שימוש במיקוד חיזוי חוסך עד 40% מתקציב הפרסום ומפחית CPA ב-30-50%. כפי שמומחים מציינים, הגברת גרדיאנט היא הסטנדרט התעשייתי למשימות סיווג בינארי עם נתונים טבלאיים.
מידע נוסף על מדדי המודל
כדי להעריך את איכות מודל הנטייה, אנו משתמשים ב-AUPRC (שטח מתחת לעקומת דיוק-רגישות) — הוא רגיש לחוסר איזון מחלקות. ערך היעד הוא ≥0.75. בנוסף, אנו שולטים בכיול ההסתברויות באמצעות עקומת כיול. אם המודל מעריך יתר על המידה את ההסתברות לקהל קר, אנו מתאימים את הסף.כיצד ליישם מיקוד חיזוי: תוכנית שלב אחר שלב
- ביקורת נתונים: בדיקת איכות מעקב האירועים (Google Tag Manager, Amplitude, צינורות מותאמים אישית).
- הנדסת תכונות: Python/Pandas ליצירת תכונות (פעילות, משפך, מגמות).
- אימון מודל: מסווג LightGBM עם כיול הסתברויות, walidacja צולבת מבוססת זמן.
- אשכולות: MiniBatchKMeans לזיהוי פלחים (עצלנים, חמים, נוטשים).
- מנוע קונטקסטואלי: מודול NLP המבוסס על BERT לסיווג דפים לפי טקסונומיית IAB (עד 30 קטגוריות).
- אינטגרציה עם DSP: API לשליחת פלחים ל-Facebook Ads, Google Ads, Yandex.Direct או פלטפורמה עצמאית.
- בדיקות A/B: השקה מול מיקוד בסיס למשך שבועיים — אנו מבטיחים עליית ROAS של 25%+ או התאמה חינם.
מה כלול בעבודה
הניסיון שלנו: מעל 50 פרויקטים מוצלחים למסחר אלקטרוני ופינטק.
- ביקורת נתונים: הערכת איכות ושלמות נתוני האירועים, הגדרת מעקב.
- פיתוח תכונות: סקריפטים של Python/Pandas ליצירת תכונות.
- מודל נטייה: מסווג LightGBM עם כיול הסתברויות, AUPRC ≥0.75.
- אשכולות: MiniBatchKMeans לזיהוי פלחים.
- מנוע קונטקסטואלי: מודול NLP המבוסס על BERT לסיווג דפים לפי טקסונומיית IAB.
- אינטגרציה עם DSP: API לשליחת פלחים לפלטפורמות פרסום.
- נסיעת מבחן: בדיקות A/B של המודל מול מיקוד בסיס למשך שבועיים — אנו מבטיחים עליית ROAS של 25%+ או התאמה חינם.
תהליך העבודה
| שלב | משך |
|---|---|
| אנליטיקה: איסוף ו-ETL של הטראקר | 2-3 ימים |
| הנדסת תכונות: בניית מאגר נתונים | 3-5 ימים |
| פיתוח ML: אימון ואימות מודל | 5-7 ימים |
| בדיקות: ניסוי A/B בקמפיין אמיתי | 7-14 ימים |
| פריסה: העלאת המודל לסביבת ייצור | 2-3 ימים |
לוח זמנים ועלות
מסגרות זמן משוערות — מ-4 עד 6 שבועות ל-MVP עובד. העלות מחושבת באופן אישי בהתאם לנפח הנתונים, מספר אירועי היעד והאינטגרציות. קבלו ייעוץ — ננעל מדדי הצלחה בהתחלה.
משאבים נוספים: LightGBM, טקסונומיית IAB.







