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
- Configure the site’s reCAPTCHA v3 – Site Key and reCAPTCHA v3 – Secret Key under Breakdance > Settings > API Keys.
- On the form, enable reCAPTCHA and use Default credentials. This example uses the shared site key, not a form-specific custom key.
- Add the following code to a custom plugin or a PHP snippets plugin that runs on front-end requests. Replace both occurrences of
contactwith the form page’s slug.
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 = 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>
}, 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
- Reload the target page with the browser’s Network panel open. Before interacting, confirm that no
recaptcha/api.jsrequest has started. - Move the pointer or focus a form field with the keyboard. Confirm that the script loads once.
- Submit the form, including an immediate submission on a slow connection, and confirm that reCAPTCHA verification completes.
- 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.