Widget AT Valid — Demo e Integrações
Validação de e-mail em tempo real para qualquer formulário. Teste abaixo e copie o snippet da sua plataforma.
Verificação de segurança necessária antes de usar a demo
Validação detalhada
Resultado completo com score, nota e sinalizadores
Validação automática (modo widget)
widget.js com regras de aceite, validação HTML5 e preventSubmit
API programática
ATValid.validate(email, callback) — valida sem se ligar ao DOM
Exemplos de integração
Uma tag de script, um ATValid.init(). Troque pk_live_… pela chave pública de app.atvalid.com/apis (restrinja aos seus domínios).
HTML puro — início rápido
Qualquer site: cole antes de </body>. Todo input[type="email"] é validado ao sair do campo.
<!-- Add before </body> -->
<script src="https://www.atvalid.com/widget/v2/widget.js"></script>
<script>
ATValid.init({
publicKey: 'pk_live_your_public_key_here',
preventSubmit: true // block the submit while the email is invalid
});
</script> MutationObserver, então formulários injetados depois (AJAX, SPAs, construtores de página) são detectados sozinhos. Nada é enviado ao endereço — a verificação acontece no servidor.Todas as opções, regras de aceite e mensagens
Valores padrão mostrados. messages.sub (v2.1) dá o motivo específico em vez de um "inválido" genérico.
ATValid.init({
publicKey: 'pk_live_your_public_key_here',
selector: 'input[type="email"]', // which inputs to bind
validateOn: 'blur', // 'blur' | 'input'
verifyAfterDelay: 1000, // ms after typing stops (validateOn: 'input')
timeout: 10, // seconds
showFeedback: true, // message under the input
preventSubmit: false, // block submit when blocked/invalid
formValidation: false, // HTML5 setCustomValidity()
blockOnRateLimit: false,
statusAppendTo: null, // CSS selector or element for the feedback
ignoredForms: [], // form names/ids to skip
ignoredInputs: [], // input names/ids to skip
allow: {
states: ['deliverable', 'risky', 'unknown'], // 'undeliverable' is never accepted by default
free: true, // Gmail, Outlook, Yahoo…
role: true, // info@, sales@, admin@…
disposable: false // temp-mail domains
},
messages: {
checking: 'Verifying email...',
valid: 'Valid email address',
invalid: 'This email appears to be invalid',
disposable: 'Disposable email addresses are not allowed',
role: 'Role-based email addresses are not allowed',
free: 'Free email addresses are not allowed',
suggestion: 'Did you mean {suggestion}?',
networkError: 'Could not verify email. Please check your connection.',
rateLimited: 'Too many requests. Please wait a moment.',
noCredits: 'Validation service temporarily unavailable',
error: 'Could not verify email at this time',
// v2.1 — specific reasons (partial overrides are fine)
sub: {
not_found: 'This mailbox does not exist',
mailbox_full: 'This mailbox is full and cannot receive email',
null_mx: 'This domain does not accept email',
no_mx: 'This domain has no mail server',
blacklist: 'This email domain is blacklisted',
parked: 'This domain is parked and does not receive email',
no_reply: 'No-reply addresses cannot be used',
greylist: 'The mail server asked us to try again later',
toxic: 'This email address cannot be accepted',
catch_all: 'We could not confirm this mailbox exists',
smtp_unknown: 'The mail server did not respond',
suspicious: 'This email address looks suspicious'
}
},
onValidate: function (email, result) { console.log(email, result); },
onError: function (email, error) { console.error(email, error.code, error.message); }
}); WordPress — Contact Form 7, WPForms, Gravity Forms, Elementor, Formidable, Ninja Forms
Adicione ao footer.php antes de </body>, ou pelo plugin "Insert Headers and Footers" / "WPCode" (rodapé do site inteiro).
<script src="https://www.atvalid.com/widget/v2/widget.js"></script>
<script>
ATValid.init({
publicKey: 'pk_live_your_public_key_here',
selector: [
'.wpcf7-email', // Contact Form 7
'.wpforms-field-email input', // WPForms
'.gfield input[type="email"]', // Gravity Forms
'.elementor-field-type-email input', // Elementor Forms
'.frm_form_field input[type="email"]', // Formidable
'.nf-form-cont input[type="email"]', // Ninja Forms
'input[type="email"]' // anything else
].join(', '),
validateOn: 'blur',
preventSubmit: true,
allow: { disposable: false, role: false }
});
</script> widget.js da combinação.RD Station — landing pages e pop-ups
Landing page → Configurações → "Código personalizado (HTML/JS)" → antes de </body>. Os formulários do RD carregam dinamicamente; o widget espera por eles.
<script src="https://www.atvalid.com/widget/v2/widget.js"></script>
<script>
ATValid.init({
publicKey: 'pk_live_your_public_key_here',
selector: 'input[type="email"], input[name="email"]',
preventSubmit: true,
formValidation: true, // RD's own validation shows our message
allow: { disposable: false }
});
</script> HubSpot — formulários, landing pages, pop-ups
Configurações → Site → Páginas → Avançado → "HTML do rodapé do site" (ou por página). Os formulários do HubSpot são renderizados dinamicamente — detectados automaticamente.
<script src="https://www.atvalid.com/widget/v2/widget.js"></script>
<script>
ATValid.init({
publicKey: 'pk_live_your_public_key_here',
selector: 'input[type="email"], .hs-input[name="email"]',
preventSubmit: true,
allow: { disposable: false }
});
// Optional: re-scan when HubSpot signals a form is ready
window.addEventListener('message', function (e) {
if (e.data && e.data.type === 'hsFormCallback' && e.data.eventName === 'onFormReady') {
ATValid.refresh();
}
});
</script> Mailchimp — formulário de inscrição incorporado
Cole depois do código de embed do Mailchimp no seu site (as landing pages hospedadas pelo Mailchimp não aceitam JS personalizado).
<!-- your Mailchimp embed form is above -->
<script src="https://www.atvalid.com/widget/v2/widget.js"></script>
<script>
ATValid.init({
publicKey: 'pk_live_your_public_key_here',
selector: '#mc-embedded-subscribe-form input[type="email"], #mce-EMAIL',
validateOn: 'input', // validate while typing (debounced 1s)
verifyAfterDelay: 1000,
preventSubmit: true,
allow: { disposable: false, role: false }
});
</script> Google Tag Manager — tag Custom HTML
Tipo de tag "HTML personalizado", acionador "Todas as páginas" (ou só páginas com formulário). Funciona em qualquer CMS sem mexer no tema.
<script>
(function () {
var s = document.createElement('script');
s.src = 'https://www.atvalid.com/widget/v2/widget.js';
s.async = true;
s.onload = function () {
ATValid.init({
publicKey: 'pk_live_your_public_key_here',
preventSubmit: true,
allow: { disposable: false },
onValidate: function (email, result) {
// push to the dataLayer for GA4 / conversion rules
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'atvalid_email_verified',
atv_accepted: result.accepted,
atv_state: result.state,
atv_sub_status: result.subStatus,
atv_score: result.score
});
}
});
};
document.head.appendChild(s);
})();
</script> onValidate envia um evento ao dataLayer para o GA4 / regras de conversão.Webflow, Wix, Shopify, Squarespace — código personalizado do site
Webflow: Configurações do projeto → Código personalizado → Rodapé. Wix: Configurações → Código personalizado → Fim do body. Shopify: theme.liquid antes de </body>. Squarespace: Configurações → Avançado → Injeção de código → Rodapé.
<script src="https://www.atvalid.com/widget/v2/widget.js"></script>
<script>
ATValid.init({
publicKey: 'pk_live_your_public_key_here',
// covers Webflow (.w-input), Wix, Shopify (customer/contact forms) and Squarespace
selector: 'input[type="email"], input.w-input[type="email"], input[name="customer[email]"], input[name="contact[email]"]',
preventSubmit: true,
allow: { disposable: false }
});
</script> React / Next.js
Carregue uma vez, ligue ao seu input, destrua ao desmontar. No Next.js marque o componente com 'use client'.
import { useEffect } from 'react';
export function ContactForm() {
useEffect(() => {
const script = document.createElement('script');
script.src = 'https://www.atvalid.com/widget/v2/widget.js';
script.async = true;
script.onload = () => {
window.ATValid.init({
publicKey: 'pk_live_your_public_key_here',
selector: '#email-input',
preventSubmit: true,
formValidation: true,
allow: { disposable: false },
onValidate: (email, result) => console.log(email, result.accepted, result.subStatus)
});
};
document.body.appendChild(script);
return () => {
window.ATValid && window.ATValid.destroy();
document.body.removeChild(script);
};
}, []);
return (
<form>
<input id="email-input" type="email" placeholder="Email" />
<button type="submit">Submit</button>
</form>
);
} ATValid.refresh() (ou confie no MutationObserver, ligado por padrão).Vue 3 / Nuxt
Mesma ideia com onMounted / onBeforeUnmount. No Nuxt, mantenha dentro de <ClientOnly> ou de um componente client.
<script setup>
import { onMounted, onBeforeUnmount } from 'vue';
let script;
onMounted(() => {
script = document.createElement('script');
script.src = 'https://www.atvalid.com/widget/v2/widget.js';
script.async = true;
script.onload = () => window.ATValid.init({
publicKey: 'pk_live_your_public_key_here',
selector: '#email',
preventSubmit: true,
allow: { disposable: false }
});
document.body.appendChild(script);
});
onBeforeUnmount(() => {
window.ATValid && window.ATValid.destroy();
script && script.remove();
});
</script>
<template>
<form><input id="email" type="email" /><button>Submit</button></form>
</template> Callbacks, eventos DOM e o objeto de resultado (v2.1)
Use onValidate ou escute atv:verified / atv:error no document.
document.addEventListener('atv:verified', function (e) {
var r = e.detail.result;
// r = {
// valid: true|false, // API-level verdict
// accepted: true|false, // passed your allow rules → decides the submit
// state: 'deliverable'|'risky'|'unknown'|'undeliverable',
// subStatus: 'ok'|'not_found'|'mailbox_full'|'disposable'|'null_mx'|'no_mx'|'typo'|
// 'blacklist'|'parked'|'no_reply'|'greylist'|'catch_all'|'suspicious'|
// 'role_based'|'toxic'|'smtp_unknown'|'risky'|'invalid', (v2.1)
// toxicity: 0..5, // reputation risk (≥3 is never accepted) (v2.1)
// catchAllConfidence: 0..10|null, // evidence the mailbox exists on a catch-all domain (v2.1)
// score: 0..100, grade: 'A'..'F',
// disposable, free, role: booleans,
// suggestion: '[email protected]' | null, // typo fix (clickable in the feedback)
// email: '[email protected]',
// raw: { ...full API response }
// }
if (!e.detail.accepted) console.log('blocked:', r.subStatus);
});
document.addEventListener('atv:error', function (e) {
// e.detail.error: NETWORK_ERROR | TIMEOUT | RATE_LIMITED | NO_CREDITS |
// DOMAIN_BLOCKED | AUTH_ERROR | API_ERROR | PARSE_ERROR | NO_KEY
console.warn(e.detail.email, e.detail.error);
}); | Atributo no input | Valores | Significado |
|---|---|---|
data-atv-valid | "true" | "false" | Aceito pelas suas regras (o que o preventSubmit verifica) |
data-atv-state | deliverable | risky | unknown | undeliverable | Estado derivado |
data-atv-bound | "1" | O widget está ligado a este input |
API programática — sem ligação ao DOM
Valide sob demanda (ex.: antes de um envio via XHR), re-escaneie, limpe o cache, desmonte.
// Validate a single address (publicKey optional if init() already ran)
ATValid.validate('[email protected]', 'pk_live_your_key', function (result) {
console.log(result.accepted, result.state, result.subStatus, result.score, result.toxicity);
});
ATValid.refresh(); // re-scan the DOM for new email inputs (SPA navigation)
ATValid.clearCache(); // forget the 5-minute in-page cache
ATValid.destroy(); // remove listeners, observer, styles and feedback Estilos
O widget injeta um CSS mínimo; sobrescreva qualquer classe na sua folha de estilos.
.atv-input-valid { border-color: #22c55e !important; box-shadow: 0 0 0 3px rgba(34,197,94,.1) !important; }
.atv-input-invalid { border-color: #ef4444 !important; box-shadow: 0 0 0 3px rgba(239,68,68,.1) !important; }
.atv-input-checking { border-color: #9ca3af !important; }
.atv-feedback { font-size: .8125rem; margin-top: .25rem; font-family: inherit; }
.atv-valid { color: #22c55e; }
.atv-invalid { color: #ef4444; }
.atv-checking { color: #9ca3af; }
.atv-suggestion { color: #d97706; cursor: pointer; text-decoration: underline; }
.atv-suggestion:hover { color: #b45309; }