Skip to content
ShopAssist Docs
Widget

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?" })
})
  • draft prefills the composer (up to 2,000 characters).
  • send: true sends 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

MethodNotes
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

On this page