Skip to content
WordPress Tutorials

Elementor Form Spam: Stopping Junk Inside the Page Builder

· 8 min read

Elementor passed 10 million active installations on WordPress.org, which puts it in the same tier as Yoast and Contact Form 7. A large share of those sites collect enquiries through the Pro form widget, and a large share of those were built by a designer, signed off by a client, and never opened by a developer again.

That combination is why Elementor form spam is such a persistent complaint. The protection on offer is real but narrow, the submissions land in three places at once, and there is rarely anybody watching the site closely enough to notice the filter has stopped working.

What Elementor Gives You

The Pro form widget exposes spam protection as field types. Elementor's own developer documentation lists reCAPTCHA, reCAPTCHA v3 and Honeypot among the registered fields; there is no native hCaptcha or Turnstile option, so those arrive via third-party addons or a general-purpose plugin.

Both built-in options are worth having and both stop at the same line. The honeypot detects automation that fills every field it can see, which is a shrinking share of the automation actually hitting your forms. Imperva put automated traffic at more than 53% of all web activity in 2025, with the report's focus now on agents that behave like people rather than scripts that fill every input. reCAPTCHA scores the session, and since Google moved it into Google Cloud its free allowance is 10,000 assessments a month counted per organisation, aggregated across every site and key you run. That is a problem if you look after a portfolio.

Neither one reads the message.

Why That Matters More In Elementor Than Elsewhere

On a bare contact form, a junk submission is an email you delete. In Elementor it is usually three things at once.

The submission is written to the Submissions screen in the admin, where it stays until someone clears it. It is emailed to whoever the form notifies. And if the form has actions attached (Mailchimp, a CRM integration, a webhook into an automation platform) it is pushed straight down that pipe as a new contact.

So one fake enquiry becomes a stored record, a notification, a mailing-list subscriber with a fake address, and a CRM contact that will never convert. That is the ripple we traced across an entire business a few months ago, starting from a single form.

Elementor reports more than 10 million active installations. reCAPTCHA's free allowance is 10,000 assessments a month per Google Cloud organisation, aggregated across all of your accounts and sites. Sources: WordPress.org, 2026; Google Cloud documentation, 2026

The Validation Hook

Elementor Pro fires elementor_pro/forms/validation after the forms module loads and before actions run, passing the form record and an AJAX handler. Add an error through the handler and the submission is rejected: nothing is stored, nothing is emailed, no integration fires.

add_action( 'elementor_pro/forms/validation', function ( $record, $ajax_handler ) {
// Target the message field by the custom ID set in the Elementor editor.
$fields = $record->get_field( array( 'id' => 'message' ) );
if ( empty( $fields ) ) {
    return;
}

$field = current( $fields );
$text  = trim( $field['value'] );
if ( $text === '' ) {
    return;
}

$response = wp_remote_post( 'https://api.babelshield.com/v1/score', array(
    'headers' => array(
        'Authorization' => 'Bearer ' . BABELSHIELD_API_KEY,
        'Content-Type'  => 'application/json',
    ),
    'body'    => wp_json_encode( array( 'text' => $text ) ),
    'timeout' => 3,
) );

if ( is_wp_error( $response ) ) {
    // Fail open: a moderation outage must not block real enquiries.
    error_log( 'Babelshield unreachable: ' . $response->get_error_message() );
    return;
}

$scores = json_decode( wp_remote_retrieve_body( $response ), true );
error_log( 'Elementor submission scored: ' . wp_json_encode( $scores ) );

if ( ( $scores['spam'] ?? 0 ) > 0.8
  || ( $scores['junk'] ?? 0 ) > 0.85
  || ( $scores['hate'] ?? 0 ) > 0.5 ) {

    $message = esc_html__( 'Your message could not be processed. Please review it and try again.', 'your-textdomain' );
    $ajax_handler->add_error( $field['id'], $message );
    $ajax_handler->add_error_message( $message );
}

}, 10, 2 );

(Endpoint, field names and thresholds are illustrative. Check the current Babelshield docs and tune to your own forms.)

Two Elementor details make or break this. First, give the message field a stable custom ID in the editor, message rather than the auto-generated one, because auto IDs change when the form is rebuilt and a designer will rebuild the form. Second, calling both add_error() and add_error_message() puts the message against the field and in the form-level notice, which is the combination that behaves predictably across Elementor's display settings.

If you want to score a specific field type across every form on the site instead, elementor_pro/forms/validation/{$field_type} fires per field and receives the field, the record and the handler.

First, Check Whose Form It Actually Is

Plenty of Elementor sites never use the Pro form widget. The designer dropped a shortcode into the layout and the form itself is Gravity Forms, Contact Form 7 or WPForms. The symptom looks identical from the client's side, so check the markup before you write any code: if the submission is not going through Elementor, the hook above will never fire. On a Gravity Form embedded in an Elementor page the hook you want is gform_entry_is_spam, and the page builder is irrelevant to the fix.

Put It Somewhere It Will Survive

The standard advice is the child theme's functions.php. On an Elementor site that is the wrong place, because the theme is the thing most likely to be swapped, rebuilt or replaced by the next person who touches the project. Put the snippet in a small must-use plugin, or a code-snippets plugin the client will not uninstall. Protection that disappears during a redesign is worse than no protection, because nobody goes looking for it.

While you are there, add a comment naming what the code does and where the API key lives. The developer who inherits this site in two years will thank you, and on an Elementor build there is usually more than one.

Flag Rather Than Block

Hard rejection is right for an obviously abusive submission and risky on a high-value lead form. If the client's business depends on enquiries, consider a middle path: block only above a high threshold, and for the borderline band let the submission through while writing the scores into a hidden field on the form. The entry lands in Submissions carrying its own scores, so whoever triages the queue can sort by them and you keep a complete record of every decision.

Start in observation mode either way. Score and log for a week without acting, look at where genuine enquiries sit against the junk, and set the thresholds in the gap. On most Elementor contact forms that gap is wide.

What The Client Notices

Nothing, which is the point. The form looks and behaves exactly as designed, with no puzzle in the flow and no third-party widget slowing the page down. The Submissions screen stops filling with promotional pitches. The mailing list stops collecting addresses that bounce. The enquiries that arrive are enquiries.

Elementor gives you a fast, visual way to build a form. Give it a check that reads what the form collects, and it stops being the easiest door on the site to walk through.

References

Elementor Developers. Form fields reference (reCAPTCHA, reCAPTCHA V3, Honeypot) and form validation hooks.

WordPress.org. Elementor plugin directory listing and installation statistics, 2026.

Google Cloud. reCAPTCHA billing and free-tier changes, 2024.

Imperva/Thales. "2026 Bad Bot Report: Bots in the Agentic Age."