Uno degli errori più comuni — e più silenziosi — nelle implementazioni di tracciamento e-commerce è la mancata corrispondenza tra l’item_id inviato negli eventi GA4/Google Ads e l’identificativo con cui i prodotti sono indicizzati su Google Merchant Center. Il risultato pratico è che Google non riesce ad associare i dati di performance alle schede prodotto, compromettendo funzionalità come il remarketing dinamico, i report sui prodotti in Performance Max e le conversioni arricchite con dati del carrello. In questa guida vediamo come individuare e verificare questi ID utilizzando tre metodi: ispezione diretta del dataLayer dalla console del browser, verifica tramite Google Tag Manager in modalità preview, e l’uso di estensioni Chrome come Omnibug ed EventWatcher.


Indice

  1. Come funziona il match tra eventi e Merchant Center
  2. Dove e come viene definito l’item_id nel dataLayer
  3. Metodo 1: ispezione via console del browser
  4. Metodo 2: verifica tramite GTM Preview Mode
  5. Metodo 3: estensioni Chrome — Omnibug ed EventWatcher
  6. Errori frequenti e come risolverli
  7. Conclusioni

Come funziona il match tra eventi e Merchant Center

Quando Google riceve un evento e-commerce — sia tramite gtag.js che tramite GTM — cerca di abbinare ogni prodotto presente nell’array items a una scheda nel Merchant Center. Il parametro utilizzato per questo abbinamento è item_id.

Su Google Merchant Center, ogni prodotto è identificato dal campo id del feed. Affinché il match avvenga, il valore di item_id passato nell’evento deve essere esattamente identico al valore del campo id del feed — incluse maiuscole, minuscole, prefissi, zeri iniziali e qualsiasi altro carattere.

Nota importante: Se utilizzi un feed supplementare o varianti di prodotto, potresti dover includere il suffisso della variante nell’ID (es. 12345_rosso_L). In Google Merchant Center, le varianti vengono registrate come item_group_id per il prodotto padre e id univoco per ciascuna variante. L’item_id nell’evento deve corrispondere all’id della variante specifica, non all’item_group_id.

Il mancato match non genera errori visibili in GA4 o Google Ads: gli eventi vengono registrati normalmente, ma la colonna “prodotti” nei report Performance Max rimane vuota o incompleta, e il remarketing dinamico non mostra il prodotto corretto. È un’anomalia silenziosa che richiede verifica attiva.


Dove e come viene definito l’item_id nel dataLayer

In un’implementazione GA4 standard via dataLayer, gli eventi e-commerce seguono questo schema:

window.dataLayer.push({
  event: 'view_item',
  ecommerce: {
    currency: 'EUR',
    value: 99.90,
    items: [
      {
        item_id: '12345',        // ← questo deve corrispondere all'id nel feed GMC
        item_name: 'Nome Prodotto',
        item_category: 'Categoria',
        price: 99.90,
        quantity: 1
      }
    ]
  }
});

In WooCommerce, l’item_id corrisponde tipicamente all’ID post di WordPress (es. 1234). In PrestaShop, di default coincide con l’ID prodotto o con la combinazione nel formato id_product-id_product_attribute (es. 42-7), a seconda di come è configurato il modulo di tracciamento. È esattamente questo punto che genera la maggior parte delle discrepanze: il feed GMC potrebbe usare un formato diverso rispetto a quello pushato nel dataLayer.

Prima di procedere con i metodi di verifica, recupera l’ID di alcuni prodotti direttamente da Google Merchant Center: Merchant Center → Prodotti → Tutti i prodotti, poi clicca su un prodotto e leggi il campo ID nella scheda attributi. Questo è il valore di riferimento con cui confrontare.


Metodo 1: ispezione via console del browser

È il metodo più diretto e non richiede strumenti aggiuntivi. Apri il browser su una pagina prodotto del sito, poi apri gli Strumenti per gli sviluppatori (F12 oppure Cmd+Option+I su Mac) e vai nella scheda Console.

Leggere l’intero dataLayer

Digita nella console:

console.log(JSON.stringify(dataLayer, null, 2));

Questo stampa l’intero array dataLayer in formato leggibile. Cerca l’oggetto con event: 'view_item' (o add_to_cart, purchase, ecc.) e individua la proprietà items[0].item_id.

Filtrare solo gli eventi e-commerce

Se il dataLayer è molto popolato, usa questo snippet per isolare rapidamente solo i push che contengono dati e-commerce:

dataLayer
  .filter(e => e.ecommerce && e.ecommerce.items)
  .forEach(e => {
    console.group('Evento: ' + e.event);
    e.ecommerce.items.forEach(item => {
      console.log('item_id:', item.item_id, '| item_name:', item.item_name);
    });
    console.groupEnd();
  });

L’output mostrerà solo gli eventi rilevanti, con ID e nome del prodotto affiancati — utile per verificare visivamente la coerenza.

Intercettare i push in tempo reale

Per le pagine dinamiche (SPA o funnels multi-step come il checkout), i push avvengono in risposta ad azioni utente e non sono già presenti nel dataLayer al caricamento della pagina. In questo caso, puoi sovrascrivere temporaneamente il metodo push per intercettare ogni nuovo evento:

const originalPush = dataLayer.push.bind(dataLayer);
dataLayer.push = function(obj) {
  if (obj && obj.ecommerce && obj.ecommerce.items) {
    console.group('[dataLayer intercept] Evento: ' + obj.event);
    obj.ecommerce.items.forEach(item => {
      console.log('item_id:', item.item_id, '| item_name:', item.item_name);
    });
    console.groupEnd();
  }
  return originalPush(obj);
};

Incolla questo snippet in console prima di eseguire l’azione (es. click su “Aggiungi al carrello”). Ogni successivo dataLayer.push() con dati e-commerce verrà stampato in tempo reale.

Attenzione: questa sovrascrittura è temporanea e valida solo per la sessione corrente del browser. Non impatta il sito né gli utenti reali.

Verificare su più pagine

Esegui la verifica almeno su: pagina prodotto (view_item), pagina carrello (view_cart), checkout (begin_checkout, add_payment_info) e pagina di conferma ordine (purchase). Le discrepanze tra item_id e feed GMC possono essere presenti solo in alcuni eventi se il valore viene costruito in modo diverso in contesti diversi.


Metodo 2: verifica tramite GTM Preview Mode

Google Tag Manager offre una modalità di anteprima (Preview & Debug) che permette di ispezionare ogni push al dataLayer, i trigger attivati e i tag eseguiti, direttamente in una finestra affiancata al sito. È il metodo più robusto per verifiche sistematiche e per documentare il comportamento in un intero funnel.

Avviare la Preview Mode

Accedi a GTM → seleziona il container del sito → Anteprima (pulsante in alto a destra). Si apre Tag Assistant; inserisci l’URL del sito e clicca Connect. Il browser aprirà il sito con la modalità di debug attiva — riconoscibile dalla barra GTM in fondo alla pagina.

Leggere i dati e-commerce nel pannello Debug

Nel pannello Tag Assistant, ogni riga nell’elenco a sinistra corrisponde a un evento. Clicca sull’evento che ti interessa (es. view_item) e seleziona la scheda Data Layer. Qui troverai la rappresentazione completa dell’oggetto pushato, incluso l’array ecommerce.items con tutti i parametri prodotto.

Verificare le variabili dei tag

Se hai configurato tag Google Ads o tag GA4 con variabili per i parametri e-commerce, clicca sul tag eseguito e controlla Event Settings Variable: vedrai i valori effettivamente passati al tag nel momento dell’esecuzione. Questo ti permette di individuare eventuali trasformazioni applicate a monte (trim, lowercase, concatenazione di prefissi) che alterano l’ID prima che venga inviato a Google.

Verificare il tag Google Ads Remarketing

Il remarketing dinamico Google Ads utilizza parametri diversi rispetto agli eventi GA4. Nel tag Google Ads Remarketing, l’ID prodotto  viene letto dall’array items del dataLayer. Nel pannello Debug, clicca sul tag di remarketing e controlla la sezione Tag Details: verifica che l’ID passato sia consistente con quello degli eventi GA4 e con il feed GMC.


Metodo 3: estensioni Chrome — Omnibug ed EventWatcher

Le estensioni browser specializzate in tracciamento intercettano le richieste di rete e i push al dataLayer in tempo reale, offrendo una visualizzazione strutturata senza necessità di accesso a GTM o di interventi in console. Sono particolarmente utili per audit su siti di terze parti o per verifiche rapide senza accesso al container GTM.

Omnibug

Omnibug intercetta le richieste HTTP in uscita verso le principali piattaforme di analytics e advertising (GA4, Google Ads, Meta Pixel, ecc.) e le decodifica in un pannello leggibile all’interno dei DevTools.

Come usarlo per verificare l’item_id:

  1. Installa l’estensione e ricarica la pagina con i DevTools aperti.
  2. Nella barra dei DevTools troverai una nuova scheda Omnibug.
  3. Naviga sulla pagina prodotto o esegui un’azione (es. aggiungi al carrello).
  4. Nel pannello Omnibug compariranno le richieste intercettate. Filtra per Google Analytics 4 o Google Ads.
  5. Clicca sulla richiesta corrispondente all’evento e-commerce. Omnibug mostra i parametri decodificati: cerca il campo Items e all’interno item_id.

Per gli eventi GA4 inviati via Measurement Protocol (es. in un setup server-side con sGTM), Omnibug non intercetterà i chiamate lato server, ma le richieste lato client verso il server GTM saranno comunque visibili (verso l’URL del tuo server container, es. https://gtm.tuosito.it/g/collect). In questo caso, usa la scheda Network dei DevTools per ispezionare il payload JSON direttamente.

EventWatcher (ex dataslayer)

EventWatcher è focalizzato specificamente sul dataLayer: intercetta ogni push() e lo presenta in un pannello strutturato nei DevTools, senza che tu debba interrogare manualmente la console.

Come usarlo per verificare l’item_id:

  1. Installa l’estensione e apri i DevTools (F12).
  2. Troverai la scheda EventWatcher (o in alcune versioni dataLayer) nella barra dei DevTools.
  3. Ricarica la pagina: EventWatcher catturerà tutti i push al dataLayer dall’inizio del caricamento.
  4. Ogni evento è espandibile: cerca event: view_item (o l’evento che ti interessa) e naviga in ecommerce → items → [0] → item_id.
  5. Per gli eventi dinamici (add_to_cart, purchase), esegui l’azione — EventWatcher cattura i push in tempo reale senza necessità di sovrascrivere manualmente il metodo push.

Nota su compatibilità: EventWatcher funziona correttamente con dataLayer standard (Array globale). Se il sito usa implementazioni non standard (es. GTM caricato in modo asincrono con ritardo, o variabili dataLayer con namespace personalizzati), potrebbe perdere alcuni push. In questi casi, la verifica via console con l’intercettore manuale descritto nel Metodo 1 rimane il fallback più affidabile.

Confronto tra i due strumenti

CaratteristicaOmnibugEventWatcher
Fonte datiRichieste HTTP intercettatePush al dataLayer
Mostra dati pre-tagNo (post-firing)Sì (pre-tag, dati grezzi)
Utile per sGTMParzialmente (richieste client)Sì (dataLayer lato client)
Multi-piattaformaSì (GA4, Ads, Meta, ecc.)No (solo dataLayer)
Richiede accesso GTMNoNo

L’approccio ottimale è usarli in combinazione: EventWatcher per verificare i dati grezzi nel dataLayer (prima di qualsiasi trasformazione applicata da GTM), Omnibug per verificare i dati effettivamente trasmessi al tag. Una discrepanza tra i due indica che GTM sta alterando l’ID prodotto — e il punto di modifica è isolabile nella configurazione delle variabili del container.


Errori frequenti e come risolverli

1. Prefisso o suffisso nel feed ma non nell’evento (o viceversa)

Alcuni merchant aggiungono prefissi agli ID nel feed GMC per distinguere tipologie di prodotto (es. RING_12345 nel feed, 12345 nell’evento). La soluzione è allineare il formato: o rimuovere il prefisso dal feed, oppure aggiungerlo dinamicamente nell’evento tramite una variabile GTM (JavaScript personalizzato o template variabile con concatenazione).

2. ID variante vs ID prodotto padre

In WooCommerce, i prodotti variabili hanno un ID per il prodotto padre e uno per ciascuna variante. Il feed GMC indicizza la variante con il proprio ID. Se nell’evento add_to_cart viene passato l’ID del prodotto padre anziché quello della variante selezionata, il match fallisce. Verifica che il tuo layer di dati passi item_id corrispondente alla variante effettivamente scelta dall’utente.

3. Cast di tipo: integer vs string

Nel dataLayer JavaScript, l’item_id potrebbe essere pushato come numero intero (item_id: 12345) anziché come stringa (item_id: "12345"). GTM legge entrambi, ma il Measurement Protocol di GA4 trasmette il valore come stringa. Nel feed GMC il campo id è sempre una stringa. Questo non causa normalmente problemi di match, ma vale la pena standardizzare usando sempre stringhe per evitare comportamenti imprevisti con ID che iniziano per zero.

4. Encoding o caratteri speciali

ID con caratteri non ASCII, slash o caratteri speciali (es. SKU/2024-XL) possono subire encoding differente tra feed e evento. Verifica il valore grezzo nel dataLayer rispetto al valore nel feed usando la console o EventWatcher, prima di qualsiasi encoding HTTP.

5. Reset dell’oggetto ecommerce mancante

Secondo le best practice di Google, prima di ogni push di un evento e-commerce occorre azzerare l’oggetto precedente con:

window.dataLayer.push({ ecommerce: null });

L’omissione di questo reset può causare la contaminazione dell’oggetto ecommerce con dati di eventi precedenti — in particolare l’array items di un evento add_to_cart potrebbe essere ereditato da un view_item precedente se il secondo push non include la chiave ecommerce. Verifica che ogni push sia preceduto dal reset, sia nel codice nativo che nelle implementazioni GTM.


Conclusioni

La verifica del match tra item_id e il feed Google Merchant Center è un controllo che dovrebbe far parte di ogni audit di tracciamento e-commerce, non solo in fase di setup ma anche periodicamente — specialmente dopo aggiornamenti del CMS, migrazioni del feed o modifiche al container GTM.

I tre metodi descritti coprono scenari diversi: la console è il metodo più immediato e non richiede strumenti aggiuntivi; GTM Preview Mode è il più completo per verifiche sistematiche e per isolare trasformazioni applicate dalle variabili; Omnibug ed EventWatcher accelerano le verifiche su siti di terze parti o quando non si ha accesso al container GTM.

Il segnale di allarme principale da monitorare è la presenza di eventi purchase in GA4 con prodotti che non compaiono nei report “Prodotti” di Performance Max, o un tasso di match inferiore all’85–90% nel report Merchant Center → Diagnostica → Prodotti corrispondenti. In entrambi i casi, la causa è quasi sempre un disallineamento nel formato dell’item_id — e con i metodi descritti in questa guida è risolvibile in pochi minuti.

Molti ecommerce si trovano nella stessa situazione: in GA4 vedono un numero di conversioni, in Google Ads un altro, nel gestionale o nella piattaforma ecommerce un altro ancora. A volte anche Merchant Center restituisce segnali che non sembrano coerenti con il resto.

Una piccola differenza tra piattaforme è normale. Il problema nasce quando le discrepanze diventano troppo ampie e iniziano a influenzare campagne, report e decisioni operative. In quel momento non stai più guardando una semplice differenza di attribuzione: stai probabilmente guardando un problema di tracciamento.

In questo articolo vediamo perché le conversioni di GA4, Google Ads, Merchant Center e ordini reali possono non coincidere, quali sono le cause più frequenti e come fare una verifica rapida per capire dove si rompe la catena del tracciamento.

Se vuoi arrivare subito al punto senza perdere tempo tra audit, debug, dataLayer, GTM, Enhanced Conversions e controlli incrociati tra piattaforme, contattami: posso analizzare il setup e individuare io il punto esatto in cui i dati si perdono, si duplicano o non vengono attribuiti correttamente.


Quando una differenza è normale e quando no

Partiamo da un punto importante: non esiste uno scenario reale in cui tutte le piattaforme riportano sempre lo stesso numero identico.

GA4, Google Ads, Merchant Center e il tuo ecommerce non lavorano con la stessa logica. Cambiano:

  • il modello di attribuzione
  • la finestra temporale di conversione
  • la presenza o meno del consenso utente

Per questo motivo, una differenza contenuta è fisiologica.

Il problema nasce quando i numeri divergono in modo sistematico e non riesci più a capire quale fonte sia affidabile. In quel caso il rischio non è solo avere report sporchi: il rischio vero è far ottimizzare Google Ads su segnali incompleti o sbagliati.

Perché non è solo un problema di reportistica

Quando il tracciamento è parziale o incoerente, succedono almeno tre cose:

  1. Le campagne imparano male: se Google Ads riceve meno conversioni di quelle reali, o riceve conversioni duplicate, lo Smart Bidding ottimizza su una fotografia distorta.
  2. I pubblici diventano meno affidabili: se gli eventi chiave non arrivano correttamente, anche remarketing, segmenti e segnali di pubblico peggiorano.
  3. Prendi decisioni sbagliate: rischi di tagliare campagne che stanno funzionando o di aumentare budget su canali che si stanno attribuendo conversioni in modo aggressivo.

Le 7 cause più comuni delle discrepanze

1. Modelli di attribuzione diversi

GA4 e Google Ads possono attribuire la stessa conversione in modi differenti. Anche quando l’evento di base è corretto, il modo in cui quella conversione viene assegnata può cambiare il totale finale.

Questo da solo può spiegare piccole differenze. Non spiega però scarti enormi e ripetuti.

2. Consent Mode configurata male o solo parzialmente

Se la Consent Mode v2 non è implementata correttamente, alcuni dati non partono, partono nel momento sbagliato oppure partono senza i segnali necessari.

Questa è una delle cause più sottovalutate delle discrepanze: il banner è presente, ma il consenso non viene propagato correttamente ai tag oppure viene letto in ritardo rispetto al momento in cui dovrebbe attivarsi il tracciamento.

3. Eventi duplicati o mancanti in Google Tag Manager

Questa è una delle anomalie più frequenti. Succede quando:

  • un evento viene inviato due volte
  • lo stesso tag si attiva su più trigger
  • il tracciamento dipende solo dalla thank-you page e salta in alcuni scenari
  • il form o il checkout usano logiche AJAX e il setup non intercetta il punto giusto

Il risultato è semplice: perdi dati oppure li conti due volte. In entrambi i casi stai alimentando le piattaforme con informazioni sbagliate.

4. Enhanced Conversions assenti, incomplete o implementate male

Un conto è tracciare una conversione. Un altro è fornire a Google segnali aggiuntivi utili al matching, come email o telefono, nel formato corretto.

Se le Enhanced Conversions non sono presenti, oppure vengono valorizzate male, Google Ads può perdere parte della capacità di associare le conversioni ai clic reali. Questo non sempre crea errori evidenti subito, ma nel tempo peggiora la qualità del dato usato per ottimizzare.

5. Conversioni importate male da GA4 a Google Ads

Molti account usano conversioni importate da GA4 dentro Google Ads. In teoria è una soluzione comoda. In pratica, se la struttura eventi non è pulita, se i parametri non sono coerenti o se si stanno importando azioni sbagliate, i numeri diventano difficili da interpretare.

Qui il problema non è solo tecnico: è proprio di architettura del tracciamento.

6. Checkout o thank-you page non affidabili

Su alcuni ecommerce la thank-you page non si carica sempre nello stesso modo, oppure viene ricaricata, memorizzata in cache, visitata più volte o non contiene tutti i dati utili.

Risultato: ordini non tracciati, ordini duplicati o valori errati.

Quando il tracciamento delle conversioni si basa solo sull’ultimo passaggio e non su una logica robusta, basta poco per sporcare tutto.

7. Merchant Center e sorgenti dati non allineati al resto del setup

Merchant Center non è il colpevole di tutte le discrepanze, ma spesso entra nel problema in modo indiretto.

Quando feed, catalogo, eventi ecommerce e conversioni non raccontano la stessa realtà, Performance Max e le campagne shopping lavorano peggio. Il punto non è solo avere prodotti approvati, ma avere una struttura dati coerente tra sito, feed e piattaforme pubblicitarie. Spesso, troppo spesso si trovano account con ID articoli diversi da quelli trasmessi via feed.


Il metodo corretto: non cercare il colpevole, cerca il punto di rottura

Un errore comune è chiedersi: “Quale piattaforma ha ragione?”

La domanda giusta è un’altra:

In quale punto della catena il dato smette di essere coerente?

La catena, nella maggior parte dei casi, è questa:

utente → consenso → evento sul sito → dataLayer / GTM → GA4 → Google Ads → utilizzo del dato nelle campagne

A volte Merchant Center si inserisce come ulteriore livello, soprattutto negli ecommerce che usano feed e campagne shopping o Performance Max.

Il lavoro non è confrontare numeri a caso. Il lavoro è isolare il punto preciso in cui il dato si perde, si duplica o cambia significato.


Check rapido in 15 minuti

Qui non stai ancora facendo un audit completo, ma una verifica veloce per capire se il problema è plausibilmente tecnico.

1. Controlla GTM Preview

Apri l’anteprima di Google Tag Manager e verifica se l’evento principale si attiva una sola volta, nel momento giusto, con i parametri corretti.

2. Controlla Tag Assistant

Guarda se i tag Google partono correttamente e se i segnali di consenso sono coerenti con lo stato del banner.

3. Controlla GA4 DebugView

Verifica che gli eventi vengano ricevuti davvero da GA4 e con la struttura prevista.

4. Controlla la conversione in Google Ads

Verifica se la conversione usata per l’ottimizzazione è quella corretta, se è primaria o secondaria, se ha un conteggio coerente e se sta ricevendo dati.

5. Controlla il percorso reale dell’utente

Simula un acquisto o un invio form e verifica se tutto il flusso regge anche nei casi non ideali: consenso negato, refresh pagina, ritorno indietro, thank-you page ricaricata, checkout non lineare.

6. Controlla il valore conversione

A volte il numero di conversioni sembra corretto, ma il valore economico è sbagliato. Per campagne ecommerce è devastante quasi quanto perdere le conversioni stesse.


I segnali che indicano quasi certamente un problema tecnico

Se vedi uno o più di questi scenari, probabilmente non sei davanti a una semplice differenza di attribuzione:

  • Google Ads registra molte meno conversioni rispetto agli ordini reali senza una spiegazione chiara
  • GA4 mostra più eventi di acquisto del numero reale di ordini
  • le conversioni aumentano dopo refresh o revisit della thank-you page
  • il form genera lead reali, ma in piattaforma ne vedi solo una parte
  • il valore conversione in Ads è incoerente rispetto al fatturato reale
  • dopo l’implementazione della Consent Mode i numeri calano in modo anomalo e non verificato
  • Performance Max fatica a stabilizzarsi nonostante traffico e catalogo adeguati

Cosa succede alle campagne quando il tracking è sporco

Un tracciamento incoerente non crea solo confusione nei report. Peggiora le performance.

Peggiora perché l’algoritmo ottimizza su segnali deboli o distorti. E se il segnale di conversione è sbagliato, anche una campagna tecnicamente ben impostata non può esprimere il suo potenziale.

Non è raro vedere account dove il problema non è nelle creatività, non è nel budget, non è neppure nella strategia d’offerta. Il problema è che il sistema sta imparando da dati incompleti.

Gli effetti più comuni

  • Smart Bidding che fatica a trovare stabilità
  • Performance Max che riceve segnali deboli o fuorvianti
  • pubblici di remarketing meno utili
  • report che sembrano precisi ma portano a decisioni sbagliate
  • difficoltà a capire quali campagne stiano davvero generando valore

Chi dovrebbe fare questa verifica subito

Questo tipo di analisi è utile soprattutto a tre profili:

  1. Imprenditori o ecommerce manager che continuano a vedere numeri diversi e non riescono più a capire quale report usare
  2. Agenzie che gestiscono advertising ma vogliono una figura verticale sul tracking per audit, debug e implementazione
  3. Ads specialist che hanno capito che senza dati affidabili non si ottimizza niente in modo serio

Se ti riconosci in uno di questi scenari, il punto non è continuare a confrontare report per ore. Il punto è fare un’analisi tecnica della catena di misurazione e capire esattamente dove intervenire.


Riepilogo: dove si rompe più spesso il tracciamento

AreaProblema tipicoEffetto
Consent ModeSegnali di consenso assenti o letti maleDati persi o parziali
GTMTag duplicati o trigger sbagliatiConversioni gonfiate o mancanti
GA4Eventi o parametri non coerentiImportazione conversioni poco affidabile
Google AdsConversioni primarie/secondarie impostate maleOttimizzazione su obiettivi errati
CheckoutThank-you page fragile o non affidabileOrdini persi o duplicati
Enhanced ConversionsDati utente assenti o formattati maleMatching peggiore
Merchant CenterFeed e dati ecommerce disallineatiCampagne shopping / PMax meno efficienti

Conclusioni

Le discrepanze tra GA4, Google Ads, Merchant Center e ordini reali non sono sempre un’anomalia. Ma quando superano una certa soglia diventano un sintomo.

E quasi sempre il sintomo porta a uno di questi problemi: consenso gestito male, eventi duplicati, eventi mancanti, importazioni sbagliate, Enhanced Conversions assenti o checkout tracciato in modo fragile.

Finché non individui il punto preciso in cui il dato si rompe, continuerai a prendere decisioni su numeri che sembrano tecnici, ma che in realtà stanno condizionando direttamente il rendimento delle campagne.

Se i numeri tra GA4, Google Ads, Merchant Center e ordini reali non coincidono, posso analizzare il tuo setup e dirti esattamente dove si rompe il tracciamento.

Collaboro anche con agenzie come consulente esterno per audit tracking, debug GTM, Enhanced Conversions e allineamento tra GA4, Google Ads e Merchant Center. Se vuoi affrontare il problema in modo tecnico e concreto, contattami.

Il tracciamento delle conversioni da form è uno degli aspetti più critici di qualsiasi strategia di web analytics. Un form non tracciato correttamente significa dati persi, attribuzioni sbagliate e campagne ottimizzate su informazioni incomplete.

Ma c’è un aspetto ancora più importante: tracciare la conversione non basta. Se vuoi sfruttare le Enhanced Conversions di Google Ads (conversioni avanzate), devi catturare i dati dell’utente nel momento esatto in cui compila il form — in particolare email, oppure altri dati utili al matching come telefono o indirizzo. Tracciare solo la thank-you page significa perdere queste informazioni per sempre.

Questo articolo è diviso in due parti:

  • Parte 1 — Teoria e Debug: come analizzare qualsiasi form, identificare il tipo di invio e usare la console per capire esattamente cosa succede
  • Parte 2 — Implementazione: script completi, configurazione GTM, trigger, variabili e tag pronti per la produzione

Se vuoi ottenere questo risultato senza sporcarti le mani con debug, dataLayer, trigger e mapping delle variabili, contattami: posso occuparmi io dell’implementazione tecnica e della verifica del tracciamento.


Parte 1: Teoria e Debug

I tre scenari di invio form

Non tutti i form si comportano allo stesso modo. Esistono tre scenari principali:

1. Form con redirect (POST tradizionale)

Il form invia i dati con un POST standard e reindirizza a una thank-you page. È lo scenario classico, ma presenta un problema critico: quando l’utente arriva sulla thank-you page, il form non esiste più. Non puoi quindi recuperare email, nome, telefono o altri dati utili per le Enhanced Conversions.

Come riconoscerlo: la pagina si ricarica completamente dopo il submit e l’URL cambia.

Soluzione: devi intercettare il submit prima del redirect, catturare i dati e solo dopo lasciare proseguire l’invio.

2. Form AJAX con evento submit

Il form invia i dati via JavaScript senza ricaricare la pagina. L’evento submit viene comunque triggerato, quindi puoi intercettarlo con un event listener.

Come riconoscerlo: la pagina non si ricarica, ma l’evento submit è presente e verificabile in console.

Soluzione: event listener su submit, con preventDefault() se necessario.

3. Form AJAX senza evento submit (terze parti)

Il form bypassa completamente il submit nativo. Cliccando il pulsante, viene eseguita una funzione JavaScript che invia i dati tramite XMLHttpRequest o Fetch API. Nessun evento submit viene triggerato.

Come riconoscerlo: il pulsante non è un <button type="submit">, oppure il form ha onsubmit="return false", oppure semplicemente l’evento submit non scatta mai.

Soluzione: intercettazione di XMLHttpRequest o Fetch API.

I form embedded di terze parti come Brevo, HubSpot, Mailchimp, Typeform rientrano quasi sempre in questo terzo scenario.


Come analizzare un form: la fase di debug

Prima di scrivere qualsiasi codice, devi capire esattamente come funziona il form. Apri gli strumenti di sviluppo del browser (F12) e segui questa procedura.

Step 1: Ispeziona la struttura del form

Nella tab Elements, trova l’elemento <form> e annota:

  • ID: es. id="sib-form"
  • Action: URL di destinazione (vuoto = stesso dominio, URL esterno = terze parti)
  • Method: GET o POST
  • Attributi speciali: onsubmit, data-*

Step 2: Mappa i campi del form

Per ogni campo, documenta l’attributo name: è quello che userai per recuperare i valori.

// Esegui in console per elencare tutti i campi del form
var form = document.getElementById('ID_DEL_FORM');
var fields = form.querySelectorAll('input, select, textarea');
fields.forEach(function(f) {
  console.log('name:', f.name, '| type:', f.type, '| value:', f.value);
});

Step 3: Verifica se l’evento submit viene triggerato

Questo è il test cruciale. Esegui in console:

// Test: l'evento submit viene triggerato?
var form = document.getElementById('ID_DEL_FORM');
form.addEventListener('submit', function(e) {
  console.log('✅ Evento SUBMIT triggerato!');
  console.log('Form data:', new FormData(form));
});
// Ora compila il form e clicca submit. Se vedi il messaggio, puoi usare un listener su submit.
// Se NON vedi nulla, il form bypassa il submit nativo.

Step 4: Monitora le chiamate di rete

Apri la tab Network, filtra per Fetch/XHR, poi compila e invia il form. Osserva:

  • URL della richiesta: dominio interno o esterno? (es. sibforms.com)
  • Metodo: POST, GET
  • Payload: clicca sulla richiesta → tab “Payload” per vedere i dati inviati
  • Response: status 200? JSON di risposta?

Step 5: Identifica il tipo di chiamata (XHR o Fetch)

Se il form non triggera submit ma vedi una chiamata in Network, devi capire se usa XMLHttpRequest o Fetch API. Esegui in console prima di inviare il form:

// Intercetta XMLHttpRequest
(function() {
  var origOpen = XMLHttpRequest.prototype.open;
  XMLHttpRequest.prototype.open = function(method, url) {
    console.log('🔵 XHR:', method, url);
    return origOpen.apply(this, arguments);
  };
})();
// Intercetta Fetch API
(function() {
  var origFetch = window.fetch;
  window.fetch = function(url, options) {
    console.log('🟢 FETCH:', url, options);
    return origFetch.apply(this, arguments);
  };
})();

Ora invia il form. In console vedrai:

  • 🔵 XHR: POST https://... → il form usa XMLHttpRequest
  • 🟢 FETCH: https://... → il form usa Fetch API

Questa informazione è fondamentale per scegliere la tecnica di intercettazione corretta.


Riepilogo: quale strategia usare

ScenarioTestStrategia
Pagina si ricarica dopo submitURL cambiaIntercetta submit, cattura dati, poi lascia proseguire
Evento submit triggeratoConsole mostra “✅ Evento SUBMIT”Event listener su submit
Nessun submit, XHR in consoleConsole mostra “🔵 XHR”Override di XMLHttpRequest.prototype
Nessun submit, Fetch in consoleConsole mostra “🟢 FETCH”Override di window.fetch

Parte 2: Implementazione

Ora che sai come analizzare un form, vediamo l’implementazione completa. Useremo come caso pratico un form Brevo (ex Sendinblue), che rappresenta lo scenario più complesso: nessun evento submit, invio tramite XHR a dominio esterno.

Caso pratico: Form Brevo embedded

Dall’analisi del form (seguendo gli step della Parte 1) emergono queste caratteristiche:

  • ID: sib-form
  • Evento submit: NON triggerato
  • Tipo chiamata: XHR a sibforms.com con parametro isAjax=1
  • Campi: NOME, COGNOME, AZIENDA, EMAIL, SMS, MESSAGGIO, CONFERMA
  • Widget custom: selettore prefisso telefonico (classe .sib-sms-select, valore in data-value)

2.1 Script di tracciamento (Tag Custom HTML)

Crea un nuovo tag in GTM di tipo Custom HTML e incolla questo codice:

<script>
(function() {
  // ==================================================
  // CONFIGURAZIONE - Modifica questi valori
  // ==================================================
  var FORM_ID = 'sib-form';                    // ID del form
  var XHR_FILTER = 'sibforms.com';             // Dominio da intercettare
  var XHR_PARAM = 'isAjax=1';                  // Parametro che identifica la chiamata
  var EVENT_NAME = 'brevo_form_submit';        // Nome evento per GTM
  var FORM_NAME = 'contact_request_form';      // Nome descrittivo del form
  
  // ==================================================
  // VERIFICA ESISTENZA FORM
  // ==================================================
  var form = document.getElementById(FORM_ID);
  if (!form) return;
  
  // ==================================================
  // PREVIENI DOPPIA ESECUZIONE
  // ==================================================
  if (window['__formTracker_' + FORM_ID]) return;
  window['__formTracker_' + FORM_ID] = true;
  // ==================================================
  // HELPER FUNCTIONS
  // ==================================================
  
  // Recupera il valore di un campo
  function getFieldValue(name) {
    var el = form.querySelector('[name="' + name + '"]');
    if (!el) return '';
    if (el.type === 'checkbox') return el.checked;
    return el.value || '';
  }
  // Recupera il prefisso internazionale dal widget Brevo
  function getSmsCountryCode() {
    var widget = form.querySelector('.sib-sms-select');
    if (!widget) return '+39';
    return widget.getAttribute('data-value') || '+39';
  }
  // Formatta il numero in formato E.164
  function formatPhoneE164(code, number) {
    if (!number) return '';
    var clean = number.replace(/\s+/g, '').replace(/^0+/, '');
    return code + clean;
  }
  // ==================================================
  // INTERCETTAZIONE XMLHttpRequest
  // ==================================================
  var origOpen = XMLHttpRequest.prototype.open;
  var origSend = XMLHttpRequest.prototype.send;
  XMLHttpRequest.prototype.open = function(method, url) {
    this._url = url;
    this._method = method;
    return origOpen.apply(this, arguments);
  };
  XMLHttpRequest.prototype.send = function(body) {
    var xhr = this;
    
    // Filtra solo le chiamate al servizio del form
    if (xhr._url && 
        xhr._url.indexOf(XHR_FILTER) !== -1 && 
        xhr._url.indexOf(XHR_PARAM) !== -1) {
      
      // Cattura i dati PRIMA dell'invio
      var smsCountryCode = getSmsCountryCode();
      var formData = {
        user_first_name: getFieldValue('NOME'),
        user_last_name: getFieldValue('COGNOME'),
        user_company: getFieldValue('AZIENDA'),
        user_email: getFieldValue('EMAIL'),
        user_phone_country_code: smsCountryCode,
        user_phone: formatPhoneE164(smsCountryCode, getFieldValue('SMS')),
        user_message: getFieldValue('MESSAGGIO'),
        user_consent: getFieldValue('CONFERMA')
      };
      // Ascolta la risposta
      xhr.addEventListener('load', function() {
        // Traccia solo se la richiesta ha avuto successo (status 2xx)
        if (xhr.status >= 200 && xhr.status < 300) {
          window.dataLayer = window.dataLayer || [];
          window.dataLayer.push({
            event: EVENT_NAME,
            form_id: FORM_ID,
            form_name: FORM_NAME,
            user_first_name: formData.user_first_name,
            user_last_name: formData.user_last_name,
            user_company: formData.user_company,
            user_email: formData.user_email,
            user_phone_country_code: formData.user_phone_country_code,
            user_phone: formData.user_phone,
            user_message: formData.user_message,
            user_consent: formData.user_consent
          });
          
          console.log('[GTM] Form tracciato:', EVENT_NAME, formData);
        }
      });
    }
    
    return origSend.apply(this, arguments);
  };
})();
</script>

Trigger per il tag

Imposta il trigger su DOM Ready (o Page View se il form è presente subito). Se il form è solo su alcune pagine, aggiungi una condizione sull’URL.


2.2 Trigger Custom Event

Crea un nuovo Trigger in GTM:

  • Tipo: Custom Event
  • Event name: brevo_form_submit
  • This trigger fires on: All Custom Events

Questo trigger scatterà ogni volta che lo script fa il push al dataLayer con l’evento brevo_form_submit.


2.3 Variabili Data Layer

Per utilizzare i dati del form nei tag, crea queste variabili di tipo Data Layer Variable:

Nome variabile GTMData Layer Variable NameUso
DLV – user_emailuser_emailEnhanced Conversions
DLV – user_first_nameuser_first_nameAddress data / CRM / reportistica
DLV – user_last_nameuser_last_nameAddress data / CRM / reportistica
DLV – user_phoneuser_phoneEnhanced Conversions
DLV – form_nameform_nameAnalytics / report

Nota: il fatto che questi dati siano disponibili nel dataLayer non significa che debbano essere sempre inviati tutti a Google Ads. Nelle Enhanced Conversions il mapping va fatto rispettando i gruppi di dati accettati dalla piattaforma.


2.4 Tag Google Ads Conversion

Crea un tag Google Ads Conversion Tracking:

  • Conversion ID: il tuo ID conversione
  • Conversion Label: la tua etichetta
  • Trigger: il trigger brevo_form_submit creato sopra

Per le Enhanced Conversions, nella sezione “Include user-provided data”, non trattare i campi come combinabili liberamente. Google Ads accetta almeno uno di questi set di dati: email (preferita), oppure indirizzo con first name, last name, postal code e country; il telefono può essere inviato come match key, ma per massimizzare qualità e copertura è consigliato insieme all’email. :contentReference[oaicite:0]{index=0}

  • Email: {{DLV - user_email}} (opzione preferita e sufficiente da sola)
  • Phone: {{DLV - user_phone}} (può essere inviato come chiave di matching; in pratica conviene quasi sempre accompagnarlo all’email)
  • First Name e Last Name: usali solo se stai passando anche i dati di indirizzo richiesti da Google Ads, cioè almeno postal code e country; facoltativamente puoi aggiungere via, città e regione. :contentReference[oaicite:1]{index=1}

In pratica: se il tuo form raccoglie solo email e telefono, configura l’Enhanced Conversion con questi due campi. Se invece vuoi usare anche nome e cognome, devi strutturare il mapping come address data, non come semplici campi anagrafici isolati. :contentReference[oaicite:2]{index=2}


2.5 Mapping corretto per Enhanced Conversions

Lo schema delle variabili utilizzato in questo articolo è compatibile con Google Ads solo se rispetti i gruppi di dati richiesti dalla piattaforma. Per le Enhanced Conversions for web, Google indica come set validi almeno uno tra: email, oppure full name + address con campi minimi obbligatori, oppure phone number come match key. :contentReference[oaicite:3]{index=3}

Variabile dataLayerFormatoQuando usarla in Google Ads
user_emailemail standardPuò essere usata da sola
user_phoneE.164 (es. +393331234567)Può essere usata come chiave di matching; in pratica è consigliato inviarla insieme all’email quando disponibile
user_first_nametestoDa usare solo come parte di address.first_name
user_last_nametestoDa usare solo come parte di address.last_name
user_postal_codeCAPNecessario se vuoi inviare i dati address
user_countrycodice paese ISO (es. IT)Necessario se vuoi inviare i dati address

Quindi, per un form lead generation standard, la configurazione più semplice e solida è quasi sempre: email + telefono in formato E.164. Se il form raccoglie anche dati di indirizzo, allora puoi estendere il mapping includendo nome, cognome, CAP e paese come blocco address. Google richiede anche la normalizzazione dei dati e il formato E.164 per il numero di telefono. :contentReference[oaicite:4]{index=4}


Debug e Verifica

Test in GTM Preview Mode

  1. Attiva la Preview Mode di GTM
  2. Vai sulla pagina con il form
  3. Compila tutti i campi e invia
  4. Nel debugger GTM, verifica che l’evento brevo_form_submit compaia nella timeline
  5. Clicca sull’evento e controlla che tutte le variabili siano popolate correttamente

Verifica in Console

Dopo aver inviato il form, esegui in console:

// Visualizza gli ultimi eventi nel dataLayer
dataLayer.filter(function(e) { return e.event; }).slice(-3);

Dovresti vedere l’evento brevo_form_submit con tutti i campi popolati.

Verifica Enhanced Conversions

  1. Google Tag Assistant: verifica che il tag di conversione riceva i parametri user_data
  2. Google Ads → Conversioni → Diagnostica: controlla che i dati vengano ricevuti e matchati

Tieni presente che Google segnala che la diagnostica e il matching delle Enhanced Conversions possono richiedere tempo per popolarsi dopo l’implementazione. :contentReference[oaicite:5]{index=5}


Troubleshooting

L’evento non compare nel dataLayer

  • Verifica che il form abbia l’ID corretto (sib-form o quello che hai configurato)
  • Verifica che XHR_FILTER e XHR_PARAM corrispondano alla chiamata reale (controlla in Network)
  • Verifica che lo script venga caricato prima del submit (usa DOM Ready come trigger)
  • Controlla nella tab Network che la chiamata restituisca status 2xx

Alcuni campi sono vuoti

  • I nomi dei campi (NOME, EMAIL, ecc.) sono case-sensitive: verifica che corrispondano esattamente agli attributi name nel form
  • Per il telefono Brevo, verifica che il widget prefisso abbia la classe .sib-sms-select
  • Esegui lo script di mappatura campi (Step 2 della Parte 1) per verificare i nomi corretti

Lo script viene eseguito due volte

  • Il flag window['__formTracker_' + FORM_ID] dovrebbe prevenirlo
  • Verifica che il tag GTM non abbia trigger multipli che lo fanno scattare più volte

Il form usa Fetch invece di XHR

Se il test della Parte 1 mostra 🟢 FETCH invece di 🔵 XHR, devi usare questo override alternativo:

<script>
(function() {
  var FORM_ID = 'il-tuo-form-id';
  var FETCH_FILTER = 'dominio-da-intercettare.com';
  var EVENT_NAME = 'form_submit';
  
  var form = document.getElementById(FORM_ID);
  if (!form) return;
  if (window['__formTracker_' + FORM_ID]) return;
  window['__formTracker_' + FORM_ID] = true;
  var origFetch = window.fetch;
  
  window.fetch = function(url, options) {
    var urlString = (typeof url === 'string') ? url : url.url;
    
    if (urlString && urlString.indexOf(FETCH_FILTER) !== -1) {
      // Cattura i dati prima dell'invio
      var formData = {
        user_email: form.querySelector('[name="email"]')?.value || ''
        // ... altri campi
      };
      
      // Esegui la fetch originale e traccia se ha successo
      return origFetch.apply(this, arguments).then(function(response) {
        if (response.ok) {
          window.dataLayer = window.dataLayer || [];
          window.dataLayer.push({
            event: EVENT_NAME,
            form_id: FORM_ID,
            user_email: formData.user_email
            // ... altri campi
          });
        }
        return response;
      });
    }
    
    return origFetch.apply(this, arguments);
  };
})();
</script>

Conclusioni

Il tracciamento dei form di terze parti richiede un approccio metodico:

  1. Analizza sempre il form con gli strumenti di debug prima di scrivere codice
  2. Identifica il tipo di invio (redirect, submit event, XHR, Fetch)
  3. Cattura i dati nel momento giusto — prima dell’invio, non dopo
  4. Verifica lo status code prima di tracciare (solo 2xx = successo)
  5. Previeni la doppia esecuzione con un flag univoco
  6. Standardizza le variabili per riutilizzare i tag su più form
  7. Formatta il telefono in E.164 per le Enhanced Conversions
  8. Mappa correttamente i dati utente in Google Ads: email da sola va bene, mentre nome e cognome hanno senso solo se accompagnati dall’indirizzo richiesto dalla piattaforma. :contentReference[oaicite:6]{index=6}

Seguendo questa metodologia potrai tracciare qualsiasi form — anche quelli più ostici — e raccogliere i dati necessari per migliorare la qualità della misurazione e delle ottimizzazioni in Google Ads. Le Enhanced Conversions for web usano infatti dati first-party forniti dall’utente, normalizzati e associati alla conversione per migliorare il matching e la misurazione. :contentReference[oaicite:7]{index=7}

Se tutto questo ti sembra troppo complicato — ed è normale che lo sia, perché tra form embedded, dataLayer, trigger GTM, Enhanced Conversions e debug tecnico gli errori sono dietro l’angolo — ci pensiamo noi. Se vuoi implementare un tracciamento affidabile senza perdere lead e senza sporcarti le mani con la parte tecnica, contattaci dal form.