Chatcomponent
Use the Chat component to create real-time chat applications.
Anchor to chatpropsChatProps
- Anchor to accessibilityLabelaccessibilityLabelstring
A label that describes the purpose or contents of the component. When set, it will be announced to users using assistive technologies and will provide them with more context.
- Anchor to blockSizeblockSizenumber
Adjust the block size.
Checkout imposes sizing restrictions for the component, therefore the size set may not be the actual size rendered.
number
: size in pixels.Learn more about block size on MDN.
- string
A unique identifier for the component.
- Anchor to inlineSizeinlineSizenumber
Adjust the inline size.
Checkout imposes sizing restrictions for the component, therefore the size set may not be the actual size rendered.
number
: size in pixels.Learn more about inline size on MDN.
- Anchor to onMessageonMessage(event: ) => void
Callback when the embedded page sends a message.
- Anchor to onReadyonReady(event: ) => void
Callback when the embedded page is ready and a message port has been created to communicate with the host page.
ChatProps
- accessibilityLabel
A label that describes the purpose or contents of the component. When set, it will be announced to users using assistive technologies and will provide them with more context.
string
- 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. `number`: size in pixels. Learn more about [block size on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/block-size).
number
- id
A unique identifier for the component.
string
- 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. `number`: size in pixels. Learn more about [inline size on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/inline-size).
number
- onMessage
Callback when the embedded page sends a message.
(event: MessageEvent) => void
- onReady
Callback when the embedded page is ready and a message port has been created to communicate with the host page.
(event: ReadyEvent) => void
export interface ChatProps extends IdProps {
/**
* 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.
*
* `number`: size in pixels.
*
* Learn more about [inline size on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/inline-size).
*/
inlineSize?: number;
/**
* 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.
*
* `number`: size in pixels.
*
* Learn more about [block size on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/block-size).
*/
blockSize?: number;
/**
* A label that describes the purpose or contents of the component. When set,
* it will be announced to users using assistive technologies and will
* provide them with more context.
*/
accessibilityLabel?: string;
/**
* Callback when the embedded page sends a message.
*/
onMessage?: (event: MessageEvent) => void;
/**
* Callback when the embedded page is ready and a message port has been created to
* communicate with the host page.
*/
onReady?: (event: ReadyEvent) => void;
}
MessageEvent
- data
The data sent by the message emitter (the embedded page). Learn more about [MessageEvent data on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/data).
any
- origin
A string representing the origin of the message emitter (the embedded page). Learn more about [MessageEvent origin on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/origin).
string
interface MessageEvent {
/**
* The data sent by the message emitter (the embedded page).
*
* Learn more about [MessageEvent data on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/data).
*/
data?: any;
/**
* A string representing the origin of the message emitter (the embedded page).
*
* Learn more about [MessageEvent origin on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/origin).
*/
origin: string;
}
ReadyEvent
- postMessage
A function to send messages to the embedded page. Learn more about [postMessage on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/postMessage).
(message: any) => void
export interface ReadyEvent {
/**
* A function to send messages to the embedded page.
*
* Learn more about [postMessage on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/postMessage).
*/
postMessage: (message: any) => void;
}
Anchor to app bridge for checkoutApp Bridge for checkout
The App Bridge script for checkout provides APIs that enables a secure communication channel between the Shopify checkout and the embedded application within the Chat iframe. It also offers convenient methods to perform common actions like resizing the iframe from within the application.
After App Bridge is set up in your app, you have access to the shopify
global variable. This variable exposes the following App Bridge functionalities and configuration information:
- Anchor to configconfig
The static configuration values that will not change during runtime.
- Anchor to extensionextension
The references and APIs to the UI extension that helped bootstrap the iframe.
- Anchor to idTokenidToken() => Promise<string>
The ID token providing a set of claims as a signed JSON Web Token (JWT) with a TTL of 5 minutes. It can be used to ensure that requests came from a Shopify authenticated user. See the ID Token documentation for more information.
- Anchor to platformplatform'browser' | 'shop-app' | 'pos'
The platform or application that the app is embedded within.
- Anchor to surfacesurface"checkout"
The Shopify surface that the app is embedded within.
- Anchor to visitorvisitor() => Promise<>
Information about the current visitor.
AppBridge
- config
The static configuration values that will not change during runtime.
Config
- extension
The references and APIs to the UI extension that helped bootstrap the iframe.
Extension
- idToken
The ID token providing a set of claims as a signed [JSON Web Token (JWT)](https://openid.net/specs/openid-connect-core-1_0.html#IDToken%5C) with a TTL of 5 minutes. It can be used to ensure that requests came from a Shopify authenticated user. See the [ID Token documentation](/docs/apps/build/authentication-authorization/session-tokens) for more information.
() => Promise<string>
- platform
The platform or application that the app is embedded within.
'browser' | 'shop-app' | 'pos'
- surface
The Shopify surface that the app is embedded within.
"checkout"
- visitor
Information about the current visitor.
() => Promise<Visitor>
interface AppBridge {
/**
* The static configuration values that will not change during runtime.
*/
config?: Config;
/**
* The Shopify surface that the app is embedded within.
*/
surface?: 'checkout';
/**
* The platform or application that the app is embedded within.
*/
platform?: 'browser' | 'shop-app' | 'pos';
/**
* The ID token providing a set of claims as a signed [JSON Web Token (JWT)](https://openid.net/specs/openid-connect-core-1_0.html#IDToken%5C)
* with a TTL of 5 minutes. It can be used to ensure that requests came from a Shopify authenticated user.
* See the [ID Token documentation](/docs/apps/build/authentication-authorization/session-tokens) for more information.
*
* @see /docs/api/checkout-ui-extensions/latest/apis/session-token
* @see /docs/apps/build/authentication-authorization/session-tokens
*/
idToken?: () => Promise<string>;
/**
* The references and APIs to the UI extension that helped bootstrap the iframe.
*/
extension?: Extension;
/**
* Information about the current visitor.
*
* @ignore async via our RPC endpoints to ensure a secure handshake between
* host and client is established.
*/
visitor?: () => Promise<Visitor>;
}
Config
- locale
The locale of the shop that’s embedding the app.
string
interface Config {
/**
* The locale of the shop that’s embedding the app.
*/
locale?: string;
}
Extension
- handle
The unique handle name of the UI extension as defined by the developer. Learn more about [extension configuration](/docs/api/checkout-ui-extensions/latest/configuration#how-it-works).
string
- port
A MessagePort instance for communicating directly to and from the UI Extension that created the iframe. It will need to be started to begin receiving messages. Learn more about [MessagePort on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort).
MessagePort
- resizeTo
Set an iframe’s size. Depending on the context, the host page may decide to apply or ignore the new sizes. For example, if the iframe is meant to fill its parent container the host would ignore the request. Conversely, if the parent container allows the iframe to fill it the host would apply the new size. Alias to `window.resizeTo()`, available here for feature discovery by the embedding app. Learn more about [resizeTo() on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/resizeTo).
(width: number, height: number) => void
interface Extension {
/**
* The unique handle name of the UI extension as defined by the developer.
*
* Learn more about [extension configuration](/docs/api/checkout-ui-extensions/latest/configuration#how-it-works).
*/
handle?: string;
/**
* A MessagePort instance for communicating directly to and from the UI
* Extension that created the iframe. It will need to be started to begin
* receiving messages.
*
* Learn more about [MessagePort on MDN](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort).
*/
port?: MessagePort;
/**
* Set an iframe’s size. Depending on the context, the host page may decide
* to apply or ignore the new sizes. For example, if the iframe is meant to
* fill its parent container the host would ignore the request. Conversely,
* if the parent container allows the iframe to fill it the host would
* apply the new size.
*
* Alias to `window.resizeTo()`, available here for feature discovery by the
* embedding app.
*
* Learn more about [resizeTo() on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/resizeTo).
*/
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
resizeTo?: Window['resizeTo'];
}
Visitor
- id
The unique token of a given user across all surfaces in a shop, present if processing permission is provided.
string
interface Visitor {
/**
* The unique token of a given user across all surfaces in a shop,
* present if processing permission is provided.
*
* @ignore this maps to the _shopify_y cookie which Trekkie refers to as a
* uniqToken.
*/
id?: string;
}
Basic Chat
examples
Basic Chat
React
import { reactExtension, Chat, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.chat.render', () => <Extension />, ); // This component requires the configuration of the `extensions.targeting.preloads.chat` in the extensions configuration file. // Its value will be used as the `src` attribute of the Chat component. function Extension() { return <Chat inlineSize={100} blockSize={50} />; }
JS
import {extension, Chat} from '@shopify/ui-extensions/checkout'; // This component requires the configuration of the `extensions.targeting.preloads.chat` in the extensions configuration file. // Its value will be used as the `src` attribute of the Chat component. export default extension('purchase.checkout.chat.render', (root) => { const chat = root.createComponent(Chat, { inlineSize: 100, blockSize: 50, }); root.appendChild(chat); });
Preview

Anchor to src-and-query-parametersChat source and query parameters
The src
of the iframe rendered by Chat is provided by the preloads
chat
key in the extension configuration file. Shopify automatically appends query parameters to the URL which allows developers to verify the authenticity of the request and the identity of the merchant. We guarantee these tokens are valid and signed by Shopify.
id_token
The ID token providing a set of claims as a signed JSON Web Token (JWT) with a TTL of 5 minutes. It can be used to retrieve merchants information on the backend as well as ensure that requests came from a Shopify authenticated source. See the ID Token documentation for more information.
locale
The locale of the shop that’s embedding the app, i.e. . This information is also available in the
shopify
global variable under config
.
handle
The unique handle name of the UI extension as defined by the developer. This information is also available in the shopify
global variable under extension
.
Chat source
shopify.extension.toml
examples
Chat source
shopify.extension.toml
[[extensions.targeting]] target = "purchase.checkout.chat.render" [extensions.targeting.preloads] chat = "https://my-chat-application.com"
Anchor to chat-dimensionsChat dimensions
To provide developers with the most flexibility when it comes to responsive changes, the iframe rendered in the page by Chat
takes the full width and height of the browser window. Only a specific part of the iframe is visible, the rest is clipped.
The and
values set on the Chat component or changed through the App Bridge
method dictates the bounding box of the visible part. That box is fixed and positioned in the bottom right corner of the iframe.
Your application can rely on the window’s dimension to change styles or apply specific behaviors to different window sizes. This allow developers to style their app as if as if the application would be outside an iframe. For example, CSS media queries can now work within the iframe.

Anchor to about-app-bridgeGetting started with App Bridge for checkout
You must add App Bridge to your hosted chat application by including the script tag pointing to the app-bridge-checkout.js
as the first script in the <head>
section as seen in the example. The script loads directly from Shopify and keeps itself up-to-date.
Hosted chat application
examples
Hosted chat application
<head> <script src="https://cdn.shopify.com/shopifycloud/checkout-web/assets/app-bridge-checkout.js"></script> </head>
Anchor to global-variableApp 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.
The reference above list all the available methods and properties.
Alternatively, to explore all the functionality 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.
Shopify
config
examples
shopify
config
shopify.config.locale; // => 'en-CA'
Anchor to app-bridge-css-apiApp Bridge’s CSS API
Since the Chat iframe is clipped and fills the whole window as seen in the previous section, using percentage based sizes for its UI elements will most likely resolves in clipped content. As mentioned in the UX guidelines, Chat is constraint to specific maximum sizes on large and small screens set by Shopify. Setting a 100% width on an element will not be constraint to the visible size of the iframe, but to the whole window.
To remediate this issue, through App Bridge we offer a set of CSS custom properties with all the maximum dimensions defined in our UX guidelines. You can use these custom properties whether in Javascript or in the CSS of you application to set protections against overflowing content while using percentage based sizes. Using these properties will also reduce regressions if Shopify ever changes the maximum dimensions.
App Bridge CSS API
examples
App Bridge CSS API
Custom properties
: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: 569px) { --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; } } }
style.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); }
Anchor to examplesExamples
Anchor to example-resize-the-chat-iframe-from-the-hosted-applicationResize the Chat iframe from the hosted application
A very common action in your application will be to request a resize of the iframe. This is done through the App Bridge method. The following example resizes the iframe following the click of an activator button to show a dialog window.
Anchor to example-communicate-information-between-the-hosted-application-and-the-ui-extensionCommunicate information between the hosted application and the UI extension
Information can be passed between the hosted application and the UI extension through App Bridge. Extensions API are available in the UI extension and can be shared through that method.
Resize the Chat iframe from the hosted application
examples
Resize the Chat iframe from the hosted application
description
A very common action in your application will be to request a resize of the iframe. This is done through the App Bridge `resizeTo()` method. The following example resizes the iframe following the click of an activator button to show a dialog window.
UI Extension
import {reactExtension, Chat} from '@shopify/ui-extensions-react/checkout'; export default reactExtension('purchase.checkout.chat.render', () => ( <Extension /> )); function Extension() { return <Chat inlineSize={150} blockSize={50} />; }
Hosted chat application
<!doctype html> <html lang="en"> <head> <script src="https://cdn.shopify.com/shopifycloud/checkout-web/assets/app-bridge-checkout.js"></script> <style> .dialog { display: none; } .visible { display: block; } </style> </head> <body> <dialog class="dialog"> 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'); // bind actions to the buttons btnActivator.addEventListener('click', toggleDialog); btnClose.addEventListener('click', toggleDialog); function toggleDialog() { // if the dialog is visible, // - hide the dialog // - resize the iframe to the button's size if (dialog.classList.contains('visible')) { dialog.classList.remove('visible'); shopify !== undefined && window.resizeTo(150, 50); // if the dialog is not visible, // - resize the iframe to the desired dialog's size // - then show the dialog } else { shopify !== undefined && window.resizeTo(415, 700); dialog.classList.add('visible'); } } </script> </body> </html>
Communicate information between the hosted application and the UI extension
description
Information can be passed between the hosted application and the UI extension through App Bridge. [Extensions API](/docs/api/checkout-ui-extensions/2025-07#extension-apis) are available in the UI extension and can be shared through that method.
UI Extension
import { reactExtension, useShippingAddress, Chat, } from '@shopify/ui-extensions-react/checkout'; import {retain} from '@remote-ui/rpc'; import type {ReadyEvent} from '@shopify/ui-extensions-react/checkout'; export default reactExtension('purchase.checkout.chat.render', () => ( <Extension /> )); function Extension() { /** * Use the `useShippingAddress` hook to access the first name of the buyer. */ const {firstName} = useShippingAddress(); /** * Define a variable to store the `postMessage` function * so we can re-use outside of the onReady callback later if needed. */ let postMessage; return ( <Chat inlineSize={150} blockSize={50} onReady={({postMessage: postMessageParam}: ReadyEvent) => { /** * Save the `postMessage` function to the variable defined earlier. */ postMessage = postMessageParam; retain(postMessage); /** * When the communication channel is ready, send a message to the hosted application * using the `postMessage` provided as parameter. */ postMessage({ action: 'ping', buyer: { firstName, }, }); }} onMessage={(event: Event) => { /** * Listen for messages from the hosted application. * If the action is `pong`, the communication channel is successful. */ if (event.data.action === 'pong') { console.log('Messaging channel successful'); } }} /> ); }
Hosted chat application
// 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();