Set up the SDK
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.
Every SDK customisation starts here: how the SDK loads with the Core Script, how to add your own options and hooks without overwriting anyone else's, and how to wait until SparkLayer is ready. It uses window.sparkOptions, the onReady hook and, on headless storefronts, window.initSpark().
How the SDK loads
The SDK comes with the SparkLayer Core Script. On Shopify, the SparkLayer app embed loads it. On other platforms, the Core Script you copy from the SparkLayer Dashboard goes in your theme's <head>:
<script async src="https://sparkcdn.io/sparkjs/<SITE_ID>/live"></script>Replace <SITE_ID> with your Site ID, and use test instead of live in test mode. The version this URL serves is set in the Dashboard: see Upgrading to the latest version. For the rest of the storefront setup, see the frontend integration guide.
Older themes may load a version 1 file such as https://cdn.sparklayer.io/spark.1.0.21.js. These URLs are legacy: replace them with the loader above. Don't use spark.latest.js either: it's a legacy bundle that lacks most of the SDK.
When the Core Script runs, it reads window.sparkOptions, starts SparkLayer and sets window.spark. Your options and hooks must therefore be in place before the Core Script loads.
Add your own options and hooks
Set your options in a <script> in the <head>, before the Core Script, and always extend the existing object rather than replacing it:
<script>
window.sparkOptions = {
...window.sparkOptions,
language: 'en',
onCartUpdate: async (cart, results) => {
// Your code here
},
};
</script>window.sparkOptions = { … } on its own replaces the whole object, so it wipes anything set earlier: the siteId and auth in the Core Script on other platforms, or another snippet's hooks. The ...window.sparkOptions line copies those across first. Every example in these docs extends the existing options, either with this spread or by adding to the object directly.
The spread keeps other settings, but a hook with the same name still replaces the earlier one. If two snippets need the same hook, combine them into one function, or keep a reference to the earlier hook and call it from yours, as the chained checkout validation example does.
For every option and hook, see Options and Hooks in the SDK reference.
Wait for SparkLayer to be ready
window.spark exists as soon as the Core Script runs, but its data isn't loaded until SparkLayer has started. Run your code from the onReady hook, which receives the Spark object once SparkLayer has initialised and the page's DOM has loaded. It runs whether or not the customer is logged in, so check with isLoggedIn() first:
window.sparkOptions = {
...window.sparkOptions,
onReady: async (spark) => {
if (!(await spark.isLoggedIn())) {
return;
}
// Safe to call spark methods here
},
};If your code can run after the Core Script has loaded (for example, from a script at the end of the page or in a separate app), use the window.sparkReady promise below instead. It resolves whether SparkLayer started before or after your code.
Wait for SparkLayer from any script
Add this once, in your theme's <head> before the SparkLayer Core Script (on Shopify, before the SparkLayer app embed). It resolves window.sparkReady with window.spark when SparkLayer calls its onReady hook, and keeps any onReady you already have.
<script>
(function () {
var options = (window.sparkOptions = window.sparkOptions || {});
var previous = options.onReady;
var resolveReady;
window.sparkReady = new Promise(function (resolve) {
resolveReady = resolve;
});
options.onReady = async function (spark) {
if (previous) await previous(spark);
resolveReady(spark);
};
})();
</script>Then, anywhere after it:
const spark = await window.sparkReady;Like the spread above, the snippet adds to window.sparkOptions instead of replacing it. Many examples on the other SDK pages start with await window.sparkReady, so add this snippet first.
Manual initialisation (headless only)
On a headless storefront you may want to decide when SparkLayer starts, for example after your app has loaded the customer. If window.sparkOptions isn't set when the Core Script runs, SparkLayer doesn't start. Instead it defines window.initSpark(options), which you call yourself:
<script>
function startSparkLayer() {
window.spark = window.initSpark({
siteId: '<SITE_ID>',
platform: 'shopify',
auth: { user: 'customer@example.com', token: '<AUTH_TOKEN>' },
onReady: async (spark) => {
// SparkLayer is ready
},
});
}
</script>
<script async src="https://sparkcdn.io/sparkjs/<SITE_ID>/live" onload="startSparkLayer()"></script>Pass every option, including hooks, to initSpark. Don't set window.sparkOptions anywhere on the page (including with the ...window.sparkOptions pattern), or SparkLayer starts automatically and initSpark isn't defined.
That rules out the window.sparkReady snippet too, because it sets window.sparkOptions. Pass an onReady hook to initSpark instead, and resolve your own promise from it. See Headless and React for a full example.
Next steps
Last updated