Caso studio
Tre dati cliente su tre erano inaccessibili al pixel: un proxy server-side a 7 dollari al mese
I Custom Pixel di Shopify girano isolati e non possono interrogare l'archivio del negozio. Un microservizio restituisce le tre metriche con 4 punti di quota su 2.000, senza mai esporre la chiave amministrativa.
Un e-commerce lifestyle su Shopify, prodotto fisico, spesa continuativa su Google, Meta e TikTok.
Il vincolo: i Custom Pixel di Shopify girano in un ambiente isolato e non possono interrogare l’archivio amministrativo del negozio. Non è una configurazione da abilitare, è una scelta di progetto della piattaforma. Valore cumulato speso dal cliente, numero di ordini storici e stato affidabile nuovo contro ritorno restano fuori dal dataLayer, e non c’è nessuna impostazione che li faccia entrare.
Il risultato: un microservizio che interroga l’archivio per conto del pixel e restituisce le tre metriche, con un costo di 4 punti di quota su 2.000 disponibili per chiamata e 7 dollari al mese di infrastruttura. La chiave amministrativa non raggiunge mai il browser.
Qui sotto c’è perché la strada classica non funzionava, come abbiamo scelto quella alternativa, e il controllo che ha intercettato un difetto prima della produzione.
Cosa contiene questo caso
- come far arrivare al pixel un dato che la piattaforma tiene fuori dalla sua portata
- come esporre un archivio protetto senza mettere una chiave con permessi alti dentro il browser
- come scegliere fra due interfacce quando una ha un limite temporale e l’altra no
- come costruire un test che distingua una risposta corretta da una risposta vuota
Indice
- Il cliente e il punto di partenza
- Architettura del proxy e modello di sicurezza
- Migrazione da REST a GraphQL
- Validazione e test in produzione
- Nota di metodo sui numeri
- Cosa non ha funzionato
- Cosa faremmo adesso
- Conclusione
Il cliente e il punto di partenza
Negozio su Shopify con tracciamento già impostato e funzionante: eventi completi, valori corretti, deduplica fra canale browser e canale server attiva. Il lavoro non nasceva da un guasto, ma da una domanda di segmentazione. Le campagne su clienti nuovi e su clienti di ritorno rendevano in modo troppo simile, e volevano capire se il problema fosse creativo o di misurazione.
Lo stato iniziale, con la fonte di ciascun dato:
| Dato | Situazione senza API | Fonte |
|---|---|---|
| Valore cumulato speso dal cliente | non disponibile nel dataLayer | ispezione payload Custom Pixel |
| Numero ordini storici | non disponibile nel dataLayer | ispezione payload Custom Pixel |
| Stato nuovo contro ritorno | approssimato, derivato da analitica interna | ispezione payload Custom Pixel |
| Chiave amministrativa | assente dal browser, correttamente | ispezione sorgente pagina |
Il terzo punto è quello che contava. Il dato c’era ed era sbagliato, che è peggio che non averlo, perché nessuno mette in dubbio un campo popolato.
Architettura del proxy e modello di sicurezza
IN SINTESI
Cosa abbiamo fatto: costruito un microservizio che sta fuori dal browser, conserva la chiave amministrativa e risponde solo a chiamate autenticate.
Perché: la chiave che serve a leggere l’archivio ha permessi alti, e nel codice del pixel sarebbe leggibile da chiunque ispezioni la pagina.
Cosa abbiamo trovato: il pixel può fare chiamate verso l’esterno, e quello basta a spostare il problema fuori dal browser.
Il numero della sezione: 2 endpoint, uno chiamato a ogni acquisto e uno una volta sola in fase di installazione.
La decisione di partenza è stata di non cercare scorciatoie dentro il pixel. Un ambiente isolato è isolato per ragioni di sicurezza, e ogni tentativo di aggirarlo introduce il rischio che si voleva evitare.
Il flusso è a cinque passaggi. Il Custom Pixel rileva il checkout completato e legge l’identificativo del cliente. Chiama il nostro endpoint inviando quell’identificativo e una chiave condivisa. Il server verifica la chiave, interroga l’archivio Shopify con la chiave amministrativa, calcola lo stato nuovo o di ritorno, e restituisce le tre metriche. Il pixel le aggiunge al dataLayer, e da lì raggiungono le piattaforme pubblicitarie.
Due endpoint con ruoli distinti. Il primo riceve identificativo e chiave a ogni acquisto e restituisce le metriche. Il secondo completa il flusso di autorizzazione una volta sola in fase di installazione, per ottenere la chiave permanente.
La chiave amministrativa non viene mai trasmessa al browser. Vive solo nelle variabili d’ambiente del server, insieme alla chiave condivisa e ai parametri dell’applicazione. Non sta nel codice e non sta nel repository.
Il servizio gestisce tutti i casi di errore restituendo sempre una risposta valida con valori di ripiego, così il pixel non si blocca mai. Chiave sbagliata, identificativo mancante, archivio non raggiungibile: in tutti e tre i casi la risposta arriva, marcata come non riuscita, con stato “nuovo cliente”, valore cumulato a zero e conteggio ordini a zero.
Cosa ha funzionato
Il ripiego sempre valido. Il tracciamento non ha mai un punto in cui può fermarsi per colpa nostra, e questo ha permesso di rilasciare senza finestra di manutenzione.
Migrazione da REST a GraphQL: tre limiti eliminati insieme
IN SINTESI
Cosa abbiamo fatto: abbandonato l’interfaccia classica per quella a query, usando i campi già aggregati sul nodo cliente.
Perché: l’interfaccia classica ha tre limiti che si sommano e peggiorano proprio sui clienti migliori.
Cosa abbiamo trovato: i campi aggregati eliminano tutti e tre i limiti con una chiamata sola.
Il numero della sezione: da N chiamate a costo proporzionale a 1 chiamata da 4 punti di quota fissi su 2.000.
L’implementazione iniziale usava l’interfaccia classica, che restituisce la lista degli ordini e li fa sommare a noi. Tre limiti, tutti strutturali.
Primo, la finestra di 60 giorni. Il permesso di lettura ordini di base restituisce solo gli ordini degli ultimi due mesi. Per la storia completa serve un permesso esteso, che richiede una revisione manuale da parte della piattaforma.
Secondo, la paginazione oltre 250. La risposta è limitata a 250 ordini per chiamata. Un cliente con 300 ordini richiede due chiamate in sequenza, uno con 600 ne richiede tre. La latenza cresce con la storia del cliente.
Terzo, il costo proporzionale. Ogni ordine restituito consuma quota. Più un cliente ha comprato, più costa interrogarlo.
I tre limiti hanno una caratteristica in comune che li rende peggiori della somma delle parti: colpiscono più duramente proprio i clienti di valore più alto, quelli su cui il dato serve davvero.
L’interfaccia a query espone sul nodo cliente due campi già sommati dalla piattaforma: numero di ordini e importo cumulato. La query è di sei righe e chiede solo quei due valori.
Nessun limite temporale, perché i campi coprono tutta la storia. Precisione costante, perché non c’è iterazione da paginare. Una sola chiamata per una sola risposta. E costo misurato nei test di 4 punti di quota su 2.000 disponibili, indipendente dal numero di ordini del cliente.
| Aspetto | Interfaccia classica | Interfaccia a query |
|---|---|---|
| Limite temporale | 60 giorni sul permesso base | nessuno |
| Precisione oltre 250 ordini | imprecisa | costante |
| Chiamate per risposta | N, una ogni 250 ordini | 1 |
| Costo quota | proporzionale al volume | 4 punti fissi |
Cosa ha funzionato
Aver cambiato interfaccia invece di chiedere il permesso esteso. La richiesta di revisione manuale avrebbe risolto solo il primo dei tre limiti, e avrebbe aggiunto un’attesa di durata non prevedibile.
Validazione: il controllo che ha fermato un difetto prima della produzione
IN SINTESI
Cosa abbiamo fatto: verificato il servizio su un record di cui conoscevamo già la risposta esatta, contata a mano nel gestionale.
Perché: una risposta “zero ordini” è plausibile per la maggior parte dei clienti, quindi un test su un identificativo casuale non distingue il corretto dal vuoto.
Cosa abbiamo trovato: il servizio restituiva zero su un record con storia nota, e il difetto era di schema.
Il numero della sezione: 34 ordini attesi contro 0 restituiti, poi 34 dopo la correzione, riverificato su altri 3 clienti reali.
La verifica è stata progettata prima di essere eseguita, e la progettazione è la parte che conta.
Un servizio di questo tipo risponde sempre qualcosa, e le risposte plausibili sono la trappola. Zero ordini è un valore credibile: lo è per la maggior parte dei clienti di qualunque negozio. Se il controllo si fa su un identificativo qualsiasi si vede zero, e non c’è modo di sapere se è la risposta giusta o il segnale che il dato non arriva.
Per questo il test è stato eseguito su un record con storia d’acquisto nota e verificabile: 34 ordini contati a mano nel gestionale.
Il servizio ne restituiva zero. Il controllo aveva fatto esattamente il suo lavoro.
La causa era di schema. L’implementazione cercava l’importo seguendo un percorso preso dalla struttura dei singoli ordini. Quel percorso esiste su un ordine, ma non esiste sul nodo cliente come valore aggregato. Il servizio chiedeva un campo che a quel livello non c’è, non riceveva niente, e restituiva zero senza segnalare nulla.
Non era un problema di autenticazione né di connettività. Sostituito con i due campi aggregati nativi, la risposta è tornata a 34.
Le verifiche in produzione dopo il rilascio sono state tre. Controllo di stato del servizio, risposta positiva. Query verificata su tre clienti reali del negozio, con quota consumata di 4 punti su 2.000. Chiamata all’endpoint con identificativo valido, che restituisce stato, valore cumulato e conteggio ordini corretti.
La classificazione finale che il pixel riceve è a tre stati: zero ordini significa nessun acquisto precedente, un ordine significa primo acquisto in assoluto, due o più significa cliente già acquisito.
Cosa ha funzionato
Aver scelto il record di test in base a quello che sapevamo già, invece che a caso. È l’unica configurazione di test in cui una risposta plausibile e sbagliata non può passare.
Nota di metodo sui numeri
Fonte di verità dichiarata: il registro ordini Shopify. Le tre metriche restituite dal servizio sono ricalcolate a ogni chiamata direttamente dall’archivio, non memorizzate né derivate.
| Numero pubblicato | Fonte | Finestra | Modello |
|---|---|---|---|
| 4 punti di quota su 2.000 | risposta API in test | per chiamata | costo dichiarato dalla piattaforma sulla query eseguita |
| 34 ordini | registro ordini, contati a mano | lifetime | conteggio ordini del singolo cliente |
| 3 clienti verificati | test in produzione | 1 giugno 2026 | confronto risposta API contro registro |
| 60 giorni, 250 ordini | documentazione piattaforma | limiti strutturali | permesso di lettura ordini di base |
| 7 dollari al mese | fattura provider hosting | ricorrente | istanza sempre attiva |
Cosa non siamo in grado di misurare, e con che grado di certezza.
L’effetto della segmentazione corretta sulle performance delle campagne non è misurato in questo lavoro, e non lo dichiariamo. Il perimetro finiva alla consegna del dato nel dataLayer, e per misurare l’effetto servirebbe un confronto fra due periodi con la stessa spesa e la stessa creatività, che non è stato impostato.
Quello che è verificato con test attivo è che le tre metriche arrivano corrette al pixel, confrontate una per una con il registro ordini su tre clienti reali. È una verifica di correttezza del dato, non di impatto commerciale, e le due cose non vanno confuse.
Cosa non ha funzionato
Abbiamo costruito la prima versione su un percorso di campo sbagliato. L’implementazione iniziale cercava l’importo cumulato seguendo la struttura dei singoli ordini invece dei campi aggregati sul nodo cliente. Il difetto non produceva errori: restituiva zero, che è un valore plausibile. Cosa abbiamo fatto invece: il test su record a risposta nota, che è diventato la regola per ogni servizio che scriviamo. Se non conosciamo la risposta attesa prima di chiedere, non è un test.
Abbiamo iniziato dall’interfaccia sbagliata. La prima implementazione era sulla REST, ed è stata riscritta per intero. La ragione è che avevamo dato per scontato che l’interfaccia più diffusa fosse anche quella adatta, senza confrontare prima i limiti delle due. Il tempo perso è quello della prima stesura. Cosa abbiamo fatto invece: adesso il confronto fra interfacce disponibili è un passaggio esplicito prima di scrivere codice, e si valuta sul comportamento ai limiti invece che sulla familiarità.
Cosa faremmo adesso
Misurare l’effetto della segmentazione a 60 giorni. Con le tre metriche in produzione esiste per la prima volta la possibilità di confrontare campagne su clienti nuovi e su clienti di ritorno con un dato reale invece che con una stima.
Estendere il servizio agli eventi a monte dell’acquisto. Oggi risponde al checkout completato. Le stesse tre metriche su una visualizzazione di prodotto permetterebbero di segmentare il retargeting per valore del cliente.
Aggiungere una cache breve. A ogni acquisto parte una chiamata. Con 4 punti su 2.000 il margine è ampio, ma una cache di pochi minuti sull’identificativo eliminerebbe le chiamate ripetute in caso di ricaricamento della pagina di conferma.
Valutare l’alternativa gratuita di hosting. Il codice non richiede modifiche per girare su un provider con piano gratuito adatto a traffico basso. Sette dollari al mese sono poco, ma sono ricorrenti.
Conclusione
I tre dati cliente che il pixel non poteva vedere adesso arrivano nel dataLayer, con un costo di 4 punti di quota su 2.000 per chiamata e 7 dollari al mese di infrastruttura.
Quello che questo lavoro lascia, ripreso dai quattro punti iniziali.
Come far arrivare al pixel un dato fuori dalla sua portata: non si aggira l’isolamento, si sposta la richiesta fuori dal browser e si fa rispondere qualcun altro.
Come esporre un archivio protetto senza mettere la chiave nel browser: la chiave sta sul server, il browser manda solo un identificativo e una parola d’ordine condivisa.
Come scegliere fra due interfacce: si confrontano sui limiti, non sulla familiarità. Quella con i campi già aggregati elimina insieme finestra temporale, paginazione e costo variabile.
Come costruire un test che distingua il corretto dal vuoto: si sceglie un record di cui si conosce già la risposta. Se la risposta attesa è un numero e ne arriva un altro, il test funziona. Se la risposta attesa è zero, il test non può dire niente.
Quando questo lavoro ha senso, e quando no
Ha senso se segmenti le campagne per cliente nuovo contro cliente di ritorno e vuoi che quella distinzione poggi sullo storico ordini invece che su una stima, e se vendi su una piattaforma che tiene i dati cliente fuori dalla portata del tracciamento.
Non ha senso se il tuo volume di ordini è tale che la segmentazione per valore del cliente non cambia nessuna decisione di budget. E non ha senso se ti aspetti che il dato migliore produca da solo un miglioramento delle campagne, perché il dato abilita una scelta e non la sostituisce.
Il primo passo è aprire il dataLayer di un acquisto sul tuo negozio e guardare se accanto allo stato del cliente c’è un numero di ordini. Se non c’è, quel campo è una stima.