Skip to main content

Debug Mode

A primeira ferramenta para troubleshooting é ativar o modo debug.
<TestlyProvider 
  apiKey="tk_live_..."
  config={{ debug: true }}
>
Com debug: true você verá logs como:
[Testly] ✅ Conversion recorded for homepage-hero-test
[Testly] ❌ API ERROR: Failed to track impression. Status: 401
[Testly] ❌ TRACKING BLOCKED: Missing critical IDs for experiment "my-test"
Sempre desenvolva com debug: true. Desative em produção para não poluir o console dos usuários.

Problemas Comuns

1. variant retorna null — causa mais comum

Sintoma:
const { variant } = useExperiment('meu-experimento');
console.log(variant); // null
A causa número 1 é mismatch entre a API Key e a organização onde o experimento foi criado. O SDK envia sua API Key para o servidor, que busca o experimento dentro daquela organização. Se você usar a key de uma conta diferente, o servidor não encontra o experimento e retorna null. Checklist:
Como verificar:
  1. Abra app.testly.com.br/settings → copie a API Key (tk_live_...)
  2. Confirme que exatamente essa key está no TestlyProvider do seu app
  3. Confirme que o experimento está listado no dashboard da mesma conta
Ative o debug e inspecione a resposta do servidor:
<TestlyProvider apiKey="..." config={{ debug: true }}>
O slug (identificador) usado em useExperiment() deve ser idêntico ao slug exibido no dashboard — case-sensitive, apenas letras minúsculas e hífens.
// ✅ Correto — exatamente como aparece no dashboard
useExperiment('homepage-hero-test')

// ❌ Errado
useExperiment('homepage-hero')        // slug diferente
useExperiment('Homepage-Hero-Test')   // case errado
useExperiment('homepage_hero_test')   // underscore em vez de hífen
O servidor só retorna variante para experimentos com status running. Se o experimento foi pausado, concluído ou arquivado, o retorno é null.Solução: Verifique o status no dashboard e ative o experimento se necessário.
// ✅ Correto
<TestlyProvider apiKey="...">
  <App>
    <MeuComponente /> {/* pode usar useExperiment */}
  </App>
</TestlyProvider>

// ❌ Errado
<App>
  <MeuComponente /> {/* NÃO pode usar useExperiment */}
  <TestlyProvider apiKey="...">...</TestlyProvider>
</App>

2. Loading nunca termina

Sintoma:
const { loading } = useExperiment('test');
console.log(loading); // sempre true
Diagnóstico:
const { variant, loading, error } = useExperiment('test');

useEffect(() => {
  console.log('variant:', variant, '| loading:', loading, '| error:', error);
}, [variant, loading, error]);
Causas e soluções:
Abra DevTools → Network → Procure por chamadas para supabase.co/functions/v1/get-variant.Possíveis problemas:
  • Request bloqueado por CORS ou firewall
  • Timeout (resposta muito lenta)
Se a request estiver falhando, verifique o erro em error e entre em contato: suporte@testly.com.br
A API Key deve ter o formato tk_live_.... Se estiver em formato diferente ou vazia, o servidor rejeita a request antes de responder.
// ✅ Formato correto
apiKey="tk_live_abc123..."

// ❌ Formatos errados
apiKey=""
apiKey="undefined"
apiKey={process.env.TESTLY_API_KEY} // sem prefixo VITE_ ou NEXT_PUBLIC_

3. Conversões não são registradas

Sintoma: convert() é chamado mas o dashboard não mostra os dados. Diagnóstico:
const { convert } = useExperiment('test');

const handleClick = async () => {
  try {
    await convert('cta_clicked');
    console.log('✅ Conversão registrada!');
  } catch (err) {
    console.error('❌ Erro:', err);
  }
};
Causas:
Por padrão, o SDK deduplicata conversões: a mesma conversão para o mesmo experimento só é registrada uma vez por sessão.
convert('cta_clicked'); // ✅ Registrada
convert('cta_clicked'); // ❌ Ignorada (dedupe)
Para testar sem dedupe, limpe o localStorage e recarregue a página, ou desative temporariamente:
<TestlyProvider config={{ dedupConversions: false }}>
// ✅ Bom — snake_case, descritivo
convert('cta_clicked')
convert('form_submitted')
convert('trial_started')

// ❌ Ruim
convert('')                           // vazio
convert('Botão Clicado!!!')           // caracteres especiais
Conversões só são contabilizadas se o usuário teve uma impressão registrada antes. A impressão é automática — mas ocorre apenas quando loading termina.Certifique-se de que o componente está renderizando o useExperiment antes de chamar convert:
const { variant, loading, convert } = useExperiment('test');

if (loading) return <Skeleton />;
// Aqui loading=false, impressão já foi registrada

return <button onClick={() => convert('clicked')}>...</button>;

4. Variante muda a cada refresh

Isso não deveria acontecer. O SDK usa cache local para manter consistência.
Procure no seu código por:
localStorage.clear(); // ❌ Remove cache do Testly
Se precisar limpar seu próprio storage, remova chaves específicas:
localStorage.removeItem('minha-chave'); // ✅ Específico
// ❌ Ruim — userId muda a cada render
const { variant } = useExperiment('test', {
  userId: Math.random().toString()
});

// ✅ Bom — userId estável
const { variant } = useExperiment('test', {
  userId: user?.id || 'anonymous'
});

5. Erro: “useExperiment must be used within TestlyProvider”

// ❌ Errado — hook fora do Provider
function App() {
  const { variant } = useExperiment('test'); // Erro!
  return (
    <TestlyProvider apiKey="...">
      <Component />
    </TestlyProvider>
  );
}

// ✅ Correto — hook dentro do Provider
function App() {
  return (
    <TestlyProvider apiKey="...">
      <Component />
    </TestlyProvider>
  );
}

function Component() {
  const { variant } = useExperiment('test'); // OK
  return <div>{variant}</div>;
}

6. TypeScript: Tipos não reconhecidos

Cannot find module '@testlyjs/react' or its corresponding type declarations
Soluções:
rm -rf node_modules package-lock.json
npm install
tsconfig.json
{
  "compilerOptions": {
    "moduleResolution": "node",
    "esModuleInterop": true,
    "skipLibCheck": true
  }
}

Verificar Requests no DevTools

Abra DevTools → Network e procure por chamadas para supabase.co/functions/v1/. get-variant — atribuição de variante:
GET .../functions/v1/get-variant?experiment_key=...&user_id=...&apikey=tk_live_...

Resposta esperada:
{ "variant_key": "control", "variant_id": "...", "experiment_id": "..." }

Resposta quando algo está errado:
{ "variant_key": null, "reason": "experiment_not_running" }  → API key ou org errada
{ "error": "Invalid API Key" }                                → key inválida
track-event — impressões e conversões:
POST .../functions/v1/track-event

Resposta esperada: { "success": true }

Casos Especiais

Next.js: Hydration Mismatch

Sintoma:
Warning: Text content did not match. Server: "control" Client: "variant-b"
Solução:
'use client';

function MeuComponente() {
  const { variant, loading } = useExperiment('test');
  const [mounted, setMounted] = useState(false);

  useEffect(() => { setMounted(true); }, []);

  if (!mounted || loading) return <Skeleton />;

  return <div>{variant}</div>;
}

React Strict Mode (Logs duplicados)

Em desenvolvimento com Strict Mode, componentes renderizam duas vezes — logs [Testly] podem aparecer duplicados. Isso é esperado e não afeta produção.

Checklist de Troubleshooting

1

Ativar debug mode

config={{ debug: true }} e recarregar a página
2

Verificar console

Procure por erros vermelhos ou logs [Testly]
3

Verificar Network tab

Há requests para supabase.co/functions/v1/get-variant? Qual a resposta?
4

Verificar API Key

A key no TestlyProvider é a mesma que está em Settings → API Key?
5

Verificar o experimento

Está em status running no dashboard? O slug é idêntico?
6

Limpar cache

localStorage.clear(); location.reload();
7

Testar em aba anônima

Elimina problemas de cache e extensões do browser

Precisa de Ajuda?

Email

suporte@testly.com.br — respondemos rápido

Documentação

Guia rápido de 5 minutos
Ao pedir ajuda, inclua:
  • Versão do SDK (npm list @testlyjs/react)
  • Framework (Next.js, Vite, etc.)
  • Logs do debug mode
  • Screenshot do Network tab
  • Código relevante (remova a API Key!)