Instalacao do widget
O widget Veridia e um unico HTML custom element. Duas tags <script> e uma tag <veridia-widget> — essa e a instalacao completa.
O que se instala
Quando voce carrega o widget, sua pagina obtem:
- Um custom element
<veridia-widget>que voce pode colocar em qualquer lugar - A biblioteca
face-api.js(~6 MB, usada para qualidade de selfie + deteccao de rosto) - O bundle do widget Veridia (~150 KB, modulo ESM)
- Dois CustomEvents:
veridia:completeeveridia:error
Os arquivos de modelo do face-api.js sao carregados lazy no primeiro uso (cerca de 14 MB) — ficam cacheados agressivamente depois.
HTML puro
A integracao mais simples possivel:
<!DOCTYPE html>
<html lang="pt">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Verificacao KYC</title>
<!-- A ordem importa: face-api primeiro, widget depois -->
<script src="https://widget.xxuxe.online/face-api.js"></script>
<script type="module" src="https://widget.xxuxe.online/veridia-widget.min.js"></script>
</head>
<body>
<main>
<h1>Verifique sua identidade</h1>
<veridia-widget
id="kyc"
publishable-key="qv_pub_test_SUA_KEY"
api-base="https://api.xxuxe.online"
user-ref="customer-12345"
country="BR"
document-type="national_id"
locale="pt">
</veridia-widget>
</main>
<script>
document.getElementById('kyc').addEventListener('veridia:complete', (e) => {
console.log('Verification ID:', e.detail.verificationId);
// Envie o ID ao seu backend para obter o veredicto
});
</script>
</body>
</html>
React (Create React App, Vite, etc.)
import { useEffect, useRef } from 'react';
export function VeridiaVerification({ userRef, onComplete, onError }) {
const widgetRef = useRef(null);
useEffect(() => {
const node = widgetRef.current;
if (!node) return;
const completeHandler = (e) => onComplete?.(e.detail);
const errorHandler = (e) => onError?.(e.detail);
node.addEventListener('veridia:complete', completeHandler);
node.addEventListener('veridia:error', errorHandler);
return () => {
node.removeEventListener('veridia:complete', completeHandler);
node.removeEventListener('veridia:error', errorHandler);
};
}, [onComplete, onError]);
return (
<veridia-widget
ref={widgetRef}
publishable-key={import.meta.env.VITE_VERIDIA_KEY}
api-base="https://api.xxuxe.online"
user-ref={userRef}
country="BR"
document-type="national_id"
locale="pt"
/>
);
}
Carregue os scripts uma vez em index.html:
<script src="https://widget.xxuxe.online/face-api.js"></script>
<script type="module" src="https://widget.xxuxe.online/veridia-widget.min.js"></script>
TypeScript: adicione isto a um arquivo *.d.ts para que JSX aceite o custom element:
declare namespace JSX {
interface IntrinsicElements {
'veridia-widget': React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement> & {
'publishable-key': string;
'api-base': string;
'user-ref'?: string;
'country'?: string;
'document-type'?: string;
'submitted-full-name'?: string;
'require-doc-back'?: string;
'locale'?: string;
'accent-color'?: string;
},
HTMLElement
>;
}
}
Next.js
No Next.js, custom elements precisam carregar apos a hidratacao. Use next/script com strategy="afterInteractive":
// app/layout.tsx (App Router)
import Script from 'next/script';
export default function RootLayout({ children }) {
return (
<html lang="pt">
<body>
{children}
<Script
src="https://widget.xxuxe.online/face-api.js"
strategy="afterInteractive"
/>
<Script
src="https://widget.xxuxe.online/veridia-widget.min.js"
type="module"
strategy="afterInteractive"
/>
</body>
</html>
);
}
// app/onboarding/kyc/page.tsx
'use client';
import { useEffect, useRef } from 'react';
import { useRouter } from 'next/navigation';
export default function KycPage() {
const widgetRef = useRef(null);
const router = useRouter();
useEffect(() => {
const node = widgetRef.current;
if (!node) return;
const handler = async (e) => {
const { verificationId } = e.detail;
// Envie ao seu backend
await fetch('/api/kyc/complete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ verificationId }),
});
router.push('/onboarding/success');
};
node.addEventListener('veridia:complete', handler);
return () => node.removeEventListener('veridia:complete', handler);
}, [router]);
return (
<main>
<h1>Verifique sua identidade</h1>
<veridia-widget
ref={widgetRef}
publishable-key={process.env.NEXT_PUBLIC_VERIDIA_KEY}
api-base="https://api.xxuxe.online"
locale="pt"
/>
</main>
);
}
Vue 3
Vue trata custom elements automaticamente. Sem necessidade de config especial:
<template>
<veridia-widget
ref="widget"
:publishable-key="publishableKey"
api-base="https://api.xxuxe.online"
:user-ref="userRef"
locale="pt"
/>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
const props = defineProps({
publishableKey: { type: String, required: true },
userRef: { type: String, required: true },
});
const emit = defineEmits(['complete', 'error']);
const widget = ref(null);
const completeHandler = (e) => emit('complete', e.detail);
const errorHandler = (e) => emit('error', e.detail);
onMounted(() => {
widget.value?.addEventListener('veridia:complete', completeHandler);
widget.value?.addEventListener('veridia:error', errorHandler);
});
onUnmounted(() => {
widget.value?.removeEventListener('veridia:complete', completeHandler);
widget.value?.removeEventListener('veridia:error', errorHandler);
});
</script>
Carregue os scripts em index.html:
<script src="https://widget.xxuxe.online/face-api.js"></script>
<script type="module" src="https://widget.xxuxe.online/veridia-widget.min.js"></script>
Angular
No Angular, voce precisa permitir custom elements no seu modulo:
// app.module.ts
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
// ...
})
export class AppModule {}
Depois use em templates:
<veridia-widget
#widget
[attr.publishable-key]="publishableKey"
api-base="https://api.xxuxe.online"
[attr.user-ref]="userRef"
locale="pt"
(veridia:complete)="onComplete($event)"
(veridia:error)="onError($event)">
</veridia-widget>
Mobile webview
O widget funciona dentro do iOS WebView e Android WebView. Dois requisitos:
- Permissoes de camera: o app host deve conceder acesso a camera. No iOS,
WKWebView.allowsInlineMediaPlayback = true. No Android, overrideonPermissionRequestpara concederRESOURCE_VIDEO_CAPTURE. - HTTPS: mesmo em WebView, o widget recusa rodar em origens inseguras.
Troubleshooting
"Este widget esta mal configurado"
Mais comum: seu dominio nao esta na lista de allowed origins do dashboard.
Fix: dashboard → API Keys → editar sua key → adicionar o dominio (ex: https://seuapp.com, ou http://localhost:3000 para dev).
O widget carrega mas nunca mostra o botao Comecar
Geralmente face-api.js falhou ao carregar. Verifique o console do browser por 404s ou erros CSP.
Fix: verifique as URLs dos scripts:
https://widget.xxuxe.online/face-api.jsdeve retornar200https://widget.xxuxe.online/veridia-widget.min.jsdeve retornar200
"Camera nao disponivel"
O usuario negou permissao de camera, ou a pagina nao e HTTPS.
Fix: garanta que sua pagina seja servida sobre HTTPS. Browsers bloqueiam camera em http:// (exceto localhost).
As capturas saem borradas / dispara o flag de qualidade
Dispositivos mobile auto-focam melhor que laptops. Diga aos usuarios que tomem seu tempo e mantenham firme.
Se sua audiencia usa principalmente desktops, ajuste accent-color e de clareza UI, mas aceite que alguns usuarios vao precisar de 2-3 retries.
React: warning sobre atributo desconhecido
React nao reconhece custom elements por padrao. Adicione a declaracao TypeScript acima, ou defina suppressHydrationWarning no parent.
Next.js: document is not defined durante build
O widget usa APIs do browser. Marque sua pagina como client component ('use client') e garanta que os scripts usem strategy="afterInteractive".
Erros CSP (Content Security Policy)
Se seu site tem CSP estrito, adicione estas directivas:
script-src 'self' https://widget.xxuxe.online;
connect-src 'self' https://api.xxuxe.online https://*.r2.cloudflarestorage.com;
img-src 'self' blob: data: https://widget.xxuxe.online;
media-src 'self' blob:;
worker-src blob:;
O connect-src para R2 e necessario para upload direto de imagens do browser.
O widget mostra o idioma errado
Defina o atributo locale explicitamente:
<veridia-widget locale="pt">
Default e o locale do browser, fallback ingles.
Verificando a instalacao
Uma instalacao funcionando deve passar este checklist:
| Check | Como verificar |
|---|---|
| Scripts carregam | Tab Network de DevTools — ambos 200 |
| Custom element registrado | document.querySelector('veridia-widget') retorna um elemento |
| Botao Comecar aparece | Visivel botao "Comecar" / "Start" |
| Prompt de camera aparece | Apos clicar em Comecar |
| Captura tem sucesso | O evento veridia:complete dispara com um verificationId |
Proximos passos
- Configuracao do widget — cada atributo, evento, opcao de estilo
- Quickstart — caminho completo de integracao
- Referencia API — API server-side para obter veredictos