Confronti il gestionale con GA4 e i conti non tornano: gli ordini registrati nel backend sono una cifra, i purchase in GA4 quasi il doppio. Il container server è attivo da tre settimane e da allora il ROAS in Google Ads sembra andato meglio. Non è andato meglio niente: stai contando due volte lo stesso acquisto.
È l’incidente più comune dopo il passaggio al server-side. Il tag lato browser resta acceso "per sicurezza", il container server inizia a mandare gli stessi eventi, e nessuno se ne accorge subito perché utenti e sessioni non raddoppiano. Raddoppiano gli eventi. Ecco come si diagnostica, si corregge e si verifica.
Cosa ti serve sul tavolo prima di aprire GTM
Prima di toccare un tag, procurati quattro cose.
Gli accessi completi: container web e container server di GTM in modalità modifica, proprietà GA4, Events Manager di Meta, account Google Ads, e il backend dell’e-commerce con l’elenco degli ordini esportabile.
Un inventario scritto dei tag attivi. Non la memoria: un foglio con tag, trigger, piattaforma di destinazione e canale di invio (browser o server). Nove volte su dieci il duplicato si vede già qui, prima di qualunque debug.
Un ordine di test che puoi completare davvero, anche a importo minimo, con la possibilità di rifarlo almeno tre o quattro volte.
Lo stesso intervallo di date e lo stesso fuso orario su tutti gli strumenti. GA4, Google Ads e il gestionale possono avere fusi diversi: se confronti giornate sfalsate di due ore, i numeri non torneranno mai e ti metterai a cercare un bug che non esiste.
Se il Data Layer del sito non è strutturato in modo stabile, la deduplicazione sarà un cerotto su una gamba rotta. In quel caso parti da come strutturare il Data Layer di un e-commerce e torna qui dopo.
Misura quanto stai duplicando, non ipotizzarlo
Il primo passo è quantificare. Apri tre colonne sullo stesso intervallo: ordini nel gestionale, eventi purchase in GA4, conversioni in Google Ads e Meta.
Uno scarto di qualche punto percentuale è fisiologico: consenso negato, ad-blocker, sessioni scadute, resi non sincronizzati. Quando GA4 supera il backend in modo evidente e costante, non è dispersione: è doppia conta. L’unica direzione sospetta è quella in cui le piattaforme contano più del gestionale, perché il tracciamento può solo perdere eventi, non inventarli.
Se hai l’export BigQuery attivo, la prova è immediata:
SELECT
(SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'transaction_id') AS tid,
COUNT(*) AS occorrenze
FROM `progetto.analytics_XXXXXX.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20250101' AND '20250131'
AND event_name = 'purchase'
GROUP BY tid
HAVING occorrenze > 1
ORDER BY occorrenze DESC
Ogni riga con occorrenze maggiori di 1 è un acquisto contato più volte. Se non hai ancora l’export, collegare il container server a BigQuery ti dà la base per questo controllo e per tutti i successivi.
Senza BigQuery lavori con DebugView: completa l’ordine di test e guarda se lo stesso evento compare due volte a pochi millisecondi di distanza dallo stesso client_id. In parallelo tieni aperto il pannello Network del browser: la chiamata parte solo verso il tuo dominio personalizzato, solo verso l’endpoint di Google, o verso entrambi?
Per Meta la verifica è più comoda: Events Manager mostra lo stato di deduplicazione degli eventi ricevuti da Pixel e Conversions API, e i Test Events ti dicono in tempo reale se la coppia browser/server viene riconosciuta come un evento solo. Su Google Ads il sintomo è più subdolo e lo trovi spiegato in dettaglio nell’articolo su perché le conversioni Google Ads non corrispondono a GA4.
Le cinque cause reali, in ordine di frequenza
1. Il tag client non è mai stato spento. GA4 configurato sia nel container web sia come tag nel container server. È la causa numero uno e si risolve in due minuti, una volta vista.
2. Doppio push nel Data Layer. Lo sviluppatore spinge l’evento nel template della thank-you page, e intanto un trigger GTM lo rigenera sull’history change di una SPA. Due eventi, due invii.
3. Trigger costruiti male. Evento attivo su "Tutte le pagine" più un trigger specifico sulla pagina di conferma. Oppure nessuna protezione contro il refresh: l’utente ricarica la conferma d’ordine e l’acquisto riparte.
4. Invii server-to-server già esistenti. Il webhook di Shopify, l’app di conversione installata l’anno scorso, l’API configurata dall’agenzia precedente. Nessuno li ha censiti e ora si sommano al container server nuovo.
5. Retry e preview dimenticata. Timeout del container server con richiesta rilanciata, o modalità anteprima lasciata attiva in produzione. Rara, ma quando capita è difficile da vedere nei report.
Ogni piattaforma deduplica a modo suo
Qui sta l’equivoco che fa più danni: si dà per scontato che "tanto deduplica da sola". Non è vero in generale, è vero per alcune piattaforme e a certe condizioni.
| Piattaforma | Chiave di deduplicazione | Cosa serve perché funzioni |
|---|---|---|
| Meta (Pixel + CAPI) | event_id + event_name |
Stesso valore nei due invii, finestra temporale limitata, coerenza di fbp e fbc |
| Google Ads | order_id / transaction_id |
Valore identico fra tag browser e invio server, più gclid/gbraid/wbraid coerenti |
| GA4 | transaction_id sulle metriche e-commerce |
Nessun identificatore universale per gli altri eventi |
| TikTok, Pinterest, LinkedIn | parametro equivalente a event_id |
Finestre e requisiti diversi, da verificare sulla documentazione di ciascuna |
L’opinione netta, e la ripeto a ogni audit: su GA4 il dual-tagging è un errore. GA4 non ha una deduplicazione generale degli eventi. Il transaction_id aiuta sulle metriche di e-commerce, ma il conteggio degli eventi, le sequenze, le audience e l’export BigQuery vedono comunque due righe. Se un evento deve passare dal server, deve passare solo dal server. Chi tiene acceso il tag client "finché non sono sicuro" si ritrova con mesi di dati inutilizzabili.
Su Meta il discorso cambia: lì la deduplicazione è documentata e pensata esattamente per far convivere Pixel e Conversions API. Mandare da entrambi i canali ha senso, a patto che l’event_id sia identico.
Genera un event_id che sopravvive al passaggio nel container server
Un buon identificatore ha quattro caratteristiche: è unico per evento (non per utente), viene generato una volta sola, è identico nei due canali, e non cambia se la pagina viene ricaricata.
Il posto giusto dove generarlo è il sito, nel push al Data Layer. Per gli acquisti usa l’ID ordine del gestionale: è già unico, è già stabile, ed è lo stesso valore che userai come transaction_id. Per eventi ripetibili come add_to_cart o view_content serve un UUID generato al momento, perché lo stesso utente può ripetere l’azione dieci volte in una sessione.
Il flusso completo è questo: il sito spinge l’evento nel Data Layer con il campo event_id; nel container web lo leggi con una variabile e lo mappi come parametro personalizzato dell’evento GA4 inviato al container server; nel container server lo recuperi con una variabile Event Data e lo passi al tag Meta o TikTok; in parallelo il Pixel lato browser invia lo stesso valore.
L’errore classico è generare l’event_id dentro il container server, per esempio con una funzione di random o con il timestamp della richiesta. In quel caso l’identificatore non coinciderà mai con quello del browser e la deduplicazione non parte, anche se tecnicamente il parametro c’è. Se il collegamento fra i due container non è ancora solido, parti da come collegare GA4 al container server side.
Deduplicare o smettere di inviare due volte?
Prima di costruire tutta l’infrastruttura degli event_id, fermati e chiediti se il doppio invio ti serve davvero.
Solo GA4: migra e basta. Spegni il tag client, sposta tutto sul server, nessuna deduplicazione da gestire.
GA4 più Google Ads: GA4 solo server, Google Ads con order_id coerente su entrambi i lati se vuoi tenere il tag browser per le conversioni avanzate. La scelta dipende da quante conversioni perdi lato client, tema che ho trattato in quanti dati si perdono con gli ad-blocker.
GA4 più Meta: è lo scenario in cui il dual-tagging ha più senso. Pixel e Conversions API insieme, event_id condiviso, recupero degli eventi bloccati da ad-blocker e da ITP.
E-commerce con webhook già attivi: spegni il webhook o spegni il tag, non tenerli entrambi. Un webhook di piattaforma e un container server che inviano lo stesso purchase sono duplicati certi, perché quasi mai condividono l’identificatore.
C’è anche un effetto sul conto. Ogni evento duplicato è una richiesta in più verso il container, e l’hosting si paga sul volume di richieste: se raddoppi gli eventi di un e-commerce con migliaia di sessioni al giorno, raddoppi la parte variabile della fattura per dati che poi butterai. Trovi i criteri di calcolo in quanto costa un container server side.
Consenso e duplicati: due buchi diversi, non confonderli
Il rischio che vedo più spesso nelle configurazioni ibride è l’invio asimmetrico: il tag browser rispetta il Consent Mode e si ferma, il container server no e manda comunque. Risultato, eventi che esistono da un solo lato e confronti che non tornano, con l’aggravante di un problema di compliance.
Lo stato del consenso va trasportato nel payload che arriva al container server, non ricostruito lì dentro con regole proprie. È il browser a sapere cosa ha scelto l’utente. La procedura operativa è in come configurare Consent Mode v2 server-side.
Tieni separate le due diagnosi. Un evento mancante perché il consenso è stato negato non è un evento "perso" da recuperare col doppio invio: è un evento che non deve esistere. Chi attiva il dual-tagging per "riprendere" quei dati sta creando un problema più grande di quello che vuole risolvere.
QA, dati storici e quando chiamare qualcuno
Prima di dire che la migrazione è chiusa, passa questa checklist.
Apri l’anteprima dei due container insieme e completa un ordine di test reale. Controlla che l’event_id compaia identico nelle due richieste e che nessuna trasformazione nel container server lo sovrascriva. Ricarica la pagina di conferma ordine e premi il tasto indietro: l’evento non deve ripartire. Ripeti con consenso accettato e con consenso negato.
Poi aspetta. Confronta backend e piattaforme a 7 giorni e a 30 giorni, scrivendo nero su bianco lo scarto che consideri accettabile. Se hai BigQuery, schedula una query sul rapporto ordini/purchase e falla girare ogni settimana: è il modo meno costoso per accorgerti di una regressione il giorno dopo, non il trimestre dopo.
Sui dati storici già sporchi non ti illudere: non si ripuliscono. Metti un’annotazione sulla finestra compromessa, escludila dai confronti anno su anno e controlla le audience di remarketing costruite in quel periodo, perché possono contenere utenti entrati per via di eventi che non sono mai esistiti.
Cosa puoi fare da solo: spegnere un tag doppio, correggere un trigger, aggiungere un parametro se hai accesso al tema. Cosa richiede uno sviluppatore: generare l’event_id a monte, gestire SPA e checkout headless, smontare webhook già in produzione. Cosa conviene affidare a un consulente: ambienti con quattro o cinque piattaforme pubblicitarie, conversioni offline importate da CRM, storici già compromessi. E se ogni evento del sito è costruito con una logica diversa, il problema non è la deduplicazione: è l’architettura di tracciamento, e si riparte da come migrare dal client side al server side senza perdere dati.
Domande frequenti
Devo disattivare il tag del browser quando attivo il container server?
Dipende dalla piattaforma. Per GA4 sì: non esiste una deduplicazione generale degli eventi, quindi tenere acceso il tag client significa contare tutto due volte. Per Meta no, anzi: Pixel e Conversions API sono pensati per convivere, purché entrambi inviino lo stesso event_id. Per Google Ads puoi mantenere il tag browser se l’order_id è identico nei due canali.
Che differenza c'è tra event_id e transaction_id?
Il transaction_id identifica l’ordine ed è un dato di business: lo stesso ordine ha sempre lo stesso ID. L’event_id identifica il singolo invio dell’evento e serve alle piattaforme per capire che due chiamate si riferiscono allo stesso fatto. Per gli acquisti puoi usare l’ID ordine come base per entrambi; per eventi ripetibili come add_to_cart serve invece un identificatore generato al momento, perché lo stesso utente può ripetere l’azione più volte.
Se un utente ricarica la pagina di conferma ordine, l'acquisto viene contato due volte?
Sì, se non hai messo una protezione. La difesa più semplice è salvare l’ID ordine già inviato in sessionStorage o in un cookie e bloccare il push al Data Layer se quell’ID risulta già tracciato. In parallelo, un transaction_id coerente permette almeno a GA4 e a Google Ads di riconoscere la transazione come già registrata sulle metriche e-commerce.
La deduplicazione risolve anche il problema degli eventi bloccati dagli ad-blocker?
No, sono due problemi distinti. Gli ad-blocker causano eventi mancanti, la deduplicazione gestisce eventi in eccesso. Il dual-tagging con event_id condiviso è il modo per far convivere le due cose su piattaforme come Meta: il server recupera ciò che il browser non riesce a inviare, e la deduplicazione evita che gli eventi passati da entrambi vengano contati due volte.