Checkout
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.
Add your own rules to SparkLayer's checkout, for rules SparkLayer's own settings don't cover. This page uses the onCheckoutValidation hook, with examples that call your own API and that combine several rules.
Add custom checkout validation
onCheckoutValidation lets you check the cart against your own rules, or your own API, before the customer can check out. For example, you could check whether a customer has already used up a one-off discount or a product quota, or limit how many free samples go in one order.
The hook must be an async function. It receives the Cart and the current checkout step (a CartUIState, so your rules can vary by step), and returns null if the cart is valid or an array of { message } objects if it isn't.
SparkLayer shows each message to the customer and won't let them check out until the hook returns null. The hook runs every time the cart loads or changes, so keep it quick: avoid network requests unless your rule needs them, and keep any you make fast.
Check the cart against your API
This example sends the cart to your own endpoint and blocks checkout if it says the cart isn't valid:
window.sparkOptions = {
...window.sparkOptions,
onCheckoutValidation: async (cart, cartUiState) => {
const response = await fetch('https://example.com/cart-validation', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(cart),
});
const { valid } = await response.json();
if (valid) {
return null;
}
return [{ message: 'This order is over your quota for one of these products.' }];
},
};Decide what should happen if your API is unreachable. Here, a failed request rejects the promise: SparkLayer logs the error to the console and doesn't apply a result.
Combine your rule with existing validation
Setting onCheckoutValidation replaces any hook another snippet has set. To add a rule without losing one that's already there, keep a reference to the earlier hook, call it, and add your messages to its list. This example limits free samples to three per order:
<script>
(function () {
var options = (window.sparkOptions = window.sparkOptions || {});
var previous = options.onCheckoutValidation;
options.onCheckoutValidation = async function (cart, cartUiState) {
var errors = (previous && (await previous(cart, cartUiState))) || [];
var samples = cart.items
.filter(function (item) {
return item.sku && item.sku.indexOf('SAMPLE-') === 0;
})
.reduce(function (total, item) {
return total + item.quantity;
}, 0);
if (samples > 3) {
errors.push({
message: 'You can order up to 3 samples per order. Remove ' + (samples - 3) + ' to continue.',
});
}
return errors.length ? errors : null;
};
})();
</script>Collect extra details at checkout
To ask customers for a PO number, a requested delivery date or your own fields at checkout, turn on checkout fields in the Help Center, or set them in code with the checkoutCustomElements option. To fill these values in from your own code, see Cart-level fields.
Next steps
Last updated