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

# Tracking cart changes

> How to send shopping cart updates to Engage with cart() and emptyCart(), and what abandoned cart automations require.

Tracking cart changes is what makes abandoned cart automations possible. For Engage to trigger one, it needs to know **every state of every cart** and, eventually, **which contact the cart belongs to**.

You can send cart data either with the [tracking script](/docs/tracking/tracking-script) or with the tracking API.

## How it works

1. Your site submits every cart change, via the tracking script or the tracking API.
2. A cart that still contains products and hasn't been touched for 30 minutes is treated as abandoned. If it is connected to a contact, it is sent to Engage. All other carts are filtered out.
3. Engage enriches the products from the product feed and triggers the automation matching the cart's locale.

## What an abandoned cart automation requires

An abandoned cart automation triggers only when all of these are true:

* The cart's `locale` matches a product feed in Engage, and an active automation is set to that language.
* At least one SKU matches a product in that feed (usually via `g:id`). Products that don't match are left out of the email; if **no** SKUs match, the automation doesn't trigger at all.
* No product in the cart has been purchased since the cart was marked abandoned - that is, no transaction has reached Engage. This can be overruled in the trigger configuration.

<Card title="Learn about abandoned cart from a user's perspective" href="https://help.engage.voyado.com/hc/en-gb/sections/17212833070492-Abandoned-cart" icon="https://mintcdn.com/voyado/Ns4bBcK3LNctK_Un/icons/help-center-link.png?fit=max&auto=format&n=Ns4bBcK3LNctK_Un&q=85&s=3e7ca2ce0b8cfb9fbd27a4bdf53b2ce1" horizontal width="128" height="128" data-path="icons/help-center-link.png" />

## Using the tracking script

Two methods are involved. Both send an HTTP POST to the Collect endpoint.

<AccordionGroup>
  <Accordion title="cart() — the cart changed">
    Call `cart()` every time the cart changes: an item added, an item removed, or a quantity updated. Call it whether or not the visitor has been identified.

    ```javascript Adding two products to the cart theme={null}
    va("cart", {
        "cartRef": "354354",
        "contactId": "afa7625d-2e97-4667-b4c1-ad3b01194bee",
        "cartUrl": "https://www.store.se/cart?id=354354",
        "locale": "sv-SE",
        "items": [
            {
                "itemId": "456436",
                "quantity": 2
            },
            {
                "itemId": "456437",
                "quantity": 2
            }
        ]
    });
    ```

    <ResponseField name="cartRef" type="string" required>
      Your reference for this cart. Must be unique per cart and must never change for the life of that cart.
    </ResponseField>

    <ResponseField name="locale" type="string" required>
      The locale of the site the cart belongs to, as an IETF language tag such as `sv-SE`. Only locales with a product feed assigned in Engage can trigger an abandoned cart automation.
    </ResponseField>

    <ResponseField name="items" type="array<object>" required>
      The full current contents of the cart.
    </ResponseField>

    <ResponseField name="items[].itemId" type="string" required>
      The product identifier, matched against SKU in Engage.
    </ResponseField>

    <ResponseField name="items[].quantity" type="int" required>
      The number of that item in the cart.
    </ResponseField>

    <ResponseField name="cartUrl" type="string">
      A link back to this cart on your site, for use in the abandoned cart email.
    </ResponseField>

    <ResponseField name="contactId" type="string">
      The Engage contact ID. If omitted, the `_vaI` cookie is used as a fallback.
    </ResponseField>
  </Accordion>

  <Accordion title="emptyCart() — the cart is now empty">
    Call `emptyCart()` when the cart has been emptied, either by the visitor or by a completed checkout. It is equivalent to calling `cart()` with no items.

    Calling it after every successful checkout is important — otherwise the cart stays populated in Engage and may trigger an abandoned cart email to someone who has already bought.

    ```javascript theme={null}
    va("emptyCart", {
        "cartRef": "354354"
    });
    ```

    <ResponseField name="cartRef" type="string" required>
      The same cart reference used for the cart's other events. Empty carts still need one.
    </ResponseField>

    <ResponseField name="contactId" type="string">
      The Engage contact ID. If omitted, the `_vaI` cookie is used as a fallback.
    </ResponseField>
  </Accordion>
</AccordionGroup>

## Using the tracking API

You can submit cart changes directly via the API instead of implementing the tracking script.

The API always requires a `contactId`, so it can only track **identified** visitors. Anonymous carts can only be tracked with the script. You are also responsible for identifying visitors who arrive from Engage email links yourself, by reading the `vtid` query parameter and passing it as `contactId`.

If you use abandoned browse as well as abandoned cart, you must also include a `sessionId` in every payload. See [sessions and sessionId](/docs/tracking/tracking-product-views#sessions-and-sessionid).

You can test the calls from your OpenAPI (Swagger) page:

```http theme={null}
[tenantname].voyado.com/api/v3/ui/index#/tracking
```

<Card title="Read about the Engage API and your OpenAPI page" href="/docs/api/the-engage-api" icon="https://mintcdn.com/voyado/Ns4bBcK3LNctK_Un/icons/developer-link.png?fit=max&auto=format&n=Ns4bBcK3LNctK_Un&q=85&s=fbd08f956358ab12f664a7158e1a1399" horizontal width="128" height="128" data-path="icons/developer-link.png" />

## Rules to follow

<Warning>
  Send a cart event **only** when the cart actually changes. Firing events at other times — on page load, on navigation — pollutes your data in Engage.
</Warning>

* **Track anonymous carts too.** A cart belonging to an anonymous visitor is still linked to their contact once they are identified.

* **Every change means one event.** Engage always works from the cart's latest state, so the data you send must match what the site currently displays. Cart updates can happen in a product page, a popup, a mini-cart or the checkout — all of them need to fire an event.

* **`cartRef` must be unique and stable.** Never share a `cartRef` between carts or visitors, and never change it for an existing cart. Getting this wrong on remove-product and empty-cart events is a common bug.

* **Always send a `cartRef`, even for empty carts.**

* **`locale` must match a product feed.** Engage needs a feed for that locale to enrich products with article data, and an active automation using that locale.

* **Anything not emptied risks being marked abandoned.** If a visitor leaves or buys without your site calling `emptyCart()`, an active abandoned cart automation will trigger on that cart.

<Card title="Verify your cart tracking" href="/docs/tracking/verifying-web-tracking#verify-cart-changes" icon="https://mintcdn.com/voyado/Ns4bBcK3LNctK_Un/icons/developer-link.png?fit=max&auto=format&n=Ns4bBcK3LNctK_Un&q=85&s=fbd08f956358ab12f664a7158e1a1399" horizontal width="128" height="128" data-path="icons/developer-link.png" />
