
Incrementality testing e holdout
Misurare l'effetto incrementale del marketing con holdout test e gruppi di controllo.
Cosa imparerai
- Comprendere il problema analitico e il contesto decisionale
- Applicare esempi, metriche e controlli a casi reali
Collegamenti
import random
Incrementality testing e holdout
La piattaforma mostra un ROAS positivo, ma il dubbio resta: quante di quelle vendite sarebbero arrivate comunque, senza esposizione? L’incrementality testing sposta la domanda dal credito attribuito al valore davvero aggiunto, usando gruppi di controllo per misurare l’impatto reale. È una difesa contro la confusione tra conversioni osservate e conversioni create. Il holdout è costoso perché rinunci a trattare una parte del pubblico, ma è proprio quel costo a comprare evidenza.
Perché ogni canale mente senza holdout
Un utente vede un annuncio Facebook e compra. Ci sono tre possibilità. Ha comprato a causa dell’annuncio, ed è incrementale: il canale crea valore reale. Avrebbe comprato comunque, ed è cannibalizzazione: stai pagando per una conversione gratuita. Oppure è un nuovo cliente organico attribuito per errore al canale, e ti stai prendendo un credito immeritato.
Senza holdout test, i casi due e tre sono indistinguibili dal primo. E nella media dei settori rappresentano il 40-70% delle conversioni attribuite. È per questo che l’incrementality non è un raffinamento accademico: è la differenza tra sapere quanto budget sta lavorando e quanto sta solo seguendo domanda già esistente.
Progettare un holdout test
Un holdout test si costruisce tenendo da parte una quota di utenti che non riceve la campagna, e confrontando poi il comportamento dei due gruppi. Lo scheletro in Python è semplice.
users = df['user_id'].unique()
holdout_size = int(len(users) * 0.10) # 10% controllo
holdout_set = set(random.sample(list(users), holdout_size))
df['is_holdout'] = df['user_id'].isin(holdout_set)
# Il gruppo holdout NON riceve campagne su questo canale
# per la durata del test
# Dopo 30 giorni: analisi
exposed = df.query('is_holdout == False')
control = df.query('is_holdout == True')
lift_absolute = exposed['converted'].mean() - control['converted'].mean()
lift_relative = lift_absolute / control['converted'].mean() * 100
from scipy.stats import ttest_ind
_, p_value = ttest_ind(exposed['converted'], control['converted'])
print(f"Incremental lift: {lift_absolute:.4f} ({lift_relative:.1f}%), p={p_value:.4f}")
Perché un holdout sia valido servono alcune condizioni. La randomizzazione deve essere vera, non “prendo gli inattivi”, altrimenti il gruppo di controllo non è comparabile. La dimensione deve bastare, con un minimo di 1.000 utenti per gruppo per avere potenza statistica. La durata copre almeno un ciclo di acquisto completo, da 2 a 4 settimane per l’e-commerce e da 1 a 3 mesi per il SaaS. Il gruppo di controllo non deve mai ricevere campagne su quel canale per l’intero periodo. E il lift va misurato su metriche di business come revenue e profit, non su metriche intermedie come CTR o click.
Tipi di holdout test
Non esiste un solo modo di tenere da parte un gruppo di controllo, e ogni metodo ha compromessi diversi.
| Tipo | Metodo | Pro | Contro |
|---|---|---|---|
| Geografico | Spegni campagne in mercato A, tieni in B | Semplice, nessun impatto UX | Mercati diversi possono avere dinamiche diverse |
| Temporale | Spegni per 2 settimane, confronta con 2 settimane prima/dopo | Facile, stesso mercato | Stagionalità, trend esterni confondono |
| Utente (gold standard) | Random split a livello utente | Il più robusto statisticamente | Utenti nel controllo potrebbero notare assenza ads |
| Ghost ads | Mostri ad placebo (es. PSA) al controllo | Controllo perfetto, utente non nota | Complesso da implementare, richiede ad server |
Calcolare il vero ROAS incrementale
Una volta raccolti i dati, il confronto chiave è tra il ROAS che tutti misurano e quello che conta davvero.
# ROAS apparente (quello che tutti misurano)
apparent_roas = exposed['revenue'].sum() / campaign_spend
# ROAS incrementale
incremental_revenue = (exposed['revenue'].mean() - control['revenue'].mean()) * len(exposed)
incremental_roas = incremental_revenue / campaign_spend
print(f"Apparent ROAS: {apparent_roas:.1f}x")
print(f"Incremental ROAS: {incremental_roas:.1f}x")
if incremental_roas > apparent_roas * 0.5:
print("Canale genuinamente efficace")
else:
print("ATTENZIONE: maggior parte delle conversioni non incrementali")
Non stupirti se un canale con ROAS apparente di 5x ha un ROAS incrementale di 1.5x. È normale, e significa che il canale resta profittevole ma molto meno di quanto sembri.
Il caso eBay: l’holdout che ha salvato 50 milioni di dollari
Nel 2012 eBay spendeva 50 milioni di dollari l’anno su Google Ads per la keyword “eBay”, cioè le proprie brand keyword. Fecero un holdout geografico: spensero le ads in 30 mercati USA e le mantennero in 30 mercati simili. Dopo 60 giorni la differenza di revenue tra i mercati con e senza ads era zero. Gli utenti che cercavano “eBay” su Google avrebbero comunque cliccato il risultato organico, primo in classifica, e comprato. Quei 50 milioni erano spesa pura senza alcun effetto incrementale.
eBay tagliò completamente le brand keyword. Il traffico organico assorbì il 99.5% del volume precedente e il revenue restò invariato. Lo chiamarono il più costoso test A/A della storia, perché il gruppo di controllo e quello esposto si comportavano esattamente allo stesso modo. Il risultato è documentato nel paper accademico di Blake, Nosko e Tadelis (2015), pubblicato su Econometrica.
Costruire un programma di incrementality permanente
Un singolo holdout è utile, ma il valore cresce quando il testing diventa una pratica continua. Ogni canale che pesa più del 5% del budget dovrebbe avere un holdout test almeno una volta l’anno. Dopo ogni cambio di strategia, come un nuovo targeting o una nuova creatività, va rifatto un test di incrementality. Ogni report di canale dovrebbe riportare sia il ROAS apparente sia quello incrementale. E l’allocazione del budget dovrebbe basarsi sul ROAS incrementale, non su quello apparente.
Prima di usare un holdout in una decisione, controlla sempre completezza dei dati, duplicati, timezone, definizioni cambiate e segmenti esclusi. Molte analisi apparentemente sofisticate falliscono perché il dato di partenza misura un comportamento diverso da quello che il team crede di osservare.
Una sequenza di lavoro e la formalizzazione
Quando affronti un caso reale, usa una sequenza che impedisce di trasformare la tecnica in un rituale: decidi cosa cambia se capisci meglio l’effetto incrementale, individua il segnale osservabile che riduce l’incertezza, scegli la baseline rispetto a cui leggere il risultato, dichiara cosa potrebbe falsare la lettura e definisci il passo operativo che segue.
Per rendere l’analisi riproducibile, definisci prima l’unità di lavoro, che può essere cliente, campagna, segmento, previsione o feature. Poi collega l’unità a una metrica osservabile come lift, errore, stabilità, valore marginale e costo operativo. Infine dichiara la decisione attesa, che sia un modello, un esperimento, un segmento attivabile o una raccomandazione.
| Elemento | Specifica richiesta |
|---|---|
| Unità di analisi | cliente, campagna, segmento, previsione o feature |
| Segnale principale | lift, errore, stabilità, valore marginale e costo operativo |
| Baseline | Periodo precedente, gruppo comparabile, benchmark o scenario controfattuale |
| Decisione | modello, esperimento, segmento attivabile o raccomandazione |
| Rischio | Scambiare un numero disponibile per una prova sufficiente |
La formalizzazione è solida quando un altro analista può riprodurre la logica, criticare le assunzioni e arrivare alla stessa decisione partendo dagli stessi dati.
Esempio: paid social sotto holdout
Paid social dichiara un ROAS di 4x, ma in una regione holdout le vendite crescono quasi allo stesso ritmo. Il caso costringe il team a misurare il lift incrementale, non solo il revenue attribuito, e a decidere se il canale merita davvero budget aggiuntivo.
| Evidenza osservata | Lettura prudente | Azione consigliata |
|---|---|---|
| Il numero migliora | Potrebbe essere effetto reale o variazione normale | Cercare confronto e segmento |
| Un segmento cambia più degli altri | La media aggregata nasconde una differenza | Separare coorti o casi d’uso |
| Il costo cresce insieme al risultato | L’impatto va letto sul margine | Stimare trade-off e sostenibilità |
Lab ed esercizio
Al livello base scrivi una scheda di una pagina: la decisione da supportare, la metrica primaria, la baseline, il rischio principale e l’azione se il segnale è confermato. Al livello intermedio costruisci una tabella con tre segmenti, periodi o scenari, indicando per ciascuno cosa cambia, quale spiegazione alternativa è plausibile e quale controllo useresti prima di raccomandare un’azione. Al livello research-grade prepara un decision memo con ipotesi, dati richiesti, criteri di esclusione, controlli di qualità, soglia decisionale, rischio residuo e piano di monitoraggio.
Come materiale usa CRM, campagne, transazioni, feature di marketing, testo, embeddings e serie storiche. Se non hai accesso a dati reali, crea un dataset sintetico con almeno 200 righe, una dimensione temporale, una dimensione segmento e una metrica di outcome.
L’errore tipico da evitare
L’errore più comune è usare l’incrementality come etichetta invece che come processo. Succede quando il team mostra un grafico senza decisione, una metrica senza baseline o una conclusione senza indicare quale assunzione potrebbe invalidarla. La domanda di controllo è: se questo risultato fosse instabile, quale scelta sbaglierei? Se la risposta non è concreta, manca ancora il collegamento tra analisi e azione. Per verificarti, chiediti quale decisione concreta dovrebbe migliorare, quale unità di analisi rende il problema misurabile, quale baseline eviti una lettura ingenua, quale errore tipico cambierebbe la conclusione e quale output consegneresti a uno stakeholder non tecnico.
Riepilogo operativo
L’incrementality testing diventa utile quando produce una decisione più chiara, non quando aggiunge terminologia. Il holdout costa, ma compra l’unica evidenza che distingue le conversioni create da quelle solo osservate, come ha imparato eBay tagliando 50 milioni di dollari senza perdere revenue. La forma corretta della lezione collega decisione, segnale, baseline, rischio e azione, e tutto il resto serve solo se rende più affidabile uno di questi passaggi.
Percorso collegato
Lezioni da leggere insieme
Questi collegamenti portano la lezione dentro il resto del corso: basi da riprendere, passaggi successivi e connessioni tematiche tra moduli.