For several years now, CAPTCHAs have become common on forms found across websites. The system has evolved significantly over time, up to the current version 3. Whereas in the past it was necessary to solve a visual test, reCAPTCHA V3 now works invisibly by analyzing the user’s behavior and assigning a score to determine the likelihood of being human or a bot.
Configuring reCAPTCHA in Magento 2
Magento 2 natively offers Google reCAPTCHA integration, particularly on account creation and contact forms. This tool can be enabled or disabled directly from the back office, and the version used can be selected.
To configure reCAPTCHA V3, navigate to:Stores -> Configuration -> Security -> Google reCAPTCHA Storefront
.
The configuration steps are as follows:
- Enter the public key and the private key, available in the Google reCAPTCHA Console.
Although Google is progressively phasing out the need for a private key depending on the use case, Magento 2 still requires it for now.
To retrieve this key, select the desired API key and go to the integration section. There you will either find a button “Integrate with a third-party service or plugin” or “Use legacy key.” - Define the minimum trust score, between 0 and 1 (0 meaning very likely a bot, 1 meaning a human). A score above 0.5 is generally recommended.
Once this configuration is complete, you can choose which forms reCAPTCHA will be active on via the Storefront section.
Transition toward keyless reCAPTCHA
Although for now the private key for Google reCAPTCHA remains accessible and necessary in Magento 2, Google is gradually moving toward a model—especially with reCAPTCHA V3—where only the public key is required.
This change simplifies server-side integration but also forces platforms like Magento to adapt their code to align with this new logic.
As long as Magento 2 has not removed this dependency, you must continue entering the private key. However, in future Magento updates, reCAPTCHA handling may evolve—or change completely.
But what about using a captcha on a custom form?
Integrating reCAPTCHA into a custom form
1. Add the option in the back office
Start by adding an entry in the admin interface to enable captcha on your custom form. This is done in the etc/adminhtml/system.xml
file:
<section id="recaptcha_frontend">
<group id="type_for">
<field id="custom_form" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1">
<label>Enable for Custom Form</label>
<source_model>Magento\ReCaptchaAdminUi\Model\OptionSource\Type</source_model>
</field>
</group>
</section>
2. Add the reCAPTCHA block to the form
Then, in the layout file, within your form block, add a reCAPTCHA block:
<block name="custom.form" template="My_Module::custom_form.phtml">
<block class="Magento\ReCaptchaUi\Block\ReCaptcha"
name="recaptcha"
template="Magento_ReCaptchaFrontendUi::recaptcha.phtml"
ifconfig="recaptcha_frontend/type_for/custom_form"> <!-- path to captcha configuration -->
<arguments>
<argument name="recaptcha_for" xsi:type="string">custom_form</argument> <!-- captcha configuration field name -->
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="recaptcha" xsi:type="array">
<item name="component" xsi:type="string">Magento_ReCaptchaFrontendUi/js/reCaptcha</item>
</item>
</item>
</argument>
</arguments>
</block>
</block>
In the corresponding template file, you can integrate the block as follows:
<form action="<?= $block->getUrl('form/send') ?>" method="post" id="custom-form">
<div>
<input name="fullname" id="fullname" title="fullname" value="" type="text">
</div>
<div>
<input name="telephone" id="telephone" title="telephone" value="" type="tel">
</div>
<div>
<input name="email" id="email" title="email" value="" type="email">
</div>
<?= $block->getChildHtml('recaptcha'); ?> <!-- block call -->
<button class="action secondary" data-role="custom-form-submit">
<span><?= __('Send form'); ?></span>
</button>
</form>
At this point, reCAPTCHA will appear on the form, but the server-side validation logic still needs to be implemented.
3. Server-side validation
Create an observer that runs before any action on your form:
<?php
namespace My\Module\Observer;
use Magento\Framework\App\Response\HttpFactory;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\UrlInterface;
use Magento\ReCaptchaUi\Model\IsCaptchaEnabledInterface;
use Magento\ReCaptchaUi\Model\RequestHandler;
class CustomFormObserver implements ObserverInterface
{
public function __construct(
private IsCaptchaEnabledInterface $isCaptchaEnabled,
private UrlInterface $url,
private RequestHandler $requestHandler,
private HttpFactory $responseFactory,
) {
}
public function execute(Observer $observer): void
{
$key = 'custom_form'; //Le nom donné au captcha
if (!$this->isCaptchaEnabled->isCaptchaEnabledFor($key)) {
return; //If captcha is not enabled, there is no need to continue
}
$request = $observer->getRequest(); //We retrieve the request from the class to which we apply the observer
$response = $this->responseFactory->create();
$redirectOnFailureUrl = $request->getServer('HTTP_REFERER') ?? $this->url->getUrl('*/*/index'); //Redirection in case of captcha failure
$this->requestHandler->execute($key, $request, $response, $redirectOnFailureUrl); //We perform the verification.
}
}
Then declare this observer in etc/frontend/events.xml
:
<event name="controller_action_predispatch_form_send">
<observer name="recaptcha_on_custom_form" instance="My\Module\Observer\CustomFormObserver"/>
</event>
No additional logic is required if the form is submitted normally.
4. Special case: AJAX submission
If your form is submitted via a JavaScript event (for example, on click
), without using the submit
method, reCAPTCHA may not work correctly. In fact, in the DOM a hidden textarea field exists, which stores a key generated upon submission. If not initialized, reCAPTCHA won’t validate properly.
Here is an example workaround:
handleCustomFormSubmit: function () {
let _self = this;
$('#custom-form').on('submit', function (e) {
e.preventDefault();
return false;
});
$('button[data-role="custom-form-submit"]').on('click', function () {
var form = $('#custom-form');
if (form.validation() && form.validation('isValid')) {
form.trigger('submit');
let captchaField = form.find('[name*="g-recaptcha-response"]');
if (captchaField.length) {
const originalFetch = window.fetch;
window.fetch = async function (...args) {
const [url] = args;
if (typeof url === 'string' && url.includes('https://www.google.com/recaptcha/api2')) {
_self.customFormSubmit();
captchaField.val('');
window.fetch = originalFetch;
}
return originalFetch.apply(this, args);
};
} else {
_self.customFormSubmit();
}
}
return false;
});
}
This code:
- Simulates a standard submission to force reCAPTCHA token generation.
- Retrieves the
g-recaptcha-response
field containing the key (check if it exists in case reCAPTCHA is disabled for this form). - Monitors AJAX requests to detect the reCAPTCHA request, then triggers the custom submission.
With these steps, you can effectively integrate Google reCAPTCHA into your custom forms in Magento 2, ensuring they work properly—even with asynchronous submission.