WordPress Contact Form 7 Email Verification Guide | checkboxHQ

checkboxHQ Team
WordPress Email Verification Contact Form 7 CF7 Email Validation WordPress Email Validation Contact Form 7 Integration Google Sheets Integration WordPress Plugin Email Verification Plugin Disposable Email Detection WordPress Forms CF7 Validation Non-blocking Verification Background Email Validation

Table of Contents

  1. Overview
  2. Prerequisites
  3. Architecture
  4. Setup Instructions
  5. Plugin Code
  6. Testing
  7. Optimization Strategies
  8. Troubleshooting

Overview

This guide shows you how to integrate checkboxHQ email verification with WordPress Contact Form 7, storing validated results in Google Sheets. The integration uses a non-blocking verification pattern - users receive instant form confirmation while email verification happens asynchronously in the background.

Key Features

  • Real-time email verification via checkboxHQ API
  • Non-blocking user experience (no form delays)
  • Automatic storage in Google Sheets
  • Domain caching to reduce API costs
  • WordPress dashboard analytics widget
  • Multisite compatible

Use Cases

  • Lead capture forms with quality assurance
  • Newsletter signups requiring valid emails
  • Contact forms where email deliverability matters
  • Registration forms needing disposable email blocking

Prerequisites

Required Accounts

  1. checkboxHQ Account - Register here

    • Get your API key from dashboard
    • Note your credit balance
  2. Google Cloud Account - Console

    • Enable Google Sheets API
    • Create service account credentials
  3. WordPress Site

    • WordPress 5.0 or higher
    • Contact Form 7 plugin installed
    • PHP 7.4 or higher

Required Plugins

Terminal window
# Install Contact Form 7
wp plugin install contact-form-7 --activate
# Our custom plugin (code provided below)

Architecture

Data Flow

User submits form
Contact Form 7 processes submission
Form success message shown to user (instant)
wp_cron schedules background job
checkboxHQ API verifies email
Results written to Google Sheets
Admin notification (optional)

Why Non-Blocking?

Blocking approach (bad):

// User waits 2-5 seconds for API response
$result = verify_email($email);
if ($result['valid']) {
send_confirmation();
}

Non-blocking approach (good):

// User sees instant success
send_confirmation();
// Verification happens in background
wp_schedule_single_event(time(), 'verify_email_async', [$email]);

Setup Instructions

Step 1: Create Google Service Account

  1. Go to Google Cloud Console

  2. Create new project: “checkboxHQ Integration”

  3. Enable Google Sheets API:

    • Navigate to “APIs & Services” → “Library”
    • Search “Google Sheets API”
    • Click “Enable”
  4. Create Service Account:

    • Go to “APIs & Services” → “Credentials”
    • Click “Create Credentials” → “Service Account”
    • Name: checkboxhq-wordpress
    • Role: “Editor”
    • Click “Done”
  5. Generate JSON Key:

    • Click on created service account
    • Go to “Keys” tab
    • “Add Key” → “Create new key” → “JSON”
    • Download the JSON file (keep it secure!)

Step 2: Create Google Sheet

  1. Create new Google Sheet: “Email Verifications”
  2. Add headers in row 1:
| Timestamp | Email | Valid | Deliverable | Disposable | Domain | Risk Score | Source Form |
  1. Share with service account:
    • Click “Share” button
    • Paste service account email (from JSON file: client_email)
    • Grant “Editor” access
    • Copy Sheet ID from URL: https://docs.google.com/spreadsheets/d/{SHEET_ID}/edit

Step 3: Install WordPress Plugin

Create file: wp-content/plugins/checkboxhq-cf7/checkboxhq-cf7.php


Plugin Code

Main Plugin File

<?php
/**
* Plugin Name: checkboxHQ Contact Form 7 Integration
* Plugin URI: https://checkboxhq.com/integrations/wordpress-cf7
* Description: Verify emails submitted via Contact Form 7 using checkboxHQ API and store in Google Sheets
* Version: 1.0.0
* Author: Your Name
* Author URI: https://yoursite.com
* License: GPL v2 or later
* Requires at least: 5.0
* Requires PHP: 7.4
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
class checkboxHQ_CF7_Integration {
private $api_key;
private $sheet_id;
private $service_account_file;
public function __construct() {
// Load settings
$this->api_key = get_option('checkboxhq_api_key');
$this->sheet_id = get_option('checkboxhq_sheet_id');
$this->service_account_file = WP_CONTENT_DIR . '/checkboxhq-service-account.json';
// Hooks
add_action('wpcf7_mail_sent', [$this, 'handle_form_submission']);
add_action('verify_email_checkboxhq', [$this, 'verify_email_async'], 10, 2);
add_action('admin_menu', [$this, 'add_settings_page']);
add_action('admin_init', [$this, 'register_settings']);
add_action('wp_dashboard_setup', [$this, 'add_dashboard_widget']);
}
/**
* Handle CF7 form submission (non-blocking)
*/
public function handle_form_submission($contact_form) {
$submission = WPCF7_Submission::get_instance();
if (!$submission) {
return;
}
$posted_data = $submission->get_posted_data();
// Extract email (adjust field name as needed)
$email = isset($posted_data['your-email']) ? sanitize_email($posted_data['your-email']) : '';
if (!$email || !is_email($email)) {
return;
}
// Get form title for tracking
$form_title = $contact_form->title();
// Schedule async verification (non-blocking)
wp_schedule_single_event(
time() + 10, // 10 second delay to avoid rate limits
'verify_email_checkboxhq',
[$email, $form_title]
);
// Log submission
$this->log_message("Scheduled verification for: $email from form: $form_title");
}
/**
* Verify email asynchronously via checkboxHQ API
*/
public function verify_email_async($email, $form_title) {
// Check domain cache first (cost optimization)
$domain = substr(strrchr($email, "@"), 1);
$cached_result = $this->get_cached_domain_result($domain);
if ($cached_result !== false) {
$this->log_message("Using cached result for domain: $domain");
$this->write_to_google_sheets($email, $cached_result, $form_title);
return;
}
// Call checkboxHQ API
$response = wp_remote_get(
'https://api.checkboxhq.com/verify/' . urlencode($email),
[
'headers' => [
'Authorization' => 'Bearer ' . $this->api_key,
'Content-Type' => 'application/json'
],
'timeout' => 15
]
);
if (is_wp_error($response)) {
$this->log_message("API Error: " . $response->get_error_message());
return;
}
$status_code = wp_remote_retrieve_response_code($response);
$body = wp_remote_retrieve_body($response);
$result = json_decode($body, true);
if ($status_code !== 200 || !isset($result['valid'])) {
$this->log_message("Invalid API response for: $email");
return;
}
// Cache domain result for common domains
$this->cache_domain_result($domain, $result);
// Write to Google Sheets
$this->write_to_google_sheets($email, $result, $form_title);
// Optional: Send admin notification for invalid emails
if (!$result['valid']) {
$this->notify_admin_invalid_email($email, $form_title);
}
}
/**
* Write verification result to Google Sheets
*/
private function write_to_google_sheets($email, $result, $form_title) {
if (!file_exists($this->service_account_file)) {
$this->log_message("Service account file not found");
return;
}
// Load Google Sheets library (install via Composer)
require_once __DIR__ . '/vendor/autoload.php';
try {
$client = new \Google_Client();
$client->setAuthConfig($this->service_account_file);
$client->addScope(\Google_Service_Sheets::SPREADSHEETS);
$service = new \Google_Service_Sheets($client);
// Prepare row data
$row = [
date('Y-m-d H:i:s'), // Timestamp
$email,
$result['valid'] ? 'TRUE' : 'FALSE',
$result['deliverable'] ?? 'N/A',
$result['disposable'] ?? 'FALSE',
$result['domain'] ?? '',
$result['risk_score'] ?? 0,
$form_title
];
$values = [$row];
$body = new \Google_Service_Sheets_ValueRange(['values' => $values]);
$params = ['valueInputOption' => 'RAW'];
$service->spreadsheets_values->append(
$this->sheet_id,
'Sheet1!A:H', // Adjust range as needed
$body,
$params
);
$this->log_message("Successfully wrote to Google Sheets: $email");
} catch (Exception $e) {
$this->log_message("Google Sheets Error: " . $e->getMessage());
}
}
/**
* Cache domain verification results (reduce API costs)
*/
private function cache_domain_result($domain, $result) {
$cache_key = 'checkboxhq_domain_' . md5($domain);
set_transient($cache_key, $result, 7 * DAY_IN_SECONDS); // Cache for 7 days
}
private function get_cached_domain_result($domain) {
$cache_key = 'checkboxhq_domain_' . md5($domain);
return get_transient($cache_key);
}
/**
* Send notification for invalid emails
*/
private function notify_admin_invalid_email($email, $form_title) {
$admin_email = get_option('admin_email');
$subject = "[CheckBoxHQ] Invalid email detected: $email";
$message = "An invalid email was submitted via form: $form_title\n\n";
$message .= "Email: $email\n";
$message .= "Time: " . date('Y-m-d H:i:s') . "\n";
wp_mail($admin_email, $subject, $message);
}
/**
* Logging helper
*/
private function log_message($message) {
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('[CheckBoxHQ CF7] ' . $message);
}
}
/**
* Settings page
*/
public function add_settings_page() {
add_options_page(
'checkboxHQ Settings',
'checkboxHQ',
'manage_options',
'checkboxhq-settings',
[$this, 'render_settings_page']
);
}
public function register_settings() {
register_setting('checkboxhq_settings', 'checkboxhq_api_key');
register_setting('checkboxhq_settings', 'checkboxhq_sheet_id');
}
public function render_settings_page() {
?>
<div class="wrap">
<h1>checkboxHQ Settings</h1>
<form method="post" action="options.php">
<?php settings_fields('checkboxhq_settings'); ?>
<table class="form-table">
<tr>
<th scope="row">API Key</th>
<td>
<input type="text" name="checkboxhq_api_key"
value="<?php echo esc_attr($this->api_key); ?>"
class="regular-text" />
<p class="description">Get your API key from <a href="https://checkboxhq.com/dashboard" target="_blank">checkboxHQ Dashboard</a></p>
</td>
</tr>
<tr>
<th scope="row">Google Sheet ID</th>
<td>
<input type="text" name="checkboxhq_sheet_id"
value="<?php echo esc_attr($this->sheet_id); ?>"
class="regular-text" />
<p class="description">Find in Sheet URL: docs.google.com/spreadsheets/d/<strong>SHEET_ID</strong>/edit</p>
</td>
</tr>
<tr>
<th scope="row">Service Account JSON</th>
<td>
<p class="description">Upload file to: <code><?php echo $this->service_account_file; ?></code></p>
<p class="description">
<?php if (file_exists($this->service_account_file)): ?>
File found
<?php else: ?>
File not found
<?php endif; ?>
</p>
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
<?php
}
/**
* Dashboard widget showing verification stats
*/
public function add_dashboard_widget() {
wp_add_dashboard_widget(
'checkboxhq_stats',
'Email Verification Stats',
[$this, 'render_dashboard_widget']
);
}
public function render_dashboard_widget() {
// Get stats from transients or calculate
$total = get_transient('checkboxhq_total_verified') ?: 0;
$valid = get_transient('checkboxhq_valid_emails') ?: 0;
$invalid = get_transient('checkboxhq_invalid_emails') ?: 0;
echo '<div class="checkboxhq-stats">';
echo '<p><strong>Total Verified:</strong> ' . number_format($total) . '</p>';
echo '<p><strong>Valid:</strong> ' . number_format($valid) . ' (' . ($total > 0 ? round($valid/$total*100, 1) : 0) . '%)</p>';
echo '<p><strong>Invalid:</strong> ' . number_format($invalid) . '</p>';
echo '<p><a href="https://docs.google.com/spreadsheets/d/' . $this->sheet_id . '" target="_blank">View Google Sheet →</a></p>';
echo '</div>';
}
}
// Initialize plugin
new checkboxHQ_CF7_Integration();

Install Dependencies

Create composer.json in plugin directory:

{
"require": {
"google/apiclient": "^2.0"
}
}

Run:

Terminal window
cd wp-content/plugins/checkboxhq-cf7
composer install

Testing

Test Checklist

  1. API Connection Test
Terminal window
# Test from command line
curl -X GET "https://api.checkboxhq.com/verify/[email protected]" \
-H "Authorization: Bearer YOUR_API_KEY"
  1. Form Submission Test

    • Submit test email via Contact Form 7
    • Check WP cron: wp cron event list
    • Verify scheduled job appears
  2. Google Sheets Test

    • Manually trigger cron: wp cron event run verify_email_checkboxhq
    • Check Google Sheet for new row
    • Verify all columns populated
  3. Cache Test

    • Submit same domain twice
    • Check debug log for “Using cached result”
    • Verify only 1 API call made

Debug Mode

Enable WordPress debug logging:

wp-config.php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);

Check logs: wp-content/debug.log


Optimization Strategies

1. Domain Caching

Reduces API costs by caching results for common domains:

// Gmail, Outlook, etc. cached for 7 days
// Reduces API calls by ~60% for typical forms

Savings Example:

  • 1,000 form submissions/month
  • 40% are Gmail/Outlook/Yahoo
  • Without caching: 1,000 API calls
  • With caching: ~600 API calls
  • Savings: 400 credits/month

2. Batch Processing

For high-volume sites, process in batches:

// Instead of individual wp_cron jobs
wp_schedule_event(time(), 'hourly', 'process_email_batch');
function process_email_batch() {
$emails = get_pending_verifications(); // Custom queue
foreach ($emails as $email) {
// Verify and write to sheets
usleep(100000); // 100ms delay between calls
}
}

3. Rate Limiting

Prevent abuse and quota exhaustion:

// Max 100 verifications per hour per IP
$ip = $_SERVER['REMOTE_ADDR'];
$limit_key = 'checkboxhq_limit_' . md5($ip);
$count = get_transient($limit_key) ?: 0;
if ($count >= 100) {
// Block or queue for later
return;
}
set_transient($limit_key, $count + 1, HOUR_IN_SECONDS);

4. Selective Verification

Only verify emails from specific forms:

// In handle_form_submission()
$verify_forms = ['Contact Form', 'Newsletter Signup'];
if (!in_array($form_title, $verify_forms)) {
return; // Skip verification
}

Troubleshooting

Common Issues

1. “Service account file not found”

Terminal window
# Upload JSON file to correct location
wp-content/checkboxhq-service-account.json
# Check file permissions
chmod 600 checkboxhq-service-account.json

2. “Invalid API key”

  • Verify key in checkboxHQ dashboard
  • Check for extra spaces in settings
  • Ensure key has not expired

3. “Permission denied” (Google Sheets)

  • Verify service account email is shared on sheet
  • Grant “Editor” role (not “Viewer”)
  • Check Sheet ID is correct

4. “Cron not running”

Terminal window
# Check if cron is disabled
wp option get disable_cron
# Manually run pending jobs
wp cron event run --due-now
# Setup server cron (better for production)
# Add to crontab:
*/5 * * * * wp cron event run --due-now --path=/var/www/html

5. API rate limit exceeded

  • Implement domain caching (see optimization)
  • Add delay between verification calls
  • Consider upgrading checkboxHQ plan

Debug Commands

Terminal window
# List all scheduled events
wp cron event list
# Test cron manually
wp cron test
# Clear transient cache
wp transient delete --all
# Check plugin status
wp plugin list
# View recent error logs
tail -f wp-content/debug.log

Security Best Practices

1. Protect API Keys

// Store in wp-config.php instead of database
define('CHECKBOXHQ_API_KEY', 'your-key-here');
// Access in code
$api_key = defined('CHECKBOXHQ_API_KEY') ? CHECKBOXHQ_API_KEY : get_option('checkboxhq_api_key');

2. Validate Input

// Always sanitize emails
$email = sanitize_email($posted_data['your-email']);
// Verify email format
if (!is_email($email)) {
return;
}

3. Restrict File Access

.htaccess
// Add to service account JSON file location
<Files "checkboxhq-service-account.json">
Order allow,deny
Deny from all
</Files>

4. Use HTTPS

Ensure WordPress site uses HTTPS for all API communications.


Advanced Features

Custom Analytics Dashboard

public function get_verification_stats() {
require_once __DIR__ . '/vendor/autoload.php';
$client = new \Google_Client();
$client->setAuthConfig($this->service_account_file);
$client->addScope(\Google_Service_Sheets::SPREADSHEETS);
$service = new \Google_Service_Sheets($client);
$response = $service->spreadsheets_values->get(
$this->sheet_id,
'Sheet1!A:H'
);
$values = $response->getValues();
// Calculate stats
$total = count($values) - 1; // Exclude header
$valid = 0;
$disposable = 0;
foreach (array_slice($values, 1) as $row) {
if (isset($row[2]) && $row[2] === 'TRUE') $valid++;
if (isset($row[4]) && $row[4] === 'TRUE') $disposable++;
}
// Cache for 1 hour
set_transient('checkboxhq_total_verified', $total, HOUR_IN_SECONDS);
set_transient('checkboxhq_valid_emails', $valid, HOUR_IN_SECONDS);
set_transient('checkboxhq_invalid_emails', $total - $valid, HOUR_IN_SECONDS);
return compact('total', 'valid', 'disposable');
}

Webhook Notifications

// Notify external service on verification
add_action('checkboxhq_email_verified', function($email, $result) {
wp_remote_post('https://your-webhook.com/endpoint', [
'body' => json_encode([
'email' => $email,
'valid' => $result['valid'],
'timestamp' => time()
])
]);
}, 10, 2);

Performance Benchmarks

Typical Performance Metrics

MetricValue
Form submission response time<100ms
Background verification time1-3 seconds
Google Sheets write time500ms - 1s
Total time (async)2-5 seconds
User-perceived delay0ms

Scaling Considerations

Small sites (<100 form submissions/day):

  • Current setup works perfectly
  • No optimization needed

Medium sites (100-1,000 form submissions/day):

  • Enable domain caching
  • Consider batch processing
  • Monitor checkboxHQ credit usage, consider upgrading

Large sites (1,000+ forms/day):

  • Implement all optimizations
  • Use dedicated worker server
  • Consider database instead of Sheets

Next Steps

  1. Install Plugin: Copy code and activate
  2. Configure API: Add checkboxHQ API key
  3. Setup Google Sheets: Create service account and sheet
  4. Test Integration: Submit test forms
  5. Monitor Results: Check Google Sheets populate
  6. Optimize: Enable caching for cost savings

Additional Resources


Support

Need help? Contact support:

  • checkboxHQ Support: [email protected]
  • WordPress Forums: wordpress.org/support
  • GitHub Issues: github.com/your-repo/issues

Additional Resources