AB_TEST - A/B Testing e Experimentação
O que é este Node?
O AB_TEST é o node responsável por rastrear experimentos A/B, registrando qual variante usuário viu e se converteu, permitindo análise estatística de resultados.
Por que este Node existe?
A/B testing valida hipóteses com dados. O AB_TEST existe para:
- Test Hypotheses: Validar ideias com dados reais
- Optimize Conversion: Descobrir o que funciona melhor
- Reduce Risk: Testar antes de lançar para todos
- Statistical Significance: Resultados confiáveis estatisticamente
Como funciona internamente?
Quando o AB_TEST é executado, o sistema:
- Registra exposição: Usuário viu variante A ou B
- Rastreia conversão: Se usuário converteu
- Calcula estatísticas: Conversion rate por variante
- Determina winner: Variante com melhor performance
Código interno (analytics-executor.service.ts:474-494):
private async trackABTest(data: any, userId: string, sessionId: string, context: any): Promise<any> {
const abTest = {
type: 'a_b_test',
experimentId: data.experimentId,
experimentName: data.experimentName,
variant: data.variant,
converted: data.converted || false,
userId: userId,
sessionId: sessionId,
timestamp: new Date().toISOString()
};
await this.storeTrackingEvent(abTest);
return {
success: true,
action: 'ab_test_tracked',
data: abTest,
timestamp: abTest.timestamp
};
}
Quando você DEVE usar este Node?
Use AB_TEST para experimentação controlada:
Casos de uso
- Landing Pages: Testar headlines, CTA buttons
- Pricing: Testar diferentes preços
- Onboarding: Testar fluxos de ativação
- Features: Testar novo design/funcionalidade
- Copy: Testar mensagens marketing
Quando NÃO usar AB_TEST
- Mudanças pequenas: Não vale estatisticamente
- Pouco tráfego: Precisa de volume para significância
- Múltiplas variáveis: Use multivariate testing
Parâmetros Detalhados
experimentId (string, obrigatório)
O que é: Identificador único do experimento.
experimentName (string, obrigatório)
O que é: Nome descritivo do experimento.
variant (string, obrigatório)
O que é: Qual variante usuário viu (control, variant_a, variant_b).
converted (boolean, opcional)
O que é: Se usuário converteu após ver variante.
Flow completo para testar:
{
"name": "AB Test - CTA Button Color",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Random Variant",
"parameters": {
"name": "variant",
"value": "{{$random(['control', 'variant_a'])}}"
}
}
},
{
"id": "tracking_1",
"type": "tracking",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Track Exposure",
"parameters": {
"trackingType": "a_b_test",
"data": {
"experimentId": "exp_button_color_001",
"experimentName": "CTA Button Color Test",
"variant": "{{variant}}",
"converted": false
}
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Check Variant",
"parameters": {
"variable": "variant",
"operator": "equals",
"value": "control"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 900, "y": 50 },
"data": {
"label": "Control: Blue Button",
"parameters": {
"message": "🔵 Clique aqui (azul)"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 900, "y": 150 },
"data": {
"label": "Variant A: Red Button",
"parameters": {
"message": "🔴 Clique aqui (vermelho)"
}
}
},
{
"id": "input_1",
"type": "input",
"position": { "x": 1100, "y": 100 },
"data": {
"label": "User Action",
"parameters": {
"message": "Digite SIM se clicou",
"variable": "clicked"
}
}
},
{
"id": "tracking_2",
"type": "tracking",
"position": { "x": 1300, "y": 100 },
"data": {
"label": "Track Conversion",
"parameters": {
"trackingType": "a_b_test",
"data": {
"experimentId": "exp_button_color_001",
"experimentName": "CTA Button Color Test",
"variant": "{{variant}}",
"converted": true
}
}
}
},
{
"id": "message_3",
"type": "message",
"position": { "x": 1500, "y": 100 },
"data": {
"label": "Result",
"parameters": {
"message": "✅ Teste registrado!\n\nVariante: {{variant}}\nClicou: SIM"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "variable_1" },
{ "source": "variable_1", "target": "tracking_1" },
{ "source": "tracking_1", "target": "condition_1" },
{ "source": "condition_1", "target": "message_1", "label": "true" },
{ "source": "condition_1", "target": "message_2", "label": "false" },
{ "source": "message_1", "target": "input_1" },
{ "source": "message_2", "target": "input_1" },
{ "source": "input_1", "target": "tracking_2" },
{ "source": "tracking_2", "target": "message_3" },
{ "source": "message_3", "target": "end_1" }
]
}
Teste: Execute várias vezes. Metade vê botão azul, metade vermelho. Sistema rastreia qual converte mais.
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| trackingType | string | Sim | Deve ser "a_b_test" |
| experimentId | string | Sim | ID único do experimento |
| experimentName | string | Sim | Nome descritivo |
| variant | string | Sim | control, variant_a, variant_b |
| converted | boolean | Não | Se usuário converteu |
Exemplo: Pricing Test
Objetivo: Testar se preço de R$ 97 ou R$ 197 converte melhor.
{
"name": "AB Test - Pricing",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Assign Price",
"parameters": {
"name": "price_variant",
"value": "{{$random(['price_97', 'price_197'])}}"
}
}
},
{
"id": "tracking_1",
"type": "tracking",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Track Price Shown",
"parameters": {
"trackingType": "a_b_test",
"data": {
"experimentId": "exp_pricing_001",
"experimentName": "Pricing Test",
"variant": "{{price_variant}}"
}
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Check Price",
"parameters": {
"variable": "price_variant",
"operator": "equals",
"value": "price_97"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 900, "y": 50 },
"data": {
"label": "Offer R$ 97",
"parameters": {
"message": "💰 Curso por R$ 97\n\nDeseja comprar?"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 900, "y": 150 },
"data": {
"label": "Offer R$ 197",
"parameters": {
"message": "💰 Curso por R$ 197\n\nDeseja comprar?"
}
}
},
{
"id": "input_1",
"type": "input",
"position": { "x": 1100, "y": 100 },
"data": {
"label": "Response",
"parameters": {
"message": "Digite SIM ou NÃO",
"variable": "response"
}
}
},
{
"id": "condition_2",
"type": "condition",
"position": { "x": 1300, "y": 100 },
"data": {
"label": "Check Purchase",
"parameters": {
"variable": "response",
"operator": "equals",
"value": "SIM"
}
}
},
{
"id": "tracking_2",
"type": "tracking",
"position": { "x": 1500, "y": 100 },
"data": {
"label": "Track Conversion",
"parameters": {
"trackingType": "a_b_test",
"data": {
"experimentId": "exp_pricing_001",
"experimentName": "Pricing Test",
"variant": "{{price_variant}}",
"converted": true
}
}
}
},
{
"id": "message_3",
"type": "message",
"position": { "x": 1700, "y": 100 },
"data": {
"label": "Success",
"parameters": {
"message": "✅ Compra confirmada!\n\nPreço testado: {{price_variant}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "variable_1" },
{ "source": "variable_1", "target": "tracking_1" },
{ "source": "tracking_1", "target": "condition_1" },
{ "source": "condition_1", "target": "message_1", "label": "true" },
{ "source": "condition_1", "target": "message_2", "label": "false" },
{ "source": "message_1", "target": "input_1" },
{ "source": "message_2", "target": "input_1" },
{ "source": "input_1", "target": "condition_2" },
{ "source": "condition_2", "target": "tracking_2", "label": "true" },
{ "source": "condition_2", "target": "end_1", "label": "false" },
{ "source": "tracking_2", "target": "message_3" },
{ "source": "message_3", "target": "end_1" }
]
}
Saída esperada:
Sistema: 💰 Curso por R$ 97. Deseja comprar?
Usuário: SIM
Sistema: ✅ Compra confirmada! Preço testado: price_97
Resposta do Node
{
"success": true,
"action": "ab_test_tracked",
"data": {
"type": "a_b_test",
"experimentId": "exp_pricing_001",
"experimentName": "Pricing Test",
"variant": "price_97",
"converted": true,
"userId": "user_123",
"sessionId": "session_456",
"timestamp": "2025-01-15T10:30:00.000Z"
},
"timestamp": "2025-01-15T10:30:00.000Z"
}
Análise de Resultados
Calcular Conversion Rate
Control (R$ 97):
- Exposures: 500
- Conversions: 100
- Conversion Rate: 20%
Variant A (R$ 197):
- Exposures: 500
- Conversions: 75
- Conversion Rate: 15%
Winner: Control (R$ 97) - 20% vs 15%
Statistical Significance
Use chi-square test ou t-test para validar se diferença é estatisticamente significante (p-value < 0.05).
Sample Size Calculator
Para 95% confiança e 80% power: - Baseline: 10% conversion - Esperado: 12% conversion - Sample size: ~3,800 por variante
Boas Práticas
✅ SIM: - Calcule sample size necessário antes - Rode experimento até atingir significância estatística - Teste uma variável por vez - Use 50/50 split para máximo power - Documente hipótese antes de iniciar
❌ NÃO: - Não pare experimento cedo (mesmo se winning) - Não teste múltiplas variáveis simultaneamente - Não mude experimento durante execução - Não ignore significância estatística
Dicas
💡 Dica 1: Use calculadoras online de sample size (Optimizely, VWO) 💡 Dica 2: Rode por no mínimo 1-2 semanas para capturar padrões semanais 💡 Dica 3: Monitore external validity (resultados se mantêm pós-teste?) 💡 Dica 4: Combine com FEATURE_FLAG para progressive rollout 💡 Dica 5: Use Bayesian A/B testing para resultados mais rápidos
Próximo Node
→ FEATURE_FLAG - Feature flags para rollout controlado → COHORT - Análise por cohort → CONVERSION - Track conversions