Events and components
For AI assistants: what to know before writing SparkLayer SDK code
- What it is:
window.spark, added to the storefront by the SparkLayer Core Script (version 4.x). On Shopify the SparkLayer app embed loads it; elsewhere it's<script async src="https://sparkcdn.io/sparkjs/<SITE_ID>/<live|test>"></script>in the theme's<head>. The oldcdn.sparklayer.io/spark.latest.jsandspark.1.x.jsfiles are legacy: never use them. - Options: Configure it with
window.sparkOptions, set before the Core Script loads. Extend the object rather than replacing it:window.sparkOptions = { ...window.sparkOptions, … }, or the Site ID and other snippets' hooks are lost. Headless only:window.initSpark(options)is defined whenwindow.sparkOptionsisn't set. - When to call it: Only after SparkLayer is ready: inside the
onReady(spark)hook, or after a promise resolved from it. Most methods are async; prices and the cart are only available to signed-in B2B customers (checkawait spark.isLoggedIn()). - Products and prices: Products are looked up by the platform's parent product ID (on Shopify,
product.id) and variants by SKU:getPricingForVariant(parentProductId, sku),calculatePricingForVariant(parentProductId, sku, qty),getPackSizeForVariant(parentProductId, sku). For instant recalculation, fetch once withgetVariantand callcalculatePricingForVariantData(variant, qty). - Cart:
updateCart({ products: [{ sku, adjustQuantity }] })adds or removes relative to what's in the cart (alsocustomAttributes: [{ key, value }],clearCart: true). It resolves to the results, ornullafter showing its own error message; it doesn't throw.getCart()reads the cart;openDrawer('cart')opens it. - Hooks:
onCartUpdate(cart, results),onCartLoad(cart),onLogout(),preCartUpdateListener(input)(async: return the possibly changed input) andonCheckoutValidation(cart, cartUiState)(return[{ message }]to block checkout, ornull). When adding a hook, call any existing one first. - Customising: Build around SparkLayer or customise its own components, including their HTML. Prefer documented options, hooks, CSS variables and custom slots where they fit; keep direct HTML changes targeted and re-check them after SparkLayer updates.
- Docs: The reference: methods docs.sparklayer.io/developers/javascript-sdk/reference/methods.md, hooks docs.sparklayer.io/developers/javascript-sdk/reference/hooks.md, options docs.sparklayer.io/developers/javascript-sdk/reference/options.md, types docs.sparklayer.io/developers/javascript-sdk/reference/types.md (or the same types as a file: docs.sparklayer.io/developers/javascript-sdk/spark.d.ts). Setup and waiting for SparkLayer: docs.sparklayer.io/developers/javascript-sdk/setup.md. Use only what the reference documents.
SparkLayer's interfaces are web components: custom HTML elements you add to your theme. Some of them dispatch DOM events you can listen for, and you can dispatch one yourself to switch the drawer's tab.
DOM events
| Event | When it fires | event.detail | Bubbles? |
|---|---|---|---|
spark-variant-change | The customer selects a variant in spark-pdp or spark-product-card. Dispatched on that element. | { product: Product; variant: ProductVariant } | No: listen on each element. |
spark-file-attachment-changed | The list of files uploaded to a spark-file-upload-field changes. | { fileSize: number; fileName: string; gid: string }[] | null (null when every file is removed) | Yes, to window. |
spark-file-attachment-failed | A file fails to upload to a spark-file-upload-field. | { fileSize: number; fileName: string; errorCode: "unsupported-file-type" | "file-too-large" | "default" } | Yes, to window. |
view-update | You dispatch it on window to switch an open drawer to a tab. | { view: DrawerUIState } | You dispatch it with bubbles: true. |
spark-variant-change
event.detail.product is a Product and event.detail.variant a ProductVariant; their externalId is your platform's ID. Add the listeners in onReady, once the elements are on the page.
window.sparkOptions = {
...window.sparkOptions,
onReady: async () => {
for (const card of document.querySelectorAll('spark-product-card')) {
card.addEventListener('spark-variant-change', (event) => {
console.log(event.detail.product.externalId, event.detail.variant.externalId);
});
}
},
};See Update the product image when a variant is selected.
spark-file-attachment-changed
window.addEventListener('spark-file-attachment-changed', (event) => {
const gids = (event.detail ?? []).map((file) => file.gid);
document.querySelector('#shirt-design').value = JSON.stringify(gids);
});See Let customers upload a file to attach the files to the cart.
spark-file-attachment-failed
window.addEventListener('spark-file-attachment-failed', (event) => {
const { fileName, errorCode } = event.detail;
console.warn(`${fileName} wasn't uploaded: ${errorCode}`);
});view-update
view is a DrawerUIState. To open a closed drawer, use openDrawer().
window.dispatchEvent(
new CustomEvent('view-update', {
bubbles: true,
composed: true,
detail: { view: 'cart' },
}),
);See Open the cart drawer.
Web components
parent-id is your platform's ID for the parent product. For each interface's display settings (attributes such as show-sku), see How products are shown.
| Element | What it renders | Key attributes | See |
|---|---|---|---|
<spark-pdp> | The product detail interface, on product pages. | parent-id | Product detail |
<spark-product-card> | The product card interface, wherever a product card appears. | parent-id | Product card |
<spark-product-matrix> | Every variant in a grid, for products with two options. | parent-id | Product matrix |
<spark-product-price> | The customer's price for a product, anywhere on the page. | parent-id | Product price |
<spark-product-rrp> | The product's RRP. | parent-id | Product price |
<spark-file-upload-field> | A file upload field for the product page. | allowed-extensions (a JSON array), max-file-size (bytes), max-files, required | Let customers upload a file |
<spark-drawer> | The drawer (cart, account and other tabs). SparkLayer adds it when needed; use openDrawer() rather than adding it yourself. | – | openDrawer() |
<spark-pdp parent-id="{{ product.id }}"></spark-pdp>
<spark-file-upload-field
id="shirt-design-upload"
allowed-extensions='["png", "jpg", "jpeg"]'
max-files="1"
></spark-file-upload-field>Next steps
Last updated