Recently I needed to implement Google reCAPTCHA on a Lightning Web Component. The information available online on this topic was surprisingly scarce and scattered. After what was a bit of an ordeal I finally managed to get it working the way I wanted it to. To give back to the Ohana and save others the hassle, I decided to do a write-up so that this is available for others struggling with the same.

As always, I am merely standing on the shoulders of giants, and it’s thanks to them that I got where I needed to be. Github user WoolWarrior’s repo was especially helpful and formed the foundation of the end result. If you’re looking to implement reCAPTCA in Experience Cloud, I recommend looking at Craig Johnson’s article about it here. And last but not least, there are the countless heroes on Stack Exchange, that community is the gift that keeps on giving. That being said, let’s get into it.

The solution I ended up with comprises of:

  • A Static Resource that renders the reCAPTCHA component and passes on details to an LWC
  • A reusable Lightning Web Component with the reCAPTCHA
  • An Apex class to do the callout and parse the received information
  • A Lightning Web Component that embeds the reCAPTCHA component and uses it to enable or disable a button

The first step is registering a site with reCAPTCHA on https://www.google.com/recaptcha/. In this example, we’re working with v3. 

Give the site a name, select reCAPTCHA v3 as the type and add your domain (minus https://www)

Submit, and you’ll get a screen with a site key and a secret key. Keep these around, you’ll need them later.

Now, head on over to your Salesforce org and go to setup. Enter ‘remote site’ in the search box and create a new remote site setting. If you don’t do this, the callouts later on will fail.

That’s it as far as the point-and-click stuff is concerned. What we’ll need next are our static resource, the apex class and the components.

We’ll use the following HTML in our static resource. So copy the code and save it as a new html page. Then create a new static resource with the following parameters:

Some things to take note of:

  • Replace the two occurrences of YOURSITEKEY with the Site Key you generated in the reCAPTCHA Admin Console (‘6LeZrQwgAAAAAGH1wMAja8uDdesGQ7tNncmc2a86’ in this example)
  • Replace the last parameter in the parent.postMessage functions with the url of your org (so replace “https://dev–fre.lightning.force.com” with whatever your base URL is)
  • The code in the script will execute when the resource is loaded and will generate a client-side token. This token will be passed on to our reusable component by meant of the postMessage functions.

Next we’ll first create our Apex class:

Make sure to replace the value of the SECRET_KEY variable with your site secret from the reCAPTHA Admin Console (‘6LeZrQwgAAAAADzKx0_R0q237f1mE4V0VoclVUMa’ in our example). Also, be aware that storing the secret key like demonstrated above is not really a good practice, but it’ll do for the sake of this example.

The class itself is rather simple, and you’ll need to flesh this out in real life, but what we’re doing here is creating a POST request to the reCAPTCHA endpoint with the Token we’ll receive from the static resource. When successful, this call will return a score. This score is a value between 0 and 1, where 0 is absolutely dodgy and 1 is okey-dokey. 

reCAPTCHA learns by seeing real traffic on your site. For this reason, scores in a staging environment or soon after implementing may differ from production. As reCAPTCHA v3 doesn’t ever interrupt the user flow, you can first run reCAPTCHA without taking action and then decide on thresholds by looking at your traffic in the admin console. I set the score threshold to 0.5 for the sake of this demonstration. If the score is bigger than 0.5 I simply return TRUE.

With the Apex class in place, let’s move on to our reusable reCAPTCHA component.

This LWC will render the static resource in an iframe, and will call the captchaLoaded method in reCaptchaLWC.js when the component loads. In the reCaptchaLWC.js we create an event listener that will fire when it receives a message with the action parameter ‘getCAPCHA’. In that case we will call our apex class.

Our apex class will receive the token, do the callout and return TRUE or FALSE. Upon receiving our result from the Apex class, we’ll also fire a Custom Event so that whatever component we’re embedding this reCAPTCHA component in will be able to receive the data.

Now, for the final part, we’ll create a simple LWC with some form fields, a button and embed our reusable component in it.

Nothing special here. The final div element in the reCaptchaExample.html is where we embed our reusable component. We’re also telling the reCaptchaExample component to execute the handleCaptchaReceived method in our reCaptchaExample.js when it receives an event of the type we defined in our reCaptchaLWC.js. 

There are two button elements in reCaptchaLWC.html, these are tied to the variable allowSubmit. If allowSubmit equals TRUE, we’ll enable the button, and if it is FALSE we’ll disable the button.

Save your work, deploy it and place the reCaptchaExample component on a record page.

You’ll see the reCAPTCHA banner on the bottom of the component. You can also test the behavior of the button by setting the treshold score to a higher or lower value in the RecaptchaHandler class. Remember that reCAPTCHA will return a score between 0 and 1. Open the console if you want to see some additional logging:

That’s it! I hope this post ever comes to be of use to someone. If you have any questions or remarks, please reach out to me on Twitter, you can find me there as @pardonder or on our company’s handler @Upeoconsulting. You can also find me and Upeo on LinkedIn here and here. You can of course also contact us by leaving your details, and we’ll get in touch with you!