Skip to content

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.

To integrate the reCAPTCHA module, follow these steps. The calling order matters because each step depends on completing the previous step.

  1. Set the endpoint and fetch configuration.

    Call setEndpoint (if needed) and setConfig during app initialization. setConfig fetches the reCAPTCHA configuration from Commerce via the recaptchaFormConfig GraphQL endpoint, then stores it in sessionStorage.

    import * as reCAPTCHA from '@dropins/tools/recaptcha.js';
    reCAPTCHA.setEndpoint('https://www.example.com/graphql');
    await reCAPTCHA.setConfig();
  2. Initialize reCAPTCHA on pages with protected forms.

    Call initReCaptcha to load the Google reCAPTCHA script and render badges. Do not call this at the top level of the application. Call it only on pages that have forms protected by reCAPTCHA.

    await reCAPTCHA.initReCaptcha();
  3. Get a token on form submission.

    Call verifyReCaptcha when the user submits the form. Pass the returned token in the X-ReCaptcha header.

    const token = await reCAPTCHA.verifyReCaptcha();
    if (token) {
    fetchGraphQlApi.setFetchGraphQlHeader('X-ReCaptcha', token);
    }
    // Proceed with the GraphQL mutation
  4. 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):

  1. Call verifyReCaptcha to retrieve the reCAPTCHA token.
  2. Set the token in the X-ReCaptcha header.
  3. Send the GraphQL mutation. Commerce validates the token server-side and returns an error if validation fails.

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 form
const badgeId = 'my-custom-form-badge';
const badge = document.createElement('div');
badge.id = badgeId;
form.appendChild(badge);
// Configure and initialize
reCAPTCHA.setEndpoint(CORE_FETCH_GRAPHQL);
await reCAPTCHA.setConfig([{ badgeId }]);
await reCAPTCHA.initReCaptcha(0); // 0ms delay if already in an idle callback
// On submit
const token = await reCAPTCHA.verifyReCaptcha();

The reCAPTCHA package exposes the following APIs:

  • setEndpoint
  • setConfig
  • initReCaptcha
  • verifyReCaptcha
  • enableLogger

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');

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.

ParameterTypeDescription
configListPropsFormTypes[]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.

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.

ParameterTypeDefaultDescription
lazyLoadTimeoutnumber3000Delay 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 delay
await reCAPTCHA.initReCaptcha();
// No delay (e.g., inside requestIdleCallback)
await reCAPTCHA.initReCaptcha(0);

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-side

For custom forms, validate the token on the server side or client side according to your implementation.

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);
  • Mixed reCAPTCHA types 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_key are 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.