Use the Chat component to create real-time chat applications. > Note: The Chat component can only be added to the chat targets of [checkout](/docs/api/checkout-ui-extensions/latest/targets/overlays/purchase-checkout-chat-render) and [Thank you](/docs/api/checkout-ui-extensions/latest/targets/overlays/purchase-thank-you-chat-render) pages.
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} />;
}
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);
});
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.
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](https://developer.mozilla.org/en-US/docs/Web/CSS/block-size).
A unique identifier for the component.
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](https://developer.mozilla.org/en-US/docs/Web/CSS/inline-size).
Callback when the embedded page sends a message.
Callback when the embedded page is ready and a message port has been created to communicate with the host page.
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).
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).
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).
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:
The static configuration values that will not change during runtime.
The references and APIs to the UI extension that helped bootstrap the iframe.
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 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.
The platform or application that the app is embedded within.
The Shopify surface that the app is embedded within.
Information about the current visitor.
The locale of the shop that’s embedding the app.
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).
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).
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).
The unique token of a given user across all surfaces in a shop, present if a user has opted-in to tracking.
Use the Chat component to create real-time chat applications. > Note: The Chat component can only be added to the chat targets of [checkout](/docs/api/checkout-ui-extensions/latest/targets/overlays/purchase-checkout-chat-render) and [Thank you](/docs/api/checkout-ui-extensions/latest/targets/overlays/purchase-thank-you-chat-render) pages.
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.
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} />;
}
<!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.shopify.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.shopify.resizeTo(415, 700);
dialog.classList.add('visible');
}
}
</script>
</body>
</html>
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} />;
}
<!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.shopify.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.shopify.resizeTo(415, 700);
dialog.classList.add('visible');
}
}
</script>
</body>
</html>
Information can be passed between the hosted application and the UI extension through App Bridge. [Extensions API](/docs/api/checkout-ui-extensions/unstable#extension-apis) are available in the UI extension and can be shared through that method.
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');
}
}}
/>
);
}
// 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.messagePort.postMessage({
action: 'pong',
});
}
};
// Ensure the messagePort is ready to start sending and receiving messages.
shopify.extension.port.start();
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');
}
}}
/>
);
}
// 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.messagePort.postMessage({
action: 'pong',
});
}
};
// Ensure the messagePort is ready to start sending and receiving messages.
shopify.extension.port.start();