36

I'm building a PHP website where I would like to put a captcha on the login form. I went with Google's new Invisible reCaptcha but I'm having trouble with implementing it (HTML part, the PHP is working).

The code I've got now for the "normal" reCaptcha is the following (as according to the Google reCaptcha instructions and this works):

<form action=test.php method="POST">
   <input type="text" name="email" placeholder="Email">
   <input type="password" name="password" placeholder="Password">

   <!-- <Google reCaptcha> -->
   <div class="g-recaptcha" data-sitekey="<sitekey>"></div>
   <!-- </Google reCaptcha> -->

   <input type="submit" name="login" class="loginmodal-submit" value="Login">
</form>

There were some instructions sent in the confirmation email when I signed up (took about 24 hours to get the confirmation). That says the following:

Invisible reCAPTCHA Integration

  1. If you haven’t integrated your site with reCAPTCHA v2, please follow our developer guide for implementation details.

  2. Please make sure that your site key that has been whitelisted for Invisible reCAPTCHA.

  3. To enable the Invisible reCAPTCHA, rather than put the parameters in a div, you can add them directly to an html button.

    3a. data-callback=””. This works just like the checkbox captcha, but is required for invisible.

    3b. data-badge: This allows you to reposition the reCAPTCHA badge (i.e. logo and ‘protected by reCAPTCHA’ text) . Valid options as ‘bottomright’ (the default), ‘bottomleft’ or ‘inline’ which will put the badge directly above the button. If you make the badge inline, you can control the CSS of the badge directly.

  4. Verifying the user’s response has no changes.

The problem I have is with the HTML implementation (therefore I need help with step 3. 1,2 and 4 is working for me). The rest I have working with normal reCaptcha and according to the instructions, it should be the same thing. I do not understand what the data-callback and data-badge is and how it works. A code example of how to implement invisible reCaptcha with how my form is setup would be great!

2
  • Do you need 'PHP' tag? The accepted answer is JavaScript generic, not PHP specific. Commented Dec 11, 2018 at 4:03
  • @MichaelFreidgeim you're right. I've changed the php tag for a javascript one.
    – L.Johnson
    Commented Dec 11, 2018 at 13:46

5 Answers 5

41

Invisible reCAPTCHA

Implementing Google's new Invisible reCAPTCHA is very similar to how we add v2 to our site. You may add it as its own container like normal, or the new method of adding it to the form submit button. I hope this guide will help you along the correct path.

Standalone CAPTCHA Container

Implementing recaptcha requires a few things:

- Sitekey
- Class
- Callback
- Bind

This will be your final goal.

<div class="g-recaptcha" data-sitekey="<sitekey>" 
   data-bind="recaptcha-submit" data-callback="submitForm"> 
</div>

When using the standalone method, you must have data-bind set to the ID of your submit button. If you do not have this set, your captcha will not be invisible.

A callback must also be used to submit the form. An invisible captcha will cancel all events from the submit button, so you need the callback to actually pass the submission on.

<script>
function submitForm() {
    var form = document.getElementById("ContactForm");
    if (validate_form(form)) {
        form.submit();
    } else {
        grecaptcha.reset();
    }
}
</script>

Notice in the example callback that there is also custom form validation. It is very important that you reset the reCAPTCHA when the validation fails, otherwise you will not be able to re-submit the form until the CAPTCHA expires.

Invisible CAPTCHA Button

A lot of this is the same as with the standalone CAPTCHA above, but instead of having a container, everything is placed on the submit button.

This will be your goal.

<button class="g-recaptcha" data-sitekey="<sitekey>" 
   data-callback="submitForm" data-badge="inline" type="submit">
  Submit</button>

There's something new here, data-badge. This is a div that gets inserted into the DOM that contains the inputs required for reCAPTCHA to function. It has three possible values: bottomleft, bottomright, inline. Inline will make it display directly above the submit button, and allow you to control how you would like it to be styled.

On to your question

<form action="test.php" method="POST" id="theForm">
    <script>
    function submitForm() {
        document.getElementById("theForm").submit();
    }
    </script>
    <input type="text" name="email" placeholder="Email">
    <input type="password" name="password" placeholder="Password">

    <div class="g-recaptcha" data-sitekey="<sitekey>" data-bind="recaptcha-submit" data-callback="submitForm"></div>

    <input type="submit" name="login" class="loginmodal-submit" id="recaptcha-submit" value="Login">
</form>

Or

<form action="test.php" method="POST" id="theForm">
    <script>
    function submitForm() {
        document.getElementById("theForm").submit();
    }
    </script>
    <input type="text" name="email" placeholder="Email">
    <input type="password" name="password" placeholder="Password">

    <button class="loginmodal-submit g-recaptcha" data-sitekey="<sitekey>" data-callback="submitForm" data-badge="inline" type="submit" value="Login">Submit</button>
</form>

I hope this helps you and future coders. I'll keep this up-to-date as the technology evolves.

11
  • This isn't fully working for me (I tried the first example). It does seem to be loading but when I press the submit button, I have to complete a captcha (not sure if this is an error or just what happens if Google suspects that I'm a bot - since it's supposed to be invisible, right?) and when I complete it, the recaptcha dialog (for pressing the pictures that corresponds to the question) disappears and if I try to hit the submit button again, nothing happens. I've tried it on fresh installs of Firefox and Chrome. FYI, the test.php file is the same file that runs this code. It calls itself.
    – L.Johnson
    Commented Dec 14, 2016 at 18:42
  • If I remove the data-bind="recaptcha-submit" part from the div, it does work but not as the invisible recaptcha but as the regular recaptcha with the checkbox.
    – L.Johnson
    Commented Dec 14, 2016 at 18:45
  • Also, if I may ask. What is data-callback="onSubmit" that's a part of the same div supposed to do? What does onSubmit actually mean? Thanks
    – L.Johnson
    Commented Dec 14, 2016 at 19:00
  • The second option does work, I'm not a big fan of how it's implemented though. It works for now but I would like to get something like the first code to work. It looks cleaner and is easier to customize. Thank you though! If you have an idea of why the first one doesn't work for me. Please let me know!
    – L.Johnson
    Commented Dec 14, 2016 at 21:04
  • 2
    Works great! Thank you
    – L.Johnson
    Commented Dec 18, 2016 at 16:28
26

Here is how to implement a client + server side (php) Invisible reCaptcha functionality:

  • Client Side
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>reCaptcha</title>

    <!--api link-->
    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
    <!--call back function-->
    <script>
        function onSubmit(token) {
            document.getElementById('reCaptchaForm').submit();
        }
    </script>
</head>
<body>
<div class="container">
    <form id="reCaptchaForm" action="signup.php" method="POST">
        <input type="text" placeholder="type anything">
        <!--Invisible reCaptcha configuration-->
        <button class="g-recaptcha" data-sitekey="<your site key>" data-callback='onSubmit'>Submit</button>
        <br/>
    </form>
</div>
</body>
</html>
  • Server Side validation: Create a signup.php file
<?php
//only run when form is submitted
if(isset($_POST['g-recaptcha-response'])) {
    $secretKey = '<your secret key>';
    $response = $_POST['g-recaptcha-response'];     
    $remoteIp = $_SERVER['REMOTE_ADDR'];


    $reCaptchaValidationUrl = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=$secretKey&response=$response&remoteip=$remoteIp");
    $result = json_decode($reCaptchaValidationUrl, TRUE);

    //get response along side with all results
    print_r($result);

    if($result['success'] == 1) {
        //True - What happens when user is verified
        $userMessage = '<div>Success: you\'ve made it :)</div>';
    } else {
        //False - What happens when user is not verified
        $userMessage = '<div>Fail: please try again :(</div>';
    }
}
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>reCAPTCHA Response</title>
    </head>
    <body>
        <?php
            if(!empty($userMessage)) {
                echo $userMessage;
            }
        ?>
    </body>
</html>
1
25

If you're looking for a fully customizable general solution which will even work with multiple forms on the same page, I'll explicitly render the reCaptcha widget by using the render=explicit and onload=aFunctionCallback parameters.

Here is a simple example:

<!DOCTYPE html>
<html>
<body>

<form action="" method="post">
    <input type="text" name="first-name-1"> <br />
    <input type="text" name="last-name-1"> <br />

    <div class="recaptcha-holder"></div>

    <input type="submit" value="Submit">
</form>

<br /><br />

<form action="" method="post">
    <input type="text" name="first-name-2"> <br />
    <input type="text" name="last-name-2"> <br />

    <div class="recaptcha-holder"></div>

    <input type="submit" value="Submit">
</form>

<script type="text/javascript">

  var renderGoogleInvisibleRecaptcha = function() {
    for (var i = 0; i < document.forms.length; ++i) {
      var form = document.forms[i];
      var holder = form.querySelector('.recaptcha-holder');
      if (null === holder){
        continue;
      }

      (function(frm){

        var holderId = grecaptcha.render(holder,{
          'sitekey': 'CHANGE_ME_WITH_YOUR_SITE_KEY',
          'size': 'invisible',
          'badge' : 'bottomright', // possible values: bottomright, bottomleft, inline
          'callback' : function (recaptchaToken) {
            HTMLFormElement.prototype.submit.call(frm);
          }
        });

        frm.onsubmit = function (evt){
          evt.preventDefault();
          grecaptcha.execute(holderId);
        };

      })(form);
    }
  };


</script>

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

</body>
</html>

As you can see, I am adding an empty div element into a form. In order to identify which forms should be protected using reCaptcha, I'll add a class name to this element. In our example I am using 'recaptcha-holder' class name.

The callback function iterates through all the existing forms and if it finds our injected element with the 'recaptcha-holder' class name, it will render the reCaptcha widget.

I've been using this solution on my Invisible reCaptcha for WordPress plugin. If somebody wants to see how this works, the plugin is available for download on WordPress directory:

https://wordpress.org/plugins/invisible-recaptcha/

Hope this helps!

5
  • Thanks, I'll look into this soon. I did actually get an issue with my registration page that contained both the login form (in the menu) and the registration one. Hopefully this might solve that issue!
    – L.Johnson
    Commented Dec 27, 2016 at 19:14
  • Thank you, it worked just as I wanted it to and I was able to have two captchas on one page.
    – L.Johnson
    Commented Dec 30, 2016 at 20:58
  • Unlike Google's documentation, this was a helpful-ish starting point. However, I recommend one suggested change to anyone finding this in the future: Use frm.addEventListener('submit', function(evt) { ... }); instead of frm.onsubmit. I used a similar but more flexible approach in my FlexForms reCAPTCHA module (github.com/cubiclesoft/php-flexforms-modules). Commented May 5, 2017 at 3:25
  • 7
    Wait a moment. Where is the server side part?
    – GDY
    Commented Jul 17, 2017 at 7:31
  • Thank you for the example. I have implemented it on my test site, it works, but asks for challenge each time I click submit. This doesnt happen with your WordPress plugin. What is the problem with html example? Commented Sep 15, 2017 at 8:55
0

Here is a working example:

<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>ReCAPTCHA Example</title>
</head>
<body>
<div class="container">

  <form method="post" action="/contact/" id="contact-form">
    <h3 class="title-divider">
      <span>Contact Us</span>
    </h3>
    <input type="text" name="name">
    <div class="captcha"><!-- BEGIN: ReCAPTCHA implementation example. -->
      <div id="recaptcha-demo" class="g-recaptcha" data-sitekey="YOUR_RECAPTCHA_SITE_KEY" data-callback="onSuccess" data-bind="form-submit"></div>
      <script>
          var onSuccess = function (response) {
              var errorDivs = document.getElementsByClassName("recaptcha-error");
              if (errorDivs.length) {
                  errorDivs[0].className = "";
              }
              var errorMsgs = document.getElementsByClassName("recaptcha-error-message");
              if (errorMsgs.length) {
                  errorMsgs[0].parentNode.removeChild(errorMsgs[0]);
              }
              document.getElementById("contact-form").submit();
          };</script><!-- END: ReCAPTCHA implementation example. -->
    </div>
    <button id="form-submit" type="submit">Submit</button>
  </form>
  <script src="https://www.google.com/recaptcha/api.js" async defer></script>
</div>
</body>
</html>

Do not forget to change YOUR_RECAPTCHA_SITE_KEY to your Google ReCAPTCHA site key.

Next step is to actually validate the data. It is done by making a POST request to the endpoint https://www.google.com/recaptcha/api/siteverify, containing your Secret key and the data from the reCAPTCHA, which is identified by g-recaptcha-response. There are a lot of different ways it could be done depending on your CMS/Framework.

You might have noticed the reCaptcha badge in the lower right corner of the screen. This exists to let users know that a form is protected by reCaptcha now that the verification checkbox has been removed. It’s possible to hide this badge however by configuring it to be inline, and then modifying it with CSS.

<style>
    .grecaptcha-badge {display: none;}
</style>

Please note that because Google collects user information to enable reCaptcha functionality, their terms of service require you to alert users to its use. If you hide the badge you can add an informational paragraph somewhere on the page instead.

-6
  1. Login with your google account

  2. Visit the google recaptcha link.

  3. Then follow the link to code integration, follow the code for both client and serverside validation. https://developers.google.com/recaptcha/docs/invisible

  4. Increase or decrease the security level once after creating the recaptcha, go to the advance settings here, https://www.google.com/recaptcha/admin#list

Not the answer you're looking for? Browse other questions tagged or ask your own question.