Pular para o conteúdo principal

Varify Realtime Tracking

Última atualização em 02 de nov. de 20268 min de leitura
important

Contas criadas a partir de 17 de setembro de 2026 podem selecionar „Varify Realtime Tracking“ diretamente em „Tracking Setup.“ Clientes existentes podem solicitar esta funcionalidade através do nosso formulário de contacto. A integração em conjunto com GA4 está disponível para clientes existentes mediante pedido.

Em resumo​

O Varify Realtime Tracking permite-te analisar as tuas experiências diretamente no Varify sem qualquer atraso. Um serviço de tracking dedicado do Varify mede os teus objetivos definidos e apresenta-os no Varify Reporting.

Podes usá-lo de duas formas:

  • Como fornecedor de tracking: o Varify mede as tuas experiências por conta própria e serve de base para os teus relatórios. Seleciona-o em „Tracking Setup.“
  • Como integração em conjunto com GA4: configuraste o Google Analytics 4 em „Tracking Setup“ e ativas adicionalmente o Varify Realtime Tracking em „Integrations.“
A escolha entre „Varify Realtime Tracking“ e „Google Analytics 4“ como o sistema de análise que avalia as experiências, cada um com o seu próprio botão.

Fornecedor ou integração?​

Como fornecedor de trackingComo integração em conjunto com GA4
Onde ativas„Tracking Setup,“ cartão „Varify Realtime Tracking“„Integrations,“ cartão „Varify Realtime Tracking“
RequisitoDisponível para a tua contaGA4 está configurado em „Tracking Setup,“ e a integração está ativada para a tua conta
Consentimento do utilizadorEscolhes durante a configuraçãoHerdado da tua configuração GA4
Os relatórios mostramDados do Varify Realtime TrackingObjetivos do Varify e objetivos do GA4 (também BigQuery), Shopify opcional
Objetivos do GA4Não podem ser importadosImportados normalmente

Usar o Varify Realtime Tracking como fornecedor de tracking​

Passo 1: Configura o teu sistema de tracking​

Vá para „Tracking Setup“ e selecione „Varify Realtime Tracking.“ Em seguida, podes decidir se queres integrar o Varify Realtime Tracking com ou sem „User Consent.“ Esta página pode ajudar-te a tomar essa decisão: https://varify.io/varify-tracking-gdpr-compliance/

Varify Tracking Setup para „Varify Realtime Tracking“, etapa „User consent“: escolhe entre „Without user consent“ e „With user consent“

Etapa 2: Ativando o Varify Realtime Tracking​

Integração sem consentimento do usuário​

Se decidiste carregar o Varify Realtime Tracking sem consentimento do utilizador, a tua configuração básica de tracking já está em vigor e podes continuar com „Configurar os teus objetivos“ abaixo.

Integração com consentimento do usuário​

É fornecido um script de ativação para integração com o consentimento do usuário. O tracking é ativado assim que este script é carregado. Integre o script de acordo com as especificações da sua plataforma de gestão de consentimento (CMP). Você também pode usar o Google Tag Manager (GTM) para integração com base em visualizações de página e um sinal de consentimento válido.

Varify Tracking Setup, etapa „Activation tag“: uma seta aponta para o script de ativação que chama window.varify.setTracking(true)

Enviar dados para o GA4​

Para também enviares os dados das tuas experiências para o GA4, ativa a integração Google Analytics 4 em „Integrations.“ Os objetivos do GA4 não podem ser importados nesta configuração. Podes encontrar a configuração aqui: Google Analytics 4 Direct Integration

Usar o Varify Realtime Tracking como integração​

Usa esta opção se o GA4 for o teu fornecedor de tracking e quiseres que o Varify meça adicionalmente as tuas experiências. Os relatórios mostram então os objetivos do Varify e os objetivos do GA4 em conjunto, além dos dados do BigQuery, e dados do Shopify se o tiveres ativado.

Passo 1: Configurar o GA4 em Tracking Setup​

Configura primeiro o Google Analytics 4. Podes encontrar as opções aqui: Set up tracking

Passo 2: Ativar a integração​

  1. Abra „Integrations“ na navegação principal.
  2. Encontre o cartão „Varify Realtime Tracking“ e ative o toggle.

Não consegue ativar? A integração tem de ser ativada para a sua conta primeiro. Envie-nos uma mensagem através do nosso formulário de contacto. Entraremos em contacto consigo.

Passo 3: Consentimento do utilizador​

O Varify Realtime Tracking segue a sua configuração do GA4. Se o GA4 só rastrear após o consentimento do utilizador, o Varify Realtime Tracking também só começa após o consentimento ter sido dado. Para mais detalhes, consulte Enviar dados para a sua ferramenta de análise web apenas após o consentimento do utilizador.

Configure as suas metas​

Para analisar as suas experiências, crie metas. Vai encontrar a secção "Goals" na barra lateral à esquerda. As metas são criadas da mesma forma em ambas as configurações.

Na seção "Goals", podes escolher entre três tipos de metas: Click Goal, Page View Goal e Custom Goal.

Diálogo do Varify „Create goal“ do tipo „Page view“: nome „Product Detail Page - Page views“ e uma correspondência de URL que contém „/products/“

Configurar Metas de Clique​

Com Click Goals, você pode medir com que frequência os participantes do experimento clicam em elementos. Para isso, defina um seletor personalizado para o elemento. Para identificar um seletor personalizado para um elemento, você pode usar, por exemplo, o editor visual da Varify. Abra-o e selecione o elemento que deseja rastrear. Em seguida, copie o seletor e insira-o no campo "Selector" em "Click Goal".

Configurar Metas de Visualização de Página​

Com Metas de Visualização de Página, você pode medir com que frequência os participantes do seu experimento visualizam páginas ou tipos de página específicos. Para isso, você pode simplesmente definir suas próprias regras personalizadas para rastrear as visualizações de página que atendem aos seus critérios.

Configurar Metas Personalizadas​

Você pode usar Custom Goals para criar metas personalizadas. Por exemplo, isso pode ser quando você deseja medir o valor de receita de um pedido. As Custom Goals são acionadas via JavaScript no seu experimento.

Contagem de Conversões​

Com essa configuração, você pode especificar se uma meta deve ser rastreada uma única vez ou várias vezes. Por padrão, em testes A/B, cada meta é rastreada apenas uma vez, já que normalmente você só está interessado em saber se um usuário atingiu a meta ou não. No entanto, o rastreamento múltiplo pode ser útil para metas de receita: nesse caso, o valor do pedido de um usuário pode ser acumulado em várias sessões.

Meta de clique da Varify „Button Click - Register“ com o seletor CSS „.register“ e as opções de contagem de conversão „Count unique“ (selecionada) e „Count multiple“

Rastreamento de Metas de Checkout do Shopify​

Metas de eventos do Shopify como «Purchase» ou «Start Checkout» não podem ser rastreadas diretamente através do seu site. A partir de 2025, o Shopify tornou obrigatório que essas só possam ser rastreadas através do custom pixel no seu site. Para rastrear essas metas, vá para «Settings > Customer Events» e clique no botão «Add Custom Pixel». Defina o nome do pixel como «Varify Realtime Tracking» e clique em «Add Pixel».

Configurações da Shopify, Customer events: setas apontam para „Customer events“ e „Add custom pixel“; o diálogo „Add custom pixel“ tem o nome do pixel „Varify Realtime Tracking“

Depois de criar o pixel, primeiro abra a seção „Customer Privacy“ e defina "Data Sale" como "Data collected does not qualify as a data sale." A Varify não vende dados e rastreia apenas valores agregados para as análises do seu experimento.

Para «Permission», você deve selecionar «Not required» se quiser rastrear sem o consentimento do usuário — conforme especificado anteriormente na configuração de tracking. Se, por outro lado, você estiver rastreando com o consentimento do usuário, pode deixar a configuração como «Required».

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

Em seguida, copie o código destacado abaixo deste parágrafo e cole-o em «Code».

Pixel personalizado do Shopify „Varify Realtime Tracking“: o campo „Code“, destacado a vermelho, com o início do 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));
});

Depois de adicionares o código, clica em "Connect" no menu no topo. A tua configuração de tracking do Shopify está agora concluída.

Pixel personalizado do Shopify „Varify Realtime Tracking“ com Customer privacy definido como „Not required“ e o botão „Connect“ no canto superior direito

Adicione os objetivos do Shopify no Varify​

O pixel personalizado apenas envia os eventos. Para usá-los nos seus experimentos, primeiro registe cada evento do Shopify como um Custom Event Goal no Varify. Só precisa de fazer isto uma vez por objetivo. Depois, pode selecionar os objetivos em qualquer experimento.

O nome do objetivo fica ao seu critério. O event name, no entanto, tem de ser exatamente igual ao nome do evento que o pixel envia, incluindo maiúsculas, minúsculas e underscores. Caso contrário, o Varify não consegue corresponder os eventos e o objetivo não vai registar nenhum dado.

Evento do ShopifyEvent name no Varify (exatamente como enviado pelo pixel)Exemplo de nome de objetivo
product_added_to_cartadd_to_cartAdd to Cart
checkout_startedcheckout_startedBegin checkout
checkout_completedcheckout_completedPurchase

O pixel envia o evento do Shopify product_added_to_cart para o Varify como add_to_cart. Use add_to_cart como event name no Varify.

Passo 1: Criar um novo Custom Event Goal​

  1. Vá a „Goals“ na barra lateral à esquerda e crie um novo objetivo.
  2. Selecione o tipo de objetivo „Custom event“ e clique em „Next.“
Criar Novo Custom Goal

Passo 2: Inserir o goal name e o event name​

  1. Insira o goal name que quiser, por exemplo „Purchase.“ Este nome é mostrado nos relatórios.
  2. Insira o event name exatamente como indicado na tabela acima, por exemplo checkout_completed.

O event name é preenchido automaticamente a partir do goal name. Substitua-o pelo event name exato da tabela. Não pode ser alterado depois, por isso verifique antes de continuar.

Criar meta de checkout concluído

Passo 3: Escolher a frequência de contagem e guardar​

No passo 3, escolha a frequência com que o objetivo deve contar („Once per visitor“ ou „Every time“). Para um objetivo de conversão normal como „Purchase,“ mantenha „Once per visitor.“ Depois clique em „Create goal.“

O snippet de tracking mostrado neste passo não é necessário para os objetivos do Shopify, porque o pixel personalizado já envia o evento.

Definir método de contagem de receita

Medir receita (receita por visitante)​

Para analisar a receita, por exemplo a receita por visitante, cria outro Custom Event Goal:

  1. Dá-lhe um nome, por exemplo, «Revenue.»
  2. Insere checkout_completed como nome do evento, o mesmo que para «Purchase.»
  3. No passo 3, ativa «Track revenue» («Measure order value alongside conversions»).
  4. Clica em «Create goal.»

Adiciona os goals à tua experiência​

Depois de criados os Custom Event Goals, podes adicioná-los a uma experiência:

  1. Abre a tua experiência e vai ao separador «Goals».
  2. Clica em «+ Custom Event Goal» e seleciona o teu goal na lista, por exemplo «Purchase» ou «Revenue.»
  3. Clica em «Save Goals.»
Adicionar Revenue à Experiência

O goal aparece agora na lista, marcado como «Custom event.»

Revenue Goal adicionado à Experiência
observação

Adiciona os teus goals antes de iniciares a experiência. Goals adicionados mais tarde não são monitorizados retroativamente.