Experimentação A/B
Pro FeatureDefina um experimento no painel, integre uma linha de JavaScript no seu site e o Zenovay atribui de forma determinística uma variante a cada visitante e reporta as taxas de conversão por variante junto com um intervalo de confiança de 95 % sobre o ganho em relação à variante de controle.
A experimentação A/B está disponível nos planos Pro, Scale e Enterprise. Atualize seu plano para habilitar este recurso.
Como funciona
A atribuição do visitante é calculada localmente pelo tracker usando um hash determinístico do ID do visitante, de modo que o mesmo visitante sempre vê a mesma variante — inclusive após recarregar a página e (quando os cookies estão habilitados) entre sessões. No modo cookieless (padrão para sites que carregam o tracker com data-cookieless="true"), a atribuição é restrita à janela e é redefinida quando a aba é fechada.
Configurar um experimento
- No painel, abra seu site → aba Experiments → New experiment.
- Dê um nome ao experimento, descreva opcionalmente uma hipótese e escolha um objetivo entre seus objetivos personalizados existentes.
- Adicione 2 a N variantes, marque uma como controle e defina uma porcentagem de divisão de tráfego por variante.
- Salve como rascunho e clique em Launch quando estiver pronto.
Embed do código
const variant = window.zenovay('experiment', 'checkout-cta-color', ['control', 'green', 'orange']);
if (variant === 'green') document.querySelector('.cta').style.background = '#22c55e';
if (variant === 'orange') document.querySelector('.cta').style.background = '#f97316';
Essa é toda a integração no lado do cliente. O tracker cuida automaticamente da atribuição, do log de exposições e da atribuição de conversões — quando o visitante posteriormente disparar o objetivo alvo (por meio da sua chamada existente de rastreamento de objetivos), o Zenovay atribui a conversão à variante que ele recebeu.
A chamada window.zenovay('experiment', …) é idempotente — chamá-la várias vezes na mesma página retorna a mesma variante e registra no máximo uma exposição por visitante, por experimento e por sessão. Passe sempre o mesmo array variants na mesma ordem em todas as páginas; a ordem faz parte do hash determinístico.
Exemplos por framework
O snippet acima é JavaScript puro e roda em qualquer ambiente de navegador. Abaixo estão padrões específicos para as stacks mais comuns.
HTML puro
Cole isto em qualquer lugar abaixo da tag <script> do tracker do Zenovay:
<button class="cta">Buy now</button>
<script>
// Wait for the tracker to load (it sets window.zenovay on init).
function applyVariant() {
if (!window.zenovay) { setTimeout(applyVariant, 50); return; }
var variant = window.zenovay('experiment', 'checkout-cta-color', ['control', 'green', 'orange']);
var cta = document.querySelector('.cta');
if (variant === 'green') cta.style.background = '#22c55e';
if (variant === 'orange') cta.style.background = '#f97316';
}
applyVariant();
</script>
React / Next.js (client component)
No Next.js App Router, marque o componente com 'use client' e chame a função dentro de useEffect para que a atribuição rode depois da hidratação:
'use client';
import { useEffect, useState } from 'react';
export default function CheckoutCTA() {
const [variant, setVariant] = useState('control');
useEffect(() => {
if (typeof window === 'undefined' || !window.zenovay) return;
const v = window.zenovay('experiment', 'checkout-cta-color', ['control', 'green', 'orange']);
setVariant(v);
}, []);
const bg = variant === 'green' ? '#22c55e' : variant === 'orange' ? '#f97316' : undefined;
return <button className="cta" style={{ background: bg }}>Buy now</button>;
}
Para minimizar uma piscada da variante de controle na primeira renderização, renderize o controle por padrão e deixe o useEffect trocar para o tratamento depois do mount. A exposição é registrada na primeira chamada a window.zenovay('experiment', …).
Vue / Nuxt
Num componente <script setup>, dispare a chamada a partir de onMounted:
<script setup>
import { ref, onMounted } from 'vue';
const variant = ref('control');
onMounted(() => {
if (!window.zenovay) return;
variant.value = window.zenovay('experiment', 'checkout-cta-color', ['control', 'green', 'orange']);
});
</script>
<template>
<button
class="cta"
:style="{ background: variant === 'green' ? '#22c55e' : variant === 'orange' ? '#f97316' : null }"
>
Buy now
</button>
</template>
Server-Side Rendering (Next.js, Remix, Nuxt SSR)
A atribuição de variantes é escopada à janela — o tracker só existe no navegador, então qualquer chamada feita no servidor retorna undefined e a primeira passagem do SSR renderiza o controle. O visitante vê então brevemente a variante de tratamento depois que o useEffect do lado do cliente roda.
Dois padrões práticos:
- Aceitar a piscada do controle. Para mudanças visuais (cor, copy) normalmente não dá problema — na velocidade típica de hidratação a troca é imperceptível.
- Renderizar a variante de tratamento apenas no cliente. Envolva o bloco experimental em uma fronteira client-only para que o SSR não emita nada e o tratamento seja pintado uma única vez na hidratação. Isso elimina a piscada ao custo de um deslocamento de layout.
'use client';
import dynamic from 'next/dynamic';
const ExperimentalCTA = dynamic(() => import('./CheckoutCTA'), { ssr: false });
export default function Page() {
return <ExperimentalCTA />;
}
Não existe endpoint de atribuição no edge ou no servidor na V1.
Google Tag Manager (GTM)
Envolva a chamada em uma tag Custom HTML que dispara depois da sua tag do tracker do Zenovay, e empurre a variante para o dataLayer para que outras tags do GTM possam lê-la:
<script>
(function () {
if (!window.zenovay) return;
var variant = window.zenovay('experiment', 'checkout-cta-color', ['control', 'green', 'orange']);
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ event: 'zenovay_experiment', experiment_id: 'checkout-cta-color', variant: variant });
})();
</script>
Outras tags do GTM (por exemplo, uma tag de reescrita de CSS) podem então disparar no evento zenovay_experiment e ler {{ DLV - variant }} para aplicar a mudança visual.
Como a significância é calculada
As taxas de conversão por variante são agregadas no servidor. O painel mostra um teste z bilateral de duas proporções para cada tratamento contra o controle, com correção de Bonferroni sobre todas as comparações do experimento. Um selo "winner" aparece quando todas as condições abaixo forem verdadeiras:
- p-valor corrigido por Bonferroni < 0,05
- Ambas as variantes atingiram pelo menos o tamanho mínimo de amostra configurado (padrão: 100 visitantes por variante)
- O lift do tratamento sobre o controle é positivo
Este é um teste frequentista com tamanho de amostra fixo. Não é um teste sequencial — espiar resultados antes do experimento terminar inflaciona o erro do Tipo I.
Lendo o painel
O painel de Experiments mostra um resumo de uma linha por variante:
| Coluna | O que mostra |
|---|---|
| Visitors | Visitantes únicos atribuídos a esta variante desde o lançamento |
| Conversions | Quantos desses visitantes dispararam o objetivo alvo |
| Conversion rate | conversions / visitors por variante |
| Lift vs control | Variação relativa da taxa de conversão em relação ao controle |
| p-value | Corrigido por Bonferroni, contra o controle (a linha do controle exibe —) |
| Status | running, winner ou not significant yet |
O gráfico abaixo plota a taxa de conversão acumulada por variante ao longo do tempo, para você ver quando as variantes começaram a divergir (ou se ainda estão andando juntas).
Fluxo recomendado
- Uma mudança por experimento. Se você trocar a cor do CTA e o título ao mesmo tempo, não dá mais para saber qual deles moveu a métrica. Mantenha tudo o resto constante.
- Escolha o objetivo antes de lançar. Adicionar ou trocar o objetivo no meio do experimento invalida tudo o que foi coletado até ali — o Zenovay vai avisar e exigir um relançamento.
- Estime o tamanho de amostra necessário. Um lift de 5 % sobre uma taxa-base de 2 % normalmente precisa de cerca de 30.000 visitantes por variante para atingir significância. Use uma calculadora de tamanho de amostra antes de lançar e só lance experimentos que seu tráfego consiga terminar.
- Não fique espiando à procura de vencedores. O teste frequentista só é válido se você definir uma regra de parada antes. Olhar o painel todo dia e parar o experimento assim que um tratamento cruza p < 0,05 infla bastante a taxa de falsos positivos.
- Arquive — não apague. Quando o experimento terminar, arquive-o pelo menu. Apagar remove também as atribuições históricas que alimentam relatórios de funil ou receita a jusante.
Limites por plano
| Plano | Máx. de experimentos simultâneos | Máx. de variantes por experimento |
|---|---|---|
| Free | — (não disponível) | — |
| Pro | 5 | 4 |
| Scale | 25 | 10 |
| Enterprise | ilimitado | ilimitado |
Privacidade e conformidade
A experimentação A/B foi construída para respeitar a postura de privacidade do Zenovay:
- Modo cookieless: a atribuição de variantes é restrita à janela (apenas em memória). Nenhum cookie ou entrada em localStorage é criado.
- Os dados de atribuição de variante são incluídos na sua exportação gratuita de dados pessoais conforme o Artigo 20 do GDPR.
- A exclusão da conta cascateia por experimentos, variantes e atribuições.
- A retenção segue o nível do seu plano (Free 365 dias, Pro 730 dias, Scale 1.460 dias).
O que não está na V1
- Multi-armed bandits, amostragem de Thompson, intervalos de credibilidade bayesianos — somente frequentista.
- p-valores sequenciais / always-valid — apenas amostra fixa.
- Decisão de variante no servidor / edge — a atribuição é no cliente.
- Regras de segmentação (geo, dispositivo, apenas visitantes recorrentes) — apenas atribuição aleatória.
- Grupos de experimentos mutuamente exclusivos.
Solução de problemas
Minhas variantes sempre retornam null ou sempre retornam control
As causas mais prováveis, por frequência:
- O tracker ainda não tinha terminado de carregar quando você chamou
window.zenovay(...). A funçãowindow.zenovayé definida de forma síncrona pelo stub de carregamento, mas só se torna útil quando o bundle do tracker termina de baixar. Chamadas anteriores retornamundefined. Envolva a chamada em um pequeno loop de espera (veja o exemplo de HTML puro) ou execute-a a partir de um hook de ciclo de vida do framework que rode após o mount. - O experimento não está com status
running. O tracker só atribui variantes para experimentos com statusrunning. Rascunhos ou experimentos pausados retornam o controle. Abra a aba Experiments e verifique o badge de status. - Você passou um array de variantes diferente do configurado no painel. As variantes listadas em
window.zenovay(...)precisam bater exatamente com os slugs do painel (incluindo a ordem). Um erro de digitação como['control', 'gren']joga todos os visitantes para o controle. - Modo cookieless + fechamento de aba. Se seu site carrega o tracker com
data-cookieless="true", o ID do visitante é escopado à janela — fechar a aba e reabrir conta como novo visitante e pode cair em outra variante. É esperado e estatisticamente válido.
Nenhuma exposição é registrada após o lançamento
- O tracker não está carregado na página onde você chama
experiment(). Confira no DevTools sewindow.zenovayestá definida na página em questão. Se estiverundefined, o<script>do tracker do Zenovay não está nessa página ou ainda não foi executado. - O experimento ainda está em
draft. Clique em Launch na tela de detalhe do experimento — rascunhos não registram exposições. - Um bloqueador de anúncios está derrubando a requisição. Incomum, mas possível se você não usa domínio first-party. Migre para tracking first-party (subdomínio personalizado) se a sua audiência usa muitos bloqueadores.
A atribuição de conversão mostra 0 mesmo com exposições visíveis
- Divergência de ID de objetivo. O objetivo alvo selecionado na criação do experimento precisa ser o mesmo que seu código (ou o auto-tracking do Zenovay) realmente dispara. Confira o slug do objetivo no painel e verifique no feed em tempo real que o objetivo dispara.
- A conversão acontece antes da atribuição. Muito raro, mas possível se seu CTA dispara o objetivo já no carregamento inicial e você chama
experiment()com atraso. Chameexperiment()o quanto antes (logo após o stub do tracker). - O visitante converteu em outro navegador / dispositivo / aba diferente daquele em que foi atribuído. Em modo cookieless a atribuição não persiste entre abas — e o vínculo com a conversão também não. O visitante será contado como dois participantes distintos.
O aviso de Sample-Ratio Mismatch não some
O sample-ratio mismatch (SRM) é a diferença entre a divisão de tráfego configurada e a divisão real observada — num experimento 50/50, ver 60/40 é uma bandeira vermelha.
- Uma variante quebra. Se o JavaScript do tratamento lança uma exceção antes do visitante chegar ao funil de conversão, menos conversões serão atribuídas a ela — mas a contagem de exposições deveria continuar equilibrada. Olhe seu tracker de erros para um pico correlacionado com o lançamento.
- Tráfego de bots enviesado para um bucket. Bots que compartilham uma família de IDs de visitante (por exemplo, fazendas de crawlers com IPs não aleatórias) podem cair desproporcionalmente em uma variante. O filtro B2B/bot na aba Visitors ajuda a quantificar.
- Você lançou, editou o array de variantes e relançou. Mudar a ordem das variantes na chamada cliente depois do lançamento bagunça o hash determinístico. Sempre relance como um novo experimento quando alterar o array de variantes.
Se o SRM persistir por mais de 24 horas com tráfego saudável, pause o experimento e abra um chamado de suporte.
FAQ
Como faço um teste A/B no meu site usando o Zenovay?
Três passos: crie um objetivo a otimizar, defina um experimento com 2+ variantes na aba Experiments, e cole uma linha de JavaScript na página onde a variante deve se aplicar. O tracker do Zenovay cuida da atribuição aleatória, do log de exposições e da atribuição de conversões. O passo a passo completo está na seção "Configurar um experimento" acima.
Como adiciono o código de tracking para variantes A/B?
O tracker do Zenovay já está na sua página se você instalou o analytics. Você adiciona apenas uma linha onde a variante deve ser renderizada:
const variant = window.zenovay('experiment', 'your-experiment-id', ['control', 'treatment-a', 'treatment-b']);
Em seguida, ramifique o estilo, o copy ou o componente conforme o valor retornado. Não há SDK separado de variantes para instalar.
Como o Zenovay decide qual variante o visitante vê?
A atribuição de variante é um hash determinístico do ID do visitante módulo os pesos de divisão de tráfego configurados. O mesmo ID de visitante sempre hashea para a mesma variante de um dado experimento, então o visitante tem uma experiência consistente entre carregamentos de página e (se cookies estão habilitados) entre sessões.
Por que minha atribuição de variante está vazia ou null?
A causa mais comum é chamar window.zenovay('experiment', …) antes do tracker terminar de carregar. A função é definida imediatamente, mas só retorna uma variante real depois do bundle ser resolvido. Envolva a chamada em um hook do ciclo de vida do framework (useEffect, onMounted) ou um pequeno setTimeout. Veja a seção de Solução de problemas para a lista completa.
Como verifico a significância estatística?
Abra a página de detalhe do experimento. Cada linha de tratamento mostra um p-valor corrigido por Bonferroni em comparação com o controle. Um badge winner verde aparece quando o p-valor está abaixo de 0,05, ambas as variantes têm pelo menos 100 visitantes e o lift do tratamento sobre o controle é positivo.
Quando devo encerrar meu experimento?
Defina uma regra de parada antes de lançar: ou um orçamento fixo de visitas (por exemplo, "encerrar em 30.000 visitantes por variante"), ou uma data fixa. Encerre o experimento quando essa regra for cumprida, independentemente do que o painel mostrar. Parar antes porque um tratamento "parece vencedor" infla bastante a taxa de falso positivo.
O que acontece se eu bater o limite do meu plano (por exemplo 5/5 no Pro)?
Você não consegue lançar um novo experimento até arquivar um existente. Rascunhos não contam para o limite — só experimentos com status running. Experimentos arquivados mantêm as atribuições e o histórico de conversões; eles só param de contar para o limite simultâneo.
Como clono um experimento ou rodo um de novo com outro copy?
Abra o experimento original, clique no ícone de menu (⋯) e escolha Clone. O novo experimento herda o objetivo, a lista de variantes e a divisão de tráfego — edite o que precisar e clique em Launch. O experimento clonado recebe um ID próprio, então os visitantes são reatribuídos de forma independente do original.
Posso editar um experimento depois de lançar?
Apenas experimentos com status draft são totalmente editáveis. Depois de clicar em Launch, o experimento fica travado: você pode pausar, arquivar ou encerrar, mas não pode mais mudar variantes, divisão de tráfego ou objetivo alvo sem invalidar a rodada. Se precisar mudar algo, encerre o experimento e clone.
Como conversões são atribuídas a uma variante?
A atribuição é automática. Quando um visitante dispara o objetivo alvo (via auto-tracking do Zenovay ou sua chamada window.zenovay('event', 'goal-slug')), o Zenovay procura a variante atribuída ao visitante nos experimentos em execução e credita a conversão lá. Nenhum código de atribuição manual é necessário.
O que é a correção de Bonferroni e por que meu plano Pro usa?
Ao comparar vários tratamentos contra um controle, aplicar ingenuamente um limiar único de p < 0,05 para cada comparação infla a chance de falso positivo (o efeito "look-elsewhere"). A correção de Bonferroni divide o limiar pelo número de comparações — num experimento com três tratamentos contra um controle, cada comparação precisa atingir p < 0,05 / 3 ≈ 0,017. Todo plano do Zenovay que suporta A/B testing aplica Bonferroni; não é exclusividade do Pro, é nossa forma padrão de reportar resultados em todos os tiers pagos.
O que é SRM e quando devo me preocupar?
Sample-Ratio Mismatch (SRM) é o desvio entre a divisão de tráfego configurada e a divisão real observada. Num experimento 50/50, 50,3/49,7 está ok, mas 60/40 com amostras saudáveis sinaliza um bug de deploy ou de atribuição. Preocupe-se quando o desvio passar de ~5 pontos percentuais em relação ao alvo após os primeiros ~10.000 visitantes. O painel sinaliza isso automaticamente.
Modo cookieless + testes A/B — funciona?
Sim. O hash determinístico usa o ID de visitante configurado no tracker — um ID de cookie estável quando cookies estão habilitados, ou um ID em memória escopado à janela em modo cookieless. O modelo estatístico não muda; a única diferença prática é que um visitante cookieless que fecha e reabre a aba é atribuído de forma independente a cada vez. Isso é normal e não invalida o experimento.
Próximos passos
- Objetivos – Defina os eventos que seu experimento vai medir
- Funis de conversão – Acompanhe trajetos de conversão em várias etapas
- Conversion Incidents – Receba alertas quando o objetivo alvo de um experimento despencar