Skip to content

Methods

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 old cdn.sparklayer.io/spark.latest.js and spark.1.x.js files 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 when window.sparkOptions isn'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 (check await 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 with getVariant and call calculatePricingForVariantData(variant, qty).
  • Cart: updateCart({ products: [{ sku, adjustQuantity }] }) adds or removes relative to what's in the cart (also customAttributes: [{ key, value }], clearCart: true). It resolves to the results, or null after 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) and onCheckoutValidation(cart, cartUiState) (return [{ message }] to block checkout, or null). 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.

Wait for SparkLayer

window.spark is set as soon as the Core Script runs, but its methods only work once SparkLayer is ready. Call them from the onReady hook, or add the Wait for SparkLayer snippet and start with const spark = await window.sparkReady;, as the examples on this page do.

The Spark object

The Spark object is available as window.spark, and is passed to the onReady and onLoad hooks. Its public members are:

type Spark = {
  options: SparkLayerOptions;
  isLoggedIn(): Promise<boolean>;
  switchImpersonatingCustomer(customerId: string | null): Promise<UserData | null>;
  refreshGlobalData(): Promise<UserData | null>;
  getActiveCustomerVerificationToken(): Promise<string | null>;
  setActiveCompanySection(sectionId: string): Promise<boolean>;
  getProduct(parentProductId: string): Promise<Product>;
  getProductBySlug(slug: string): Promise<Product>;
  getVariant(parentProductId: string, variantSku: string): Promise<ProductVariant>;
  getPriceForProduct(parentProductId: string): Promise<SimplifiedProductPrice>;
  getPricingForVariant(
    parentProductId: string,
    variantSku: string,
  ): Promise<{
    price: number | null;
    rrp: number | null;
    rrpCurrencyCode: string | null;
    priceBreaks: VariantPriceBreak[];
    currencyCode: string;
  }>;
  getRrpPriceForVariant(
    parentProductId: string,
    variantSku: string,
  ): Promise<{ rrp: number | null; currencyCode: string | null }>;
  getPackSizeForVariant(parentProductId: string, variantSku: string): Promise<number>;
  calculatePricingForVariant(
    parentProductId: string,
    variantSku: string,
    qty: number,
    qtyAcrossVariants?: number | null,
  ): Promise<ProductVariantPricing>;
  calculatePricingForVariantData(
    variant: ProductVariantDataPricing,
    qty: number,
    qtyAcrossVariants?: number | null,
  ): ProductVariantPricing;
  getCart(): Promise<Cart | null>;
  getCartCache(): Cart | null;
  updateCart(
    input: Partial<UpdateCart>,
    cartSuccessHandledLocally?: boolean,
    cartErrorsHandledLocally?: boolean,
  ): Promise<CartResults[] | null>;
  addCustomLineItem(customItem: CustomLineItemInput): Promise<Cart | null>;
  externalClearBasket(): Promise<void>;
  openDrawer(initialTab?: DrawerUIState): void;
  closeDrawer(): void;
  uploadFile(fileName: string, fileData: Blob): Promise<string>;
  fetch<Q extends GraphqlQueryOrMutation<unknown, Record<string, unknown>, GraphqlError | GraphqlExtensionError>>(
    query: Q,
    variables?: VariablesOf<Q>,
    useImpersonatingCustomer?: boolean,
    bypassAppProxy?: boolean,
    signal?: AbortSignal,
  ): Promise<FetchResponse<ResponseOf<Q>, ErrorOf<Q>>>;
};

options

Type: SparkLayerOptions

The options SparkLayer is running with, after merging your sparkOptions with the platform defaults. See Options.

Any script
const spark = await window.sparkReady;
console.log(spark.options.platform, spark.options.language);

Customers and session

isLoggedIn()

Checks whether the user is logged in.

Signature
isLoggedIn(): Promise<boolean>;

Returns: Promise<boolean>

Any script
const spark = await window.sparkReady;
if (await spark.isLoggedIn()) {
  // Show B2B content
}

switchImpersonatingCustomer()

Switches the customer a sales agent is impersonating, or ends impersonation when you pass null.

Signature
switchImpersonatingCustomer(customerId: string | null): Promise<UserData | null>;
NameTypeDescription
customerIdstring | nullThe customer to impersonate, or null to end impersonation.

Returns: Promise<UserData | null>

Any script
const spark = await window.sparkReady;
const customer = await spark.switchImpersonatingCustomer('<CUSTOMER_ID>');
await spark.switchImpersonatingCustomer(null); // End impersonation

refreshGlobalData()

Refetches the current active customer and site configuration, and updates the cached copy both are read from.

Signature
refreshGlobalData(): Promise<UserData | null>;

Returns: Promise<UserData | null>

Any script
const spark = await window.sparkReady;
const user = await spark.refreshGlobalData();

getActiveCustomerVerificationToken()

Refetches the current active customer and returns a fresh form customer verification token. It uses the impersonated customer when a sales agent is impersonating, otherwise the logged-in customer.

Signature
getActiveCustomerVerificationToken(): Promise<string | null>;

Returns: Promise<string | null>

Any script
const spark = await window.sparkReady;
const token = await spark.getActiveCustomerVerificationToken();

setActiveCompanySection()

Selects the company section used for purchasing. If the cart isn't empty, the user is asked to confirm and the cart is cleared. The page then reloads.

Signature
setActiveCompanySection(sectionId: string): Promise<boolean>;
NameTypeDescription
sectionIdstringThe ID of one of the logged-in customer's company sections.

Returns: Promise<boolean>: false if the section isn't available to the customer, the user cancels, or the cart couldn't be cleared.

Any script
const spark = await window.sparkReady;
const user = await spark.refreshGlobalData();
const section = user?.companySections[0];
if (section) await spark.setActiveCompanySection(section.id);

Products and pricing

Each method takes your platform's parent product ID and, for a variant, its SKU. Prices are for the logged-in customer.

getProduct()

Fetches the GraphQL product object for a parent product ID.

Signature
getProduct(parentProductId: string): Promise<Product>;
NameTypeDescription
parentProductIdstringThe parent product ID.

Returns: Promise<Product>

Throws: if the product isn't found or an error occurs fetching it.

Any script
const spark = await window.sparkReady;
const product = await spark.getProduct('6660191387839');
console.log(product.variants.map((variant) => variant.sku));

getProductBySlug()

Fetches the GraphQL product object for a product slug.

Signature
getProductBySlug(slug: string): Promise<Product>;
NameTypeDescription
slugstringThe product slug.

Returns: Promise<Product>

Throws: if the product isn't found or an error occurs fetching it.

Any script
const spark = await window.sparkReady;
const product = await spark.getProductBySlug('mother-mug');

getVariant()

Fetches the GraphQL variant object for a parent product ID and variant SKU.

Signature
getVariant(parentProductId: string, variantSku: string): Promise<ProductVariant>;
NameTypeDescription
parentProductIdstringThe parent product ID.
variantSkustringThe variant SKU.

Returns: Promise<ProductVariant>

Throws: if the product or variant isn't found or an error occurs fetching the product.

Any script
const spark = await window.sparkReady;
const variant = await spark.getVariant('6660191387839', 'MUG-MOM');
console.log(variant.name, variant.stockDisplay?.status);

getPriceForProduct()

Fetches the pricing for a parent product, including price breaks, the lowest price and the number of prices.

Signature
getPriceForProduct(parentProductId: string): Promise<SimplifiedProductPrice>;
NameTypeDescription
parentProductIdstringThe parent product ID.

Returns: Promise<SimplifiedProductPrice>: all price-related data for the parent product, including price breaks, the lowest price and the number of prices. Use the number of prices to decide whether to show "from" before the price.

Throws: if the product isn't found or an error occurs fetching it.

Any script
const spark = await window.sparkReady;
const { fromPrice, numberOfPrices, currencyCode } = await spark.getPriceForProduct('6660191387839');
const label = `${numberOfPrices > 1 ? 'From ' : ''}${fromPrice} ${currencyCode}`;

getPricingForVariant()

Fetches the pricing for a variant.

Signature
getPricingForVariant(
  parentProductId: string,
  variantSku: string,
): Promise<{
  price: number | null;
  rrp: number | null;
  rrpCurrencyCode: string | null;
  priceBreaks: VariantPriceBreak[];
  currencyCode: string;
}>;
NameTypeDescription
parentProductIdstringThe parent product ID.
variantSkustringThe variant SKU.

Returns: all price-related data for the variant: price, rrp, rrpCurrencyCode, priceBreaks (each a VariantPriceBreak) and currencyCode.

Throws: if the product or variant isn't found or an error occurs fetching the product.

Any script
const spark = await window.sparkReady;
const pricing = await spark.getPricingForVariant('6660191387839', 'MUG-MOM');
console.log(pricing.price, pricing.currencyCode, pricing.priceBreaks);

getRrpPriceForVariant()

Fetches the RRP for a variant.

Signature
getRrpPriceForVariant(
  parentProductId: string,
  variantSku: string,
): Promise<{ rrp: number | null; currencyCode: string | null }>;
NameTypeDescription
parentProductIdstringThe parent product ID.
variantSkustringThe variant SKU.

Returns: the RRP (null if not set for the currency) and the currency code.

Throws: if the product or variant isn't found or an error occurs fetching the product.

Any script
const spark = await window.sparkReady;
const { rrp, currencyCode } = await spark.getRrpPriceForVariant('6660191387839', 'MUG-MOM');

getPackSizeForVariant()

Fetches the pack size for a variant.

Signature
getPackSizeForVariant(parentProductId: string, variantSku: string): Promise<number>;
NameTypeDescription
parentProductIdstringThe parent product ID.
variantSkustringThe variant SKU.

Returns: Promise<number>: the variant's pack size, or 1 if none is set.

Throws: if the product or variant isn't found or an error occurs fetching the product.

Any script
const spark = await window.sparkReady;
const packSize = await spark.getPackSizeForVariant('6660191387839', 'MUG-MOM');
const quantity = Math.ceil(10 / packSize) * packSize; // Round 10 up to whole packs

calculatePricingForVariant()

Returns the price for a quantity of a variant, given its parent product ID and SKU.

Signature
calculatePricingForVariant(
  parentProductId: string,
  variantSku: string,
  qty: number,
  qtyAcrossVariants?: number | null,
): Promise<ProductVariantPricing>;
NameTypeDescription
parentProductIdstringThe parent product ID.
variantSkustringThe variant SKU.
qtynumberThe quantity to calculate pricing for.
qtyAcrossVariants?number | nullFor tiered pricing, the quantity across variants (if configured). Defaults to null.

Returns: Promise<ProductVariantPricing>: the total price (quantity × unit price), the unit price and the price breaks.

Throws: if the product or variant isn't found or an error occurs fetching the product.

Any script
const spark = await window.sparkReady;
const pricing = await spark.calculatePricingForVariant('6660191387839', 'MUG-MOM', 2);
console.log(pricing.totalPrice, pricing.unitPrice, pricing.currencyCode);

calculatePricingForVariantData()

Calculates the pricing for a variant from variant data you already have, without fetching.

Signature
calculatePricingForVariantData(
  variant: ProductVariantDataPricing,
  qty: number,
  qtyAcrossVariants?: number | null,
): ProductVariantPricing;
NameTypeDescription
variantProductVariantDataPricingVariant data, including the RRP and price breaks. A ProductVariant or CartItem works.
qtynumberThe quantity to calculate pricing for.
qtyAcrossVariants?number | nullFor tiered pricing, the quantity across variants (if configured). Defaults to null.

Returns: ProductVariantPricing: the total price (quantity × unit price), the unit price and the price breaks.

Any script
const spark = await window.sparkReady;
const variant = await spark.getVariant('6660191387839', 'MUG-MOM');
const pricing = spark.calculatePricingForVariantData(variant, 24); // No request

See Live price as the quantity changes for a full example.

Cart

See Cart for worked examples.

getCart()

Fetches the cart from GraphQL.

Signature
getCart(): Promise<Cart | null>;

Returns: Promise<Cart | null>: the cart, or null if it couldn't be fetched (an error toast is shown).

Any script
const spark = await window.sparkReady;
const cart = await spark.getCart();
console.log(cart?.items.length, cart?.totals.total.charge.gross.number);

getCartCache()

Gets the cached cart, if available, without a request.

Signature
getCartCache(): Cart | null;

Returns: Cart | null: the cached cart, or null if it isn't available.

Any script
const spark = await window.sparkReady;
const cart = spark.getCartCache() ?? (await spark.getCart());

updateCart()

Runs an update cart mutation, shows the appropriate toasts and returns the result. It makes every change to the cart: adding, updating and removing items, and setting cart-level fields.

Signature
updateCart(
  input: Partial<UpdateCart>,
  cartSuccessHandledLocally?: boolean,
  cartErrorsHandledLocally?: boolean,
): Promise<CartResults[] | null>;
NameTypeDescription
inputPartial<UpdateCart>Follows the GraphQL updateCart mutation's variables. Each product is a CartItemInput.
cartSuccessHandledLocally?booleanDon't show success toasts, as you'll handle the result yourself (useful in the cart, where the update itself shows the change). Defaults to false.
cartErrorsHandledLocally?booleanDon't show toasts for the messages in the results, as you'll handle them yourself. Defaults to false.

Returns: Promise<CartResults[] | null>: the results, or null if the update failed. It doesn't throw: on failure it shows an error toast and logs the error to the console. See What updateCart returns.

Any script
const spark = await window.sparkReady;
const results = await spark.updateCart({
  products: [{ sku: 'RED-SHIRT-M', adjustQuantity: 1 }],
});

addCustomLineItem()

Adds a custom line item (a free-text name, price and quantity not tied to a SKU) to the cart. The active customer must have custom cart items enabled, otherwise the request is rejected.

Signature
addCustomLineItem(customItem: CustomLineItemInput): Promise<Cart | null>;
NameTypeDescription
customItemCustomLineItemInputThe name, unit price (as a decimal string) and quantity.

Returns: Promise<Cart | null>: the refreshed cart, or null if the item couldn't be added.

Any script
const spark = await window.sparkReady;
const cart = await spark.addCustomLineItem({ name: 'Artwork set-up', quotedPrice: '25.00', quantity: 1 });

externalClearBasket()

Tells SparkLayer to clear the basket. Designed for your order confirmation (thank you) page.

Signature
externalClearBasket(): Promise<void>;

Returns: Promise<void>

Order confirmation page
const spark = await window.sparkReady;
await spark.externalClearBasket();

Drawer

openDrawer()

Opens the SparkLayer drawer, optionally on a specific tab.

Signature
openDrawer(initialTab?: DrawerUIState): void;
NameTypeDescription
initialTab?DrawerUIStateThe tab to open on. Defaults to "cart".

Returns: void

Any script
const spark = await window.sparkReady;
spark.openDrawer('account');

To switch a drawer that's already open to another tab, dispatch the view-update event.

closeDrawer()

Closes the SparkLayer drawer.

Signature
closeDrawer(): void;

Returns: void

Any script
const spark = await window.sparkReady;
spark.closeDrawer();

Files and GraphQL

uploadFile()

Uploads a file to the SparkLayer file store. Pass the returned ID as a cart item attribute to attach the file (see Attach a file).

Signature
uploadFile(fileName: string, fileData: Blob): Promise<string>;
NameTypeDescription
fileNamestringThe name of the file, including its extension. It must match the type of the data in fileData.
fileDataBlobThe file data as a Blob.

Returns: Promise<string>: the uploaded file's ID (a GID).

Throws: if the file type isn't supported, the file is too large, the file path is invalid, or the upload fails.

Any script
const spark = await window.sparkReady;
const gid = await spark.uploadFile('design.png', fileBlob);
await spark.updateCart({
  products: [{ sku: 'SHIRT-CUSTOM', adjustQuantity: 1, customAttributes: [{ key: 'Design', value: JSON.stringify([gid]) }] }],
});

fetch()

Runs a GraphQL query or mutation as the authenticated user.

Signature
fetch<Q>(
  query: Q,
  variables?: VariablesOf<Q>,
  useImpersonatingCustomer?: boolean,
  bypassAppProxy?: boolean,
  signal?: AbortSignal,
): Promise<FetchResponse<ResponseOf<Q>, ErrorOf<Q>>>;

Type parameter: Q extends GraphqlQueryOrMutation<unknown, Record<string, unknown>, GraphqlError | GraphqlExtensionError>. See GraphqlQueryOrMutation.

NameTypeDescription
queryQThe GraphQL query string.
variables?VariablesOf<Q>The GraphQL variables.
useImpersonatingCustomer?booleanWhether to make the request as the customer being impersonated, rather than as the sales agent.
bypassAppProxy?booleanCall the API directly rather than through the platform's app proxy.
signal?AbortSignalAborts the request, for example when its result is no longer needed.

Returns: Promise<FetchResponse<ResponseOf<Q>, ErrorOf<Q>>>: a standard Response object. Check status, and call json() to get the data and errors.

Any script
const spark = await window.sparkReady;
const response = await spark.fetch(`query { loggedInCustomer { id email } }`);
if (response.status === 200) {
  const { data, errors } = await response.json();
  if (!errors?.length) console.log(data.loggedInCustomer.email);
}

See Run a GraphQL query.

Next steps

Was this page helpful?

Last updated