Google reCAPTCHA V3

reCAPTCHA by Google is a free service that protects your website from spam and abuse. It's designed to be friendly to humans, much more friendly than image-based CAPTCHA. It uses advanced risk analysis techniques to tell humans and bots apart to protect your website from spam.

reCAPTCHA v3 allows you to verify if an interaction is legitimate without any user interaction. It is a pure JavaScript API returning a score, giving you the ability to take action in the context of your site.

Validating the request

When you call grecaptcha.execute() to validate the user Google will return a string token. That token should then be populated into a hidden form field and submitted with the form. The BranchCMS system will then verify the token by contacting Google with the reCAPTCHA API keys. Google will return a response that indicates whether or not the token validated and a score based on the information Google gathered about the request. If the score is equal to or higher than the minimum allowed score that you configure when you set up the reCAPTCHA then the form submission will be accepted. If the score is lower than the minimum score then the submission is rejected and an error message is returned to the form to indicate that the reCAPTCHA validate was not successful. 

See the Output the CAPTCHA in the template section for more information.

Get started

Step 1 - Set up the reCAPTCHA with Google

To get started with reCAPTCHA you must first have a Google account.  Once you are logged into Google go to https://www.google.com/recaptcha/admin to register your new website.  The usage of reCAPTCHA is limited to the domains that you register. It's recommended that if you have multiple domains that you register each one separately.

  1. Label - Give a meaningful, but short name that describes your site.
  2. reCAPTCHA type - Choose "reCAPTCHA v3".
  3. Domains - Enter the domain or domains that you plan to use reCAPTCHA on.
  4. Owners - this should be your Google account email
  5. Accept the reCAPTCHA Terms of service
  6. Check off the "Send alerts to owners"
  7. Click the "Submit" button.

See the Settings documentation on the Google site for more information.  

Step 2 - Get the API keys

Once you've registered your site you then need to get the API credentials. reCAPTCHA gives you a "Site Key" and "Secret Key"

You will need to copy those to the Google reCAPTCHA V3 configuration page in BranchCMS.

  1. In BranchCMS click on the "Site Settings" link at the upper right of the administration and then click on "Spam Protection".
  2. Then click on "Configure reCAPTCHA V3".
  3. Copy the "Site key" value from the Google reCAPTCHA page and paste it into the "Site Key" field.
  4. Copy the "Secret key" value from the Google reCAPTCHA page and past it into the "Secret Key" field. 
  5. Save the settings by clicking the blue "Save Google reCAPTCHA" button.

Make sure that if either of those values ends in punctuation that you get the punctuation too. 

Optional - Set the default action

Google reCAPTCHA V3 requires that an action is set when the reCAPTCHA is executed. You can set the default action to use with forms. This value is used with the Javascript code that is outputted with the {{ form.captcha.tag }} variable.

Integrate with your form

Now that reCAPTCHA is set up for your site you can use it on your forms. By default, CAPTCHA is disabled on all forms. To enable it, edit the form and go to the CAPTCHA tab. 

Pick Captcha Type

Choose "Google reCAPTCHA V3" for the "CAPTCHA Type" field. That will show you the status of the reCAPTCHA integration. 

Template variables

The following template variables are available for Google reCAPTCHA V3

Variables Description
form.captcha.action

The reCAPTCHA page action to record.

You set a default action for all uses of the reCAPTCHA V3 when you configure it.

form.captcha.error

The error message if the reCAPTCHA does not validate.

form.captcha.errorCode

The error code if the reCAPTCHA does not validate.

form.captcha.failed

Boolean value on whether or not the reCAPTCHA validation failed.

form.captcha.input

The hidden form field that will hold the reCAPTCHA token to submit with the form. This has to be within the opening and closing form fields.

It will be automatically outputted with the {{ form.captcha.tag }} variable. Or, you can output it directly with the {{ form.captcha.input.tag }} variable.

If you use {{ form.captcha.input.tag }} do not also use {{ form.captcha.tag }} as the field will then be included twice.

form.captcha.isUsable

A boolean value on whether or not the reCAPTCHA V3 has been set up and enabled.

form.captcha.js

The Google reCAPTCHA Javascript file that needs to be loaded onto the page.

You can manipulate it by changing the {{ form.captcha.js.src }} value.

{% set form.captcha.js.src = form.captcha.js.src ~ '&callback=myCallback' %}

The <script> tag to output the Javascript file is automatically included in the {{ form.captcha.tag }} variable. Or, you can output it directly with the {{ form.captcha.js.tag }} variable.

If you use {{ form.captcha.js.tag }} do not also use {{ form.captcha.tag }} as that will cause the Javascript file to be loaded twice.

You can also set it to be outputted with other Javascript files.

{% do _page.addJs(form.captcha.js.src) %}

form.captcha.script

This holds the default Javascript that will be outputted with the {{ form.captcha.tag }} variable. It includes a Javascript Promise that will execute the reCAPTCHA to validate the form.

You can output it as a string:

{{ form.captcha.script }}

Or, you can treat it as an array and access its values as described below.

form.captcha.script.function

This holds the Javascript Promise function name that your code will need to use to call the Javascript Promise when the form is submitted. The name is randomly generated each time the page loads.

{{ form.captcha.script.function }}

form.captcha.script.tag

This provides another way to output the default Javascript that will be outputted with the {{ form.captcha.tag }} variable. It includes a Javascript Promise that will execute the reCAPTCHA to validate the form.

The following tags output the same value:

{{ form.captcha.script }}

{{ form.captcha.script.tag }}

form.captcha.sitekey

This holds the Google reCAPTCHA API site key.

form.captcha.tag

This will output the default reCAPTCHA tag. It includes the hidden form field that holds the reCAPTCHA token and the Javascript Promise that will execute the reCAPTCHA.

form.captcha.type

This holds the reCAPTCHA type. For reCAPTCHA V3 the value is "recaptchaV3".

Output the CAPTCHA in the template

Google reCAPTCHA V3 is different from the other reCAPTCHA types in that it requires more manual Javascript to make it work. The {{ form.captcha.tag }} variable will output some default Javascript that can be used to integrate the CAPTCHA into your form. You can, however, do your own custom implementation if you want.

Testing for CAPTCHA type

You may want to use some logic to display the reCAPTCHA in your templates if there is a chance that a different type of CAPTCHA could be chosen.

The reCAPTCHA V3 CAPTCHA type is designated by the "recaptchaV3" value for the form.captcha.type variable.

{% if form.captcha.type == 'recaptchaV3' %}
   {# Output the Google reCAPTCHA V3 #}
{% endif %}

Use the default Javascript

The easiest method for using reCAPTCHA V3 with your form is to make use of the default output from the {{ form.captcha.tag }} variable. That will output the following:

  • A hidden form field to hold the reCAPTCHA token.
  • Some Javascript that will set up a Javascript Promise that needs to be used to execute the reCAPTCHA when the form is submitted.
{% set form.class = 'myForm' %}
{{ form.openTag }}
   {# Display fields #}
   {% for field in form.fields %}
     <p>{{ field.label.tag }}<br>{{ field.tag }}</p>
   {% endfor %}

   <p><button type="submit">Submit</button></p>
   {{ form.captcha.tag }}
{{ form.closeTag }}

<script>
/**
 * Intercept the form submit event. Then execute the reCAPTCHA and when that is successful submit the form.
 * You may want to modify this and incorporate it in your form validation.
 */
var form = document.querySelector('.myForm');
form.addEventListener('submit', function(e) {
    e.preventDefault();
    {# Call the Javascript Promise function to execute the reCAPTCHA #}
    {{ form.captcha.script.function }}(grecaptcha).then(function() {
      form.submit();
    });
});
</script>

Javascript function parameters

The Javascript Promise function that is outputted from the form.captcha.script.tag and form.captcha.tag accepts two parameters.

  1. The grecaptcha object. This required value should be available as a global variable after the Google Javascript file is included on the page. You should not have to change this value.
  2. The optional options object.

Below are the options that can be passed to the options parameter.

Option Description
action

The Google reCAPTCHA action to set. You would use this if you wanted to set the action in your Javascript. By default the default action set when the reCAPTCHA was configured in the administration is used. You could also set the action in the Twig code.

{% set form.captcha.action = 'myAction' %}

Below is how you would set the action in your Javascript.

{{ form.captcha.script.function }}(grecaptcha, {action: 'myAction'});

inputSelector

If your page will have multiple forms with Google reCAPTCHA V3 then you need to have a unique selector for the hidden input field that will hold the reCAPTCHA token that is submitted with the form. First you will want to make sure that the input class is unique. You can then specify that class as the selector when building your Javascript.

{{ form.captcha.script.function }}(grecaptcha, {inputSelector: '.{{ form.captcha.input.class }}'});

setField

This is a boolean value for whether or not to set the reCAPTCHA token as the value for the reCAPTCHA hidden input field. It defaults to true.  If you're using this code for a form submission then you should probably just leave this as true.

{{ form.captcha.script.function }}(grecaptcha, {setField: false});

Custom implementation

If you have unique needs for your forms you can use the different CAPTCHA template variables and your own custom Javascript to execute the reCAPTCHA. You must execute the reCAPTCHA and populate the hidden form field with the token value before the form is submitted. If you don't then the form will not validate and be processed.

{% set form.class = 'myForm' %}
{{ form.openTag }}
   {# Display fields #}
   {% for field in form.fields %}
     <p>{{ field.label.tag }}<br>{{ field.tag }}</p>
   {% endfor %}
   {{ form.captcha.input.tag }}
   <p><button type="submit">Submit</button></p>
{{ form.closeTag }}

{# Set the Javascript file to load asynchronously and to be deferred. This is optional and it helps with performance. #}
{% set form.captcha.js.async = true %}
{% set form.captcha.js.defer = true %}
{{ form.captcha.js.tag }}
<script>
/**
 * Intercept the form submit event. Then execute the reCAPTCHA and when that is successful submit the form.
 * You may want to modify this and incorporate it in your form validation.
 */
var form = document.querySelector('.myForm');
form.addEventListener('submit', function(e) {
    e.preventDefault();
    grecaptcha.execute('{{ form.captcha.sitekey }}', {action: '{{ form.captcha.action }}'}).then(function(token) {
      document.querySelector('.{{ form.captcha.input.class }}').value = token;
      form.submit();
    });
});
</script>

Overriding CAPTCHA Settings

You can override certain CAPTCHA values. This can be useful if you need to customize the function or if you are including multiple reCAPTCHAs on the same page. Because it's not common to have multiple reCAPTCHAs on one page, by default all reCAPTCHAs on the page will use the same function and have the same input class. These will need to be changed in order for them to work correctly.

Values that you can override include:

  • The reCAPTCHA action
  • Any of the hidden input tag attributes like the class or id
  • The name of the Javascript Promise function that will be used to execute the reCAPTCHA to validate the form
Value Description
form.caption.action

You can customize the reCAPTCHA action for individual forms if desired.

{% set form.captcha.action = 'myAction' %}

form.captcha.input.class

You can override the class attribute of the hidden input that will hold the reCAPTCHA token. We recommend using the random_string function to ensure that the input class is unique.

{% set form.captcha.input.class = 'captchaInput' ~ random_string() %}

form.captcha.input.id

You can override the id attribute of the hidden input that will hold the reCAPTCHA token. We recommend using the random_string function to ensure that the input id is unique.

{% set form.captcha.input.id = 'captchaInputId' ~ random_string() %}

form.captcha.script.function

You can override the name of the Javascript promise function that will be used to execute the reCAPTCHA validation, get the token, and apply the token to the CAPTCHA input tag. We recommend using the random_string function to ensure that the function name is unique.

{% set form.captcha.script.function = 'captchaFunction' ~ random_string() %}

Including Google reCAPTCHA on other pages

Google recommends that you include the reCAPTCHA V3 code on all pages of your website so that they have more information about someone's traffic and if they are a bot.

It's recommended that when you set a custom reCAPTCHA action that is different from the default one used for the forms. That way when you're reviewing the reCAPTCHA analytics in the Google reCAPTCHA admin you can view the top actions and their scores.

A common approach is to include the code to output the reCAPTCHA V3 code in a Snippet that is outputted near the closing </body> tag. Using the Snippet centralizes the code and outputting it near the closing </body> tag helps with performance and rendering. 

Because you may be including this snippet on a page that has a form protected by Google reCAPTCHA you'll want to make sure that you're not including the Google Javascript file multiple times. Use the _page.hasJs() tag to test for the existence of some registered Javascript code. This allows you to only include the Javascript code if it hasn't already been included for a form. If the reCAPTCHA is being used to protect a form on a page then there is no reason to also include the reCAPTCHA code on the page to register a page action.

Ideally you want to have this code before you output any Javascript using {{ _page.js() }} in your page footers. That will improve support for multiple reCAPTCHAs on one page if your pages need that.

{% if _core.service.recaptchaV3.isUsable %}
    {% if _page.hasJs('recaptchaV3') == false %}
        {# You can set a custom action. #}  
      {% set _core.service.recaptchaV3.action = 'myAction' %}
      {% do _page.registerJs('recaptchaV3') %}
      {{ _core.service.recaptchaV3.js.tag }}
      {{ _core.service.recaptchaV3.script.tag }}
   {% endif %}
{% endif %}

The reCAPTCHA code is accessed through the _core.services.recaptchaV3 variable. You should only use this to include the reCAPTCHA code on a page outside of a form. Within a form you should continue to use the form.captcha variables.

The _core.services.recaptchaV3 variable is an array that holds the same information that the form.captcha variable does. The major difference is that the Javascript code to call grecaptcha.execute() is automatically run with _core.services.recaptchaV3.

Including reCAPTCHA in your form and on the page

You will also want to adjust your form template code that outputs the reCAPTCHA Javascript to use a similar method of testing for existing registered Javascript code.

{% set form.class = 'myForm' %}
{{ form.openTag }}
   {# Display fields #}
   {% for field in form.fields %}
     <p>{{ field.label.tag }}<br>{{ field.tag }}</p>
   {% endfor %}

   <p><button type="submit">Submit</button></p>
   {% if _page.hasJs('recaptchaV3') == false %}
      {# Include the hidden input tag, reCAPTCHA Javascript file and the Javascript promise function #}
      {{ form.captcha.tag }}
      {% do _page.registerJs('recaptchaV3') %}
   {% else %}
      {# Only output the hidden input tag as the reCAPTCHA Javascript file and the Javascript promise function have already been included on the page. #}
      {{ form.captcha.input.tag }}
   {% endif %}
{{ form.closeTag }}

<script>
/**
 * Intercept the form submit event. Then execute the reCAPTCHA and when that is successful submit the form.
 * You may want to modify this and incorporate it in your form validation.
 */
var form = document.querySelector('.myForm');
form.addEventListener('submit', function(e) {
    e.preventDefault();
    {# Call the Javascript Promise function to execute the reCAPTCHA #}
    {{ form.captcha.script.function }}(grecaptcha).then(function() {
      form.submit();
    });
});
</script>

Multiple reCAPTCHAs on one page

If you need to have multiple forms on a single page that all use reCAPTCHA then you need to do a few additional steps to make sure that everything works.

The basic need is that the hidden input that holds the reCAPTCHA token that is submitted with the form needs to have a unique selector. Also, the Javascript that adds the token to the hidden input needs to know that selector.

There are a few ways to do this.

Option 1 - Just make the input class unique

You can make the hidden input class unique by simply setting the new class value. We recommend using the random_string function to ensure that the class name is unique.

{% set form.captcha.input.class = 'myValue' ~ random_string() %}

You may also want to set the input id to be unique if you are concerned about HTML purity.

{% set form.captcha.input.class = 'myValue' ~ random_string() %}
{% set form.captcha.input.id = 'newId' ~ random_string() %}

Alternately, you could use a built-in helper method to set both the input class and id value to a unique value.

{% do form.captcha.makeInputUnique() %}

You will then need to use that class as the inputSelector for the Javascript function that runs the reCAPTCHA.

In this example code we're making the input class and id unique, we're supporting multiple uses of reCAPTCHA on the same page, and we're using the same Javascript function to process the reCAPTCHA across each form.

{% set form.class = 'myForm' %}
{{ form.openTag }}
   {# Display fields #}
   {% for field in form.fields %}
     <p>{{ field.label.tag }}<br>{{ field.tag }}</p>
   {% endfor %}

   <p><button type="submit">Submit</button></p>
   {# Make the captcha input unique #}
   {% do form.captcha.makeInputUnique() %}

   {# Handle multiple instances of the reCAPTCHA on the same page #}
   {% if _page.hasJs('recaptchaV3') == false %}
      {# Include the hidden input tag, reCAPTCHA Javascript file and the Javascript promise function #}
      {{ form.captcha.tag }}
      {% do _page.registerJs('recaptchaV3') %}
   {% else %}
      {# Only output the hidden input tag as the reCAPTCHA Javascript file and the Javascript promise function have already been included on the page. #}
      {{ form.captcha.input.tag }}
   {% endif %}
{{ form.closeTag }}

<script>
/**
 * Intercept the form submit event. Then execute the reCAPTCHA and when that is successful submit the form.
 * You may want to modify this and incorporate it in your form validation.
 */
var form = document.querySelector('.myForm');
form.addEventListener('submit', function(e) {
    e.preventDefault();
    {# Call the Javascript Promise function to execute the reCAPTCHA #}
    {# Pass the input class selector so that this forms reCAPTCHA input gets updated #}
    {{ form.captcha.script.function }}(grecaptcha, {inputSelector: '.{{ form.captcha.input.class }}'}).then(function() {
      form.submit();
    });
});
</script>

Option 2 - Make the input and the Javascript function unique

The default Javascript that BranchCMS builds for the reCAPTCHA validation includes a function that is executed that runs the reCAPTCHA validation. In addition to making the input class unique you could also make this Javascript function unique and have a separate set of Javascript code to process this forms reCAPTCHA.

You can do it the long way:

{% set form.captcha.input.class = 'myValue' ~ random_string() %}
{% set form.captcha.input.id = 'newId' ~ random_string() %}
{% set form.captcha.script.function = 'myFunction' ~ random_string() %}

Or the shorter way:

{% do form.captcha.makeInputUnique() %}
{% do form.captcha.makeScriptUnique() %}

Or the shortest way:

{% do form.captcha.makeUnique() %}

The next thing to do is to use both the updated input class and the updated Javascript function on your page.

In this example code we're doing the following:

  • making the input class and id unique
  • supporting multiple uses of reCAPTCHA on the same page
  • setting the reCAPTCHA Javascript to be added to the inline Javascript for the page that will be outputted later with {{ _page.js() }} at the end of the HTML. Learn more about outputting Javascript on your page.
{% set form.class = 'myForm' %}
{{ form.openTag }}
   {# Display fields #}
   {% for field in form.fields %}
     <p>{{ field.label.tag }}<br>{{ field.tag }}</p>
   {% endfor %}

   <p><button type="submit">Submit</button></p>
   {# Make the captcha input unique #}
   {% do form.captcha.makeUnique() %}

   {# Handle multiple instances of the reCAPTCHA on the same page #}
   {% if _page.hasJs('recaptchaV3') == false %}
      {# Include the hidden input tag, reCAPTCHA Javascript file and the Javascript promise function #}
      {{ form.captcha.tag }}
      {% do _page.registerJs('recaptchaV3') %}
   {% else %}
      {# Output the hidden input tag as the reCAPTCHA Javascript file has already been included on the page. #}
      {{ form.captcha.input.tag }}
      {# Add the captcha Javascript to the inline Javascript for the page to be outputted after the reCAPTCHA Javascript file #}
      {% do form.captcha.script.inlineJs() %}
   {% endif %}
{{ form.closeTag }}

<script>
/**
 * Intercept the form submit event. Then execute the reCAPTCHA and when that is successful submit the form.
 * You may want to modify this and incorporate it in your form validation.
 */
var form = document.querySelector('.myForm');
form.addEventListener('submit', function(e) {
    e.preventDefault();
    {# Call the Javascript Promise function to execute the reCAPTCHA #}
    {{ form.captcha.script.function }}(grecaptcha).then(function() {
      form.submit();
    });
});
</script>

Because you are adding the reCAPTCHA Javascript code to the inline Javascript for the page you want to make sure that you include the Google reCAPTCHA script tag before you  output any Javascript with the {{ _page.js() }} tag.

{# Do this before you output any inline Javascript in the footer #}
{% if _core.service.recaptchaV3.isUsable %}
    {% if _page.hasJs('recaptchaV3') == false %}
      {% do _page.registerJs('recaptchaV3') %}
      {{ _core.service.recaptchaV3.js.tag }}
      {{ _core.service.recaptchaV3.script.tag }}
   {% endif %}
{% endif %}

{# Output any inline Javascript or script tags added to the page #}
{{ _page.js() }}

</body>
</html>