6 Replies Latest reply on Apr 18, 2018 1:05 AM by Markus Bianchi

    Invisible recaptcha vs visible recaptcha

    Grégoire Michel

      When implement an invisible recaptcha following the method described by Sanford Whiteman here, the

       

      var recaptchaResponse = grecaptcha.getResponse();
      

       

      returns an empty response, and the validation fails.

       

      this is the complete code used:

       

        In the <head>

      <meta class="mktoBoolean" id="GoogleRecaptcha" mktoName="Google Recaptcha" default="false" true_value="true" false_value="false" false_value_name="Deactivated" true_value_name="Activated">
      

       

      in the <body>

      <div id="InvisibleRecaptcha" class="g-recaptcha" data-sitekey="${GoogleRecaptchaSiteKey}" data-size="invisible" data-callback="donothing"></div>
      

       

      in the forms whenready:

      var formEl = form.getFormElem()[0],
        emailEl = formEl.querySelector('#Email'),
        submitEl = formEl.querySelector('BUTTON[type="submit"]'),
        recaptchaEl = document.querySelector('.g-recaptcha’),
        formElId = form.getId();
      
      if (${GoogleRecaptcha}) {
        form.submittable(false);
        // force resize reCAPTCHA frame
        recaptchaEl.querySelector('IFRAME').setAttribute('height','140');
        // move reCAPTCHA inside form container    
        formEl.appendChild(recaptchaEl);
      }
        
      form.onValidate(function(builtInValidation){        
        //code to handle the recaptcha
        if(${GoogleRecaptcha}) {
          if (!builtInValidation) return;
                  
          //calling the recaptcha 
            var recaptchaResponse = grecaptcha.getResponse();
            if (!recaptchaResponse) {
              recaptchaEl.classList.add('mktoInvalid');
            } else {
              recaptchaEl.classList.remove('mktoInvalid');
              form.addHiddenFields({
                lastRecaptchaUserInput: recaptchaResponse,
                lastRecaptchaEnabledFormID: formElId
              });
              form.submittable(true);
            }
          }      
      });
      
      
      
      
      
      

       

      Any idea about what I am missing?

       

      The same code works perfectly well with a visible (v2) recaptcha.

       

      -Greg

        • Re: Invisible recaptcha vs visible recaptcha
          Markus Bianchi

          Hi Greg,

           

          You'll need to use...

           

          grecaptcha.execute(reCAPTCHA);
          

           

          ...when someone tries to submit the form. If you don't programmatically "execute" the Invisible reCAPTCHA...

           

          grecaptcha.getResponse();
          

           

          ...will always return an empty response. (Invisible) reCAPTCHA uses a callback that you should use to handle completion of the captcha after executing it. Also, if you want to support multiple forms on the same page, you'll have to create multiple instances of reCAPTCHA (for each form) and should thus not include the following HTML as described in the documentation.

           

          <div class="g-recaptcha"
               data-sitekey="your_site_key"
               data-callback="onSubmit"
               data-size="invisible">
          </div>
          

           

          Instead, just include the reCAPTCHA script on your page and embed the forms as you would do normally.

           

          <script src='https://www.google.com/recaptcha/api.js?render=explicit'></script>
          <script src="https://app-lon07.marketo.com/js/forms2/js/forms2.min.js"></script>
          <form id="mktoForm_1"></form>
          <script>MktoForms2.loadForm("//app-lon07.marketo.com", "123-ABC-456", 1);</script>
          

           

          Then use the following script to use it for all forms. If needed you can also slightly adjust it to only use reCAPTCHA for one or a couple of forms.

           

          /**
           * Use Google's reCAPTCHA to protect against spam and other types of automated abuse.
           * @param {Object} mktoForm
           * @param {Object} options
           * @param {String} options.size 'invisible', 'compact', 'normal'
           * @param {String} options.siteKey Public reCAPTCHA sitekey
           * @param {String} options.fieldName Marketo SOAP name for field that holds response value
           * @param {String} options.errorMessage Error message depending on choosen `size`
           * @return {Void}
           */
          function useReCAPTCHA(mktoForm) {
            var options =
              arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
          
            if (
              !Object.prototype.hasOwnProperty.call(options, "fieldName") ||
              !Object.prototype.hasOwnProperty.call(options, "sitekey") ||
              !Object.prototype.hasOwnProperty.call(options, "errorMessage") ||
              !Object.prototype.hasOwnProperty.call(options, "size")
            ) {
              if (console) {
                console.warn("Parameters for reCAPTCHA are missing.");
              }
              return;
            }
          
            var formEl = mktoForm.getFormElem()[0];
            var formId = mktoForm.getId();
            var reCAPTCHAEl = document.createElement("div");
          
            reCAPTCHAEl.setAttribute("id", "reCAPTCHA_" + formId);
            formEl.parentNode.insertBefore(reCAPTCHAEl, formEl.nextSibling);
          
            var reCAPTCHA = grecaptcha.render("reCAPTCHA_" + formId, {
              size: options.size,
              sitekey: options.sitekey,
              callback: function callback() {
                mktoForm.submittable(true);
                mktoForm.submit();
              },
              "error-callback": function errorCallback() {
                mktoForm.showErrorMessage(options.errorMessage);
              }
            });
          
            mktoForm.onValidate(function(isValid) {
              if (!isValid || !mktoForm.submittable()) {
                return;
              }
          
              var reCAPTCHAResponse = grecaptcha.getResponse(reCAPTCHA);
          
              if (!reCAPTCHAResponse) {
                if (options.size === 'invisible') {
                  grecaptcha.execute(reCAPTCHA);
                } else {
                  mktoForm.showErrorMessage(options.errorMessage);
                }
                mktoForm.submittable(false);
              } else {
                var hiddenFields = {};
                hiddenFields[options.fieldName] = reCAPTCHAResponse;
                mktoForm.addHiddenFields(hiddenFields);
              }
            });
          }
          
          MktoForms2.whenReady(function(mktoForm) {
            useReCAPTCHA(mktoForm, {
              size: "invisible",
              sitekey: "KEY",
              fieldName: "lastreCAPTCHAResponse",
              errorMessage: "Sorry, something wen't wrong"
            });
          });
          

           

          Please note that I haven't tested it fully (yet) but feel free to test if it works for you. It did for me in my tests.

           

          Best regards,
          Markus

          1 of 1 people found this helpful