Spam Protection
Core Forms provides five layers of spam protection that can be used individually or combined. Spam submissions are stored in the database (marked as spam) but do not trigger any actions.
Protection Methods
1. Honeypot Field (Default On)
A hidden field that legitimate users never see or fill in. Bots that auto-fill all fields will be caught. This is enabled by default on all forms with no configuration required.
The honeypot field is rendered inside the form automatically and hidden with CSS. If it contains a value on submission, the submission is flagged as spam.
2. Google reCAPTCHA v3
Invisible score-based CAPTCHA that runs in the background without user interaction.
Setup:
- Go to Core Forms > Settings > Spam Protection
- Enter your reCAPTCHA v3 Site Key and Secret Key
- Save settings
reCAPTCHA is automatically added to all forms when configured. It evaluates user behavior and assigns a score (0.0 to 1.0). Scores below the threshold are flagged as spam.
// The reCAPTCHA integration hooks into form validation
add_filter( 'cf_validate_form', [ $recaptcha, 'validate_recaptcha' ], 10, 3 );
// And adds the reCAPTCHA widget to form markup
add_filter( 'cf_form_markup', [ $recaptcha, 'add_recaptcha_to_form' ], 10, 2 );
// And enqueues the script when a form is rendered
add_filter( 'cf_form_html', [ $recaptcha, 'enqueue_recaptcha_on_form_render' ], 10, 2 );
3. Cloudflare Turnstile
A privacy-focused CAPTCHA alternative from Cloudflare. Presents a simple widget that verifies users without puzzles.
Setup:
- Go to Core Forms > Settings > Spam Protection
- Enter your Turnstile Site Key and Secret Key
- Save settings
add_filter( 'cf_validate_form', [ $turnstile, 'validate_turnstile' ], 10, 3 );
add_filter( 'cf_form_markup', [ $turnstile, 'add_turnstile_to_form' ], 10, 2 );
add_filter( 'cf_form_html', [ $turnstile, 'enqueue_turnstile_on_form_render' ], 10, 2 );
4. Akismet Integration
Leverages the Akismet anti-spam service (requires the Akismet plugin to be installed and configured).
Akismet checks submission content against its global spam database. It runs at a lower priority (20) so it executes after CAPTCHA checks:
add_filter( 'cf_validate_form', [ $akismet, 'check_for_spam' ], 20, 3 );
5. Math CAPTCHA
A simple math question (e.g., "What is 3 + 7?") that bots typically cannot solve. No external service required.
add_filter( 'cf_validate_form', [ $math, 'validate_math_captcha' ], 15, 3 );
add_filter( 'cf_form_markup', [ $math, 'add_math_captcha_to_form' ], 20, 2 );
Validation Order
Spam checks run in priority order via the cf_validate_form filter:
| Priority | Check | Class |
|---|---|---|
| 10 | reCAPTCHA v3 | Recaptcha |
| 10 | Cloudflare Turnstile | Turnstile |
| 15 | Math CAPTCHA | MathCaptcha |
| 20 | Akismet | Akismet |
The honeypot is checked separately during form processing in Forms::process().
Spam Handling
When a submission is flagged as spam:
- The
is_spamflag is set totrueon the submission. - The submission is saved to the database (so you can review false positives).
- No actions are triggered -- no emails, webhooks, or integrations fire.
- A success response is returned to the browser to trick bots into thinking the submission succeeded.
- A
spamanalytics event is recorded for reporting.
Custom Validation
Add your own spam checks using the cf_validate_form filter:
add_filter( 'cf_validate_form', function( $error_code, $form, $data ) {
// If another validator already flagged an error, pass through
if ( '' !== $error_code ) {
return $error_code;
}
// Block submissions with known spam phrases
$spam_phrases = [ 'buy now', 'click here', 'free offer' ];
$message = strtolower( $data['message'] ?? '' );
foreach ( $spam_phrases as $phrase ) {
if ( strpos( $message, $phrase ) !== false ) {
return 'spam';
}
}
return $error_code;
}, 25, 3 );
Recommended Configuration
| Form Type | Recommended Protection |
|---|---|
| Contact form (low traffic) | Honeypot + Math CAPTCHA |
| Contact form (high traffic) | Honeypot + Turnstile or reCAPTCHA |
| Public-facing form | Honeypot + Turnstile + Akismet |
| Internal/logged-in form | Honeypot only |