---
title: Chat
description: >-
  Embeds a real-time chat experience in checkout, letting buyers get live
  support without leaving the page.
api_version: 2026-07
source_url:
  html: >-
    https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/overlays/chat
  md: >-
    https://shopify.dev/docs/api/checkout-ui-extensions/latest/web-components/overlays/chat.md
api_name: checkout-ui-extensions
---

# Chat

The chat component embeds a hosted chat application inside checkout so buyers can get real-time support while they complete their purchase. The component renders an iframe whose contents are served from your app, and it provides a secure messaging channel between checkout and the embedded page.

**Note:**

The chat component can only be rendered in the chat targets of the checkout (`purchase.checkout.chat.render`) and Thank you (`purchase.thank-you.chat.render`) pages.

**Requires access to the \*\*Chat in checkout extensions\*\* scope. Request access in the Partner Dashboard.:**

### Support Targets (31)

### Supported targets

* [purchase.​checkout.​actions.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/navigation#navigation-target)
* [purchase.​checkout.​block.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/block#block-target)
* [purchase.​checkout.​cart-line-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/order-summary#line-item-targets)
* [purchase.​checkout.​cart-line-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/order-summary#checkout-cart-line-list-)
* [purchase.​checkout.​chat.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/web-components/overlays/chat)
* [purchase.​checkout.​contact.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/information#information-target)
* [purchase.​checkout.​delivery-address.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/shipping#render-after-delivery-address-)
* [purchase.​checkout.​delivery-address.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/shipping#delivery-address-targets)
* [purchase.​checkout.​footer.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/footer#footer-target)
* [purchase.​checkout.​header.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/header#header-target)
* [purchase.​checkout.​payment-method-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/payment#render-after-payment-methods-)
* [purchase.​checkout.​payment-method-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/payment#payment-targets)
* [purchase.​checkout.​pickup-location-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/local-pickup#render-after-pickup-locations-)
* [purchase.​checkout.​pickup-location-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/local-pickup#location-list-targets)
* [purchase.​checkout.​pickup-location-option-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/local-pickup#location-option-item-target)
* [purchase.​checkout.​pickup-point-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/pickup-points#render-after-pickup-points-)
* [purchase.​checkout.​pickup-point-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/pickup-points#pickup-points-targets)
* [purchase.​checkout.​reductions.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/order-summary#checkout-reductions-after-)
* [purchase.​checkout.​reductions.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/order-summary#reductions-targets)
* [purchase.​checkout.​shipping-option-item.​details.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/shipping#shipping-option-item-targets)
* [purchase.​checkout.​shipping-option-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/shipping#render-after-shipping-option-)
* [purchase.​checkout.​shipping-option-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/shipping#render-after-shipping-options-)
* [purchase.​checkout.​shipping-option-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/checkout/shipping#shipping-option-list-targets)
* [purchase.​thank-you.​announcement.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/thank-you/announcement#thank-you-announcement-)
* [purchase.​thank-you.​block.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/thank-you/block#block-target)
* [purchase.​thank-you.​cart-line-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/thank-you/order-summary#line-item-targets)
* [purchase.​thank-you.​cart-line-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/thank-you/order-summary#thank-you-cart-line-list-)
* [purchase.​thank-you.​chat.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/web-components/overlays/chat)
* [purchase.​thank-you.​customer-information.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/thank-you/information#information-target)
* [purchase.​thank-you.​footer.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/thank-you/footer#footer-target)
* [purchase.​thank-you.​header.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07/targets/thank-you/header#header-target)

#### Use cases

* **Live support:** Connect buyers with a support agent or chatbot to answer questions before they complete checkout.
* **Order assistance:** Help buyers resolve issues with shipping, payment, or discounts without leaving the page.
* **Post-purchase follow-up:** Offer order updates or upsell opportunities on the Thank you page.

***

## Properties

Configure the following properties on the chat component.

* **accessibility​Label**

  **ChatProps$1**

  A label that describes the purpose of the chat, announced by assistive technologies like screen readers.

* **block​Size**

  Adjust the block size.

  Checkout imposes [sizing restrictions](https://shopify.dev/docs/apps/build/checkout/chat#component-states) for the component, therefore the size set may not be the actual size rendered.

  Learn more about [block size on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/block-size).

* **inline​Size**

  Adjust the inline size.

  Checkout imposes [sizing restrictions](https://shopify.dev/docs/apps/build/checkout/chat#component-states) for the component, therefore the size set may not be the actual size rendered.

  Learn more about [inline size on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/inline-size).

### ChatProps

* accessibilityLabel

  A label that describes the purpose of the chat, announced by assistive technologies like screen readers.

  ```ts
  ChatProps$1
  ```

* blockSize

  Adjust the block size. Checkout imposes \[sizing restrictions]\(/docs/apps/build/checkout/chat#component-states) for the component, therefore the size set may not be the actual size rendered. Learn more about \[block size on MDN]\(https://developer.mozilla.org/en-US/docs/Web/CSS/block-size).

  ```ts
  ```

* inlineSize

  Adjust the inline size. Checkout imposes \[sizing restrictions]\(/docs/apps/build/checkout/chat#component-states) for the component, therefore the size set may not be the actual size rendered. Learn more about \[inline size on MDN]\(https://developer.mozilla.org/en-US/docs/Web/CSS/inline-size).

  ```ts
  ```

### Events

The chat component provides event callbacks for handling the embedded page lifecycle. Learn more about [handling events](https://shopify.dev/docs/api/polaris/using-polaris-web-components#handling-events).

* **ready**

  **CallbackEventListener\<typeof tagName>**

  A callback that fires when the embedded page is ready and a message port has been created to communicate with the host page.

### CallbackEventListener

A typed event listener for custom element events. The listener receives a \`CallbackEvent\` with the correct \`currentTarget\` type for the associated custom element tag.

```ts
(EventListener & {
    (event: CallbackEvent<TTagName, Event> & TData): void;
}) | null
```

### CallbackEvent

An event type that narrows the \`currentTarget\` to the specific HTML element associated with the custom element tag. This provides type-safe event handling in callback listeners.

```ts
TEvent & {
    currentTarget: HTMLElementTagNameMap[TTagName];
}
```

### Methods

The chat component exposes methods for communicating with the embedded page. Learn more about [using methods](https://shopify.dev/docs/api/polaris/using-polaris-web-components#methods).

* **content​Window**

  **{ postMessage(message: any): void; }**

  **required**

  Returns an object exposing a `postMessage` method used to send messages to the embedded page rendered inside the chat iframe. Pair this with the `ready` event (or `onReady` callback) to know when the message channel is available.

***

## Examples

### Basic chat

Render a chat experience in checkout. This example renders an `s-chat` element sized for a support widget. The iframe source is provided by the `chat` key under `preloads` in the extension configuration file.

## Basic chat

![A minimized chat component in checkout](https://shopify.dev/assets/assets/images/templated-apis-screenshots/checkout-ui-extensions/2025-07/chat-component-minimized-STaKmVzE.png)

## Preact

```jsx
import '@shopify/ui-extensions/preact';
import {render} from 'preact';


// This extension requires `extensions.targeting.preloads.chat` in the
// extension configuration file. Its value is used as the iframe `src`.
export default function extension() {
  render(<Extension />, document.body);
}


function Extension() {
  return (
    <s-chat
      accessibilityLabel="Chat with our support team"
      inlineSize="100px"
      blockSize="50px"
    />
  );
}
```

### Resize the chat iframe from the hosted application

A common action in your application is to request a resize of the iframe. The visible region of the chat iframe is controlled from the hosted application with `window.resizeTo()`. This example resizes the iframe when an activator button is clicked to reveal a dialog, and resizes it back when the dialog is closed.

## Resize the chat iframe from the hosted application

##### Preact

```jsx
// @extension-target: purchase.checkout.chat.render
import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
  render(<Extension />, document.body);
}

// The resize logic lives in the hosted application, which calls
// `window.resizeTo()` through App Bridge. The extension just renders the chat.
function Extension() {
  return (
    <s-chat
      accessibilityLabel="Chat with our support team"
      inlineSize="150px"
      blockSize="50px"
    />
  );
}
```

##### Hosted chat application

```html
<!doctype html>
<html lang="en">
  <head>
    <script src="https://cdn.shopify.com/shopifycloud/checkout-web/assets/app-bridge-checkout.js"></script>
  </head>
  <body>
    <dialog class="dialog" aria-label="Chat with our support team">
      How can we help you today?
      <button class="btn-close">Close</button>
    </dialog>
    <button class="btn-activator">Chat with us</button>

    <script type="text/javascript">
      const btnActivator = document.querySelector('.btn-activator');
      const btnClose = document.querySelector('.btn-close');
      const dialog = document.querySelector('.dialog');

      btnActivator.addEventListener('click', openDialog);
      btnClose.addEventListener('click', () => dialog.close());

      // The native `close` event fires for both the Close button and the
      // Escape key, so resizing the iframe back down lives here.
      dialog.addEventListener('close', () => {
        shopify !== undefined && window.resizeTo(150, 50);
      });

      function openDialog() {
        // Resize the iframe to fit the dialog, then open it with the native
        // dialog API. `showModal()` moves focus into the dialog, traps focus,
        // closes on Escape, and exposes it to assistive technologies as modal.
        shopify !== undefined && window.resizeTo(415, 700);
        dialog.showModal();
      }
    </script>
  </body>
</html>
```

### Communicate information between the hosted application and the UI extension

Information can be passed between the UI extension and the hosted application. From the extension, send a message into the iframe with the component's [`contentWindow.postMessage`](#methods) method once the `ready` event (or `onReady` callback) has fired. Inside the iframe, the hosted application listens and replies through `shopify.extension.port`. Back in the extension, listen for the reply with a `message` listener added once the `ready` event has fired.

## Communicate information between the hosted application and the UI extension

##### Preact

```jsx
// @extension-target: purchase.checkout.chat.render
import '@shopify/ui-extensions/preact';
import {render} from 'preact';
import {useEffect, useRef} from 'preact/hooks';

export default function extension() {
  render(<Extension />, document.body);
}

function Extension() {
  const chatRef = useRef(null);

  useEffect(() => {
    const chat = chatRef.current;
    if (chat == null) return;

    // Listen for messages coming back from the hosted application. The sandbox
    // relays the raw message payload (not a `MessageEvent`), so its fields are
    // read directly off the argument rather than from `event.data`.
    function handleMessage(message) {
      if (message?.action === 'pong') {
        console.log('Messaging channel successful');
      }
    }

    // `ready` fires once the message channel is available.
    function handleReady() {
      window.addEventListener('message', handleMessage);

      // Read the buyer's first name to personalize the chat experience, then
      // send it into the iframe with the element's `contentWindow.postMessage`.
      const firstName = shopify.shippingAddress?.value?.firstName;
      chat.contentWindow.postMessage({
        action: 'ping',
        buyer: {firstName},
      });
    }

    chat.addEventListener('ready', handleReady);

    // Tear down the listeners when the extension unmounts.
    return () => {
      chat.removeEventListener('ready', handleReady);
      window.removeEventListener('message', handleMessage);
    };
  }, []);

  return (
    <s-chat
      ref={chatRef}
      accessibilityLabel="Chat with our support team"
      inlineSize="150px"
      blockSize="50px"
    />
  );
}
```

##### Hosted chat application

```js
// Create a variable to store the buyer's first name.
// We'll be able to use this to personalize the chat experience.
let buyerFirstName;

// In the hosted application Javascript, listen for messages from the UI extension.
shopify.extension.port.onmessage = async (event) => {
  // if the message's data has a ping action, respond with a pong
  if (event.data.action === 'ping') {
    buyerFirstName = event.data.buyer.firstName;

    await shopify.extension.port.postMessage({
      action: 'pong',
    });
  }
};

// Ensure the messagePort is ready to start sending and receiving messages.
shopify.extension.port.start();
```

***

## Chat dimensions

To give you the most flexibility for responsive layouts, the iframe rendered by chat takes the full width and height of the browser window, and only a clipped region is visible. The `inlineSize` and `blockSize` values you set on the component (or change at runtime through App Bridge) define the bounding box of that visible region, fixed to the bottom-right corner.

Because the iframe fills the window, your application can rely on the window's dimensions to apply responsive styles. For example, CSS media queries work inside the iframe as if your application were rendered outside of one. Checkout imposes [maximum dimensions](https://shopify.dev/docs/apps/build/checkout/chat/ux-for-chat#build-within-the-chat-component-dimensions) on large and small screens.

![Illustration of the chat iframe filling the window with only a clipped region visible](https://shopify.dev/assets/assets/images/templated-apis-screenshots/checkout-ui-extensions/2025-07/chat-component-iframe-clipping-B2YxDEbl.png)

***

## App Bridge for checkout

App Bridge for checkout provides a secure communication channel between checkout and the application embedded in the chat iframe, along with helpers for common actions such as resizing the iframe. After App Bridge is set up, your application has access to the `shopify` global variable, which exposes functionality and configuration for the embedded page.

### Getting started with App Bridge for checkout

Add App Bridge to your hosted chat application by including the `app-bridge-checkout.js` script as the first script in the `<head>` of your page. The script loads directly from Shopify and keeps itself up to date.

## html

```html
<head>
  <script src="https://cdn.shopify.com/shopifycloud/checkout-web/assets/app-bridge-checkout.js"></script>
</head>
```

Inbound messages from checkout are received inside the iframe through App Bridge. To send messages from the extension into the iframe, use the component's [`contentWindow.postMessage`](#methods) method, and pair it with the `ready` event (or `onReady` callback) to know when the message channel is available.

### App Bridge's global variable

After App Bridge is set up in your app, you have access to the `shopify` global variable. This variable exposes various App Bridge functionalities, such as resizing the iframe or retrieving details of the shop.

To explore everything available on the `shopify` global variable:

* Open the Chrome developer console while in checkout.
* Switch the frame context to your app's iframe.
* Enter `shopify` in the console.

### App Bridge CSS API

Because the chat iframe is clipped and fills the whole window, percentage-based sizes resolve against the window rather than the visible region, which can clip your content. App Bridge exposes a set of [CSS custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) matching the [maximum dimensions](https://shopify.dev/docs/apps/build/checkout/chat/ux-for-chat#build-within-the-chat-component-dimensions) defined in the UX guidelines. Use them — in CSS or JavaScript — to guard against overflowing content while still using percentage-based sizes, and to stay resilient if Shopify changes the maximum dimensions.

## css

```css
:root {
  --shopify-checkout-chat-minimized-max-inline-size: 224px;
  --shopify-checkout-chat-minimized-max-block-size: 72px;
  --shopify-checkout-chat-maximized-max-inline-size: 415px;
  --shopify-checkout-chat-maximized-max-block-size: 700px;


  @media screen and (max-width: 579px) {
    --shopify-checkout-chat-maximized-max-inline-size: 100dvi;
    --shopify-checkout-chat-maximized-max-block-size: 93dvb;


    @supports not (inline-size: 100dvi) {
      --shopify-checkout-chat-maximized-max-inline-size: 100vi;
      --shopify-checkout-chat-maximized-max-block-size: 93vb;
    }
  }
}
```

## css

```css
.activator {
  inline-size: 100%;
  max-inline-size: var(--shopify-checkout-chat-minimized-max-inline-size);
}


.dialog {
  inline-size: 100%;
  max-inline-size: var(--shopify-checkout-chat-maximized-max-inline-size);
}
```

***

## Chat source and query parameters

The iframe `src` is provided by the `chat` key under `preloads` in the extension configuration file. Shopify automatically appends query parameters that let you verify the authenticity of the request and the identity of the merchant:

* **`id_token`**: A signed [JSON Web Token (JWT)](https://openid.net/specs/openid-connect-core-1_0.html#IDToken%5C) with a 5-minute TTL, used to retrieve merchant information on your backend and to ensure that requests came from a Shopify-authenticated source. See the [ID token documentation](https://shopify.dev/docs/apps/build/authentication-authorization/session-tokens).
* **`locale`**: The locale of the shop embedding the app, for example `en-CA`. Also available on the `shopify` global variable under `config`.
* **`handle`**: The unique handle of the UI extension as defined by the developer. Also available on the `shopify` global variable under `extension`.

***
