Get API key
← Code samples
Forms

WordPress (Contact Form 7)

Protect every Contact Form 7 form from bots, spam, and disposable email addresses with Verifence Shield — no changes to your form templates required.

A drop-in plugin that protects every Contact Form 7 form on your site with Verifence Shield, a honeypot, and optional email validation. It injects the widget and hooks into CF7's built-in spam pipeline, so no changes to your form templates are needed.

What it does

ProtectionHow
Bot blockingInvisible proof-of-work challenge + browser fingerprinting via Shield
HoneypotHidden field injected into every form — bots that fill it are silently blocked
Behavioural analysisTiming, mouse movement, and keystroke variance checked on the Shield side
Spam text classificationMessage body scored for spam probability (requires spam detection enabled)
Email validationDisposable and role-account addresses blocked via the scan API (optional)

Requirements

  • WordPress 5.8+ and PHP 8.0+
  • Contact Form 7 5.5 or higher
  • A Verifence account with a Shield site configured

Configuration

In your Verifence dashboard, open Shield Sites, copy the site key and secret key, and set the allowed domain to your WordPress domain. Then, in WordPress under Settings → Verifence Shield, fill in:

SettingDescription
Site KeyPublic key from your Shield site
Secret KeyPrivate key — never exposed to browsers
API Key(Optional) Verifence API key for email validation
Enable email validationBlocks disposable email addresses at submission
Block role accountsAlso blocks info@, admin@, support@, etc.
Spam score thresholdSubmissions above this % spam probability are blocked (default: 85)
Message field nameThe CF7 field name of your message textarea (default: your-message)

How it works

Browser phase (automatic)

When a page with a CF7 form loads, the plugin injects a .shield-widget element (with your site key) and a honeypot field into every form. The widget renders invisibly, adds its own hidden shield-token field, runs the proof-of-work challenge and behavioural checks, and populates shield-token with a signed token before CF7 sends the AJAX request. This is the exact snippet the plugin adds:

JavaScript
function addShieldFields(form) {
  if (form.querySelector('.shield-widget')) return;

  var siteKey = (window.vcf7Shield && window.vcf7Shield.siteKey) || '';
  if (!siteKey) return;

  // Shield widget container — renders here and injects a hidden
  // "shield-token" field it populates with a signed token on submit.
  var widget = document.createElement('div');
  widget.className = 'shield-widget';
  widget.setAttribute('data-sitekey', siteKey);
  form.appendChild(widget);

  if (typeof Shield !== 'undefined') {
    Shield.render(widget);
  }
  // ...also injects a visually-hidden honeypot field
}

document.addEventListener('DOMContentLoaded', function () {
  document.querySelectorAll('.wpcf7-form').forEach(addShieldFields);
});

// CF7 re-renders forms after AJAX — re-inject on wpcf7:init
document.addEventListener('wpcf7:init', function (e) {
  var root = (e.detail && e.detail.apiResponse) ? e.target : document;
  root.querySelectorAll('.wpcf7-form').forEach(addShieldFields);
});

Server phase (on every submission)

When CF7 processes the form, the plugin:

  • Blocks immediately if the honeypot field is non-empty.
  • Reads the widget-populated shield-token and calls /api/shield/siteverify with the token, email, and message text.
  • Blocks if success is false, or if the spam score exceeds your threshold.
  • If email validation is enabled, checks the email against /api/scan/email for disposable and role addresses.
  • Otherwise lets CF7 proceed normally and send the email.
PHP — server-side read
// The Shield widget injects and populates a field named "shield-token".
$token = isset( $_POST['shield-token'] )
    ? sanitize_text_field( wp_unslash( $_POST['shield-token'] ) )
    : '';

$result = $this->post_json( '/api/shield/siteverify', [
    'secret' => $this->option( 'secret_key' ),
    'token'  => $token,
    'email'  => $email,
    'text'   => $message,
] );

if ( empty( $result['success'] ) ) {
    return true; // treated as spam by CF7 — submission blocked
}

Fail-open behaviour

If the Verifence API is unreachable (network error, timeout), the plugin fails open — it does not block the submission, so a temporary outage never stops legitimate contact-form traffic.

JavaScript disabled? The widget never renders, so shield-token is empty. Shield treats an empty token as fail-open and siteverify returns { "success": true, "degraded": true } — the submission is allowed, not blocked, so a genuine visitor with a script blocker still gets through. The honeypot and (if enabled) email validation still run on every submission.

Notes

  • Works alongside CF7's own CAPTCHA and Flamingo — it adds to the spam pipeline rather than replacing anything.
  • The secret key is stored in wp_options and only ever sent server-to-server over HTTPS. It is never exposed to the browser.
  • When a submission is blocked, CF7 shows its standard spam-rejection message, which you can customise under CF7's Messages settings.

Ready to build it?

Create a free account and grab an API key in minutes.

Get started free