Smartflow
O Smartflow é o funnel de cadastro/KYC embutido do SDK Zarv. Sua configuração é imperativa: você chama Zarv('smartflow', config), que monta o funnel como um iframe na sua página.
🎮 Abrir o playground interativo → — teste tela única, prefill, identify, complete, tema e modal ao vivo, com a versão atual do SDK.
Configuração básica
<div id="zarv-smartflow"></div>
<script async src="https://js.zarv.com/sdk.js"></script>
<script>
Zarv('smartflow', {
publicKey: 'pk-XXXXXXXX', // a chave pública do flow (admin Zarv)
mount: '#zarv-smartflow', // embed inline; ou mode: 'modal'
onComplete: ({ leadId }) => console.log('finalizou', leadId),
onDecision: ({ leadId, status }) => console.log('decisão', status), // approved | rejected | manual
});
</script>O campo publicKey é obrigatório: é a chave pública do flow, no formato pk-<id>, obtida no admin Zarv (aba Avançado da campanha). Ela pode ser regenerada no admin — ao regenerar, a chave antiga para de funcionar imediatamente e qualquer embed que ainda a use deixa de carregar até você atualizar o snippet.
Opções de configuração
| Campo | Tipo | Descrição |
|---|---|---|
publicKey | string | Obrigatório. Chave pública do flow (pk-<id>) do admin. |
mount | string | Seletor CSS do elemento onde o funnel é embutido inline. |
mode | 'inline' | 'modal' | Forma de exibição: embutido na página ou em modal centralizada. |
height | number | Altura, em px, do embed inline. Por padrão há auto-resize ao conteúdo. |
modal | { width?, height?, margin? } | Ajustes da modal. A modal é sempre centralizada; por padrão ajusta à altura do conteúdo (auto-resize). height fixa a altura. |
screen | 'face' | 'cnh' | 'address' | 'email' | 'phone' | Embute UMA tela isolada em vez do fluxo inteiro. Omita para o fluxo completo. |
leadId | string | Usa um lead existente. Omita para iniciar uma auto-sessão (um lead é criado automaticamente). |
prefill | { name?, nationalId?, birthDate? } | Persiste dados de identidade no lead, preenchendo a próxima tela. |
theme | 'light' | 'dark' | 'auto' | Tema da interface. |
closeOnComplete | boolean | Fecha a modal ao finalizar. Default: true em mode: 'modal', false inline. Com onDecision registrado, o fechamento automático espera a decisão (fechar antes derrubaria o iframe que a acompanha). |
onStep | function | Callback onStep(step, { progress, leadId }) a cada passo. |
onProgress | function | Callback onProgress(progress) com o progresso do funnel. |
onComplete | function | Callback onComplete({ leadId, status? }) ao concluir o fluxo. Dispara uma vez; status vem preenchido quando a decisão já é conhecida nesse momento. |
onDecision | function | Callback onDecision({ leadId, status }) quando a decisão da verificação chega: approved, rejected ou manual. Veja Fim do fluxo. |
onClose | function | Callback onClose() quando a modal é dispensada pelo usuário. |
Posicionamento
Você pode embutir o funnel inline na página ou exibi-lo em uma modal.
Inline — informe mount com o seletor do elemento alvo (ou use mode: 'inline'). Por padrão o iframe faz auto-resize, acompanhando a altura do conteúdo; use height para fixar uma altura em px:
Zarv('smartflow', {
publicKey: 'pk-XXXXXXXX',
mount: '#zarv-smartflow',
// height: 640, // opcional; sem isso, auto-resize ao conteúdo
});Modal — use mode: 'modal'. A modal é sempre centralizada e, por padrão, ajusta à altura do conteúdo da tela (auto-resize). Use modal para ajustar largura, altura e margem:
Zarv('smartflow', {
publicKey: 'pk-XXXXXXXX',
mode: 'modal',
modal: { width: 480, margin: 24 }, // height fixa a altura, se informado
onClose: () => console.log('modal fechada'),
});modalSteps — mesmo embutido inline, você pode promover telas específicas (ex.: liveness / captura de documento) para uma modal overlay, listando os nomes das etapas:
Zarv('smartflow', {
publicKey: 'pk-XXXXXXXX',
mount: '#zarv-smartflow',
modalSteps: ['face', 'cnh'], // essas etapas abrem em modal; as demais ficam inline
});Tela única (componentes isolados)
Use screen para embutir uma única tela em vez do fluxo inteiro:
Zarv('smartflow', {
publicKey: 'pk-XXXXXXXX',
mount: '#zarv-smartflow',
screen: 'face',
onComplete: ({ leadId }) => console.log('face concluída', leadId),
});Valores possíveis: 'face', 'cnh', 'address', 'email', 'phone'. Omita screen para rodar o fluxo inteiro.
As telas são chamadas de forma independente — elas não seguem a ordem do fluxo. Ao concluir uma tela, o SDK dispara onComplete para que você trate o próximo passo do seu lado. A ordem do funnel é respeitada apenas pela versão hosted, não pelo SDK.
Fim do fluxo: onComplete e onDecision
Dois momentos distintos encerram um cadastro embutido:
onComplete({ leadId, status? })— o visitante chegou à tela final do funnel. A verificação (face, CNH, risco) pode ainda estar rodando; nesse casostatusvem ausente. Dispara uma única vez.onDecision({ leadId, status })— a decisão da verificação foi tomada:approved,rejectedoumanual(revisão humana). Se a decisão já era conhecida quando o visitante chegou à tela final, dispara imediatamente após oonComplete; caso contrário, dispara assim que o backend decide (o funnel acompanha por polling e avisa o SDK).
Quem decide o que acontece no fim é você: redirecionar a própria página, fechar a modal, mostrar UI própria. Sem handler, o funnel mostra a tela de resultado dentro do iframe (ou redireciona para as URLs de resultado configuradas na campanha, quando existirem).
Zarv('smartflow', {
publicKey: 'pk-XXXXXXXX',
mode: 'modal',
onDecision: ({ leadId, status }) => {
if (status === 'approved') location.href = '/bem-vindo';
else if (status === 'manual') mostrarBannerEmAnalise();
else location.href = '/nao-aprovado';
},
});Notas:
- Em
mode: 'modal'comonDecisionregistrado, ocloseOnCompleteespera a decisão para fechar — fechar noonCompletederrubaria o iframe cujo polling é a fonte da decisão. - O
onDecisioné o sinal de UX no browser; o canal autoritativo server-side continua sendo o webhook da campanha (use-o para efeitos de negócio, não o callback). - Com o autopilot desligado na campanha, todo cadastro finaliza como
manual— a aprovação/reprovação acontece depois, pela análise humana, e chega via webhook.
Contexto do lead
Para continuar um cadastro já iniciado, passe leadId com um lead existente. Se você omitir leadId, o SDK inicia uma auto-sessão e cria um lead automaticamente — o leadId resultante é entregue nos callbacks (por exemplo, em onComplete({ leadId })).
Prefill de identidade
Use prefill para persistir dados de identidade no lead, preenchendo a próxima tela:
Zarv('smartflow', {
publicKey: 'pk-XXXXXXXX',
mount: '#zarv-smartflow',
prefill: { name: 'Ana', nationalId: '...', birthDate: '1990-01-02' },
});Identify em runtime
Depois de iniciar uma sessão (mesmo sem leadId), você pode identificar o usuário e anexar o seu próprio externalId:
Zarv('smartflow', {
action: 'identify',
externalId: 'id-do-parceiro-123',
name: 'Ana', nationalId: '...', birthDate: '1990-01-02',
});Essa chamada atualiza o lead da sessão ativa: ela preenche apenas os campos que ainda estão vazios, enquanto o externalId é sempre setado. Assim, a próxima tela já vem preenchida com os dados informados.
Complete em runtime
Quando o seu fluxo termina, chame complete para finalizar o cadastro: ele anexa metadados que você coletou no seu lado e dispara a verificação do usuário na sessão ativa.
Zarv('smartflow', {
action: 'complete',
metadata: { pedido: 'ABC-123', plano: 'pro' }, // anexado em metadata.custom no lead
onComplete: ({ leadId, status }) => {
// verificação disparada (a decisão chega depois via webhook da campanha)
},
onError: (err) => {
if (err.error === 'basic_data_incomplete') {
// o usuário ainda não informou os dados básicos (nome / CPF / nascimento)
}
},
});| Campo | Tipo | Descrição |
|---|---|---|
action | 'complete' | Obrigatório. |
metadata | object | Metadados adicionais do seu fluxo; persistidos sob metadata.custom no lead (vão também no webhook). |
onComplete | ({ leadId, status }) => void | Disparado quando a verificação é acionada com sucesso. |
onError | ({ error, status }) => void | Disparado em erro. |
Comportamento:
- Se o usuário não finalizou os dados básicos (
IsBasicDataCompletedé falso), ocompleteretorna errobasic_data_incomplete(HTTP 422) noonError— nada é publicado. - A verificação é disparada conforme o estado do lead (ex.: após o face capture, a re-validação de liveness/face no ZarvID). É idempotente: um lead que já está em verificação/decidido não é re-enfileirado.
- A decisão final (aprovado / em revisão / reprovado) não volta por este
onComplete— ela chega de forma assíncrona pelo webhook da campanha e, no browser, pelo callbackonDecisiondo mount.
Identificação do SDK
O SDK se identifica ao funnel com o parâmetro sdk=<versão> na URL do iframe (ex.: sdk=0.38.0). O funnel propaga esse parâmetro por toda a sessão e:
- registra
sdk_versionnos metadados do lead (junto deutm_*/referrer), permitindo segmentar cadastros por superfície de aquisição (SDK embed vs. funnel hosted) e por versão do SDK; - marca os eventos de analytics do funnel com
sdk_version; - ativa o modo embed automaticamente (não é preciso nenhum parâmetro adicional).
Nada a configurar do seu lado — o parâmetro é adicionado e transportado automaticamente.
Origens de embed (frame-ancestors)
Por padrão, o funnel permite ser embutido em js.zarv.com e js.zarv.dev (as origens oficiais do SDK) e nos domínios ativos do próprio flow.
Se um parceiro embutir o funnel em um host diferente do domínio do flow, é preciso adicionar essa origem em "AllowedEmbedOrigins" do flow (no admin). Sem isso, o navegador bloqueia o iframe via frame-ancestors.