Re: Step by step guide to recaptcha

Sarah_Bartell1
Level 1

I've read through all the discussions and threads on implementing google's recaptcha in a marketo form (we are getting tons of spam and the honeypot thing isn't working).

I have the site key needed from Google, I have the code written by Sanford Whiteman​, and now I have no idea how to start to implement this - I'm pretty sure I can figure out the form part with the css and js but i'm mostly confused by the back-end portion with the webhook.

Does anyone have a step by step guide? We need to get this done on our site asap.

Thanks much!

24 REPLIES 24
Rachit_Puri2
Level 7

Implementing Google Recaptcha may not be a great idea. We implemented this on our website, and start running into issues. Since we target executives, captcha created a very bad user experience for our audience. We saw a sharp dip in our conversions for many of our campaigns. In fact, in China, the captcha didn't work at all and caused many issues. In the end, we decide to remove the captcha, and put some backend checks in place to ensure that the spam leads are not sent to the reps, and we clean them regularly.

Casey_Grimes
Level 10

Yeah, China is definitely a unique situation for captchas. You're better off using a locally-hosted solution such as BotDetect (which is among many things you have to think to de-Google). That said, I really think long term the solution to this problem is going to lean towards using some combination of DNSBLs (Spamhaus, StopForumSpam, Akismet, etc. I've also recently used CleanTalk in a non-Marketo context and have been impressed thus far) and/or creating some sort of collective marketing automation blacklist database. At the end of the day, that's really all noCAPTCHA is doing--it's just maintaining a giant blacklist.

Daniel_Martin
Level 2

I don't know if this could help you, but in our company every Marketo form is followed up by an automatic, operational email (Thank you email) to validate the email address. In case the spambot is not using a valid email address, you can create a, lets say, daily scheduled smart-campaign, which it will take every contact created through that form, that never received the "thank you" email (Was Sent Email + Not Was Delivered Email) and make Marketo to add them automatically to a list, or directly delete them.

This is also useful when you want to share an asset (like a brochure pdf, a link to a report or intelligence, etc), so you make sure that no one will fill the form with "test@test.com" and receive the asset.

Again, I don't know if this solution will be suitable for your business model, but I hope it will help you

Akshay_Pant
Level 5

HI Sarah Bartell​,

Please refer to this link :

http://jennamolby.com/how-to-build-a-spam-free-marketo-form-without-using-a-captcha/?source=marketo-...

I think this stuff would really helpful for making spam free recaptcha.

Regards,

Akshay Pant

SanfordWhiteman
Level 10 - Community Moderator

Except anybody who wants to spam such a form can trivially work around that code. I mean, the rules are right there in the view-source. It's not the same as a ReCAPTCHA... at all.

Sarah_Bartell1
Level 1

As I mentioned above, we tried the honeypot field and it didn't work. We still got hit over 30k times by a spambot. We've opened a ticket with Marketo support to see if anyone can walk us through the ReCaptcha, but if anyone has done this in Marketo before and has a quick step by step guide, or could list out the process for us in the meantime, that would be super helpful!

SanfordWhiteman
Level 10 - Community Moderator

It's not something I've ever documented end-to-end (too many other blog posts and projects in motion) but the ingredients on the back end (you seem to understand the front end) are:

  • Set up 3 fields, LastReCAPTCHAUserResponse (string), LastReCAPTCHAServerStatus (boolean), LastReCAPTCHAServerSuccess (datetime), LastReCAPTCHAServerFailure (datetime)
  • LastReCAPTCHAUserResponse is what holds the unique ReCAPTCHA response ID on the form end, the others are used only on the back end
  • A webhook calls the Google ReCAPTCHA endpoint and passes {{lead.LastReCAPTCHAUserResponse}}
  • The webhook response mapping maps the Google response to LastReCAPTCHAServerStatus
  • In a trigger SC, catch a change to LastReCAPTCHAServerStatus and set either LastReCAPTCHAServerSuccess or LastReCAPTCHAServerFailure to {{system.datetime}} based on whether the status is good/bad
  • Take other flow actions to sort leads into suspect/deletable lists accordingly. You don't want to delete suspect leads immediately when first rolling out. First quarantine the leads, check 'em out, and then you can start deleting them nightly or immediately.

No one at Support is going to understand this at all, sorry to say. This is pretty much my baby when it comes to Marketo.

Tags (2)
Vlada_Prasolova
Level 5

Hi!

i might have a stupid question here, but i'm trying to recreate this one and i'm a bit confused why you need both LastReCAPTCHAUserResponse (string) and LastReCAPTCHAServerStatus (boolean)?

i have so far created webhook, mapped sucess to the server status and even managed to receive correct response

my server status is TRUE, according to your suggestion, which means that i have validaded the CAPTCHA

i've timestamped the date and the form ID

so far i've used all fields you mention but the actual LastReCAPTCHAUserResponse

​am i missing something vital here? where should this go?

SanfordWhiteman
Level 10 - Community Moderator

LastReCAPTCHAUserResponse is for the end-user fingerprint (generated in the browser, added to the form). You have to be using some field for this, maybe you already had one and thus can skip LastReCAPTCHAUserResponse.

Lawrence_Mien1
Level 2

This may be horribly incorrect, but I was following this guide and trying to modify it for a landing page form rather than an embedded form and for the life of me can't get it to work.

I added the forms2 code below like so, but maybe it's not incorrect? It's the only part where I havent followed it to a tee...

<div class="mktoForm" id="primaryForm" mktoName="Primary Form" style="margin-bottom:40px;padding:10px 20px;min-height:80px;"></div>

<div>

                <script>

                MktoForms2.whenReady(function (form) {

                      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}" == "block") {

                        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}" == "block") {

                          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);

                          }

                      }     

                    });

                });

                </script>

            </div>

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


What could be wrong here?
Just in case the html code section isnt showing up correctly....

SanfordWhiteman
Level 10 - Community Moderator

Far better to supply your code inline, highlighted with the Advanced Editor's syntax highlighter.

https://s3.amazonaws.com/blog-images-teknkl-com/syntax_highlighter.gif

Or just link to the URL on which you're trying the code.

Note on Marketo LPs, forms customization JS needs to go just before the closing </body> tag, if you're not already doing this. You can't put it in the <head> or elsewhere in the <body> because it depends on the Forms 2.0 library loading first.

Also, image attachments don't show up in all versions of the Community. I didn't see anything there until I switched browsers -- you can paste images directly into posts if necessary.

Lawrence_Mien1
Level 2

Ah okay. I think I included used the right container for the post.

This is what I have for the form

<div class="mktoForm" id="primaryForm" mktoName="Primary Form" style="margin-bottom:40px;padding:10px 20px;min-height:80px;"></div>

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

I had this just right after the form, but now i've moved it to just before the </body> tag

<script>

MktoForms2.whenReady(function (form) {

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}" == "block") {

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}" == "block") {

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);

}

}

});

});

</script>

Lawrence_Mien1
Level 2

Sanford Whiteman​ it seems it still doesn't work, so there must be something wrong with my code...

SanfordWhiteman
Level 10 - Community Moderator

What's the URL where this is running?

Lawrence_Mien1
Level 2
SanfordWhiteman
Level 10 - Community Moderator

You have an invalid quotation mark:

pastedImage_0.png

Which throws this in the console:

pastedImage_1.png

Fix that and try again.

Lawrence_Mien1
Level 2

Hmm I've made the change but it still hasn't gone through.
This is the flow steps i'm calling the webhook with, so the results are showing that it's doing nothing...


Screen Shot 2019-01-24 at 2.37.52 PM.png

SanfordWhiteman
Level 10 - Community Moderator

Trying to troubleshoot backwards from the Call Webhook activity isn't going to work. You shouldn't be looking on the Marketo side at all, except perhaps for the Filled Out Form activity (the only way to audit what was posted by the browser). The browser is where everything happens.

Here you can see you've purposely added a condition which prevents the reCAPTCHA fingerprint from being added to the form:

pastedImage_4.png

You really need someone to troubleshoot this who can quickly trace JS code and knows what's needed.

Mark_Brailsford
Level 2

Sanford this approach makes sense to me. Would it work in an embedded form? Also, where's a good place to learn about implementing the webhook that calls the Google ReCAPTCHA endpoint?

SanfordWhiteman
Level 10 - Community Moderator

Sure, it works in an embedded form just fine.

Greg went deeper into some of the steps in this offsite doc. It should be wrapped up in a Products blog post at some point.