# Events and analytics

URL: https://docs.sparklayer.io/developers/javascript-sdk/events-and-analytics

Run your own code from SparkLayer's hooks and DOM events, send B2B events to Google Analytics or Tag Manager, and push cart changes to any analytics tool.

> **For AI assistants:** what to know before writing SparkLayer JavaScript 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 https://docs.sparklayer.io/developers/javascript-sdk/reference/methods.md, hooks https://docs.sparklayer.io/developers/javascript-sdk/reference/hooks.md, options https://docs.sparklayer.io/developers/javascript-sdk/reference/options.md, types https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md (or the same types as a file: https://docs.sparklayer.io/developers/javascript-sdk/spark.d.ts). Setup and waiting for SparkLayer: https://docs.sparklayer.io/developers/javascript-sdk/setup.md. Use only what the reference documents.

Run your own code at key moments in SparkLayer, react to what customers do in its interfaces, and send B2B events to your analytics. This page covers the `onLoad`, `onReady`, `onCartLoad`, `onCartUpdate` and `onLogout` hooks, SparkLayer's DOM events and web components, and the `analytics` option.

## Hooks

Hooks are `async` functions you set on `window.sparkOptions` before the Core Script loads (see [Add your own options and hooks](https://docs.sparklayer.io/developers/javascript-sdk/setup.md#add-your-own-options-and-hooks)). SparkLayer calls them at these points:

| Hook | When it runs | Receives |
| --- | --- | --- |
| [`onLoad`](https://docs.sparklayer.io/developers/javascript-sdk/reference/hooks.md#onload) | Once while SparkLayer initialises, after translations have loaded and before `onReady`, whether or not the customer is logged in. | The `Spark` object |
| [`onReady`](https://docs.sparklayer.io/developers/javascript-sdk/reference/hooks.md#onready) | When SparkLayer has initialised and the page's DOM has loaded. The place to start most of your code. | The `Spark` object |
| [`onCartLoad`](https://docs.sparklayer.io/developers/javascript-sdk/reference/hooks.md#oncartload) | When the cart is loaded. | The `Cart` |
| [`onCartUpdate`](https://docs.sparklayer.io/developers/javascript-sdk/reference/hooks.md#oncartupdate) | Each time the cart is updated. | The updated `Cart` and the `CartResults` for each change |
| [`onLogout`](https://docs.sparklayer.io/developers/javascript-sdk/reference/hooks.md#onlogout) | When the customer logs out. | Nothing |

Two more hooks change what SparkLayer does rather than react to it: `preCartUpdateListener` edits an update before SparkLayer's add to cart sends it (see [Cart](https://docs.sparklayer.io/developers/javascript-sdk/cart.md#add-attributes-to-sparklayers-add-to-cart)), and `onCheckoutValidation` blocks checkout (see [Checkout](https://docs.sparklayer.io/developers/javascript-sdk/checkout.md)).

If `onReady`, `onCartLoad` or `onCartUpdate` throws an error, SparkLayer shows a system error with a code that names the hook. See [Hook error codes](https://docs.sparklayer.io/developers/javascript-sdk/reference/hooks.md#hook-error-codes).

## DOM events and web components

SparkLayer's interfaces are web components, such as `<spark-pdp>` and `<spark-product-card>`, that you add to your theme. Some of them dispatch DOM events you can listen for:

- `spark-variant-change`: the customer selects a variant in `spark-pdp` or `spark-product-card`. It doesn't bubble, so listen on each element. See [Update the product image when a variant is selected](https://docs.sparklayer.io/developers/javascript-sdk/products-and-pricing.md#update-the-product-image-when-a-variant-is-selected).
- `spark-file-attachment-changed` and `spark-file-attachment-failed`: a file is added to, removed from or fails to upload to a `spark-file-upload-field`. See [Let customers upload a file](https://docs.sparklayer.io/developers/javascript-sdk/cart.md#let-customers-upload-a-file).
- `view-update`: you dispatch this one on `window` to switch an open drawer to a tab. See [Open the cart drawer](https://docs.sparklayer.io/developers/javascript-sdk/cart.md#open-the-cart-drawer).

For every web component and event, with the shape of each `event.detail`, see [Events and components](https://docs.sparklayer.io/developers/javascript-sdk/reference/events-and-components.md) in the SDK reference.

## Google Analytics

SparkLayer can send B2B events, such as add to cart, begin checkout and purchase, to Google Analytics (GA4), Google Tag Manager or your own function. You turn this on with the `analytics` option in `sparkOptions`, listing a `handler` and the `events` to send for each provider.

For the configuration, the list of events and a custom handler example, see [Event tracking for analytics](https://docs.sparklayer.io/developers/frontend/technical-information.md#event-tracking-for-analytics-google-analytics-ga4).

## Send cart changes to your analytics

For tools other than [Google Analytics](#google-analytics), push cart changes to the data layer from the `onCartUpdate` hook. This snippet keeps any `onCartUpdate` you already have:

```html title="Theme <head>, before the SparkLayer script"
<script>
  (function () {
    var options = (window.sparkOptions = window.sparkOptions || {});
    var previous = options.onCartUpdate;

    options.onCartUpdate = async function (cart, results) {
      if (previous) await previous(cart, results);
      window.dataLayer = window.dataLayer || [];
      (results || []).forEach(function (result) {
        window.dataLayer.push({
          event: 'b2b_cart_change',
          sku: result.sku,
          name: result.name,
          quantity: result.resultantQuantity,
          currency: cart.currencyCode,
        });
      });
    };
  })();
</script>
```

## Next steps

- [Event tracking for analytics](https://docs.sparklayer.io/developers/frontend/technical-information.md#event-tracking-for-analytics-google-analytics-ga4): Turn on GA4 or Google Tag Manager, and see every event SparkLayer sends.
- [Cart](https://docs.sparklayer.io/developers/javascript-sdk/cart.md): Change the cart from your own code and open the cart drawer.
- [Hooks](https://docs.sparklayer.io/developers/javascript-sdk/reference/hooks.md): When each hook runs, what it receives and returns, with an example of each.
