---
title: JavaScript SDK
slug: tech-docs/javascript-sdk
docTags: 
createdAt: 2025-12-17T10:28:49.605Z
---

![](https://api.archbee.com/api/optimize/kxppJrvFK15E9wXbMKaTP/NkaRla7kkyo_iSxYad5CD-20260922-084855.jpg)

With the SparkLayer SDK, you can enhance your frontend development and create more customised experiences for your users. The SDK provides a range of straightforward functions to access data stored within SparkLayer, as well as granting access to the GraphQL API and a cart update function. These features empower developers to build more advanced and dynamic applications on top of the SparkLayer platform.

### Example use-cases

The SparkLayer SDK empowers developers to build more advanced and dynamic applications on top of the SparkLayer platform. Use-cases can include:

| Area                                   | Details                                                                                                                                                                                                         |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Accessing Data and APIs                | Provides functions to access data within SparkLayer and utilize the GraphQL API, enabling the development of advanced and dynamic applications.                                                                 |
| Manual Initialization                  | Allows manual initialization of the SDK, useful in headless commerce implementations.                                                                                                                           |
| Customizing User Experiences           | Allows calculation of pricing data, updating the shopping cart and retrieving updated cart information, customisation of the look and feel.                                                                     |
| Product Variant Image Updating         | Custom code can be added to update product images when a variant is selected, enhancing user shopping experience by providing visual feedback.                                                                  |
| Custom Checkout Validation             | Enables custom validation logic at checkout for personalized API calls to verify cart contents and manage checkout permissions based on custom rules (e.g., managing one-time discounts, product quota limits). |
| Adding Custom Attributes to Cart Items | Offers a method to include custom attributes with cart items, ensuring customizations are visible under the product SKU and persist through to past orders.                                                     |

:::hint{type="info"}
**Please note:**
The SparkLayer SDK must not be used to modify the HTML and CSS we provide via our components within your storefront. These components may be subject to update by SparkLayer which may impact any changes you make, however we do ensure our SDK is always backwards compatible. If you're unsure of the recommended use cases, our team will be happy to advise.
:::

### Manual initialisation

If you don't want SparkLayer to initialise automatically useful in headless situations, instead of setting `window.sparkOptions` you can manually call `window.initSpark()` once the script has loaded like so (requires at least version 1.0.21):

```html
<script src="https://cdn.sparklayer.io/spark.1.0.21.js"></script>
<script>
window.spark = window.initSpark({ /* options */ })
<script>
```

### Example customisation

The following code snippet illustrates how to use the SparkLayer library. In this example, we're using the calculatePricingForVariant function, which takes in the parent ID, SKU, and quantity as parameters to calculate pricing data.

```html
<script>
  window.sparkOptions = {
    siteId: "b2bshopifydemostore",
    platform: "shopify",
    // etc...
  };
</script>
<script async src="https://cdn.sparklayer.io/spark.1.0.1.js"></script>
<script>
  // Prints the following to the console: {totalPrice: 8.32, unitPrice: 4.16, currencyCode: 'gbp'}
  console.log(await window.spark.calculatePricingForVariant('6660191387839', 'MUG-MOM', 2));
  // Below is an example of updating the cart
  const products = {
    products: [
        {
            sku: 'BRACE-COLOURED',
            adjustQuantity: 3,
        },
    ],
    clearCart: false, // can be set to true to clear the cart!
  };
  console.log(await window.spark.updateCart(products)); // Returns the result of the cart changes
  // Below is an example of how to change a custom field on the cart
  console.log(await window.spark.updateCart({
    customFields: [
        {
            name: 'season',
            value: 'in-season',
        },
    ],
  }));
  console.log(await window.spark.getCart()); // Returns the updated cart
  await window.spark.updateCart({clearCart:true}); // Clears the basket
</script>
```

See [Modifying Cart Contents](docId:1nctQXIhRYueptnOWkOl7) for the full `updateCart` reference - adding/removing items, custom attributes, and handling the result.

By viewing the [spark module](docId\:fui0C-tBIzxq2bZvtZ0PM), you can see the functions available.

### Updating the product image when a variant is selected

When using either the spark-product-card or spark-pdp widget to select a variant, the product image is not updated by default to match the selected variant. Fortunately, this behavior can be easily customised using some theme code. Here's an example of how to accomplish this with the spark-product-card widget - the process is virtually the same for spark-pdp.

Broadly, the following code changes are necessary:

1. Add an event listener to the `spark-pdp` or the `spark-product-card` elements for the `spark-variant-change` event
2. Within the event listener callback, show / hide product images as appropriate

### Listen for the event

When the variant selector is changed, a `spark-variant-change` event is dispatched on the `spark-product-card` element. Use the following code to listen for the event.

```javascript
window.addEventListener("DOMContentLoaded", (event) => {
    const productCards = document.querySelectorAll("spark-product-card");
    for (productCard of productCards) {
        productCard.addEventListener("spark-variant-change", (e) => {
            console.log("spark-variant-change", e.data)
        });
    }
  },
};
```

:::hint{type="info"}
**Please note:**
Note: the event listeners can only be registered once the `spark-product-card` has been added to the page, which is why we suggest using the `onReady` option.
:::

### Show the product image

Choosing the best approach for updating variant images depends on the site's theme and markup. We've tested the following process using Shopify's Dawn theme.

The first step is to ensure that all variant images are present within the Document Object Model (DOM). If you're using Shopify, this can be done by iterating through product variants within the Liquid template that renders the product card images. You'll want to hide images for all but one variant (the first variant, which is selected by default). For the Shopify Dawn theme, the easiest way to do this is by setting the opacity to 0 (`style="opacity: 0"`).

Next, add the `data-variant-id` data attribute to all variant image tags, setting it to the variant ID.

When the user selects a variant, the following properties on the event object indicate which variant was chosen:

- `event.detail.product.externalId` - Platform (e.g., Shopify) ID of the product.
- `event.detail.variant.externalId` - Platform (e.g., Shopify) ID of the variant.

In order to display the correct image, the callback function needs to locate the image elements for the product card within the DOM.

Here's a full working example:

```javascript
window.sparkOptions = {
  onReady() {
    const productCards = document.querySelectorAll("spark-product-card");
    for (productCard of productCards) {
      productCard.addEventListener("spark-variant-change", (e) => {
        const cardEl = e.target.closest(".card-wrapper");
        const variantId = e.detail.variant.externalId;

        if (!cardEl) {
          return;
        }

        // hide all variant images
        cardEl
          .querySelectorAll(`img[data-variant-id]`)
          .forEach((el) => (el.style.opacity = "0"));

        // show appropriate image
        const variantImgEl = cardEl.querySelector(
          `img[data-variant-id="${variantId}"]`,
        );

        variantImgEl && (variantImgEl.style.opacity = "1");
      });
    }
  },
};
```

### Adding custom checkout validation

Implementing custom checkout validation enables the client to create personalized calls to any API to verify the contents of the customer's cart and accordingly permit or restrict them from completing the checkout. A potential use case could be managing one-time discounts for unique customers, and utilizing an API to check if the customer has already exhausted their quota.

To set this up, assign an asynchronous function to the `onCheckoutValidation` spark option. The function must be asynchronous to prevent the user interface from being blocked while the API call is taking place. This function should return an array of error objects or null if there are no errors.

Here is an example of how this might work:

```javascript
window.sparkOptions = {
  onCheckoutValidation: async (cart) => {
    // Do API call to validate
    res = await fetch("example.com/cart-validation", {
      method: "POST",
      body: JSON.stringify(cart),
    });
    // If valid, return null.
    if (res.json().valid) {
      return null;
    }
    // If not valid, return array of error objects.
    return [
      {
        message:
          "Unable to checkout with item due to it hit product quota ordering limits.",
      },
    ];
  },
};
```

In the above example, the asynchronous function onCheckoutValidation receives a cart object as a parameter. This object is then passed as a POST request to the 'cart-validation' endpoint of the example.com API. If the response from the API call is valid, the function returns null, indicating that the checkout can proceed. If the response from the API call is not valid, the function returns an array of error messages, which can then be handled by your front-end to alert the user that they cannot proceed with checkout."

### Opening the Cart when adding a product

SparkLayer provides an `onCartUpdate` callback function that triggers whenever the cart is modified. This function can be used to automatically open the cart drawer:

```javascript
window.sparkOptions = {
  onCartUpdate: async function (cart, results) {
    /* if the drawer hasn't been loaded yet, add it */
    if (!document.querySelector('spark-drawer')) {
      const el = document.createElement('spark-drawer');
      el.setAttribute('initial-tab', 'cart');
      document.body.appendChild(el);
    }

    /* switch the drawer to the Cart tab */
    window.dispatchEvent(
      new CustomEvent('view-update', {
        bubbles: true,
        composed: true,
        detail: { view: 'cart' },
      }),
    );
   return cart
  },
};
```

### Adding custom attributes or file attachments to a cart item

See [Modifying Cart Contents](docId:1nctQXIhRYueptnOWkOl7) and [Customizing Add to Cart](docId\:dqn6YkfT1nH2i_0QZaywX) for adding custom attributes - including file attachments - to cart items.

### Integrating Google Analytics with SparkLayer SDK

### Enabling Google Analytics or GTM

To enable GA4 or GTM within your SparkLayer setup, configure the `analytics` option in your `sparkOptions`. You can specify multiple analytics providers, each with their respective event handlers and the events you wish to track.

```javascript
window.sparkOptions = {
  // ... other SparkLayer options ...

  analytics: {
    providers: [
      {
        handler: 'ga', // Use 'ga' for Google Analytics
        events: {
          addToCart: true,
          cartUpdate: true,
          shoppingListSave: true,
          shoppingListLoad: true,
          shoppingListDelete: true,
          csvUpload: true,
          quickAdd: true,
          finalStageCheckout: true,
          shippingUpdate: true,
          beginCheckout: true,
          purchase: true,
          viewCart: true
        }
      },
      {
        handler: 'gtm', // Use 'gtm' for Google Tag Manager
        events: {
          addToCart: true,
          cartUpdate: true,
          shoppingListSave: true,
          shoppingListLoad: true,
          shoppingListDelete: true,
          csvUpload: true,
          quickAdd: true,
          finalStageCheckout: true,
          shippingUpdate: true,
          beginCheckout: true,
          purchase: true,
          viewCart: true
        }
      },
      {
        handler: function(eventName, eventParam) {
          console.log('Event fired to custom provider:', eventName, eventParam);
          // Implement your custom analytics logic here
        },
        events: {
          addToCart: true,
          cartUpdate: true,
          shoppingListSave: true,
          shoppingListLoad: true,
          shoppingListDelete: true,
          csvUpload: true,
          quickAdd: true,
          finalStageCheckout: true,
          shippingUpdate: true,
          beginCheckout: true,
          purchase: true,
          viewCart: true
        }
      }
    ]
  }
};
```

### Configuration details

- providers: An array of analytics providers you wish to integrate. Each provider object can define a `handler` and the specific `events` to track.

### Provider Options

| Provider Type | Description                                                                                                                                                                                    |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 'ga'          | Integrates with Google Analytics (GA4). This works best when using [Shopify's GA4 solution](https://help.shopify.com/en/manual/reports-and-analytics/google-analytics/google-analytics-setup). |
| 'gtm'         | Integrates with Google Tag Manager.                                                                                                                                                            |
| function      | Allows for a custom analytics handler. Use this to integrate with other analytics platforms or to implement bespoke tracking logic.                                                            |

### Available Events

| Event Name           | Description                                                             |
| -------------------- | ----------------------------------------------------------------------- |
| `addToCart`          | Triggered when a product is added to the cart.                          |
| `cartUpdate`         | Fired when the cart is updated (e.g., quantity changes, item removals). |
| `shoppingListSave`   | Occurs when a shopping list is saved.                                   |
| `shoppingListLoad`   | Occurs when a shopping list is loaded.                                  |
| `shoppingListDelete` | Occurs when a shopping list is deleted.                                 |
| `csvUpload`          | Triggered when a CSV file is uploaded.                                  |
| `quickAdd`           | Fired during quick add actions.                                         |
| `finalStageCheckout` | Occurs at the final stage of the checkout process.                      |
| `shippingUpdate`     | Fired when shipping details are updated during the checkout.            |
| `beginCheckout`      | Triggered when the checkout process begins.                             |
| `purchase`           | Occurs upon successful purchase completion.                             |
| `viewCart`           | Fired when the cart is viewed.                                          |

### Custom Analytics Provider

If you need to integrate with an analytics service not natively supported by SparkLayer, you can define a custom handler function. This function receives the event name and parameters, allowing you to implement any tracking logic as needed.

```javascript
{
  handler: function(eventName, eventParam) {
    // Example: Send event data to a custom analytics service
    fetch('https://your-analytics-endpoint.com/track', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        event: eventName,
        parameters: eventParam
      })
    })
    .then(response => response.json())
    .then(data => {
      console.log('Custom analytics event tracked:', data);
    })
    .catch(error => {
      console.error('Error tracking custom analytics event:', error);
    });
  },
  events: {
    addToCart: true,
    cartUpdate: true,
    // ... other events ...
  }
}
```

## Configuring redirect on login

To configure redirection within SparkLayer, you need to include the spark-redirect.js script in your HTML. This script should be placed outside of the `{%- if customer.metafields.sparklayer.authentication -%}` conditional block in order for it to be picked up even if the user isn't authenticated.

```html
<script async src="https://cdn.sparklayer.io/spark-redirect.js"></script>
```

By default, if a user is not authenticated, they will be redirected to the `/account/login` page. You can customize this login path by setting the `window.sparkRedirectLoginPath` variable before including the script:

```html
<script>
    window.sparkRedirectLoginPath = "/account/login";
</script>
<script async src="https://cdn.sparklayer.io/spark-redirect.js"></script>
```

Some links (for example, the 'View Order' button in certain emails) will trigger specific functionality on sparklayer once the user has logged in. In order for this to work, you need to add the spark-redirect.js script above in addition to the core spark script.
