Adding reCaptcha V2 Spam Protection

This guide will help you add spam protection to your forms with Google reCAPTCHA. In this example, you'll display spam protection after a specified number of failed login attempts.
We do support Google reCAPTCHA V2 and reCAPTCHA V3. For adding reCAPTCHA V3 please visit "Adding reCAPTCHA V3 spam protection"

Requirements

To follow this tutorial, you should be familiar with creating pages and forms, especially user sign in forms. You should also know how to add an integration to your site using the Partner Portal.

Steps

Adding reCAPTCHA protection is a four-step process:

Step 1: Add Google reCAPTCHA V2 keys

Go to our Partner Portal, and add reCAPTCHA keys in the Integrations section. Keys can be generated on https://www.google.com/recaptcha.

Step 2: Create sign-in page with spam protection


Start with a simple sign-in page with spam protection enabled by default.
Create a sign-in page and sign-in form configuration.
Form configuration needs to have the attribute spam_protection: { "recaptcha_v2": {} } with configuration to enable protection, available options can be found in Form tutorial
Also use the {% spam_protection %} tag to generate required JS (you can include required JS code on your own).

views/pages/sign-in-recaptcha.liquid


---
slug: sign-in-recaptcha
---
<h2>Sign in</h2>

{% include_form 'sign_in_with_recaptcha' %}

forms/sign_in_with_recaptcha.liquid


---
name: sign_in_with_recaptcha
resource: Session
spam_protection:
  recaptcha_v2:
fields:
  email:
  password:
---
{% form %}
    <input name="{{ form.fields.email.name }}" value="{{ form.fields.email.value}}" type="email">
    <input name="{{ form.fields.password.name }}" type="password">

  <div class="form-group">
    {{ form.errors.base }}
    {% spam_protection "recaptcha_v2" %}
  </div>

  <button>Sign In</button>
{% endform %}

Step 3: Count failed attempts

In order to show reCAPTCHA only after a specified number of failed login attempts, you need to know how many times the user tried to log in. You can count this and store the number in a session. Use mutation session_create_field.
You also need the sign-in form configuration without spam protection.

forms/sign_in_without_recaptcha.liquid


---
name: sign_in_without_recaptcha
resource: Session
fields:
  email:
  password:
callback_actions: >
  {% graphql res = "clear_failed_signin_attempts" %}
---
{% form %}
    <input name="{{ form.fields.email.name }}" value="{{ form.fields.email.value}}" type="email">
    <input name="{{ form.fields.password.name }}" type="password">

  {% if form.errors != empty %}
    {% assign attempts = context.session.failed_attempts | default: 1 | plus: 1 %}
    {% graphql res = "set_failed_signin_attempts", attempts: attempts %}
  {% endif %}

  <button>Sign In</button>
{% endform %}


graphql/set_failed_signin_attempts.graphql

mutation set_failed_signin_attempts($attempts: Any!) {
  session_create_field(name: "failed_attempts", value: $attempts)
}

Step 4: Show spam protection only after the specified number of failed login attempts

Once you have the number of failed attempts in the session, you can display the correct form, with or without spam protection. context variable has information about the session.

views/pages/sign-in-recaptcha.liquid


---
slug: sign-in-recaptcha
---
<h2>Sign in </h2>

{% assign signin_failed_attempts = context.session.failed_attempts | plus: 0 %}
{% if signin_failed_attempts > 3 %}
  {% include_form 'sign_in_with_recaptcha' %}
{% else %}
  {% include_form 'sign_in_without_recaptcha' %}
{% endif %}


After the user signed in successfully, you should clear session information with callback {% graphql res = "clear_failed_signin_attempts" %}

graphql/clear_failed_signin_attempts.graphql

mutation clear_failed_signin_attempts {
  session_delete_field(name: "failed_attempts")
}

Live example and source code

To play with live example create developer account at https://examples.platform-os.com and go to the sign-in-recaptcha page.

Source code can be found on GitHub.

Additional resources

Questions?

We are always happy to help with any questions you may have.