Reputation: 71
as I understand, it seems to be possible to use both v2 and v3 on the same page (see https://github.com/google/recaptcha/issues/279), but can't find any example of it :/
I already have HTML pages with invisible v2, and first, I want to evaluate the accuracy of the v3 score without breaking my current v2 (v3 will be only for test purposes). I was also wondering if it could be possible to use v3 and render v2 challenges for low scores.
Any idea ?
(sorry for my english, it's not my mother tongue ;)
Upvotes: 7
Views: 9231
Reputation: 923
V2 and V3 can be used on the same page. This can be done while loading recaptcha/api.js
only once (instead of once per version) — but it requires a particular loading sequence to avoid race conditions.
Invalid site key or not loaded in api.js
or as the wrong sitekey version being passed in verify API calls.Unfortunately, Google's documentation doesn't address this fully: https://developers.google.com/recaptcha/docs/loading#loading_recaptcha_asynchronously
Here's what to do instead:
onload
callback and grecaptcha.ready
. Instead of Google's approach of checking grecaptcha === 'undefined'
within ready
, you should check !window.recaptchaLoaded
to avoid race conditions.window.recaptchaLoaded = false;
window.onRecaptchaLoaded = function() {
window.recaptchaLoaded = true;
}
if (typeof grecaptcha === 'undefined') {
grecaptcha = {
ready: function(cb) {
if (!window.recaptchaLoaded) {
const c = '___grecaptcha_cfg';
window[c] = window[c] || {};
(window[c]['fns'] = window[c]['fns']||[]).push(cb);
} else {
cb();
}
}
};
}
onload
option and load the recaptcha script with your V3 sitekey, async or deferred:<script defer src="https://www.google.com/recaptcha/api.js?onload=onRecaptchaLoaded&render=V3_SITE_KEY"></script>
grecaptcha.render
with your V2 sitekey, wrapped in grecaptcha.ready
grecaptcha.ready(function() {
grecaptcha.render("g-recaptcha", {
'sitekey': 'V2_SITE_KEY'
});
});
To use V3, call grecaptcha.execute
with your V3 sitekey, wrapped in grecaptcha.ready
grecaptcha.ready(() => {
grecaptcha.execute('V3_SITE_KEY', {action: 'your_action'}).then((token) => {
...
});
});
This solution works by loading reCAPTCHA asynchronously, using explicit rendering of the V2 reCAPTCHA widget, and programatically invoking the V3 challenge.
Upvotes: 3
Reputation: 527
Yes, this explains how : Can I run reCAPTCHA v2 and v3 on the same page?
Worked well with two v3 and one v2 checkbox on the same page.
Upvotes: 4
Reputation: 3255
The following example (written by Anton Cherniavskyi) works.
However, I think it only works with v2 invisible
+ v3
, ie.: You can't use v2 checkbox
+ v3
.
<script src="https://www.google.com/recaptcha/api.js?onload=v2_onload"></script>
<script src="https://www.google.com/recaptcha/api.js?onload=v3_onload&render=V3_SITE_KEY"></script>
<div class="g-recaptcha" data-size="invisible" data-sitekey="V2_INVISIBLE_SITE_KEY" data-callback="v2_callback"></div>
<script type="text/javascript">
function v2_onload() { console.log('v2 loaded'); }
function v3_onload() { console.log('v3 loaded'); }
function v2_callback(token) { console.log('v2 token: ' + token); }
function v3_callback(token) { console.log('v3 token: ' + token); }
// call these manually
function test_v2() { grecaptcha.execute(); }
function test_v3() { grecaptcha.execute(V3_SITE_KEY/*, {action: '...'}*/).then(v3_callback); }
</script>
Upvotes: 2