How do I show multiple recaptchas on a single page?

145,790

Solution 1

A similar question was asked about doing this on an ASP page (link) and the consensus over there was that it was not possible to do with recaptcha. It seems that multiple forms on a single page must share the captcha, unless you're willing to use a different captcha. If you are not locked into recaptcha a good library to take a look at is the Zend Frameworks Zend_Captcha component (link). It contains a few

Solution 2

With the current version of Recaptcha (reCAPTCHA API version 2.0), you can have multiple recaptchas on one page.

There is no need to clone the recaptcha nor try to workaround the problem. You just have to put multiple div elements for the recaptchas and render the recaptchas inside them explicitly.

This is easy with the google recaptcha api:
https://developers.google.com/recaptcha/docs/display#explicit_render

Here is the example html code:

<form>
    <h1>Form 1</h1>
    <div><input type="text" name="field1" placeholder="field1"></div>
    <div><input type="text" name="field2" placeholder="field2"></div>
    <div id="RecaptchaField1"></div>
    <div><input type="submit"></div>
</form>

<form>
    <h1>Form 2</h1>
    <div><input type="text" name="field3" placeholder="field3"></div>
    <div><input type="text" name="field4" placeholder="field4"></div>
    <div id="RecaptchaField2"></div>
    <div><input type="submit"></div>
</form>

In your javascript code, you have to define a callback function for recaptcha:

<script type="text/javascript">
    var CaptchaCallback = function() {
        grecaptcha.render('RecaptchaField1', {'sitekey' : '6Lc_your_site_key'});
        grecaptcha.render('RecaptchaField2', {'sitekey' : '6Lc_your_site_key'});
    };
</script>

After this, your recaptcha script url should look like this:

<script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>

Or instead of giving IDs to your recaptcha fields, you can give a class name and loop these elements with your class selector and call .render()

Solution 3

Simple and straightforward:

1) Create your recaptcha fields normally with this:

<div class="g-recaptcha" data-sitekey="YOUR_KEY_HERE"></div>

2) Load the script with this:

<script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>

3) Now call this to iterate over the fields and create the recaptchas:

<script type="text/javascript">
  var CaptchaCallback = function() {
    jQuery('.g-recaptcha').each(function(index, el) {
        grecaptcha.render(el, {
            'sitekey' : jQuery(el).attr('data-sitekey')
            ,'theme' : jQuery(el).attr('data-theme')
            ,'size' : jQuery(el).attr('data-size')
            ,'tabindex' : jQuery(el).attr('data-tabindex')
            ,'callback' : jQuery(el).attr('data-callback')
            ,'expired-callback' : jQuery(el).attr('data-expired-callback')
            ,'error-callback' : jQuery(el).attr('data-error-callback')
        });
    });
  };
</script>

Solution 4

This answer is an extension to @raphadko's answer.

If you need to extract manually the captcha code (like in ajax requests) you have to call:

grecaptcha.getResponse(widget_id)

But how can you retrieve the widget id parameter?

I use this definition of CaptchaCallback to store the widget id of each g-recaptcha box (as an HTML data attribute):

var CaptchaCallback = function() {
    jQuery('.g-recaptcha').each(function(index, el) {
        var widgetId = grecaptcha.render(el, {'sitekey' : 'your code'});
        jQuery(this).attr('data-widget-id', widgetId);
    });
};

Then I can call:

grecaptcha.getResponse(jQuery('#your_recaptcha_box_id').attr('data-widget-id'));

to extract the code.

Solution 5

This is easily accomplished with jQuery's clone() function.

So you must create two wrapper divs for the recaptcha. My first form's recaptcha div:

<div id="myrecap">
    <?php
        require_once('recaptchalib.php');
        $publickey = "XXXXXXXXXXX-XXXXXXXXXXX";
        echo recaptcha_get_html($publickey);
    ?>
</div>

The second form's div is empty (different ID). So mine is just:

<div id="myraterecap"></div>

Then the javascript is quite simple:

$(document).ready(function() {
    // Duplicate our reCapcha 
    $('#myraterecap').html($('#myrecap').clone(true,true));
});

Probably don't need the second parameter with a true value in clone(), but doesn't hurt to have it... The only issue with this method is if you are submitting your form via ajax, the problem is that you have two elements that have the same name and you must me a bit more clever with the way you capture that correct element's values (the two ids for reCaptcha elements are #recaptcha_response_field and #recaptcha_challenge_field just in case someone needs them)

Share:
145,790

Related videos on Youtube

oym
Author by

oym

Updated on July 08, 2022

Comments

  • oym
    oym almost 2 years

    I have 2 forms on a single page. One of the forms has a recaptcha displaying all the time. The other should display a recaptcha only after a certain event such as maxing out login attempts. So there are times when I would need 2 recaptchas to appear on the same page. Is this possible? I know I could probably use a single one for both, but the way I have the layout, I would much prefer to have 2. Thanks.

    Update: well I guess it may not be possible. Can anybody recommend another capture library to use side by side with reCaptcha? I really want to be able to have 2 captchas on the same page.

    Update 2: What if put each form in an iframe? Would this be an acceptable solution?

    • oym
      oym almost 15 years
      I tried that..when I try to duplicate the captcha code it will just display the captcha that comes first
    • El Yobo
      El Yobo about 9 years
      Anyone coming across this for the new recaptcha API, this is possible by using the explicit loading described with examples in the docs at developers.google.com/recaptcha/docs/display#recaptcha_metho‌​ds
    • Edward
      Edward about 8 years
      An iframe should be possible but is a bad way of solving the problem, compared to using JavaScript like in Hüseyin Yağlı's answer. Most browsers should support JavaScript and the default reCAPTCHA uses JavaScript anyway. I don't know though what would need to be done to solve the problem without JavaScript support though.
  • Ogugua Belonwu
    Ogugua Belonwu almost 12 years
    You will encounter issues when you request for a new challenge as it will be updating only one recaptcha instance
  • Oxi
    Oxi over 11 years
    this does not work ... means only the original captcha( the first one called <div id="myrecap"> here )only will be refreshed , and other not refreshed
  • Serj Sagan
    Serj Sagan over 11 years
    Actually Oxi, your concern was addressed by my previous comment
  • Serj Sagan
    Serj Sagan over 8 years
    You're probably doing it wrong... how about a link to your code in jsfiddle.net Anyways, there is no longer a need to do any of this... you should be using Hüseyin Yağlı answer.
  • Ivan Juarez
    Ivan Juarez over 8 years
    Coincidentally, do you know how to add hidden recaptcha field for jquery validation for each field?, currently I have it working only with 1 recaptchafield but can it work with two recaptchas? <input type="hidden" class="hiddenRecaptcha required" name="hiddenRecaptcha" id="hiddenRecaptcha">
  • Hüseyin Yağlı
    Hüseyin Yağlı over 8 years
    @IvanJuarez This is a good question to ask as a new question.
  • Gene Kelly
    Gene Kelly over 8 years
    For those of you wanting to use grecaptcha.getResponse() with multiple instances you can simply reference each render as 0,1,2,etc. For example the first instance would be referenced as grecaptcha.getResponse(0).
  • Edward
    Edward about 8 years
    It is possible with reCAPTCHA actually, just not possible to do without JavaScript. Most browsers should support JavaScript and the default ReCaptcha uses JavaScript anyway so this solution is good. Hüseyin Yağlı's answer explains the solution. reCAPTCHA documentation for this solution is at developers.google.com/recaptcha/docs/display#explicit_render‌​. I don't know though what would need to be done to solve the problem without JavaScript support though.
  • ryanpcmcquen
    ryanpcmcquen almost 8 years
    Excellent answer, but your script has to use https, not a protocol relative link: developers.google.com/recaptcha/docs/display#auto_render
  • Greg Alexander
    Greg Alexander over 7 years
    This is the right way IMO, this makes it dynamic in that I can have unlimited instances without defining static ids
  • Mirza Obaid
    Mirza Obaid over 7 years
    Save my time its perfect solution
  • VanDir
    VanDir over 7 years
    If you need to extract manually the captcha code (like in ajax requests) look my answer.
  • Marcio Mazzucato
    Marcio Mazzucato about 7 years
    Could you please take a look in my question? The POST parameter is going empty.
  • Ray S.
    Ray S. almost 7 years
    have a javascript only version?
  • JxAxMxIxN
    JxAxMxIxN almost 7 years
    I used this almost exactly and in addition to 'sitekey' I also added a 'callback' like so: grecaptcha.render(el, {'sitekey' : $(this).attr('data-sitekey'), 'callback':CaptchaSubmit});
  • the_nuts
    the_nuts almost 7 years
    data-sitekey="YOUR_KEY_HERE" is useless and can be removed from the div (if you need to change the key, less places to edit)
  • Gkiokan
    Gkiokan almost 7 years
    Actually you have a typo there. The Attribute data-sitekey is needen and makes this even more dynamic in case you would have multiple sitekeys, why ever. The correct line would be grecaptcha.render(el, {'sitekey' : $(el).attr('data-sitekey') });
  • codacopia
    codacopia over 6 years
    Wow! This took some working on, but to add to @GeneKelly's note regarding grecaptcha.getResponse(0) and grecaptcha.getResponse(1) to validate multiple instances I would add that the indexing does have to correspond with the grecaptcha.render ordering. For this example, grecaptcha.render('RecaptchaField1'... would be verified with grecaptcha.getResponse(0) and grecaptcha.render('RecaptchaField2'... would be verified with grecaptcha.getResponse(1), etc...
  • Black
    Black over 5 years
    Wow, I was searching for hours for this. Thanks!!
  • Black
    Black over 5 years
    I edited your post and implemented it fully like described in the API, I also replaced $ with jQuery to make it compatible with the prototype framework.
  • Eugen Konkov
    Eugen Konkov over 5 years
    The problem with this that when you executing grecaptcha.execute() the callback will be called only for first div with recaptcha despite on where you click
  • masud_moni
    masud_moni over 5 years
    working like a charm in the frontend. but what about the server side validation? (new GoogleRecaptchaApi)->reCaptchaValidate(request('captcha') It is showing false
  • Carlos Espinoza
    Carlos Espinoza almost 5 years
    It's absolutely possible with reCAPTCHA actually
  • good_afternoon
    good_afternoon over 4 years
    This works until I make the "size": "invisible". Anyone know why?
  • Lucas Bustamante
    Lucas Bustamante over 4 years
    Hey, thanks for that. What is the #your_recaptcha_box_id?
  • MeSo2
    MeSo2 about 4 years
    where is the 2 forms part?
  • surinder singh
    surinder singh about 4 years
    sorry not getting you
  • surinder singh
    surinder singh about 4 years
    just put <div class="g-recaptcha" data-sitekey="your_site_key"></div> where u needed , in forms/divs
  • 00-BBB
    00-BBB over 3 years
    @masud_moni mine is added to $post as 'g-recaptcha-response'
  • kneidels
    kneidels over 3 years
    This is working great for me in ajax, BUT- in a case where there is an error on the form (eg, user not found) - and a relevant error is returned from the ajax method, i ould usually resat the captcha by calling grecaptcha.reset(); which worked great in a single-form-per-page setup. But in a multiple form per page, this reset command does not effect/reset the captcha. I tried calling the CaptchaCallback function as well, but it did not solve the issue.
  • kneidels
    kneidels over 3 years
    Answering my comment above. See: stackoverflow.com/questions/31344626/…
  • Svetoslav Stefanov
    Svetoslav Stefanov over 2 years
    Woah, thank you! Couldn't find such a thing in the official documentation. This way you could have multiple captchas, without having explicit rendering. I have a case where I have normal rendering everywhere around the site and I need explicit rendering only in one place - this solved my issue.
  • Bloggrammer
    Bloggrammer over 2 years
    Can the site_key ''6Lc_your_site_key" be the same for the multiple Recaptcha?