reCAPTCHA integration
The reCAPTCHA module enables reCAPTCHA protection, which is natively supported by Adobe Commerce. It supports both reCAPTCHA v3 Invisible and reCAPTCHA Enterprise. The module automatically detects the configured type in Commerce Admin and loads the appropriate script and API.
The module also provides an API that allows merchants to integrate reCAPTCHA protection into custom form implementations.
Google reCAPTCHA in the Admin Systems Guide describes how to configure Adobe Commerce.
Integration
Section titled “Integration”To integrate the reCAPTCHA module, follow these steps. The calling order matters because each step depends on completing the previous step.
-
Set the endpoint and fetch configuration.
Call
setEndpoint(if needed) andsetConfigduring app initialization.setConfigfetches the reCAPTCHA configuration from Commerce via therecaptchaFormConfigGraphQL endpoint, then stores it insessionStorage.import * as reCAPTCHA from '@dropins/tools/recaptcha.js';reCAPTCHA.setEndpoint('https://www.example.com/graphql');await reCAPTCHA.setConfig(); -
Initialize
reCAPTCHAon pages with protected forms.Call
initReCaptchato load the GooglereCAPTCHAscript and render badges. Do not call this at the top level of the application. Call it only on pages that have forms protected byreCAPTCHA.await reCAPTCHA.initReCaptcha(); -
Get a token on form submission.
Call
verifyReCaptchawhen the user submits the form. Pass the returned token in theX-ReCaptchaheader.const token = await reCAPTCHA.verifyReCaptcha();if (token) {fetchGraphQlApi.setFetchGraphQlHeader('X-ReCaptcha', token);}// Proceed with the GraphQL mutation -
Commerce validates the token. If validation fails, Commerce returns an error.
Flow for forms covered by Adobe Commerce natively
Section titled “Flow for forms covered by Adobe Commerce natively”Use the following workflow for standard Adobe Commerce integrations (login, registration, contact, and so on):
- Call
verifyReCaptchato retrieve thereCAPTCHAtoken. - Set the token in the
X-ReCaptchaheader. - Send the GraphQL mutation. Commerce validates the token server-side and returns an error if validation fails.
Flow for custom form integrations
Section titled “Flow for custom form integrations”For custom forms not natively covered by Commerce, you need to add an inline badge container and call setConfig with your badge ID. setConfig is safe to call even if the global initializer has already run. The fetch uses force-cache and the badge entry is additive.
import * as reCAPTCHA from '@dropins/tools/recaptcha.js';import { CORE_FETCH_GRAPHQL } from '../../scripts/commerce.js';
// Create a badge container in your formconst badgeId = 'my-custom-form-badge';const badge = document.createElement('div');badge.id = badgeId;form.appendChild(badge);
// Configure and initializereCAPTCHA.setEndpoint(CORE_FETCH_GRAPHQL);await reCAPTCHA.setConfig([{ badgeId }]);await reCAPTCHA.initReCaptcha(0); // 0ms delay if already in an idle callback
// On submitconst token = await reCAPTCHA.verifyReCaptcha();reCAPTCHA API
Section titled “reCAPTCHA API”The reCAPTCHA package exposes the following APIs:
setEndpointsetConfiginitReCaptchaverifyReCaptchaenableLogger
setEndpoint
Section titled “setEndpoint”Sets the GraphQL endpoint that the module uses to fetch the configuration. This is optional if reCAPTCHA uses the same endpoint used by the rest of the application. It inherits from the fetch-graphql package.
Must be called before setConfig if the endpoint differs from the default.
import * as reCAPTCHA from '@dropins/tools/recaptcha.js';
reCAPTCHA.setEndpoint('https://www.example.com/graphql');setConfig
Section titled “setConfig”Fetches the reCAPTCHA configuration from Commerce via the recaptchaFormConfig GraphQL endpoint, then stores the normalized result in sessionStorage. The module queries all known form types in a single request and determines the reCAPTCHA type (v3 or Enterprise) automatically.
Must be called before initReCaptcha and verifyReCaptcha.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
configList | PropsFormTypes[] | Optional. Array of { badgeId: string } objects specifying additional DOM element IDs where inline reCAPTCHA badges should be rendered. |
The following example calls the setConfig function without parameters for standard Commerce forms:
import * as reCAPTCHA from '@dropins/tools/recaptcha.js';
await reCAPTCHA.setConfig();Now pass a configList to add inline badge containers for custom forms:
await reCAPTCHA.setConfig([{ badgeId: 'my-form-badge' }]);The configList entries are additive. This example shows how to add extra badge containers to the forms returned by the backend. They do not filter, restrict, or override which forms are enabled.
initReCaptcha
Section titled “initReCaptcha”This function loads the Google reCAPTCHA script and initializes badges. The module automatically selects the correct script based on the configured reCAPTCHA type:
- v3:
https://www.google.com/recaptcha/api.js - Enterprise:
https://www.google.com/recaptcha/enterprise.js
This function must be called after calling setConfig. Call initReCaptcha on pages with protected forms, not globally. Otherwise, the reCAPTCHA scripts load on every page.
Parameters
Section titled “Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
lazyLoadTimeout | number | 3000 | Delay in milliseconds before loading the script. Use 0 when calling from an idle callback or when the form is already in the viewport. |
import * as reCAPTCHA from '@dropins/tools/recaptcha.js';
// Default: 3-second lazy load delayawait reCAPTCHA.initReCaptcha();
// No delay (e.g., inside requestIdleCallback)await reCAPTCHA.initReCaptcha(0);verifyReCaptcha
Section titled “verifyReCaptcha”Retrieves a reCAPTCHA token via the Google API. The Enterprise type uses grecaptcha.enterprise.execute(). The v3 type uses grecaptcha.execute(). If reCAPTCHA is disabled in the Commerce Admin, the function returns undefined, allowing forms to proceed without protection.
Must be called after setConfig and initReCaptcha.
For forms supported by native Adobe Commerce functionality, pass the token as an X-ReCaptcha header:
import * as reCAPTCHA from '@dropins/tools/recaptcha.js';
const token = await reCAPTCHA.verifyReCaptcha();if (token) { fetchGraphQlApi.setFetchGraphQlHeader('X-ReCaptcha', token);}// Proceed with mutation — Commerce validates the token server-sideFor custom forms, validate the token on the server side or client side according to your implementation.
enableLogger
Section titled “enableLogger”Enables [ReCaptcha]-prefixed debug-logging in the browser console. The logs trace the full lifecycle for development and debugging:
- Config fetch and normalization (which forms are enabled, which type is detected)
- Forms skipped due to missing
website_key - Mixed-type warnings
- Script loading URL
- Badge rendering per form
- Token requests and results
import * as reCAPTCHA from '@dropins/tools/recaptcha.js';
reCAPTCHA.enableLogger(true);Limitations
Section titled “Limitations”- Mixed
reCAPTCHAtypes are not supported. If you configure the Commerce Admin with both v3 and Enterprise types, the module disables reCAPTCHA entirely and logs a warning. All forms must use the same type. - Per-form type support is planned for a future release. This will allow the v3 type on some forms and the Enterprise type on others, simultaneously.
- Forms with empty
website_keyare skipped. If a form is enabled in Commerce Admin but has no website key configured, it is treated as disabled and a debug log is emitted.