Wix Form Email Verification API Integration (Step-by-Step)
checkboxHQ + Wix + Airtable Integration Guide
Overview
This guide demonstrates how to integrate checkboxHQ’s email verification API with Wix forms and store validated results in Airtable using a non-blocking verification approach. checkboxHQ validates emails asynchronously after form submission, ensuring a smooth user experience without delays or interruptions.
This setup is ideal for:
- Lead capture forms that need post-submission email quality scoring
- Newsletter signups with background verification for list hygiene
- Contact forms that store all submissions but flag invalid emails for review
- E-commerce sites wanting to verify customer emails without friction
- Any workflow requiring clean email data without impacting form conversion rates
Architecture
Wix Form Submission → Immediate Success Response to User ↓ Wix Automation (Webhook) → Serverless Function ↓ checkboxHQ API Verification (background) ↓ Airtable Storage (with verification results)Key Principle: The user receives immediate confirmation of their submission. Email verification happens in the background without blocking the user’s experience.
Prerequisites
-
checkboxHQ Account
- API token from checkboxhq.com
- Available credits for API calls
-
Wix
- Wix site with Premium plan (required for Automations)
- Form created on your site (Wix Forms)
-
Airtable
- Airtable account with a base created
- Personal Access Token
-
Serverless Platform (choose one)
- Netlify Functions (recommended for beginners)
- Vercel Functions
- AWS Lambda
- Cloudflare Workers
Step 1: Set Up Airtable Base
Create Your Base Structure
Create a table called Email Submissions with these fields:
| Field Name | Field Type | Description |
|---|---|---|
| Submission ID | Single line text | Unique identifier for tracking |
| The submitted email address | ||
| Name | Single line text | Submitter’s name (if collected) |
| Form Name | Single line text | Which Wix form was submitted |
| Submission Date | Created time | Auto-populated timestamp |
| Status | Single select | Options: Valid, Disposable Email, Invalid Domain, Verification Error, Pending Verification |
| Verification Status | Single select | Options: Pending, In Progress, Completed, Failed |
| Is Disposable | Checkbox | Whether email is from disposable provider |
| Is Public Provider | Checkbox | Whether email is from public provider (Gmail, etc.) |
| Has MX Record | Checkbox | Whether domain has valid MX records |
| Has A Record | Checkbox | Whether domain has valid A records |
| Domain | Single line text | Extracted domain from email |
| Provider | Single line text | Email provider name if identified |
| Verified At | Date & time | When verification completed |
| Verification Error | Long text | Error message if verification failed |
Why this structure?
- Initial submission creates record immediately with “Pending Verification” status
- Background verification updates the same record with results
- You can filter and view submissions while verification is in progress
- No user waits for verification to complete
Get Airtable Credentials
- Go to airtable.com/create/tokens
- Create a Personal Access Token with these scopes:
data.records:readdata.records:write
- Note your:
- Base ID: Found in API documentation (starts with
app) - Table Name:
Email Submissions(or your custom name) - Access Token: Your newly created token
- Base ID: Found in API documentation (starts with
Step 2: Create Serverless Function
Example: Netlify Function (Non-Blocking Pattern)
Create a file: netlify/functions/wix-verify-email.js
const fetch = require('node-fetch');
exports.handler = async (event, context) => { // Set CORS headers for Wix const headers = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'Content-Type', 'Access-Control-Allow-Methods': 'POST, OPTIONS' };
// Handle preflight OPTIONS request if (event.httpMethod === 'OPTIONS') { return { statusCode: 200, headers, body: '' }; }
// Only allow POST requests if (event.httpMethod !== 'POST') { return { statusCode: 405, headers, body: JSON.stringify({ error: 'Method not allowed' }) }; }
try { // Parse Wix webhook payload const payload = JSON.parse(event.body);
// Wix sends form data in this structure const email = payload.email || payload.data?.email; const name = payload.name || payload.data?.name || ''; const formName = payload.formName || payload.data?.formName || 'Contact Form'; const submissionId = payload.submissionId || Date.now().toString();
if (!email) { return { statusCode: 400, headers, body: JSON.stringify({ error: 'Email is required' }) }; }
// STEP 1: Immediately store submission in Airtable (user already received success) await storeInitialSubmission(email, name, formName, submissionId);
// STEP 2: Perform verification asynchronously (fire and forget) // Don't await - let it run in background verifyAndUpdateAsync(email, submissionId).catch(error => { console.error('Background verification error:', error); // Log error but don't fail the webhook response });
// STEP 3: Return immediate success to Wix // User experience is not impacted by verification delay return { statusCode: 200, headers, body: JSON.stringify({ success: true, message: 'Submission received and being processed', submissionId: submissionId }) };
} catch (error) { console.error('Error:', error); return { statusCode: 500, headers, body: JSON.stringify({ error: 'Submission processing failed', details: error.message }) }; }};
// Store initial submission immediately (before verification)async function storeInitialSubmission(email, name, formName, submissionId) { const AIRTABLE_TOKEN = process.env.AIRTABLE_TOKEN; const AIRTABLE_BASE_ID = process.env.AIRTABLE_BASE_ID; const AIRTABLE_TABLE_NAME = process.env.AIRTABLE_TABLE_NAME || 'Email Submissions';
const airtablePayload = { records: [ { fields: { 'Email': email, 'Name': name, 'Form Name': formName, 'Submission ID': submissionId, 'Status': 'Pending Verification', 'Verification Status': 'In Progress' } } ] };
const response = await fetch( `https://api.airtable.com/v0/${AIRTABLE_BASE_ID}/${encodeURIComponent(AIRTABLE_TABLE_NAME)}`, { method: 'POST', headers: { 'Authorization': `Bearer ${AIRTABLE_TOKEN}`, 'Content-Type': 'application/json' }, body: JSON.stringify(airtablePayload) } );
if (!response.ok) { const errorText = await response.text(); throw new Error(`Airtable error: ${errorText}`); }
const result = await response.json(); return result.records[0].id; // Return Airtable record ID}
// Async verification that updates the existing recordasync function verifyAndUpdateAsync(email, submissionId) { try { // Perform CheckBoxHQ verification const verificationData = await verifyEmailWithCheckBox(email);
// Update the existing Airtable record with verification results await updateAirtableRecord(submissionId, verificationData);
console.log(`Verification completed for ${email}`); } catch (error) { console.error(`Verification failed for ${email}:`, error);
// Update record with error status await updateAirtableRecord(submissionId, { verification_error: error.message, verification_status: 'Failed' }); }}
// CheckBoxHQ API Integration Functionsasync function verifyEmailWithCheckBox(email) { const CHECKBOX_API_KEY = process.env.CHECKBOX_API_KEY;
// Perform all verifications (adjust based on your needs)
// 1. Disposable email check (1 credit) const disposableCheck = await fetch('https://api.checkboxhq.com/api/v1/verify_disposable/', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': CHECKBOX_API_KEY }, body: JSON.stringify({ email }) });
if (!disposableCheck.ok) { throw new Error(`Disposable check failed: ${disposableCheck.statusText}`); }
const disposableData = await disposableCheck.json();
// 2. DNS verification (2 credits) const dnsCheck = await fetch('https://api.checkboxhq.com/api/v1/verify_dns/', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': CHECKBOX_API_KEY }, body: JSON.stringify({ email }) });
if (!dnsCheck.ok) { throw new Error(`DNS check failed: ${dnsCheck.statusText}`); }
const dnsData = await dnsCheck.json();
// 3. Public provider check (1 credit) const publicCheck = await fetch('https://api.checkboxhq.com/api/v1/verify_public_provider/', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': CHECKBOX_API_KEY }, body: JSON.stringify({ email }) });
if (!publicCheck.ok) { throw new Error(`Public provider check failed: ${publicCheck.statusText}`); }
const publicData = await publicCheck.json();
// Combine all verification results return { email: disposableData.email, is_disposable: disposableData.is_disposable, is_valid_format: disposableData.is_valid_format, domain: disposableData.domain, provider: disposableData.provider || dnsData.provider || publicData.provider, has_mx_record: dnsData.has_mx_record, has_a_record: dnsData.has_a_record, mx_records: dnsData.mx_records, a_records: dnsData.a_records, is_public_provider: publicData.is_public_provider };}
async function updateAirtableRecord(submissionId, verificationData) { const AIRTABLE_TOKEN = process.env.AIRTABLE_TOKEN; const AIRTABLE_BASE_ID = process.env.AIRTABLE_BASE_ID; const AIRTABLE_TABLE_NAME = process.env.AIRTABLE_TABLE_NAME || 'Email Submissions';
// First, find the record by Submission ID const searchUrl = `https://api.airtable.com/v0/${AIRTABLE_BASE_ID}/${encodeURIComponent(AIRTABLE_TABLE_NAME)}?filterByFormula={Submission ID}="${submissionId}"`;
const searchResponse = await fetch(searchUrl, { headers: { 'Authorization': `Bearer ${AIRTABLE_TOKEN}` } });
const searchData = await searchResponse.json();
if (!searchData.records || searchData.records.length === 0) { throw new Error(`Record not found for submission ID: ${submissionId}`); }
const recordId = searchData.records[0].id;
// Determine final status let status = 'Valid'; if (verificationData.verification_error) { status = 'Verification Error'; } else if (verificationData.is_disposable) { status = 'Disposable Email'; } else if (!verificationData.has_mx_record) { status = 'Invalid Domain'; }
// Update the record with verification results const updatePayload = { fields: { 'Is Disposable': verificationData.is_disposable || false, 'Is Public Provider': verificationData.is_public_provider || false, 'Has MX Record': verificationData.has_mx_record || false, 'Has A Record': verificationData.has_a_record || false, 'Domain': verificationData.domain || '', 'Provider': verificationData.provider || '', 'Status': status, 'Verification Status': verificationData.verification_error ? 'Failed' : 'Completed', 'Verified At': new Date().toISOString() } };
if (verificationData.verification_error) { updatePayload.fields['Verification Error'] = verificationData.verification_error; }
const updateResponse = await fetch( `https://api.airtable.com/v0/${AIRTABLE_BASE_ID}/${encodeURIComponent(AIRTABLE_TABLE_NAME)}/${recordId}`, { method: 'PATCH', headers: { 'Authorization': `Bearer ${AIRTABLE_TOKEN}`, 'Content-Type': 'application/json' }, body: JSON.stringify(updatePayload) } );
if (!updateResponse.ok) { const errorText = await updateResponse.text(); throw new Error(`Airtable update error: ${errorText}`); }
return await updateResponse.json();}Environment Variables
Add these to your Netlify dashboard (or equivalent):
CHECKBOX_API_KEY=your_checkbox_api_key_hereAIRTABLE_TOKEN=your_airtable_token_hereAIRTABLE_BASE_ID=appXXXXXXXXXXXXXXAIRTABLE_TABLE_NAME=Email SubmissionsDeploy the Function
- Create a Git repository with your function code
- Connect to Netlify (or your chosen platform)
- Deploy automatically
- Your function will be available at:
https://yoursite.netlify.app/.netlify/functions/wix-verify-email
Step 3: Configure Wix Form
Create or Select Your Form
- In Wix Editor, add or select a Form element
- Ensure it has:
- Email input field (required)
- Name input field (optional but recommended)
- Publish your site
Set Up Wix Automation
Step-by-Step Instructions:
-
Access Automations
- In your Wix Dashboard, click Automations in the left sidebar
- Click + New Automation or + Create Automation
-
Choose Trigger
- Select Wix Forms as your trigger
- Choose Form is submitted
- Select which form triggers this automation (or choose “Any form”)
- Click Apply
-
Add Webhook Action
- Click the + icon to add an action
- Select Send via webhook or HTTP Request
- Configure the webhook:
-
Webhook Configuration
Target URL: https://yoursite.netlify.app/.netlify/functions/wix-verify-emailHTTP Method: POSTData to Send: All keys and values -
Map Form Fields (if using “Customize structure”)
Key: email Value: [Insert Variable] → Email fieldKey: name Value: [Insert Variable] → Name fieldKey: formName Value: [Insert Variable] → Form nameKey: submissionId Value: [Insert Variable] → Submission ID -
Activate Automation
- Give your automation a name (e.g., “Email Verification”)
- Click Activate
Form Submission Flow (Non-Blocking)
When a user submits the form:
- User submits → Wix captures the submission
- Wix shows success → User sees confirmation immediately (no delay)
- Wix triggers automation → Sends webhook to your serverless function
- Function stores initial record → Creates Airtable entry with “Pending Verification”
- Function returns success → Webhook completes quickly (~300-500ms)
- Background verification starts → CheckBoxHQ APIs called asynchronously
- Airtable record updated → Verification results populate the existing record
Key Benefit: Steps 1-5 happen in under 1 second. Steps 6-7 happen in the background without impacting user experience or conversion rates.
Step 4: Testing Your Integration
Test Checklist
-
Submit Test Form
- Fill out your Wix form with a test email
- Verify you get immediate success message
-
Check Airtable
- Open your Airtable base
- Verify new record appears with “Pending Verification” status
- Wait 5-10 seconds
- Refresh and verify verification results appear
-
Test Different Email Types
- Valid Gmail:
[email protected](should show as Valid, Public Provider) - Disposable:
[email protected](should show as Disposable) - Invalid domain:
[email protected](should show Invalid Domain)
- Valid Gmail:
-
Check Function Logs
- Go to Netlify Functions dashboard
- View logs for
wix-verify-email - Verify no errors
Debugging Common Issues
Issue: Webhook not triggering
- Verify automation is activated in Wix
- Check webhook URL is correct (copy-paste without typos)
- Ensure site is published (not just preview)
Issue: Records not appearing in Airtable
- Check Airtable credentials in environment variables
- Verify table name matches exactly (case-sensitive)
- Check function logs for errors
Issue: Verification not completing
- Verify checkboxHQ API key is valid
- Check you have available credits
- Review function logs for API errors
Step 5: Advanced Features
Enhanced Error Handling
// Add retry logic with exponential backoffasync function verifyEmailWithRetry(email, maxRetries = 3) { let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await verifyEmailWithCheckBox(email); } catch (error) { lastError = error; console.log(`Verification attempt ${attempt} failed for ${email}:`, error.message);
// Wait before retrying (exponential backoff) if (attempt < maxRetries) { await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, attempt))); } } }
throw new Error(`Failed after ${maxRetries} attempts: ${lastError.message}`);}Webhook Signature Verification (Security)
// Add security check to verify webhook is from Wixfunction verifyWixWebhook(payload, signature) { // Wix sends webhooks as JWT tokens // Implement JWT verification here // See: https://dev.wix.com/docs/build-apps/develop-your-app/api-integrations/events-and-webhooks/about-webhooks}Conditional Verification (Cost Optimization)
// Only verify business emails (skip free providers to save credits)async function smartVerification(email) { const domain = email.split('@')[1]; const freeProviders = ['gmail.com', 'yahoo.com', 'hotmail.com', 'outlook.com'];
if (freeProviders.includes(domain.toLowerCase())) { // Skip full verification for known free providers return { email, is_public_provider: true, is_disposable: false, provider: domain, skip_reason: 'Known free provider' }; }
// Full verification for business emails return await verifyEmailWithCheckBox(email);}Optimization Strategies
Why Non-Blocking Verification Matters
Conversion Rate Impact:
- Blocking verification: 2-5 second delay = 10-20% form abandonment
- Non-blocking verification: <1 second response = optimal conversion rates
- Users get immediate confirmation while quality checks happen behind the scenes
Credit Management
checkboxHQ API endpoints consume different credits:
verify_disposable: 1 creditverify_public_provider: 1 creditverify_dns: 2 credits
Cost-Effective Strategy for Background Verification:
async function optimizedBackgroundVerification(email) { // Strategy 1: Sequential verification (stop early if disposable) const disposableCheck = await checkDisposable(email);
if (disposableCheck.is_disposable) { // Stop here - no need to check DNS for disposable emails (saves 2 credits) return { ...disposableCheck, verification_type: 'disposable-only', credits_used: 1 }; }
// Strategy 2: Parallel verification for non-disposable emails const [dnsCheck, publicCheck] = await Promise.all([ checkDNS(email), // 2 credits checkPublic(email) // 1 credit ]);
return { ...disposableCheck, ...dnsCheck, ...publicCheck, verification_type: 'comprehensive', credits_used: 4 };}Domain-Level Caching
// Cache verification results by domain to reduce API callsconst CACHE_TTL = 7 * 24 * 60 * 60 * 1000; // 7 days
async function verifyWithCache(email) { const domain = email.split('@')[1];
// Check cache (using Redis, Upstash, or similar) const cached = await getCachedDomainInfo(domain);
if (cached) { console.log(`Using cached verification for domain: ${domain}`); return { ...cached, email, from_cache: true }; }
// Not cached - perform full verification const verification = await verifyEmailWithCheckBox(email);
// Cache domain-level results await cacheDomainInfo(domain, verification);
return verification;}The checkboxHQ Philosophy: Why Non-Blocking?
User Experience First
| Blocking Verification | Non-Blocking Verification (CheckBoxHQ) |
|---|---|
| User waits 2-5 seconds | User gets instant confirmation (<1s) |
| Form feels slow/broken | Form feels fast and responsive |
| 10-20% form abandonment | Minimal abandonment |
| API timeout = failed submission | API issues don’t affect users |
| Poor mobile experience | Works great on any connection |
Business Impact
Higher Conversion Rates:
- Every second of delay = 7% conversion loss
- Non-blocking maintains optimal conversion rates
- Capture the lead, verify in the background
Clean Data Without Trade-offs:
- Still get full verification results
- Act on results via automation
- Better than no verification at all
Smart Actions Based on Verification
Instead of blocking users, use verification data to:
✅ Segment your email lists - Different campaigns for business vs. public emails
✅ Prioritize sales follow-ups - Focus on verified, non-disposable emails first
✅ Flag for manual review - Let humans handle edge cases
✅ Track form quality - Monitor which sources attract disposable emails
✅ Clean before export - Filter when syncing to CRM/Email Service Provider
✅ Trigger different workflows - Send instant confirmation to verified emails
❌ Don’t block form submissions - This hurts conversion and user trust
❌ Don’t make users wait - Verification delay = lost opportunities
❌ Don’t fail forms on API errors - Always capture the lead first
Post-Verification Actions
Airtable Automations for Follow-Up
Once verification completes in the background, trigger actions based on results:
Automation 1: Send to CRM (Valid Emails Only)
Trigger: When "Status" = "Valid"Action: Create record in your CRM or send to Zapier/MakeAutomation 2: Flag for Review (Invalid Emails)
Trigger: When "Status" = "Disposable Email" OR "Invalid Domain"Action: Send Slack notification to team for manual reviewAutomation 3: Segment Marketing Lists
Trigger: When "Is Public Provider" = trueAction: Add to consumer email listWhen "Is Public Provider" = false AND "Status" = "Valid"Action: Add to business/B2B email listIntegration with Email Marketing
// Add to your verification functionasync function sendToEmailMarketing(email, verificationData) { // Only send verified, non-disposable emails if (!verificationData.is_disposable && verificationData.has_mx_record) {
const tags = []; if (verificationData.is_public_provider) { tags.push('consumer'); } else { tags.push('business'); }
await fetch('https://api.youremailprovider.com/subscribe', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.EMAIL_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ email: email, tags: tags }) }); }}Monitoring & Analytics
Track API Usage
Monitor your checkboxHQ credit usage:
async function checkAPIUsage() { const response = await fetch('https://api.checkboxhq.com/api/v1/billing/usage', { headers: { 'Authorization': `Bearer ${process.env.CHECKBOX_ACCESS_TOKEN}` } });
const usage = await response.json(); console.log(`API Usage: ${usage.requests_used}/${usage.requests_limit} (${usage.percentage_used}%)`);
// Alert if running low on credits if (usage.percentage_used > 80) { await sendLowCreditAlert(usage); }
return usage;}Airtable Analytics Views
Create these views in Airtable:
- Pending Verifications: Filter by “Verification Status” = “Pending” or “In Progress”
- Disposable Emails: Filter by “Is Disposable” = checked
- Valid Business Emails: Filter by “Status” = “Valid” AND “Is Public Provider” = unchecked
- Verification Errors: Filter by “Status” = “Verification Error”
- Daily Summary: Group by “Submission Date” with counts
Troubleshooting
Common Issues
Issue: Submissions not appearing in Airtable
- Check webhook is configured correctly in Wix Automations
- Verify webhook URL is accessible (test with curl or Postman)
- Check serverless function logs for errors
- Ensure Airtable credentials are correct in environment variables
Issue: Records stuck in “In Progress” status
- Background verification may have failed silently
- Check function logs for errors
- Verify checkboxHQ API key is valid and has credits
- Ensure error handling updates records on failure
Issue: Verification taking too long
- Normal for DNS checks (can take 5-30 seconds)
- This doesn’t affect user experience (they already got confirmation)
- Consider implementing caching for popular domains
- Check if sequential verification strategy could reduce time
Issue: Wix Automation not triggering
- Verify automation is activated (not just saved)
- Check that form is published on live site
- Test with actual form submission (not preview mode)
- Premium Wix plan required for Automations
Issue: CORS errors
- Ensure CORS headers are set in function response
- Check
Access-Control-Allow-Originis set to*or specific domain - Verify OPTIONS method is handled for preflight requests
Issue: Authentication errors from checkboxHQ
- Verify
x-api-keyheader is correctly set - Check API key is active in checkboxHQ dashboard
- Ensure environment variables are deployed (not just local)
- API keys are case-sensitive
Issue: Airtable write failures
- Verify Personal Access Token has write permissions
- Check Base ID and Table Name are exactly correct
- Ensure field names match case-sensitively
- Check you haven’t exceeded Airtable rate limits (5 requests/second)
Debug Mode
Add detailed logging for troubleshooting:
const DEBUG = process.env.NODE_ENV !== 'production';
function log(stage, ...args) { if (DEBUG) { console.log(`[${new Date().toISOString()}] [${stage}]`, ...args); }}
// Usage in your handlerexports.handler = async (event, context) => { log('WEBHOOK', 'Received submission:', event.body);
const email = payload.email; log('PARSED', 'Email extracted:', email);
await storeInitialSubmission(email, name, formName, submissionId); log('STORAGE', 'Initial record created:', submissionId);
verifyAndUpdateAsync(email, submissionId).catch(error => { log('VERIFY-ERROR', 'Background verification failed:', error); });
log('RESPONSE', 'Returning success to Wix');
return { statusCode: 200, body: JSON.stringify({ success: true }) };};Security Best Practices
1. Never Expose API Keys
// ❌ WRONG - Don't hardcode keysconst API_KEY = 'sk_live_abc123';
// ✅ CORRECT - Use environment variablesconst API_KEY = process.env.CHECKBOX_API_KEY;2. Validate Webhook Source
// Verify webhook is actually from Wixfunction isValidWixWebhook(event) { // Check user agent const userAgent = event.headers['user-agent']; if (!userAgent || !userAgent.includes('Wix')) { return false; }
// Additional verification can be added here return true;}3. Rate Limiting
// Simple rate limiting by IPconst submissions = new Map();
function checkRateLimit(ip) { const now = Date.now(); const userSubmissions = submissions.get(ip) || []; const recentSubmissions = userSubmissions.filter( time => now - time < 60000 // Last minute );
if (recentSubmissions.length >= 5) { throw new Error('Rate limit exceeded - max 5 submissions per minute'); }
submissions.set(ip, [...recentSubmissions, now]); return true;}4. Input Validation
function validateEmail(email) { // Basic format validation const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(email)) { throw new Error('Invalid email format'); }
// Length validation if (email.length > 254) { throw new Error('Email too long'); }
return true;}Cost-Benefit Analysis
Per-Submission Cost Breakdown
Infrastructure Costs (Free Tier Sufficient for Most):
- Airtable Free: 1,200 records/month
- Netlify Free: 125,000 function invocations/month
- Vercel Free: 100,000 function invocations/month
Verification Costs:
Scenario 1: Basic validation (disposable + public provider)
- checkboxHQ: 2 credits per submission
- Best for: Basic lead quality scoring
- Use case: Newsletter signups, content downloads
Scenario 2: Comprehensive validation (all checks)
- checkboxHQ: 4 credits per submission (disposable + public + DNS)
- Best for: Sales leads, high-value conversions
- Use case: Demo requests, contact sales forms
Scenario 3: Smart sequential validation
- checkboxHQ: 1-4 credits (adaptive based on results)
- Check disposable first (1 credit)
- Only check DNS if not disposable (saves 2 credits on 30-40% of submissions)
- Best for: Cost optimization with high volume
ROI Calculation: Blocking vs Non-Blocking
Example: 1,000 Monthly Form Submissions
| Metric | Blocking Verification | Non-Blocking (checkboxHQ) |
|---|---|---|
| Form Response Time | 3-5 seconds | <1 second |
| Conversion Rate | 8% (industry avg with delays) | 10% (no delay penalty) |
| Actual Conversions | 80 submissions | 100 submissions |
| Lost Opportunities | 20 submissions | 0 submissions |
| Customer Value | Missed $2,000+ potential revenue | Full capture |
The Math:
- 2-second delay = 10-20% conversion loss
- Non-blocking captures 100% of interested visitors
- Lost conversion costs far exceed verification API costs
Recommended Strategy
Start with comprehensive validation (4 credits):
- Captures all leads (no blocking)
- Full verification data for segmentation
- Optimize later based on your form quality patterns
- Worth the investment to maintain high conversion rates
When you reach high volume (>10,000/month):
- Implement smart sequential validation (saves 30-40% on credits)
- Add domain caching (saves another 20-30%)
- Batch processing for efficiency
Alternative Platforms
Vercel Functions
export default async function handler(req, res) { // Set CORS headers res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === 'OPTIONS') { return res.status(200).end(); }
if (req.method !== 'POST') { return res.status(405).json({ error: 'Method not allowed' }); }
// Same logic as Netlify function // ...}Cloudflare Workers
addEventListener('fetch', event => { event.respondWith(handleRequest(event.request))})
async function handleRequest(request) { // Handle CORS if (request.method === 'OPTIONS') { return new Response(null, { headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type' } }) }
// Same logic adapted for Cloudflare Workers // ...}Next Steps
- Test the integration with various email types
- Monitor API usage in using checkboxHQ’s billing endpoint
- Set up alerts for low credit balance
- Create Airtable views to analyze submission quality
- Build automations with Airtable + Zapier/Make for follow-up workflows
- A/B test different form configurations
- Review analytics monthly to optimize verification strategy
Support Resources
- checkboxHQ: [email protected]
- Wix Support: https://support.wix.com
- Airtable Support: https://support.airtable.com
- Netlify Functions: https://docs.netlify.com/functions/overview
Additional Resources
- checkboxHQ API Documentation
- Wix Automations Guide
- Wix Webhooks Documentation
- Airtable API Documentation
- Netlify Functions Guide