Passa al contenuto principale

Varify Realtime Tracking

Ultimo aggiornamento il 02 nov 20267 min di lettura
important

Gli account creati a partire dal 17 settembre 2026 possono selezionare „Varify Realtime Tracking“ direttamente in „Tracking Setup.“ I clienti esistenti possono richiedere questa funzionalità tramite il nostro modulo di contatto. L'integrazione insieme a GA4 è disponibile su richiesta per i clienti esistenti.

In breve​

Varify Realtime Tracking ti consente di analizzare i tuoi esperimenti direttamente in Varify senza ritardi. Un servizio di tracciamento Varify dedicato misura i tuoi obiettivi definiti e li mostra in Varify Reporting.

Puoi utilizzarlo in due modi:

  • Come tuo provider di tracciamento: Varify misura i tuoi esperimenti autonomamente ed è la base dei tuoi report. Lo selezioni in „Tracking Setup.“
  • Come integrazione insieme a GA4: Hai configurato Google Analytics 4 in „Tracking Setup“ e attivi inoltre Varify Realtime Tracking in „Integrations.“
La scelta tra „Varify Realtime Tracking“ e „Google Analytics 4“ come analytics che valuta gli esperimenti, ciascuno con il proprio pulsante.

Provider o integrazione?​

Come provider di tracciamentoCome integrazione insieme a GA4
Dove lo attivi„Tracking Setup,“ scheda „Varify Realtime Tracking“„Integrations,“ scheda „Varify Realtime Tracking“
RequisitoDisponibile per il tuo accountGA4 è configurato in „Tracking Setup,“ e l'integrazione è abilitata per il tuo account
Consenso dell'utenteLo scegli durante la configurazioneEreditato dalla tua configurazione GA4
I report mostranoDati di Varify Realtime TrackingObiettivi Varify e obiettivi GA4 (anche BigQuery), Shopify opzionale
Obiettivi GA4Non possono essere importatiImportati come di consueto

Usa Varify Realtime Tracking come tuo provider di tracciamento​

Passo 1: Configura il tuo sistema di tracciamento​

Vai su „Tracking Setup“ e seleziona „Varify Realtime Tracking.“ Puoi quindi decidere se integrare Varify Realtime Tracking con o senza „User Consent.“ Questa pagina può aiutarti a prendere questa decisione: https://varify.io/varify-tracking-gdpr-compliance/

Varify Tracking Setup per „Varify Realtime Tracking“, passo „User consent“: scegli tra „Without user consent“ e „With user consent“

Passo 2: Abilitare Varify Realtime Tracking​

Integrazione senza consenso dell'utente​

Se hai deciso di caricare Varify Realtime Tracking senza il consenso dell'utente, la tua configurazione di tracciamento di base è già impostata e puoi proseguire con „Set up your goals“ qui sotto.

Integrazione con consenso dell'utente​

Viene fornito uno script di attivazione per l'integrazione con il consenso dell'utente. Il tracciamento viene attivato non appena questo script viene caricato. Integra lo script secondo le specifiche della tua piattaforma di gestione del consenso (CMP). Puoi anche utilizzare Google Tag Manager (GTM) per l'integrazione basata sulle visualizzazioni di pagina e su un segnale di consenso valido.

Varify Tracking Setup, passo „Activation tag“: una freccia indica lo script di attivazione che richiama window.varify.setTracking(true)

Invia dati a GA4​

Per inviare i tuoi dati degli esperimenti anche a GA4, attiva l'integrazione Google Analytics 4 in „Integrations.“ Gli obiettivi GA4 non possono essere importati in questa configurazione. Trovi la configurazione qui: Google Analytics 4 Direct Integration

Usa Varify Realtime Tracking come integrazione​

Usa questa opzione se GA4 è il tuo provider di tracciamento e vuoi che Varify misuri i tuoi esperimenti in aggiunta. I report mostrano quindi insieme gli obiettivi Varify e gli obiettivi GA4, oltre ai dati BigQuery, e ai dati Shopify se li hai abilitati.

Passo 1: Configura GA4 in Tracking Setup​

Configura prima Google Analytics 4. Trovi le opzioni qui: Set up tracking

Passo 2: Attiva l'integrazione​

  1. Apri „Integrations“ nella navigazione principale.
  2. Trova la scheda „Varify Realtime Tracking“ e attiva l'interruttore.

Non riesci ad attivarlo? L'integrazione deve prima essere abilitata per il tuo account. Inviaci un messaggio tramite il nostro modulo di contatto. Ti risponderemo.

Fase 3: Consenso dell'utente​

Varify Realtime Tracking segue la configurazione di GA4. Se GA4 effettua il tracciamento solo dopo il consenso dell'utente, anche Varify Realtime Tracking si avvia solo dopo che il consenso è stato dato. Per maggiori dettagli, consulta Invia dati al tuo strumento di web analytics solo dopo il consenso dell'utente.

Configura i tuoi obiettivi​

Per analizzare i tuoi esperimenti, crea degli obiettivi. Troverai la sezione "Goals" nella barra laterale a sinistra. Gli obiettivi vengono creati allo stesso modo in entrambe le configurazioni.

Nella sezione "Goals", puoi scegliere tra tre tipi di obiettivi: Click Goal, Page View Goal e Custom Goal.

Dialogo Varify „Create goal“ di tipo „Page view“: nome „Product Detail Page - Page views“ e una corrispondenza URL che contiene „/products/“

Configurazione degli obiettivi di clic​

Con Click Goals, puoi misurare quante volte i partecipanti all'esperimento fanno clic sugli elementi. Per farlo, definisci un selettore personalizzato per l'elemento. Per identificare un selettore personalizzato per un elemento, puoi utilizzare ad esempio l'editor visivo di Varify. Aprilo e seleziona l'elemento che vuoi tracciare. Poi copia il selettore e inseriscilo nel campo "Selector" sotto "Click Goal."

Configurazione degli obiettivi di visualizzazione pagina​

Con i Page View Goal puoi misurare quanto spesso i partecipanti all'esperimento visualizzano pagine o tipi di pagina specifici. Per farlo, puoi semplicemente definire regole personalizzate per tracciare le visualizzazioni di pagina che soddisfano i tuoi criteri.

Configurazione degli obiettivi personalizzati​

Puoi usare i Custom Goal per creare obiettivi personalizzati. Ad esempio, questo può essere il caso quando vuoi misurare il valore del fatturato di un ordine. I Custom Goal vengono attivati tramite JavaScript nel tuo esperimento.

Conteggio delle conversioni​

Con questa impostazione puoi specificare se un obiettivo debba essere tracciato una o più volte. Per impostazione predefinita, nell'A/B testing ogni obiettivo viene tracciato una sola volta, poiché di solito interessa solo sapere se un utente ha raggiunto l'obiettivo o meno. Il tracciamento multiplo, tuttavia, può essere utile per gli obiettivi legati al fatturato: in questo caso, il valore dell'ordine di un utente può essere accumulato su più sessioni.

Click goal di Varify „Button Click - Register“ con il selettore CSS „.register“ e le opzioni di conversion counting „Count unique“ (selezionata) e „Count multiple“

Tracciamento degli obiettivi di checkout Shopify​

Gli obiettivi di evento Shopify come «Purchase» o «Start Checkout» non possono essere tracciati direttamente tramite il tuo sito web. A partire dal 2025, Shopify ha reso obbligatorio che questi possano essere tracciati solo tramite il pixel personalizzato sul tuo sito web. Per tracciare questi obiettivi, vai su «Settings > Customer Events» e clicca sul pulsante «Add Custom Pixel». Imposta il nome del pixel su «Varify Realtime Tracking» e clicca su «Add Pixel.»

Impostazioni Shopify, Customer events: le frecce indicano „Customer events“ e „Add custom pixel“; la finestra di dialogo „Add custom pixel“ ha il nome del pixel „Varify Realtime Tracking“

Dopo aver creato il pixel, apri prima la sezione „Customer Privacy“ e imposta "Data Sale" su "Data collected does not qualify as a data sale." Varify non vende dati e traccia solo valori aggregati per le tue analisi dell'esperimento.

Per «Permission», dovresti selezionare «Not required» se vuoi tracciare senza il consenso dell'utente—come specificato in precedenza nella configurazione del tracciamento. Se invece stai tracciando con il consenso dell'utente, puoi lasciare l'impostazione su "Required."

Customer privacy del pixel Shopify „Varify Realtime Tracking“: Permission „Not required“ e Data sale „Data collected does not qualify as data sale“

Successivamente, copia il codice evidenziato sotto questo paragrafo e incollalo sotto "Code."

Pixel personalizzato Shopify „Varify Realtime Tracking“: il campo „Code“, evidenziato in rosso, con l'inizio dello script Varify Shopify Web Pixel
/**
* Varify Shopify Web Pixel — links experiments/variations a customer saw to
* whether they completed a purchase.
*/

let storage;

// Store's currency, used to normalize order totals before sending them.
const SHOP_CURRENCY = init.data?.shop?.paymentSettings?.currencyCode || 'EUR';

// Free FX API, used only when an order's currency differs from the store's.
const FX_API = 'https://api.frankfurter.dev/v1/latest';
const FX_TTL_MS = 6 * 60 * 60 * 1000;
const FX_TIMEOUT_MS = 2000;

const VARIFY_INGESTION_ENDPOINT = 'https://w.varify.io/events';

// One id per pixel session, reused for every event this pixel sends.
const pixelSessionId = crypto.randomUUID();

// Reads this pixel's saved data (experiments seen, anonymous id, etc.),
// cached in-memory after the first read.
async function getVarifyData() {
if (storage) {
return storage;
}
storage = (async () => {
try {
const raw = await browser.localStorage.getItem('varify-data');
return raw ? JSON.parse(raw) : {};
} catch (error) {
// Don't cache a broken read — retry from scratch next time.
storage = undefined;
console.error('Varify: error reading local storage', error);
return {};
}
})();
return storage;
}

// Units of `currency` per 1 unit of the store's currency, or null if
// unavailable — callers should skip sending rather than guess a rate.
async function getFxRate(currency) {
const cacheKey = `varify-fx-${SHOP_CURRENCY}-${currency}`;

try {
const cached = await browser.localStorage.getItem(cacheKey);
if (cached) {
const { rate, ts } = JSON.parse(cached);
if (rate && ts && Date.now() - ts < FX_TTL_MS) {
return rate;
}
}
} catch (error) {
// Fall through and fetch fresh below.
}

try {
const url = `${FX_API}?from=${encodeURIComponent(SHOP_CURRENCY)}&to=${encodeURIComponent(currency)}`;

let res;
if (typeof AbortController === 'function') {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), FX_TIMEOUT_MS);
try {
res = await fetch(url, { signal: controller.signal });
} finally {
clearTimeout(timer);
}
} else {
res = await fetch(url);
}

if (!res.ok) {
console.warn(`Varify: FX API returned ${res.status} for ${currency}.`);
return null;
}

const json = await res.json();
const rate = json?.rates?.[currency];

if (typeof rate !== 'number' || !isFinite(rate) || rate <= 0) {
console.warn(`Varify: FX API gave no usable rate for ${currency}.`, json);
return null;
}

await browser.localStorage.setItem(
cacheKey,
JSON.stringify({ rate, ts: Date.now() }),
);
return rate;
} catch (error) {
console.warn(`Varify: FX lookup failed for ${currency}.`, error);
return null;
}
}

// Varify's endpoint only accepts flat text/number values, so a list of
// experiments becomes two comma-separated strings (ids and variation ids).
function flattenExperiments(entries) {
return {
experiment_ids: entries.map((entry) => entry.experimentId).join(','),
variation_ids: entries
.map((entry) =>
entry.variationId === null ? 'original' : entry.variationId,
)
.join(','),
};
}

// Edge's identifier also contains "Chrome/", so it must be checked first.
function detectBrowser(userAgent) {
if (userAgent.includes('Firefox/')) return 'Firefox';
if (userAgent.includes('Edg/')) return 'Edge';
if (userAgent.includes('Chrome/')) return 'Chrome';
if (userAgent.includes('Safari/')) return 'Safari';
return 'Unknown';
}

function detectDevice(userAgent) {
if (/Tablet|iPad/i.test(userAgent)) return 'tablet';
if (/Mobi|Android/i.test(userAgent)) return 'mobile';
return 'desktop';
}

function detectOs(userAgent) {
if (/iPhone|iPad|iPod/i.test(userAgent)) return 'iOS';
if (userAgent.includes('Android')) return 'Android';
if (userAgent.includes('Win')) return 'Windows';
if (userAgent.includes('Mac')) return 'macOS';
if (userAgent.includes('Linux')) return 'Linux';
return 'Unknown';
}

// Browser timezone, e.g. "Europe/Berlin" — not GPS or IP-based location.
function detectLocation() {
try {
return Intl.DateTimeFormat().resolvedOptions().timeZone || undefined;
} catch {
return undefined;
}
}

// Non-identifying browser/page details, added to every event. The pixel
// sandbox may not expose all of these — each lookup is best-effort and
// simply omitted if unavailable.
function collectBrowserInfo() {
const info = {};

try {
const userAgent =
typeof navigator !== 'undefined' ? navigator.userAgent : undefined;
if (typeof userAgent === 'string') {
info.userAgent = userAgent;
info.browser = detectBrowser(userAgent);
info.device = detectDevice(userAgent);
info.os = detectOs(userAgent);
}
} catch (error) {
// Not available in this environment.
}

try {
if (typeof window !== 'undefined' && window.location) {
info.path = window.location.pathname;
info.domain = window.location.hostname;
}
} catch (error) {
// Not available in this environment.
}

const location = detectLocation();
if (location) {
info.location = location;
}

return info;
}

// Sends one event to Varify. Never throws — failures are logged and
// swallowed so the pixel/checkout is never affected. Falls back to reading
// the anonymous id from local storage if one wasn't passed in, and returns
// whichever id was actually used so the caller can persist it.
async function sendVarifyEvent(name, teamSqid, anonymousId, properties) {
const anonymousIdWithFallback =
anonymousId || localStorage.getItem('varify_anonymous_id');

if (!teamSqid || !anonymousIdWithFallback) {
console.warn(
`Varify: skipping "${name}" event — missing teamSqid or anonymousId.`,
'Team Sqid',
teamSqid,
'Anonymous ID',
anonymousIdWithFallback,
);
return anonymousIdWithFallback;
}

try {
await fetch(VARIFY_INGESTION_ENDPOINT, {
method: 'POST',
keepalive: true,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
events: [
{
id: crypto.randomUUID(),
name,
teamId: String(teamSqid),
anonymousId: anonymousIdWithFallback,
sessionId: pixelSessionId,
properties: { ...collectBrowserInfo(), ...properties },
},
],
}),
});
} catch (error) {
console.error(`Varify: error sending "${name}" event`, error);
}

return anonymousIdWithFallback;
}

// Fired by Varify's tracking script when a customer is shown an experiment.
// Remembers it locally so it can be attached to a later checkout event.
analytics.subscribe('varify', async (event) => {
const {
varify_experimentId,
varify_variationId,
varify_anonymousId,
teamId,
teamSqid,
storageType = 'localStorage',
} = event.customData || {};

if (!varify_experimentId || !teamId || !teamSqid) {
console.warn('Varify: event missing experimentId or teamId. Event:', event);
return;
}

const validVariationId =
varify_variationId !== undefined ? varify_variationId : null;

const existingData = await getVarifyData();

if (!existingData.data) {
existingData.data = [];
}

const experimentEntry = {
experimentId: varify_experimentId,
variationId: validVariationId,
timestamp: Date.now(),
};

existingData.data = existingData.data.filter(
(entry) => entry.experimentId !== varify_experimentId,
);

existingData.data.push(experimentEntry);
existingData.teamId = teamId;
existingData.teamSqid = teamSqid;
existingData.storageType = storageType;

// Only present once Varify's tracking script has finished loading —
// don't overwrite a previously-saved id with nothing.
if (varify_anonymousId) {
existingData.anonymousId = varify_anonymousId;
}

await browser.localStorage.setItem(
'varify-data',
JSON.stringify(existingData),
);
});

// How long an experiment exposure counts toward a later purchase.
const WINDOW_MS = 28 * 24 * 60 * 60 * 1000;

const pruneEntries = (entries) => {
const threshold = Date.now() - WINDOW_MS;
return (entries || []).filter(
(entry) =>
entry.timestamp && entry.experimentId && entry.timestamp >= threshold,
);
};

// Fired by Shopify whenever a product is added to the cart (online store
// pages, not checkout). Sent as "add_to_cart" so it can be used as a goal.
analytics.subscribe('product_added_to_cart', async (event) => {
const existingData = await getVarifyData();
if (!existingData.data || existingData.data.length === 0) return;

existingData.data = pruneEntries(existingData.data);
if (existingData.data.length === 0) return;

const line = event.data?.cartLine;
const productId = line?.merchandise?.product?.id?.split('/').pop();
const variantId = line?.merchandise?.id?.split('/').pop();

await sendVarifyEvent(
'add_to_cart',
existingData.teamSqid,
existingData.anonymousId,
{
...flattenExperiments(existingData.data),
product_id: productId,
variant_id: variantId,
quantity: line?.quantity,
value: line?.cost?.totalAmount?.amount,
currency: line?.cost?.totalAmount?.currencyCode,
},
);
});

analytics.subscribe('checkout_started', async (event) => {
const existingData = await getVarifyData();
if (!existingData.data || existingData.data.length === 0) {
return;
}

existingData.data = pruneEntries(existingData.data);

await browser.localStorage.setItem(
'varify-data',
JSON.stringify(existingData),
);

if (existingData.data.length > 0) {
const resolvedAnonymousId = await sendVarifyEvent(
'checkout_started',
existingData.teamSqid,
existingData.anonymousId,
flattenExperiments(existingData.data),
);

// Persist the fallback id, if used, so it doesn't need re-deriving.
if (
resolvedAnonymousId &&
resolvedAnonymousId !== existingData.anonymousId
) {
existingData.anonymousId = resolvedAnonymousId;
await browser.localStorage.setItem(
'varify-data',
JSON.stringify(existingData),
);
}
}

// Warm the rate while the customer is still typing.
const currency = event.data?.checkout?.currencyCode;
if (currency && currency !== SHOP_CURRENCY) {
getFxRate(currency);
}
});

analytics.subscribe('checkout_completed', async (event) => {
const orderId = event.data?.checkout?.order?.id;
const money = event.data?.checkout?.subtotalPrice;
let orderRevenue = money?.amount;
const orderCurrency = money?.currencyCode;

// 0 is a valid revenue (100% discount) and must not count as missing.
if (!orderId || orderRevenue == null || !orderCurrency) {
console.warn(
'Varify: checkout_completed missing orderId, revenue or currency.',
);
return;
}

// subtotalPrice is presentment currency and the event carries no rate or
// shop-money amount. Convert to shop currency here, or skip.
if (orderCurrency !== SHOP_CURRENCY) {
const rate = await getFxRate(orderCurrency);
if (!rate) {
console.warn(
`Varify: skipping order ${orderId} — ${orderRevenue} ${orderCurrency}, no FX rate available.`,
);
return;
}
const converted = +(orderRevenue / rate).toFixed(2);
console.info(
`Varify: converted order ${orderId} — ${orderRevenue} ${orderCurrency} @ ${rate} -> ${converted} ${SHOP_CURRENCY}.`,
);
orderRevenue = converted;
}

const parsedData = await getVarifyData();
if (!parsedData.data || parsedData.data.length === 0 || !parsedData.teamId) {
console.warn('Varify: no valid data in local storage.');
return;
}

// The order-status page refires checkout_completed on every visit.
if (!Array.isArray(parsedData.sentOrders)) {
parsedData.sentOrders = [];
}
if (parsedData.sentOrders.includes(orderId)) {
return;
}

parsedData.data = pruneEntries(parsedData.data);
if (parsedData.data.length === 0) {
return;
}

const lineItems = event.data?.checkout?.lineItems;
let cartProducts = [];

if (lineItems && Array.isArray(lineItems)) {
cartProducts = lineItems
.map((item) => {
const productId = item.variant?.product?.id?.split('/').pop();
const variantId = item.variant?.id?.split('/').pop();

if (productId && variantId) {
return {
productId,
variantId,
};
}
return null;
})
.filter((p) => p !== null);
}

const resolvedAnonymousId = await sendVarifyEvent(
'checkout_completed',
parsedData.teamSqid,
parsedData.anonymousId,
{
...flattenExperiments(parsedData.data),
order_id: String(orderId),
value: orderRevenue,
currency: SHOP_CURRENCY,
cart_product_ids: cartProducts.map((p) => p.productId).join(','),
cart_variant_ids: cartProducts.map((p) => p.variantId).join(','),
},
);

// Persist the fallback id, if used, so it doesn't need re-deriving.
if (resolvedAnonymousId) {
parsedData.anonymousId = resolvedAnonymousId;
}

parsedData.sentOrders = [...parsedData.sentOrders, orderId].slice(-50);
await browser.localStorage.setItem('varify-data', JSON.stringify(parsedData));
});

Dopo aver aggiunto il codice, clicca su "Connect" nel menu in alto. Il tuo tracking Shopify è ora impostato.

Pixel personalizzato Shopify „Varify Realtime Tracking“ con Customer privacy impostato su „Not required“ e il pulsante „Connect“ in alto a destra

Aggiungi gli obiettivi Shopify in Varify​

Il pixel personalizzato invia solo gli eventi. Per usarli nei tuoi esperimenti, registra prima ogni evento Shopify come Custom Event Goal in Varify. Devi farlo solo una volta per obiettivo. Successivamente, potrai selezionare gli obiettivi in qualsiasi esperimento.

Il nome dell'obiettivo è a tua scelta. L'event name, invece, deve essere esattamente identico al nome dell'evento inviato dal pixel, incluse maiuscole, minuscole e underscore. Altrimenti Varify non riesce ad abbinare gli eventi e l'obiettivo non registrerà alcun dato.

Evento ShopifyNome evento in Varify (esattamente come inviato dal pixel)Esempio di nome obiettivo
product_added_to_cartadd_to_cartAdd to Cart
checkout_startedcheckout_startedBegin checkout
checkout_completedcheckout_completedPurchase

Il pixel invia l'evento Shopify product_added_to_cart a Varify come add_to_cart. Usa add_to_cart come nome evento in Varify.

Passo 1: Crea un nuovo Custom Event Goal​

  1. Vai su „Goals“ nella barra laterale a sinistra e crea un nuovo obiettivo.
  2. Seleziona il tipo di obiettivo „Custom event“ e clicca su „Next.“
Crea nuovo Custom Goal

Passo 2: Inserisci il nome dell'obiettivo e il nome dell'evento​

  1. Inserisci qualsiasi goal name desideri, ad esempio „Purchase.“ Questo nome viene mostrato nei report.
  2. Inserisci l'event name esattamente come indicato nella tabella sopra, ad esempio checkout_completed.

Il nome dell'evento viene compilato automaticamente a partire dal nome dell'obiettivo. Sovrascrivilo con il nome evento esatto indicato nella tabella. Non può essere modificato in seguito, quindi controllalo prima di continuare.

Crea obiettivo di checkout completato

Passo 3: Scegli la frequenza di conteggio e salva​

Nel passo 3, scegli con quale frequenza l'obiettivo deve contare („Once per visitor“ o „Every time“). Per un normale obiettivo di conversione come „Purchase,“ mantieni „Once per visitor.“ Poi clicca su „Create goal.“

Lo snippet di tracking mostrato in questo passo non è necessario per gli obiettivi Shopify, poiché il pixel personalizzato invia già l'evento.

Imposta il metodo di conteggio delle entrate

Misura le entrate (entrate per visitatore)​

Per analizzare le entrate, ad esempio le entrate per visitatore, crea un altro Custom Event Goal:

  1. Assegnagli un nome, ad esempio „Revenue.“
  2. Inserisci checkout_completed come nome evento, lo stesso usato per „Purchase.“
  3. Nel passaggio 3, attiva „Track revenue“ („Measure order value alongside conversions“).
  4. Clicca su „Create goal.“

Aggiungi gli obiettivi al tuo esperimento​

Una volta creati i Custom Event Goal, puoi aggiungerli a un esperimento:

  1. Apri il tuo esperimento e vai alla scheda „Goals“.
  2. Clicca su „+ Custom Event Goal“ e seleziona il tuo obiettivo dall'elenco, ad esempio „Purchase“ o „Revenue.“
  3. Clicca su „Save Goals.“
Aggiungi Revenue all'esperimento

L'obiettivo ora appare nell'elenco, contrassegnato come „Custom event.“

Obiettivo Revenue aggiunto all'esperimento
nota

Aggiungi i tuoi obiettivi prima di avviare l'esperimento. Gli obiettivi aggiunti in seguito non vengono tracciati retroattivamente.