Skip to content
ShopAssist Docs
InstallOther sites (Generic)

Checkout and cart for Generic stores

Configure cart mode, the checkout URL template with items, code, conversation id and locale, and the JavaScript cart handler.

Applies to: GenericView as Markdown

Generic stores choose how the assistant adds products to the cart and sends shoppers to checkout in Settings → Checkout and cart.

Cart modes

cart_modeHow "add to cart" worksDiscount codes
noneThe assistant links product pages—
urlThe widget opens your add-to-cart URL (from the product's add_to_cart_url, or the template below)In the checkout template
hookYour page registers a JavaScript cart handler; the widget calls itOptional (applyDiscount)

Checkout URL template

With a template, the assistant can send a shopper straight to checkout with the products it recommended:

https://shop.example.com/cart/add-multiple?items={items}&coupon={code}&sa_cid={conversation_id}&lang={locale}
PlaceholderValue
{items}Comma-separated sku:quantity pairs (SKU or variant id), each part URL-encoded
{code}The discount code, or empty
{conversation_id}The ShopAssist conversation id (conv_…), or empty; store it on the order for attribution
{locale}The shopper's language, for example da-DK

Without a template, the assistant links your cart page (cart_url) or checkout page (checkout_url) if set, otherwise product pages. Every URL must be HTTPS on one of your allowed domains. ShopAssist appends utm_source=shopassist&utm_medium=chat.

JavaScript cart handler

In hook mode, register a handler after the widget script:

ShopAssist.setCartHandler({
  async add(lines) {
    // lines: [{ sku, variant_id, quantity, title }]
    const response = await fetch("/api/cart/lines", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ lines: lines.map(({ sku, quantity }) => ({ sku, quantity })) }),
    })
    if (!response.ok) throw new Error("cart failed")
    return await response.json() // optional CartSnapshot: { items_count, subtotal, lines, discount_codes, cart_token }
  },
  async applyDiscount(code) {
    const response = await fetch("/api/cart/discount", { method: "POST", body: JSON.stringify({ code }) })
    return { applied: response.ok }
  },
  async linkConversation(conversationId) {
    await fetch("/api/cart/attributes", { method: "POST", body: JSON.stringify({ sa_cid: conversationId }) })
  },
  cartUrl: "/cart",
  checkoutUrl: "/checkout",
})

A rejected promise is reported to the shopper as "couldn't add to cart". The full interface:

/** Cart handler of Generic stores in hook mode (08 §11.6). A rejected promise reports `platform_error`. */
interface GenericCartHandler {
  add(
    lines: { sku: string | null; variant_id: string; quantity: number; title: string }[],
  ): Promise<CartSnapshot | void>
  applyDiscount?(code: string): Promise<{ applied: boolean; message?: string | null }>
  removeDiscount?(code: string): Promise<void>
  getCart?(): Promise<CartSnapshot | null>
  /** Store the conversation id on the merchant's cart/order. */
  linkConversation?(conversationId: string): Promise<void>
  cartUrl?: string
  checkoutUrl?: string
}

Stock disclosure

Settings → Checkout and cart → Stock disclosure sets what your platform would show: exact quantities, levels only ("few left") or nothing. The assistant applies the stricter of this and your stock disclosure guardrail.

Last updated on

On this page