This page is the curated reference. The complete, generated type reference lives at /kit/api/elements and is regenerated from the published typings. For a walkthrough, start with Web components setup.
<qb-product-image> renders one <img>, <qb-cart-count> writes its number, <qb-seo> writes into <head>, <qb-checkout> renders the checkout’s <iframe>, and <qb-currency-select>, <qb-consent-banner> and <qb-consent-settings> render a default <select>, dialog or button only when you give them no markup of your own.
Setup functions
configure
<body> unless the page has its own <qb-consent-banner>) and the shop’s own analytics gated on it. Takes every ShopkitConfig option (except that consent takes the richer shape below) plus:
string
The currency the page browses in until the shopper picks one: sent on every product, cart and checkout request. Leave it out to start in the shop’s own currency. Prices format with the currency each response states (
product.currency, cart.currency); this value is only the formatting fallback for a platform older than those fields. See Currencies.string
BCP 47, for number formatting. Defaults to the browser’s.
boolean | ElementsConsentOptions | ConsentStore
default:"true"
Cookie consent for the page, on by default.
false turns it all off: no banner, no analytics, nothing appended to checkout URLs. A ConsentStore you already hold is used as is.boolean | ElementsAnalyticsOptions
default:"true"
The merchant’s own GA4, GTM and Meta pixel from the admin, gated on consent: nothing from Google or Meta loads before the shopper agrees (unless
loadBeforeConsent). false keeps the banner and loads no pixel.defineElements
prefix: "shop-" gives <shop-product> for a name collision; warnOnUnhandledActions: false silences the typo warning.
Other exports
Every element class is exported too:
QbShopElement, QbProductElement, QbOptionsElement, QbOptionValuesElement, QbAddToCartElement, QbBuyNowElement, QbProductListElement, QbProductImageElement, QbCartElement, QbCartItemsElement, QbCartCountElement, QbCheckoutButtonElement, QbCheckoutElement, QbOrderConfirmationElement, QbSeoElement, QbCurrencySelectElement, QbConsentBannerElement, QbConsentSettingsElement, QbConsentGateElement.
Bindings
Put these on any element inside a component. Values are paths into the component’s scope (product.images.0.url), never expressions. A missing branch renders empty instead of throwing.
Bindings written on a scope-owning element itself (
qb-product, qb-product-list, qb-options, qb-option-values, qb-cart, qb-cart-items, qb-order-confirmation) are never applied; each binds only what is inside it.
Repeats
qb-product-list, qb-options, qb-option-values and qb-cart-items clone their <template> once per item.
- The
<template>must be a direct child of the repeating element. Nested in a<ul>or<div>, it is never found and the list renders nothing. - Rows are inserted after the template as siblings, so the repeating element is the list container: style it as the grid.
- Rows are keyed and reused, so a quantity input keeps its caret while its line re-renders.
Actions
data-qb-action on any element, resolved by the nearest enclosing component that knows the verb. click and change both dispatch.
Quantity for an add, in order:
data-qb-quantity="3" on the clicked element, an input[data-qb-quantity-input] inside the wrapper, the wrapper’s quantity attribute, then 1. In a cart row, input[data-qb-quantity] (no suffix) is the bound quantity of the line and commits on change.
Events
Every element emitsqb:-prefixed CustomEvents that bubble and compose, so one listener on document catches them all.
qb-shop
Optional. The ambient shop fromconfigure() or the script tag covers a normal page. Use <qb-shop> for two shops on one page, one section against a different API, one section selling into a campaign storefront, or a client you built yourself. A <qb-shop> ancestor wins for its subtree.
Changing
storefront-id builds a new client and cart store. currency is the currency the subtree browses in by default; changing the attribute later switches that client with setCurrency() without rebuilding it or its cart. A <qb-shop> for the same shop as the page reuses the page’s analytics hub.
qb-product
Resolves one product and holds its variant selection. React twin:<ProductProvider>.
slug walks the catalog; on a large catalog resolve the product server-side and assign el.product.
The product is fetched in the client’s currency and reloads when it changes; a product assigned as el.product is re-read by its id. The currency attribute is only a formatting fallback for a product that does not state its own product.currency. With analytics on, it tracks view_item once per product.
PriceView
VariantView
qb-options
Repeats its<template> once per option group the product actually has, in display order. No attributes. A product with no options renders nothing.
qb-option-values
Nested in aqb-options row, repeats once per value of that group.
Keep unavailable values clickable; dim them with
[data-available="false"]. Clicking one keeps the new choice and clears what contradicts it.
qb-add-to-cart
Wraps your button inside aqb-product and keeps its disabled in step: not addable until the selection pins one variant, or while a mutation is in flight.
qb-buy-now
“Buy now”: adds the selected variant to the remembered cart and goes to the hosted checkout. Sits inside aqb-product.
After it navigates it stays
pending until the page is restored from the back/forward cache.
qb-product-list
Repeats a product card. With no filter attribute it lists the catalog in the merchant’s order; any ofsearch, category-id, sort-by, min-price, max-price switches to search. Changing an attribute aborts the previous request.
A
qb-product-image inside a row is handed that row’s product. Setting cursor replaces the page; it does not append. The list re-runs its query when the client’s currency changes, and product.priceFormatted uses each product’s own product.currency. With search set and analytics on, it tracks search once per term.
qb-product-image
Renders one<img> with the CDN URL resolved, reused across updates so a variant swap does not flash. Finds its product from an enclosing qb-product or list row.
qb-cart
Scope for a cart view. Shares the page’s single cart store. Loaded on first mount and never created speculatively. Re-reads the same cart when the client’s currency changes; formatted figures usecart.currency.
qb-cart-items
Repeats the cart lines.qb-cart-count
Writes the cart’s item count as its own text. No attributes. Reflectszero and state.
qb-checkout-button
Wraps your button. Starts the session on click and navigates withlocation.assign. Disabled while the cart is empty; guarded against a double click.
no-redirect stops the navigation so you can use event.detail.url yourself. There is no language attribute; the checkout uses the shop’s language unless you start it yourself with checkout.start({ language }).
qb-checkout
The hosted checkout rendered inline in an iframe. It follows the cart, resumes the return leg of redirect payment methods from?qb_checkout_session= and ?qb_checkout_shop=, and falls back to the redirect when a shop or page cannot embed. See Embedded checkout.
The
detail of each checkout-* event is the matching EmbeddedCheckout event payload. Attributes are read once, when the session is created.
qb-order-confirmation
Polls the order confirmation on the thank-you page. The session id comes fromsession-id, a ?session_id= query parameter, or the session the kit remembered when the checkout started (the normal case).
timedOut is not a payment failure. A direct visit with nothing remembered lands in status="unknown"; render a neutral page for it.
With analytics on, a completed order is reported as the purchase event once, deduplicated across reloads.
qb-currency-select
The currency switcher. Reads the shop’s currencies (shop.get(), so the key needs checkout:read) and switches the client with setCurrency() on a choice. The choice is remembered, and every qb-product, qb-product-list and cart element on the page reprices (the cart elements by re-reading the same cart). A switch made anywhere else is reflected too. React twin: useCurrency().
The added
<select> is the one piece of markup it writes; no <select> is generated next to static set-currency buttons. Hide it for a single-currency shop with qb-currency-select[empty] { display: none; }. See Currencies.
qb-consent-banner
The cookie banner. Left empty it renders the kit’s default accessible, styled dialog; with your own markup inside, it binds your markup to the consent store. A page configured byconfigure(), <qb-shop> or the script tag gets a default banner appended to <body> automatically, unless it places its own.
Every decision writes the
qb_consent cookie and dispatches qb:consent on document with the state as detail.
qb-consent-settings
A “Cookie settings” control for a footer: reopens the banner’s preferences. Left empty it renders a<button type="button"> labelled in lang; or wrap your own link or button. Hidden when the page turned consent off.
qb-consent-gate
Content that waits for consent: an embedded video, a chat widget.<template> child is the gated content and is cloned in only once category is granted; every other child is the placeholder shown until then.
qb-seo
Writes the title, description, canonical, OpenGraph, Twitter card and JSON-LD into<head> from the product it sits inside. Everything it writes carries data-qb-seo and is removed on update. Only for client-rendered pages; a server-rendered page should use buildSeo().
Errors
Errors are mostly silent by design. A failed product lookup setsstate="error" on qb-product. A failed cart mutation is captured by the store: the add resolves null, no success event fires, the cart elements reflect state="error", and the message is in cartStore.getSnapshot().error. qb:error with { error, context } fires for startup failures (no shop, a bad key), a checkout start that fails and a confirmation that cannot run.