Visão Geral
CTAs são os elementos mais testados em qualquer produto — pequenas mudanças de texto ou cor podem ter grande impacto:
✅ Impacto direto na taxa de conversão
✅ Simples de implementar e medir
✅ Resultados rápidos (tráfego concentrado no elemento)
Neste guia, você aprenderá a testar:
Texto do botão
Cor e estilo
Formulários de captura de lead
Exemplo 1: Texto do Botão
O texto é o fator que mais impacta a taxa de clique em CTAs.
Criar o experimento no dashboard
Acesse o dashboard do Testly
Clique em “Novo Experimento”
Nome: cta-button-text
Variantes:
Controle : “Começar Grátis”
Variante B : “Criar Minha Conta”
Variante C : “Experimentar por 14 Dias”
Implementação
'use client' ;
import { useExperiment } from '@testlyjs/react' ;
interface CTAButtonProps {
destination ?: string ;
className ?: string ;
}
export function CTAButton ({ destination = '/signup' , className = '' } : CTAButtonProps ) {
const { variant , loading , convert } = useExperiment ( 'cta-button-text' );
if ( loading ) {
return (
< div className = { `h-12 bg-gray-200 rounded-lg animate-pulse ${ className } ` } />
);
}
const labels = {
'control' : 'Começar Grátis' ,
'variant-b' : 'Criar Minha Conta' ,
'variant-c' : 'Experimentar por 14 Dias' ,
};
const handleClick = () => {
convert ( 'cta_button_clicked' );
window . location . href = destination ;
};
return (
< button
onClick = { handleClick }
className = { `bg-blue-600 hover:bg-blue-700 text-white px-8 py-3 rounded-lg font-semibold transition-colors ${ className } ` }
>
{ labels [ variant as keyof typeof labels ] || labels . control }
</ button >
);
}
Use o mesmo componente <CTAButton> em múltiplos lugares da página — todos exibirão a mesma variante para o mesmo usuário (atribuição é determinística por userId).
Exemplo 2: Cor do Botão
Cor tem impacto menor que texto, mas ainda vale testar em páginas de alto tráfego.
components/CTAButtonColor.tsx
'use client' ;
import { useExperiment } from '@testlyjs/react' ;
export function CTAButtonColor () {
const { variant , convert } = useExperiment ( 'cta-button-color' );
const colorStyles = {
'control' : 'bg-blue-600 hover:bg-blue-700' ,
'variant-b' : 'bg-green-600 hover:bg-green-700' ,
'variant-c' : 'bg-orange-600 hover:bg-orange-700' ,
};
const handleClick = () => {
convert ( 'cta_clicked' );
window . location . href = '/signup' ;
};
return (
< button
onClick = { handleClick }
className = { `text-white px-8 py-3 rounded-lg font-semibold transition-colors ${
colorStyles [ variant as keyof typeof colorStyles ] || colorStyles . control
} ` }
>
Começar Grátis
</ button >
);
}
Isolamento : Teste cor e texto em experimentos separados. Misturar variáveis dificulta saber qual fator causou a diferença.
Testar campos do formulário de signup para reduzir fricção.
components/SignupForm.tsx
'use client' ;
import { useState } from 'react' ;
import { useExperiment } from '@testlyjs/react' ;
export function SignupForm () {
const { variant , convert } = useExperiment ( 'signup-form-fields' );
const [ email , setEmail ] = useState ( '' );
const [ name , setName ] = useState ( '' );
// Controle: pede email + nome
// Variante B: pede só email (menos fricção)
const isMinimalForm = variant === 'variant-b' ;
const handleSubmit = async ( e : React . FormEvent ) => {
e . preventDefault ();
convert ( 'form_submitted' );
const payload = isMinimalForm ? { email } : { email , name };
await fetch ( '/api/signup' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ( payload ),
});
};
return (
< form onSubmit = { handleSubmit } className = "flex flex-col gap-4 max-w-sm mx-auto" >
{ ! isMinimalForm && (
< input
type = "text"
placeholder = "Seu nome"
value = { name }
onChange = { ( e ) => setName ( e . target . value ) }
className = "px-4 py-3 rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
) }
< input
type = "email"
placeholder = "Seu email"
required
value = { email }
onChange = { ( e ) => setEmail ( e . target . value ) }
className = "px-4 py-3 rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
< button
type = "submit"
className = "bg-blue-600 hover:bg-blue-700 text-white py-3 rounded-lg font-semibold"
>
Criar Conta Grátis
</ button >
</ form >
);
}
Formulários com menos campos convertem mais, mas podem capturar dados de menor qualidade. Meça a qualidade do lead (ativação, retenção) além da taxa de cadastro.
Testar se elementos de urgência aumentam conversões.
components/UrgencyCTA.tsx
'use client' ;
import { useExperiment } from '@testlyjs/react' ;
export function UrgencyCTA () {
const { variant , convert } = useExperiment ( 'cta-urgency' );
const handleClick = () => {
convert ( 'urgency_cta_clicked' );
window . location . href = '/signup' ;
};
return (
< div className = "text-center" >
< button
onClick = { handleClick }
className = "bg-blue-600 hover:bg-blue-700 text-white px-8 py-4 rounded-lg font-semibold text-lg"
>
Começar Grátis
</ button >
{ /* Texto de suporte — testado na Variante B */ }
{ variant === 'variant-b' && (
< p className = "mt-3 text-sm text-gray-500" >
⚡ Setup em 5 minutos · Sem cartão de crédito · Cancele quando quiser
</ p >
) }
{ variant === 'variant-c' && (
< p className = "mt-3 text-sm text-orange-600 font-medium" >
🔥 Últimas vagas no plano gratuito — oferta por tempo limitado
</ p >
) }
</ div >
);
}
Urgência falsa (escassez fabricada) pode aumentar conversão no curto prazo, mas prejudica confiança. Prefira urgência real ou ressaltar benefícios genuínos.
Rastreando Múltiplos CTAs
Se a mesma página tem vários CTAs (header, meio, footer), use conversion_type para distinguir:
// Header CTA
const handleHeaderCTA = () => {
convert ( 'cta_clicked_header' );
};
// Footer CTA
const handleFooterCTA = () => {
convert ( 'cta_clicked_footer' );
};
Isso permite ver qual posição converte melhor dentro do mesmo experimento.
Próximos Passos
Hero Section Teste títulos e layouts de hero
Pricing Page Teste estruturas de preço
Onboarding Flow Melhore a experiência de onboarding
Boas Práticas Metodologias de experimentação