Putting email verification on your signup form is one of the highest-leverage product changes you can make. Bad addresses never enter your database, your bounce rate stays low, your sender reputation stays clean, and your downstream email metrics improve immediately.
But integrate it wrong and you lose more in conversion than you gain in list quality. Synchronous blocking calls add 500-2000ms to your form submission. Aggressive 'invalid email' errors reject legitimate users with unusual domains. Bad UX confuses users into abandoning signup entirely.
This guide walks through the patterns that get both right: clean lists AND high conversion. The rules apply to any verification API, not just BounceZero.
The Decision Tree: Block, Warn, or Accept
Before writing any code, decide what your form does for each verification result. There are three actions:
- Block - refuse the signup; user must change the address.
- Warn - show a soft warning but accept the signup.
- Accept - proceed silently; flag the account internally for later treatment.
The right action depends on the result type and your product. A sensible default for most SaaS:
| Verification result | Action | Rationale |
|---|---|---|
verified (definitely deliverable) | Accept | Clean signup. |
invalid (syntax error, bad MX, mailbox doesn't exist) | Block | This will hard-bounce. Don't accept it. |
disposable (mailinator, tempmail, etc.) | Block (for paid products) or Warn (for free trial) | Disposable addresses cause refund-fraud, free-trial abuse, and inflated metrics. |
role-based (info@, support@, admin@) | Warn | Real address but high complaint risk. Some senders accept; others block. |
catch-all (domain accepts everything) | Accept | We genuinely cannot prove deliverability. Most are real. |
likely_valid (high probability, not 100%) | Accept | Treat as real. |
unknown (verification timed out / unavailable) | Accept | Don't punish the user for our API issue. Re-verify async. |
The critical rule: never block on unknown. If your verifier returns 'I can't determine', accept the signup and re-check asynchronously. Blocking on unknown punishes legitimate users for verifier outages.
The Three Integration Patterns
Three places you can put verification in the signup flow. Each has different conversion impact.
Pattern 1 - On Blur (recommended for most cases)
User tabs out of the email field; you call the verifier; show the result inline before they hit submit.
``
User types: [email protected]
[onblur fires]
API returns: invalid (typo, suggest gmail.com)
Form shows: "Did you mean [email protected]? [Use suggestion]"
User clicks suggestion > form value updates > user continues to other fields
`
Pros: catches typos at the moment of entry, low perceived latency (user is moving to next field anyway), high acceptance of suggestions because the user just typed it.
Cons: requires good debounce/UX so it doesn't fire 12 times if user is editing.
Pattern 2 - On Submit (blocking)
User submits form; you verify; you either proceed or show an error.
`
User submits form
[Show "Verifying..." state with spinner - disable submit button]
API returns: invalid
Show inline error: "This email address doesn't appear to be deliverable. Please check the spelling."
User corrects, submits again
`
Pros: simple to implement, every signup is verified.
Cons: adds 200-1500ms to perceived submit time. Users abandon if it feels slow. Required mitigation: hide latency behind a spinner with reassuring copy.
Pattern 3 - Accept + Verify Async
Form always accepts; verification runs in the background; you downgrade the account or trigger a re-verify email if the address turns out invalid.
`
User submits form
[Form succeeds immediately - user sees welcome screen]
Verification runs async (job queue)
If invalid: send re-verify email asking user to confirm/correct
If disposable: flag account for limited access
``
Pros: zero conversion friction. Best for free signup flows where verification cost matters less than getting the user in.
Cons: bad addresses enter your DB temporarily. Need a cleanup process. Some users never see the re-verify email (because the address really is bad).
The Debouncing Problem (and the Fix)
If you fire your verification API on every keystroke or on every onChange event, you'll waste 10-30 API calls per signup AND degrade UX (results bouncing in and out as the user types). Debounce.
Right pattern:
``javascript
let debounceTimer;
let lastVerifiedValue = '';
emailInput.addEventListener('blur', () => {
const value = emailInput.value.trim().toLowerCase();
if (!value || value === lastVerifiedValue) return;
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return; // skip if obviously wrong
clearTimeout(debounceTimer);
debounceTimer = setTimeout(async () => {
lastVerifiedValue = value;
const result = await fetch('/api/verify-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: value })
}).then(r => r.json());
handleVerificationResult(result);
}, 300); // wait 300ms after last blur
});
`
Key rules:
- Only verify on blur
, not on everyinputevent. - Skip verification if the value matches the last verified value (user blurred without changing).
- Pre-filter with a regex syntax check - don't waste an API call on alice@
oralice@gmail. - Use 200-300ms debounce on blur` itself in case user tabs back and forth.
- Always normalize: trim, lowercase the local-part if your verifier doesn't (most do).
Did-You-Mean: The Single Biggest Conversion Win
Typos in email addresses are the single highest source of signup friction you can fix. Every major verifier returns 'did you mean' suggestions for common typos: gnail.com > gmail.com, hotmial.com > hotmail.com, outloook.com > outlook.com, etc.
For most SaaS forms, exposing these suggestions inline lifts overall signup completion by 1-3%. That's a multi-thousand-dollar yearly impact on a product with even modest signup volume.
The UX pattern that works:
``
[Email input: [email protected]]
[Below input, in soft yellow]:
Did you mean [email protected]? [Use this]
`
- Don't auto-correct silently. Some users genuinely use unusual domains.
- Make the suggestion ONE click to accept.
- Don't show the suggestion in red - yellow/orange is right. Red feels like an error; this is a helpful hint.
- Dismiss the suggestion if the user manually corrects.
Most verifier APIs return a did_you_mean` field directly. If yours doesn't, you can implement a simple Levenshtein-distance check against a list of top-100 mailbox domains.
Handling Verifier Latency and Failures
Real-world verifier APIs respond in 200-1500ms most of the time, but occasionally take 5-15 seconds (provider throttling, network blips, complex catch-all detection). Your signup form needs to handle both.
Pattern: Timeout + accept on failure
``javascript
async function verifyWithTimeout(email, timeoutMs = 1500) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
try {
const res = await fetch('/api/verify-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email }),
signal: controller.signal
});
clearTimeout(timeoutId);
return await res.json();
} catch (err) {
clearTimeout(timeoutId);
return { result: 'unknown', reason: err.name === 'AbortError' ? 'timeout' : 'network_error' };
}
}
// Then in form submit:
const verdict = await verifyWithTimeout(email, 1500);
if (verdict.result === 'invalid' || verdict.result === 'disposable') {
showError(verdict);
return; // block
}
// All other results (verified, catch-all, role, unknown) > accept and proceed
``
Key rules:
- Set a hard timeout (1-2 seconds is reasonable).
- On timeout, ACCEPT the signup. Don't punish users for our network issues.
- Log the timeout/failure so you can re-verify async later.
- Always have a fallback path that doesn't depend on the verifier being available.
Server-Side vs Client-Side: Both
Common mistake: implementing verification only on the client. Anyone can bypass client-side validation with curl, devtools, or a bot.
Right architecture: both, with different purposes.
- Client-side (in the form): For UX. Real-time typo correction, inline feedback, suggestions. Fast feedback during form completion.
- Server-side (in your signup handler): For security and final enforcement. Re-verify on the server before creating the account. Catches anything the client skipped, was bypassed, or returned 'unknown' on the client.
The client-side call shouldn't even use your verifier's primary API key - it should hit a proxy endpoint you control that rate-limits per-IP and returns only what the client needs to display. The server-side call uses your real API key and stores the full verification result against the account.
``
Client > POST /api/verify-email-public (rate-limited, IP-scoped)
↓
Your backend proxy
↓
Server > BounceZero verification API
↓
Result returned to client (filtered to safe fields)
``
On signup submission, your backend runs a SECOND verification using the canonical email value (post-typo-correction) and stores the result in the account record. This is the value of record.
What to Measure
If you ship verification at signup and don't measure, you can't tell if you helped or hurt. Track these:
A/B test the integration before rolling fully. Half your signups get the verifier, half don't. After 1-2 weeks, compare both groups on (a) completion rate and (b) downstream bounce rate. The right integration improves both.
Common Mistakes That Drop Conversion
From auditing signup flows that added verification and saw conversion drop:
unknown - verifier had a hiccup; legitimate user is told their email is invalid.[email protected] to [email protected] because of domain rarity. Always require user confirmation.role-based as invalid - many legitimate signups use marketing@, team@, hello@. Warn at most; do not block.Recommended Integration Plan
If you're starting from zero and want the lowest-risk path to clean lists + higher conversion:
Week 1: Add server-side verification on the signup endpoint only. Block obvious-invalid (syntax errors, bad MX, mailbox doesn't exist). Accept everything else. Baseline your bounce rate.
Week 2: Add client-side typo-correction (did-you-mean) with no blocking. Show suggestions only.
Week 3: Add the on-blur inline verification. Show 'this email looks invalid' for clear failures; accept everything else.
Week 4: A/B test blocking on disposable for paid signup flows. Measure conversion + downstream metrics.
Week 5: Add the async re-verification flow for any signup that returned unknown at submit. Send a 're-verify your email' message after 24 hours if unconfirmed.
At each step, measure. Don't add the next layer until the current one is proven to help.
Frequently Asked Questions
Will adding email verification hurt my signup conversion?
Done wrong, yes - 5-15% drop is typical for aggressive blocking with no UX care. Done right (typo suggestions, accept-on-timeout, warn instead of block for ambiguous results), it actually improves conversion because you catch typos that would otherwise fail silently. A/B test it on your specific flow; the right integration shows both higher completion AND lower downstream bounce rate.
Should I verify on every keystroke, on blur, or only on submit?
On blur is the right answer for most cases. Keystroke is wasteful (10-30 API calls per signup). Submit-only delays the user's first feedback to the worst possible moment. Blur fires once per field, debounced to 200-300ms, only when the user is actively moving on. Catches typos at the moment of entry without wasting API quota.
What should I do when the verification API is slow or down?
Set a hard client-side timeout (1.5-2 seconds), and on timeout ACCEPT the signup. Log the timeout, re-verify asynchronously. The cost of blocking a legitimate user is always higher than the cost of accepting a likely-good signup that needs cleanup later. Treat your verifier as advisory - never as a single point of failure.
Should I block disposable emails at signup?
For paid products: yes (refund fraud, trial abuse). For free signups: warn but accept (you'll lose legitimate users who use disposable for privacy reasons). For premium tiers: block. The decision depends on your unit economics - what's the cost of one disposable signup vs the conversion loss from blocking it?
Drop-in Real-Time Verification API
BounceZero's API returns verification results in 200-700ms with built-in did-you-mean suggestions. 100 free credits, no card required.
Get an API Key