> ## Documentation Index
> Fetch the complete documentation index at: https://docs.molin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Storefront events API

> Send the cart, purchases and the logged-in customer to Molin AI, so search ranks the products your customers actually buy.

**Shopify, Shoprenter, UNAS and Shoper shops:** skip this page, the widget collects this data for you, and [Help Molin learn what your shoppers buy](https://docs.molin.ai/home/general/shopper-activity.md) lists what to do on each platform. Everyone else needs two things first:

* load the [widget script](https://docs.molin.ai/apis/experimental/widget-script.md) on **every page**, including the cart and order confirmation pages
* wrap every call below in this helper, so it waits until the widget has loaded:

```javascript theme={null}
function withMolin(fn) {
  if (window.Molin) {
    fn(window.Molin);
  } else {
    window.addEventListener('molin:ready', () => fn(window.Molin), { once: true });
  }
}
```

## Logged-in customer

Call `linkCustomer` on every page load while a customer is logged in. Send only your internal customer id, never an email, phone number or name.

```javascript theme={null}
withMolin((Molin) => Molin.linkCustomer({ id: String(customer.id) }));
```

When the customer logs out, call [`Molin.reset()`](https://docs.molin.ai/apis/experimental/personalization-api#data-persistence).

## Cart

Call `setCart` on every page load and after every cart change. Always send the whole cart, and `lines: []` once it is empty.

```javascript theme={null}
withMolin((Molin) =>
  Molin.setCart({
    lines: [/* line items */],
    total: 448,
    currency: 'EUR',
  }),
);
```

## Purchase

Call `trackPurchase` on the order confirmation page, once the order is confirmed. Reloading the page is safe, each `orderId` counts once.

```javascript theme={null}
withMolin((Molin) =>
  Molin.trackPurchase({
    orderId: 'ORD-2026-000123',
    lines: [/* line items */],
    total: 457, // what the shopper paid, shipping included
    currency: 'EUR',
  }),
);
```

## Line items

Each entry in `lines` is one product. Identify it with at least one of `url`, `sku`, `gtin` or `variantId`, matching your product feed character for character.

```javascript theme={null}
{
  // at least one of url, sku, gtin, variantId is required
  url: 'https://store.example/products/alpine-winter-jacket',
  sku: 'AWJ-001',
  gtin: '5901234123457',
  variantId: '8123456789',
  quantity: 2,
  price: 199.5,
}
```

> [accordion] Field rules
>
> A call that breaks these rules is rejected. Send ids as strings, for example `String(id)`, not as numbers. An empty `sku`, `gtin` or `variantId` is ignored.
>
> | Field | Rule | Example |
> | - | - | - |
> | `id` (customer), `orderId` | Not empty, at most 200 characters | `'101'` |
> | `url` | Product page URL without tracking parameters such as `?utm_source=…`, a path is resolved against the page it is sent from | `'https://store.example/products/alpine-winter-jacket'` |
> | `sku` | Your own article number | `'AWJ-001'` |
> | `gtin` | The barcode (EAN, UPC) | `'5901234123457'` |
> | `variantId` | The variant id, or the product id when the product has no variants | `'8123456789'` |
> | `quantity` | More than 0 | `2` |
> | `price` | One unit, as shown to the shopper | `199.5` |
> | `total` | 0 or more, it may differ from the sum of the lines | `448` |
> | `currency` | Three-letter ISO 4217 code, lowercase is accepted | `'EUR'` |
> | `lines` | At most 200 line items | `[]` |

## Checking that it works

Filter the browser's DevTools console by `Molin: storefront events error`. No errors means the calls work. An error names the call and the field to fix, for example `setCart was not sent` with `lines.0.price`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.