Widget de captura de leads para landing pages e sites institucionais. Instala com uma tag <script>, sem framework e sem dependências.
- Validação brasileira: telefone com DDD real e 9º dígito; nome e pelo menos um contato
- Atribuição de campanha: guarda as UTMs,
gclidefbclidda primeira página da sessão (first touch), então o lead não chega como "direto" só porque o visitante navegou antes de converter - LGPD: checkbox de consentimento com link para a política e
consent_atno payload - Anti-spam sem CAPTCHA: honeypot e tempo mínimo de preenchimento (bots recebem um falso "sucesso")
- Não perde lead: se a sua API cair, o widget oferece continuar no WhatsApp com a mensagem já escrita
- Acessível (rótulos,
aria-invalid, erros anunciados, Esc fecha), responsivo e com tema claro/escuro - Shadow DOM: o CSS do site não quebra o widget, e vice-versa
<script type="module"
src="https://cdn.jsdelivr.net/gh/Ph20sr/lead-widget/src/lead-widget.js"
data-lead-widget
data-endpoint="https://api.seusite.com.br/leads"
data-whatsapp="11987654321"
data-title="Peça um orçamento"
data-subtitle="Retornamos em até 1 hora útil."
data-color="#16a34a"
data-position="right"
data-privacy-url="/privacidade"></script>| atributo | padrão | descrição |
|---|---|---|
data-endpoint |
— | URL que recebe o POST JSON |
data-whatsapp |
— | número para o fallback |
data-title, data-subtitle |
"Fale com a gente" | textos do painel |
data-color |
#4f46e5 |
cor de destaque |
data-position |
right |
left ou right |
data-privacy-url |
— | link da política de privacidade |
data-source |
hostname | identifica o site de origem |
{
"name": "Maria Souza",
"phone": "+5511987654321",
"email": null,
"message": "Quero um orçamento de site",
"consent": true,
"consent_at": "2026-10-05T16:58:37.929Z",
"source": "seusite.com.br",
"attribution": {
"utm_source": "instagram",
"utm_medium": "ads",
"utm_campaign": "lancamento",
"landing_page": "https://seusite.com.br/promo",
"referrer": "https://l.instagram.com/",
"page": "https://seusite.com.br/contato"
},
"created_at": "2026-10-05T16:58:37.929Z"
}O widget também dispara window → leadwidget:submit com o mesmo payload, útil para Google Tag Manager ou Meta Pixel:
addEventListener('leadwidget:submit', (e) => {
dataLayer.push({ event: 'generate_lead', source: e.detail.attribution.utm_source });
});server/leads.php é um endpoint pronto para PHP e MySQL. Ele tem CORS por allowlist, revalida tudo no servidor, limita envios por IP e grava a atribuição em uma coluna JSON. Qualquer backend que aceite POST application/json e responda 2xx serve.
npm test # validação, atribuição e payload (node:test)
npm run demo # http://localhost:5173MIT