Homepage platformOS Logo

Adding hCaptcha Spam Protection

Last edit: Mar 19, 2021

This guide will help you add spam protection to your forms using hCaptcha. It includes:

Requirements

To follow this topic, you should be familiar with forms, form configuration options, and Authorization Policies, including how to add an Authorization Policy and associate it with a form.

Steps

Step 1: Create Authorization Policy for the hCaptcha

To add hCaptcha to a form, first create an Authorization Policy.

app/authorization_policies/is_hcaptcha_authorized.liquid

---
name: is_hcaptcha_authorized
redirect_to: /sign-in-hcaptcha
flash_alert: Invalid captcha authorization.
---
{{ context.params | hcaptcha }}

Step 2: Add form configuration header to your form in the configuration body

Add the Authorization Policy it to your form.

app/forms/sign_in_with_hcaptcha.liquid

---
name: sign_in_with_hcaptcha
resource: Session
authorization_policies:
  - modules/sign_in_hcaptcha/is_hcaptcha_authorized
fields:
  email:
  password:
---
{% form html-class: 'w-50' %}
  <div class="form-group">
    <label for="form_email">Email</label>
    <input class="form-control" name="{{ form.fields.email.name }}" value="{{ form.fields.email.value}}" id="form_email" type="email">
  </div>

  <div class="form-group">
    <label for="form_password">Password</label>
    <input class="form-control" name="{{ form.fields.password.name }}" id="form_password" type="password">
    {% if form.errors.password %}
      <p>{{ form.errors.password }}</p>
    {% endif %}
  </div>

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

  {% spam_protection "hcaptcha" %}

  <button class="btn btn-primary">Log In</button>
{% endform %}

Example 1: Regular form in a page (without form configuration)

This example shows how to add a regular form in a page (without form configuration) with the hcaptcha tags inside. This form posts to a page which has an authorization policy with the same content as in the example above.

app/authorization_policies/check_regular_hcaptcha_authorized.liquid


---
name: check_regular_hcaptcha_authorized
redirect_to: /unauthorized
flash_alert: Sorry
---
{{ params | hcaptcha }}

app/authorization_policies/check_authencity_token.liquid


---
name: check_authenticity_token
redirect_to: /unauthorized
flash_alert: Sorry
---
{{ context.csrf_request_valid }}

app/views/pages/regular_form_in_page.liquid


---
slug: regular_form_in_page
layout_name: 1col
---

<h1>Test hcaptcha in a regular form page.</h1>

<form action="/regular_page_post" method="post">
  <input type="hidden" name="authenticity_token" value="{{ context.authenticity_token }}" />

  {% spam_protection "hcaptcha" %}

  <input type="submit" name="submit" value="Submit" />
</form>

app/views/pages/regular_page_post.liquid


---
slug: regular_page_post
layout_name: 1col
method: post
authorization_policies:
  - check_regular_hcaptcha_authorized
  - check_authenticity_token
---

Protected page

Example 2: Protect page with the slug /main-content

To protect the page with the slug /main-content, create two pages:

  • /main-content
  • /content-protection

/main-content has an authorization policy with the same content as above, and uses redirect_to /content-protection (when the hcaptcha check fails). /content-protection has a regular form in it (no form configuration) with hcaptcha tags inside and posts to /main-content. This way main-content is hcaptcha protected by content-protection.

app/authorization_policies/check_authorized_for_content.liquid


---
name: check_authorized_for_content
redirect_to: /content-protection
flash_alert: Please solve the captcha correctly.
---
{{ params | hcaptcha }}

app/views/pages/main-content.liquid


---
slug: main-content
layout_name: 1col
method: post
authorization_policies:
  - check_authorized_for_content
---

Protected content

app/views/pages/content-protection.liquid


---
slug: content-protection
layout_name: 1col
---

<h1>Please solve the captcha below to access the protected content.</h1>

<form action="/main-content" method="post">
  <input type="hidden" name="authenticity_token" value="{{ context.authenticity_token }}" />

  {% spam_protection "hcaptcha" %}

  <input type="submit" name="submit" value="Submit" />
</form>

Example 3: Implementing hCaptcha using YML and GraphQL mutations

hCaptcha can also be used to protect a form implemented using the form configuration feature. In the example below, hcaptcha is added under spam_protection for the form configuration. The form is included from the captcha_form page. When successfully submitted, it will create a model of type model_with_title and will redirect to the /success_page.

app/schema/model_with_title.yml

---
name: model_with_title
custom_attributes:
- name: title
  type: string
---

app/forms/form_with_captcha.liquid


---
name: form_with_captcha
resource: model_with_title
resource_owner: "anyone"
configuration:
spam_protection:
  hcaptcha:
fields:
  properties:
    title:
return_to: /success_page
---

{% form html-novalidate: true, html-class: 'model-form' %}

<input name="{{ form.fields.properties.title.name }}" value="{{ form.fields.properties.title.value }}" type="text" />

{% spam_protection 'hcaptcha' %}

<input type="submit" name="submit" value="Submit" />

{% endform %}

app/views/pages/captcha_form.liquid


---
slug: captcha_form
layout_name: 1col
---

<h1>Test captcha form.</h1>

{% include_form 'form_with_captcha' %}

app/views/pages/success_page.liquid


---
slug: success_page
---

Success!

Live example and source code

To play with the live example visit the sign-in-hcaptcha page.

Source code can be found on GitHub.

Contribute to this page

Github Icon

Questions?

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

contact us