Skip to content

reCAPTCHA in custom forms

Captcha support in Hyvä

Hyvä only supports the following reCaptcha versions:

The reCAPTCHA integration has to be fully configured in the system configuration at "Security > Google reCAPTCHA Storefront".
Your Google API Website Key and Secret Key need to be specified for reCAPTCHA to be available.

Disabling legacy Captcha

We currently don’t support the (old/default) Magento captcha, which is enabled by default.

Please disable the default Captcha integration since otherwise forms won’t work:

bin/magento config:set customer/captcha/enable 0

Magento allows the configuration of which forms should use reCAPTCHA through the system configuration. This is available only for forms that are part of the Magento store front out of the box.

Using reCaptcha for custom forms

In the following example, the code required to check the system configuration for a given form is omitted for clarity, as it is often not required for custom forms.

Use the following steps in order to implement reCAPTCHA v3 invisible in custom forms.

1. Declare the recaptcha_validation child block

Add a child block called recaptcha_validation as a child to the block rendering your form. Assign the template Magento_ReCaptchaFrontendUi::js/script_token.phtml.

<block name="my-form-block" template="My_Module::my-form.phtml">
    <block name="recaptcha_validation"
           template="Magento_ReCaptchaFrontendUi::js/script_token.phtml"/>
</block>

2. Render the reCAPTCHA hidden field

In your form, render the hidden reCAPTCHA input field and legal notice.
Both are supplied by blocks declared automatically for every page.

<?php

use Hyva\Theme\ViewModel\ReCaptcha;

/**
 * @var \Magento\Framework\View\Element\Template $block
 * @var \Magento\Framework\Escaper $escaper
 */

?>
<form action="<?= $escaper->escapeUrl($block->getUrl('my_module/action/post')) ?>"
      method="post"
      id="my-form"
      x-data="initMyForm()"
      @submit.prevent="submitForm()"
>
    <?= $block->getBlockHtml('formkey') ?>

    <!-- Render the hidden input field that will be validated server side -->
    <?= $block->getBlockHtml(ReCaptcha::RECAPTCHA_INPUT_FIELD_BLOCK) ?>

    <!-- Other Form Fields Here -->

    <!-- Render the legal notice block -->
    <div class="w-full grecaptcha-legal">
        <?= $block->getBlockHtml(ReCaptcha::RECAPTCHA_LEGAL_NOTICE_BLOCK) ?>
    </div>

    <div class="actions-toolbar">
        <div class="primary">
            <button type="submit" class="action submit primary">
                <?= $escaper->escapeHtml(__('Submit')) ?>
            </button>
        </div>
    </div>
</form>

3. Add client side reCAPTCHA validation

First, make the form part of an alpine component (if it isn't already anyway).
Then render the recaptcha_validation child block declared earlier in step 1 above.

The form element is expected to be assigned to a variable $form.
Any errors will be declared on the this.errors property of the component.

<script>
  function initMyForm() {
    return {
      submitForm() {
        // Do not rename $form!
        // In recaptcha_validation it is expected to be declared

        const $form = document.getElementById('#my-form');
        <?= $block->getChildHtml('recaptcha_validation'); ?>

        if (this.errors === 0) {
          $form.submit();
        }
      }
    }
  }
</script>