> This page is for Developer.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.bigcommerce.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.bigcommerce.com/_mcp/server.

# Integrating Google Pay direct pay with your custom checkout

Google Pay direct pay is a single-click variant of the Google Pay payment flow. Instead of the shopper selecting Google Pay, clicking **Sign in to Google Pay** to open the payment sheet, and then clicking **Place Order** to submit, the direct-pay flow renders a branded Google Pay button in place of the **Place Order** button. Clicking the button opens the Google Pay payment sheet and — on success — submits the order and redirects to the confirmation page in one step.

Stores using [checkout-js](https://github.com/bigcommerce/checkout-js) **v1.812.1** or higher support Google Pay direct pay out of the box once the feature is enabled for the store. If your store uses a custom checkout built on top of [checkout-sdk-js](https://github.com/bigcommerce/checkout-sdk-js), you will need to integrate direct pay by following the instructions in this article.

## Requirements

Google Pay direct pay is available to any store that already supports Google Pay. Check [Guide to Alternative Payment Methods: Google Pay](https://support.bigcommerce.com/s/article/Google-Pay) for a list of compatible payment gateways.

Before following the integration steps, ensure your custom checkout project is using the [checkout-sdk](https://www.npmjs.com/package/@bigcommerce/checkout-sdk) **v1.921.0** or higher. We recommend reviewing the [README file](https://github.com/bigcommerce/checkout-sdk-js?tab=readme-ov-file#initialize-instance) to familiarize yourself with checkout service usage.

Direct pay is gated by a server-side feature flag named `PI-5111.google_pay_direct_pay_on_click`. The flag is delivered alongside the rest of the store config in the `checkout-settings` request.

**`Check whether direct pay is enabled`**

```js title="Check whether direct pay is enabled" showLineNumbers={false}
const features = checkoutService
    .getState().data
    .getConfig()?.checkoutSettings.features ?? {};

const isDirectPayEnabled = Boolean(features['PI-5111.google_pay_direct_pay_on_click']);
```

![checkout-settings request with the PI-5111.google\_pay\_direct\_pay\_on\_click flag enabled](/_fern-img/013c5d1d6b3e3953738ffcca6c7ee6df2d5f9b366b9c4c786e830b6d3be0d569.webp)
If `isDirectPayEnabled` is `false`, continue using the standard Google Pay wallet-button flow. The rest of this article describes what to render when the flag is `true`.

> **Note**
>
> Direct pay must **only** be activated when the shopper selects Google Pay in the payment-step accordion. If the shopper already chose Google Pay upstream — for example, by clicking the Google Pay button on the cart page, product detail page, or customer step — they have already interacted with the Google Pay payment sheet, and showing the direct-pay button would force them to do so a second time. See [Step 1](#step-1-detect-whether-google-pay-was-pre-selected) below.

## Configuring direct pay in the payment step

### Step 1: Detect whether Google Pay was pre-selected

When your payment-step component mounts, capture whether Google Pay is already the active payment method on the checkout. If it is, fall back to the standard wallet-button flow instead of direct pay.

**`Detect pre-selection at mount time`**

```js title="Detect pre-selection at mount time" showLineNumbers={false}
const checkout = checkoutService.getState().data.getCheckout();

const isPaymentSelectedAtMount = checkout?.payments?.some(
    (payment) => payment.providerId === method.id,
) ?? false;
```

Save `isPaymentSelectedAtMount` in a ref (or equivalent stable variable) so subsequent re-renders do not change the rendered flow mid-session.

See the [Checkout JS repository](https://github.com/bigcommerce/checkout-js/blob/master/packages/google-pay-integration/src/GooglePayPaymentMethod.tsx) for an example of how `GooglePayPaymentMethod.tsx` uses a `useRef` to capture this value at mount.

### Step 2: Decide which component to render

Combine the feature flag from above with the pre-selection guard:

**`Decide which Google Pay component to render`**

```js title="Decide which Google Pay component to render" showLineNumbers={false}
if (isDirectPayEnabled && !isPaymentSelectedAtMount) {
    // Render the direct-pay component (see steps 3-6 below)
} else {
    // Render the existing wallet-button Google Pay component
}
```

### Step 3: Render the Google Pay button container

The direct-pay button is rendered into a DOM element that you provide. In the default checkout, the existing **Place Order** button slot — element ID `checkout-payment-continue` — is reused so the Google Pay button visually replaces it. You can use the same ID or pick your own.

**`Provide a container for the direct-pay button`**

```html title="Provide a container for the direct-pay button" showLineNumbers={false}
<div id="checkout-payment-continue"></div>
```

### Step 4: Hide the Place Order button

When the direct-pay flow is active, the standard **Place Order** button must not be visible — the Google Pay button takes its place. Hide it before initializing the payment.

**`Hide the Place Order button`**

```js title="Hide the Place Order button" showLineNumbers={false}
paymentForm.hidePaymentSubmitButton(method, true);
```

Remember to restore it (`hidePaymentSubmitButton(method, false)`) when the direct-pay component unmounts — for example, when the shopper switches to a different payment method.

### Step 5: Initialize the payment in container mode

Call `checkoutService.initializePayment` and pass the new `container` option on the Google Pay options object. When `container` is set, the SDK creates a branded Google Pay button via `GooglePayPaymentsClient.createButton` and inserts it into the container — there is no need to provide your own `walletButton` element.

The full option set for `GooglePayPaymentInitializeOptions` in container mode:

| Option               | Type                                  | Default     | Description                                                                                                                                                                                                                                               |
| -------------------- | ------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `container`          | `string`                              | —           | ID of the DOM element to render the Google Pay button into. Required for direct pay.                                                                                                                                                                      |
| `buttonColor`        | `'default' \| 'black' \| 'white'`     | `'default'` | Forwarded to Google Pay's `createButton`.                                                                                                                                                                                                                 |
| `buttonSizeMode`     | `'static' \| 'fill'`                  | `'fill'`    | Forwarded to Google Pay's `createButton`.                                                                                                                                                                                                                 |
| `buttonType`         | `'pay' \| 'buy' \| 'checkout' \| ...` | `'pay'`     | Forwarded to Google Pay's `createButton`.                                                                                                                                                                                                                 |
| `onInit`             | `(renderButton: () => void) => void`  | —           | Optional callback. When provided, the SDK calls it once initialization is complete and waits for you to invoke `renderButton()`. Useful if you need to defer rendering until the container is in the DOM. If omitted, the button is rendered immediately. |
| `onError`            | `(error: Error) => void`              | —           | Called when initialization or interaction with the Google Pay payment sheet fails.                                                                                                                                                                        |
| `loadingContainerId` | `string`                              | —           | ID of the element used to host the loading indicator while the order is being submitted.                                                                                                                                                                  |

Use the following code:

**`Initialize Google Pay in container mode`**

```js title="Initialize Google Pay in container mode" showLineNumbers={false}
await checkoutService.initializePayment({
    gatewayId: method.gateway,
    methodId: method.id, // for example, 'googlepaybraintree'
    [method.id]: {
        container: 'checkout-payment-continue',
        buttonColor: 'default',
        buttonSizeMode: 'fill',
        buttonType: 'pay',
        loadingContainerId: 'checkout-app',
        onError: (error) => {
            // Surface the error in your UI here
        },
    },
});
```

See the [Checkout JS repository](https://github.com/bigcommerce/checkout-js/blob/master/packages/google-pay-integration/src/GooglePayPaymentMethodComponent.tsx) for an example of container-mode initialization.

### Step 6: Handle the click, payment sheet, and order submission

Once the SDK has rendered the button, the entire flow — opening the Google Pay payment sheet, capturing the shopper's payment method, submitting the order, and redirecting to `/checkout/order-confirmation` — is handled internally by `GooglePayPaymentStrategy`. You do not need to wire up `checkoutService.submitOrder` for the direct-pay flow.

If the shopper cancels the payment sheet, or if the order submission fails, the SDK re-loads the checkout state so the full list of payment methods becomes available again. The error is passed to your `onError` callback so you can display a message and allow the shopper to retry or pick another method.

### Step 7: De-initialize the payment step

When the shopper switches to a different payment method, navigates back to a previous step, or otherwise unmounts the direct-pay component, call `checkoutService.deinitializePayment` and restore the **Place Order** button.

**`De-initialize the payment step`**

```js title="De-initialize the payment step" showLineNumbers={false}
paymentForm.hidePaymentSubmitButton(method, false);

await checkoutService.deinitializePayment({
    gatewayId: method.gateway,
    methodId: method.id,
});
```

De-initialization removes the SDK-created button element from the container, releasing the slot so the **Place Order** button can be shown again.

## Default payment step example

The image below depicts the Google Pay direct-pay button as it appears in the default checkout.

![Google Pay direct-pay button as it appears in the default checkout](/_fern-img/9a35d8e8a35fdb9afe53bb96fddff540b3ddfdad3a3224225b067e88e5c66b29.webp)

*The payment step of checkout with Google Pay direct pay implemented*

## Falling back to the wallet-button flow

When `isDirectPayEnabled` is `false`, or when Google Pay was pre-selected upstream, continue using the existing wallet-button flow. In that flow:

* The shopper sees the **Sign in to Google Pay** button (rendered into the `walletButton` element you provide).
* After completing the Google Pay payment sheet, the shopper returns to the payment step with their payment details populated.
* The shopper clicks **Place Order** to submit.

This flow is unchanged by the direct-pay feature. See the [Checkout JS repository](https://github.com/bigcommerce/checkout-js/blob/master/packages/google-pay-integration/src/GooglePayPaymentMethod.tsx) for an example of how the same component branches between the two flows.

## Resources

### Source code

* [Checkout JS repository](https://github.com/bigcommerce/checkout-js) (BigCommerce GitHub)
* [Checkout SDK repository](https://github.com/bigcommerce/checkout-sdk-js) (BigCommerce GitHub)

### Related articles

* [Open Checkout Tutorial](/developer/docs/admin/checkout-and-cart/open-checkout)
* [Getting Started with Checkout SDK](/developer/docs/admin/checkout-and-cart/checkout-sdk)