Re: Invisible recaptcha vs visible recaptcha

Grégoire_Miche2
Level 10

Invisible recaptcha vs visible recaptcha

When implement an invisible recaptcha following the method described by Sanford Whitemanhere, 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

6 REPLIES 6
SanfordWhiteman
Level 10 - Community Moderator

Re: Invisible recaptcha vs visible recaptcha

What's the URL?

Grégoire_Miche2
Level 10

Re: Invisible recaptcha vs visible recaptcha

Hi Sanford

Here it is. And thx

-Greg

SanfordWhiteman
Level 10 - Community Moderator

Re: Invisible recaptcha vs visible recaptcha

The invisible form doesn't have an internal IFRAME (and doesn't need to be moved), so you need to take out these lines:

recaptchaEl.querySelector('IFRAME').setAttribute('height','140'); 

formEl.appendChild(recaptchaEl); 

Grégoire_Miche2
Level 10

Re: Invisible recaptcha vs visible recaptcha

Hi Sanford,

Thx

I commented the 2 lines, but it is still not working. I also added an onsubmit function, as per the doc, it seems mandatory, to no avail

-Greg

SanfordWhiteman
Level 10 - Community Moderator

Re: Invisible recaptcha vs visible recaptcha

OK, now onto the next bug(s).

You don't want to call grecaptcha.render() in the onValidate, as it's already rendered (that's throwing an error that's ending form submission).

Also remove that onSubmit, it's not doing anything.

Markus_Bianchi5
Level 2

Re: Invisible recaptcha vs visible recaptcha

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