JavaScript API
The window.ShopAssist API to open the chat, pass page context, consent, identity and cart handlers, and subscribe to events.
The loader creates window.ShopAssist. The signatures below are read from the widget's published type definitions at build time, so they always match the widget.
interface ShopAssistApi {
readonly __sa: true
/** Loader semver. */
readonly version: string
readonly ready: Promise<{ status: WidgetStatus }>
/**
* Opens the panel. `draft` prefills the composer (≤ 2,000 characters); `send: true` sends the draft as the
* shopper's first message once the panel is open, honoured only with transient user activation. Opening creates
* a session and writes strictly-necessary sessionStorage: call it only in response to a shopper action.
*/
open(opts?: { draft?: string; send?: boolean }): void
close(): void
toggle(): void
/** Show the launcher (if hidden by `hide()`). */
show(): void
/** Hide launcher and bubble (the panel closes); display rules still apply. */
hide(): void
isOpen(): boolean
/** Generic stores only. */
identify(provider: IdentityProvider | null): void
/** Manual/managed consent mode only. */
setConsent(consent: Partial<{ preferences: boolean; analytics: boolean; marketing: boolean }>): void
/** SPA/headless navigation. */
setPageContext(ctx: EmbedPage): void
/** UI locale override (not persisted). */
setLocale(locale: string): void
/** Generic stores only. */
setCartHandler(handler: GenericCartHandler | null): void
/** Returns an unsubscribe function. */
on<E extends ShopAssistEventName>(event: E, cb: (payload: ShopAssistEvents[E]) => void): () => void
off<E extends ShopAssistEventName>(event: E, cb: (payload: ShopAssistEvents[E]) => void): void
/**
* → beacon `order.completed {order_id, total_amount, currency, items_count}`; dropped unless this tab has a session
* and the 08 §14.1 consent rule holds.
*/
track(
event: "order.completed",
props: { order_id: string; total: { amount: string; currency: string }; items_count?: number },
): void
/** Removes host, listeners and streams; `forget` also purges every widget storage key. */
shutdown(opts?: { forget?: boolean }): void
}Before the loader runs
Queue calls with ShopAssistQueue. The loader runs them in order once it starts, and later pushes run immediately:
;(window.ShopAssistQueue = window.ShopAssistQueue || []).push(["on", "cart.added", (e) => console.log(e)])
;(window.ShopAssistQueue = window.ShopAssistQueue || []).push(["open"])The loader also dispatches the window event shopassist:ready (with detail.status) when ShopAssist.ready resolves. Methods never throw: invalid arguments are ignored with a warning in debug mode (data-debug="1").
Opening the chat
document.querySelector("#ask-button").addEventListener("click", () => {
ShopAssist.open({ draft: "Is this available in size 42?" })
})draftprefills the composer (up to 2,000 characters).send: truesends the draft as the shopper's first message once the panel is open, but only directly after a real click (transient user activation), so scripts can't write for the shopper.- Opening creates a chat session and writes strictly necessary session storage: call
open()only in response to a shopper action.
Methods
| Method | Notes |
|---|---|
open({ draft?, send? }), close(), toggle(), isOpen() | Panel control |
show(), hide() | Show or hide the launcher; display rules still apply |
setPageContext(page) | Single-page navigation (headless) |
setLocale(locale) | Interface language override, not persisted |
setConsent({ preferences, analytics, marketing }) | Manual consent mode only (consent) |
identify(provider) | Generic stores only (identity JWT) |
setCartHandler(handler) | Generic stores only (cart handler) |
on(event, cb) / off(event, cb) | Events; on returns an unsubscribe function |
track("order.completed", props) | Report a completed order for attribution (dropped without a session and analytics consent) |
shutdown({ forget? }) | Remove the widget; forget: true also deletes all widget storage keys |
Page context
/** Page context the merchant passes on SPA navigation (`setPageContext`, 08 §3.2). */
interface EmbedPage {
type?: PageTypeHint | null
/** Platform-native id (mapped to external ids, 08 §3.4). */
productId?: string | number | null
variantId?: string | number | null
categoryId?: string | number | null
title?: string | null
}Identity provider
/** Identity-token provider of Generic stores (08 §10.6): returns a signed JWT (03 §2.5) or null for guests. */
type IdentityProvider = (ctx: { sessionId: string; storeId: string }Another live chat on the same store
If you keep another chat (Shopify Inbox, Tidio, Gorgias, Zendesk, Intercom), separate the launchers (different positions, or data-launcher="none" and your own button) and open the other chat from ShopAssist.on("handoff.requested", …) with its own JavaScript API.
Last updated on