How do I defer Google Recaptcha V3
9 posts by 2 authors in: Forums > CMS Builder
Last Post: August 5, 2022 (RSS)
By JeffC - July 30, 2022
Hi
I am using the Google Recaptcha V3 plugin (recaptchaPluginV3.php). Everything works great without using async but it's slowing the loading of my page. To defer it I assume I need to add async to line 167 of the plugin like this:
function recaptcha_displayHeaders($action = 'default') {
if(isset($GLOBALS['INCLUDE_RECAPTCHA'])):
?>
<script async src="https://www.google.com/recaptcha/api.js?render=<?php echo urlencode(recaptcha_settings('site_key')); ?>"></script>
<script>
grecaptcha.ready(function() {
grecaptcha.execute('<?php echo urlencode(recaptcha_settings('site_key')); ?>', {action: <?php echo json_encode(recaptcha_settings('page')); ?>}).then(function(token) {
document.getElementById("g-recaptcha-response").value = token;
});
});
</script>
<?php
But this results in the error: Recaptcha response not found, please ensure JavaScript is enabled in your browser.
I've found some documentation that should help, but I can't fathom it out. https://developers.google.com/recaptcha/docs/loading
The docs say:
When loading reCAPTCHA asynchronously, keep in mind that reCAPTCHA cannot be used until it has finished loading… In some situations, adjusting script ordering can be enough to prevent race conditions. Alternatively, you can prevent race conditions by including the following code snippet on pages that load reCAPTCHA. If you are usinggrecaptcha.ready()
to wrap API calls, add the following code snippet to ensure that reCAPTCHA can be called at any time.
I would appreciate a bit of help incorporating this, as when I try I still get an error.
<script async src="https://www.google.com/recaptcha/api.js"></script>
<script>
// How this code snippet works:
// This logic overwrites the default behavior of `grecaptcha.ready()` to
// ensure that it can be safely called at any time. When `grecaptcha.ready()`
// is called before reCAPTCHA is loaded, the callback function that is passed
// by `grecaptcha.ready()` is enqueued for execution after reCAPTCHA is
// loaded.
if(typeof grecaptcha === 'undefined') {
grecaptcha = {};
}
grecaptcha.ready = function(cb){
if(typeof grecaptcha === 'undefined') {
// window.__grecaptcha_cfg is a global variable that stores reCAPTCHA's
// configuration. By default, any functions listed in its 'fns' property
// are automatically executed when reCAPTCHA loads.
const c = '___grecaptcha_cfg';
window[c] = window[c] || {};
(window[c]['fns'] = window[c]['fns']||[]).push(cb);
} else {
cb();
}
}
// Usage
grecaptcha.ready(function(){
grecaptcha.render("container", {
sitekey: "ABC-123"
});
});
</script>
By daniel - August 2, 2022
Hi Jeff,
I believe in Google's example, you're supposed to replace the "grecaptcha.ready" portion with what you actually want to use. So I think it would look something like this:
<script async src="https://www.google.com/recaptcha/api.js"></script>
<script>
// How this code snippet works:
// This logic overwrites the default behavior of `grecaptcha.ready()` to
// ensure that it can be safely called at any time. When `grecaptcha.ready()`
// is called before reCAPTCHA is loaded, the callback function that is passed
// by `grecaptcha.ready()` is enqueued for execution after reCAPTCHA is
// loaded.
if(typeof grecaptcha === 'undefined') {
grecaptcha = {};
}
grecaptcha.ready = function(cb){
if(typeof grecaptcha === 'undefined') {
// window.__grecaptcha_cfg is a global variable that stores reCAPTCHA's
// configuration. By default, any functions listed in its 'fns' property
// are automatically executed when reCAPTCHA loads.
const c = '___grecaptcha_cfg';
window[c] = window[c] || {};
(window[c]['fns'] = window[c]['fns']||[]).push(cb);
} else {
cb();
}
}
grecaptcha.ready(function() {
grecaptcha.execute('<?php echo urlencode(recaptcha_settings('site_key')); ?>', {action: <?php echo json_encode(recaptcha_settings('page')); ?>}).then(function(token) {
document.getElementById("g-recaptcha-response").value = token;
});
});
</script>
Can you try that out, and let me know if it fixes the issue?
Thanks!
Technical Lead
interactivetools.com
By JeffC - August 3, 2022
Thanks for the reply Daniel. I'm still getting the error:
Recaptcha response not found, please ensure JavaScript is enabled in your browser
By daniel - August 3, 2022
Hey Jeff,
I didn't notice that the second snippet was missing the API key when loading api.js - that may be the issue here. Can you try this out?
<script async src="https://www.google.com/recaptcha/api.js?render=<?php echo urlencode(recaptcha_settings('site_key')); ?>"></script>
<script>
// How this code snippet works:
// This logic overwrites the default behavior of `grecaptcha.ready()` to
// ensure that it can be safely called at any time. When `grecaptcha.ready()`
// is called before reCAPTCHA is loaded, the callback function that is passed
// by `grecaptcha.ready()` is enqueued for execution after reCAPTCHA is
// loaded.
if(typeof grecaptcha === 'undefined') {
grecaptcha = {};
}
grecaptcha.ready = function(cb){
if(typeof grecaptcha === 'undefined') {
// window.__grecaptcha_cfg is a global variable that stores reCAPTCHA's
// configuration. By default, any functions listed in its 'fns' property
// are automatically executed when reCAPTCHA loads.
const c = '___grecaptcha_cfg';
window[c] = window[c] || {};
(window[c]['fns'] = window[c]['fns']||[]).push(cb);
} else {
cb();
}
}
grecaptcha.ready(function() {
grecaptcha.execute('<?php echo urlencode(recaptcha_settings('site_key')); ?>', {action: <?php echo json_encode(recaptcha_settings('page')); ?>}).then(function(token) {
document.getElementById("g-recaptcha-response").value = token;
});
});
</script>
If that doesn't work, feel free to send a 2nd-level support request (https://www.interactivetools.com/support/request/) and I can take a look at it directly.
Thanks,
Technical Lead
interactivetools.com
By JeffC - August 3, 2022
Hi Daniel
Thanks for the reply. I did notice the missing API key in your first post and tried with and without.
I won't post a 2nd level request. I don't have budget to fix it, and the problem is only a small one. I aim to make my pages load as fast as they can, but this one is actually pretty quick already.
Thanks for trying.
By daniel - August 4, 2022
Hey Jeff,
This is something I could check out at no charge - it'd be useful for us to know as well. But as it's a minor issue I also understand if it's not worth the trouble.
Take care,
Technical Lead
interactivetools.com
By daniel - August 4, 2022
Thanks John!
It appears that the script provided in Google's docs is slightly inaccurate - at least for our usage here - so I've made a small change and it appears to be working with async. For anyone else reading, here is the final updated script:
<script async src="https://www.google.com/recaptcha/api.js?render=<?php echo urlencode(recaptcha_settings('site_key')); ?>"></script>
<script>
if(typeof grecaptcha === 'undefined') {
grecaptcha = {};
}
grecaptcha.ready = function(cb){
if(typeof grecaptcha.execute === 'undefined') {
// window.__grecaptcha_cfg is a global variable that stores reCAPTCHA's
// configuration. By default, any functions listed in its 'fns' property
// are automatically executed when reCAPTCHA loads.
const c = '___grecaptcha_cfg';
window[c] = window[c] || {};
(window[c]['fns'] = window[c]['fns']||[]).push(cb);
} else {
cb();
}
}
grecaptcha.ready(function(){
grecaptcha.execute('<?php echo urlencode(recaptcha_settings('site_key')); ?>', {action: <?php echo json_encode(recaptcha_settings('page')); ?>}).then(function(token) {
document.getElementById("g-recaptcha-response").value = token;
});
});
</script>
Cheers,
Technical Lead
interactivetools.com