Skip to main content
Documentation/Developers/APIs/Forms/Lazy-Load reCAPTCHA

Lazy-Load reCAPTCHA

The breakdance_load_recaptcha_script filter controls whether Breakdance enqueues its reCAPTCHA script. A custom loader can defer the download until a visitor interacts with the page while keeping reCAPTCHA enabled on the form.

Breakdance already loads the script asynchronously. Deferring it further gives reCAPTCHA less time to observe the page; Google recommends loading early for better context. See Google’s loading guidance.

Add a Loader for a Form Page

  1. Configure the site’s reCAPTCHA v3 – Site Key and reCAPTCHA v3 – Secret Key under Breakdance > Settings > API Keys.
  2. On the form, enable reCAPTCHA and use Default credentials. This example uses the shared site key, not a form-specific custom key.
  3. Add the following code to a custom plugin or a PHP snippets plugin that runs on front-end requests. Replace both occurrences of contact with the form page’s slug.
PHP
add_filter('breakdance_load_recaptcha_script', function ($load) {
    $site_key = BreakdanceAPIKeysgetKey('recaptcha_site_key');
    return is_page('contact') && $site_key ? false : $load;
});

add_action('wp_head', function () {
    if (!is_page('contact')) {
        return;
    }

    $site_key = BreakdanceAPIKeysgetKey('recaptcha_site_key');
    if (!$site_key) {
        return;
    }
    $url = 'https://www.google.com/recaptcha/api.js?render=' . rawurlencode($site_key);
    ?>
    <script>
    (() => {
        let requested = false;
        const load = () => {
            if (requested || window.grecaptcha?.execute) return;
            requested = true;
            const script = document.createElement('script');
            script.src = <?php echo wp_json_encode($url, JSON_HEX_TAG | JSON_HEX_AMP); ?>;
            script.async = true;
            document.head.appendChild(script);
        };

        // Queue token requests made before the API finishes loading.
        if (!window.grecaptcha) {
            window.grecaptcha = {
                ready(callback) {
                    const config = window.___grecaptcha_cfg ||= {};
                    (config.fns ||= []).push(callback);
                    load();
                }
            };
        }

        ['scroll', 'mousemove', 'pointerdown', 'touchstart', 'keydown', 'focusin']
            .forEach(event => window.addEventListener(event, load, {
                once: true, passive: true, capture: true
            }));
    })();
    </script>
    <?php
}, 1);

The filter receives a boolean, initially true. Returning false suppresses Breakdance’s script enqueue; it does not disable server-side verification. Pages outside the condition retain the previous filter value.

The loader starts on the first listed interaction. Its grecaptcha.ready() queue also starts the download if a form requests a token before an interaction occurs, then waits for the API to load. Only the public site key goes into the script; the secret key remains in WordPress.

Verify Deferred Loading

  1. Reload the target page with the browser’s Network panel open. Before interacting, confirm that no recaptcha/api.js request has started.
  2. Move the pointer or focus a form field with the keyboard. Confirm that the script loads once.
  3. Submit the form, including an immediate submission on a slow connection, and confirm that reCAPTCHA verification completes.
  4. Check another page with a protected form; its normal script loading should continue.

Other plugins or custom code can load reCAPTCHA independently. If the request still starts before interaction, inspect its initiator. A blocked or failed download prevents token creation; do not turn off form verification to hide a loading error.

See Spam Protection and Advanced Options for the form’s built-in controls.