> ## 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 checkout changes

> How to send checkout updates to Customer Engagement with checkout(), and how they drive Abandoned Checkout automations.

Tracking checkout changes is what makes Abandoned Checkout automations possible. Each checkout event tells Customer Engagement *what a visitor is about to buy*: the products, prices, discounts, coupon, and whether they have selected a shipping and payment method. Every event is tied to a cart through `cartRef`, and to a contact through `contactId` or the visitor's identification cookie.

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

## How it works

1. Your site submits every checkout change, via the tracking script or the tracking API.
2. A checkout 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 Customer Engagement. All other checkouts are filtered out.
3. Customer Engagement enriches the products from the product feed and triggers the **Abandoned Checkout** automation matching the checkout's locale.

### Checkout, cart and product views in one session

Checkout works together with [cart changes](/docs/tracking/tracking-cart-changes) and [product views](/docs/tracking/tracking-product-views).

Customer Engagement uses the `sessionId` to identify the winning "abandoned" signal for a session. If a single abandoned session contains all three event types (checkout, cart and product view), only one Abandoned Checkout signal is produced, not one per event type.

To get this right, send the events from the same session with the same `sessionId`. The tracking script handles this for you. If you use the tracking API, you must include the `sessionId` yourself (see below).

## Using the tracking script

Call `checkout()` every time the checkout state changes: an item is added, removed or updated, a coupon is applied, or the visitor selects a shipping or payment method. Call it whether or not the visitor has been identified.

```javascript Tracking a checkout theme={null}
va("checkout", {
    "cartRef": "354354",
    "checkoutRef": "CHK-20931",
    "contactId": "afa7625d-2e97-4667-b4c1-ad3b01194bee",
    "cartUrl": "https://www.store.se/cart?id=354354",
    "checkoutUrl": "https://www.store.se/checkout?id=CHK-20931",
    "locale": "sv-SE",
    "currencyCode": "SEK",
    "coupon": "SUMMER10",
    "totalAmount": 1708.2,
    "totalDiscountAmount": 189.8,
    "shippingMethodSelected": true,
    "paymentMethodSelected": true,
    "items": [
        {
            "itemId": "456436",
            "quantity": 2,
            "index": 0,
            "salesPrice": 499.0,
            "totalSalesPrice": 998.0,
            "totalDiscount": 99.8,
            "totalSalesPriceAfterDiscount": 898.2,
            "category": "Women",
            "category2": "Shoes",
            "brand": "Acme"
        },
        {
            "itemId": "456437",
            "quantity": 1,
            "index": 1,
            "salesPrice": 899.0,
            "totalSalesPrice": 899.0,
            "totalDiscount": 89.9,
            "totalSalesPriceAfterDiscount": 809.1,
            "category": "Women",
            "category2": "Bags",
            "brand": "Acme"
        }
    ]
});
```

### Checkout fields

<ResponseField name="cartRef" type="string" required>
  The reference of the cart this checkout belongs to. Must be the same `cartRef` you use in [cart events](/docs/tracking/tracking-cart-changes) for that cart.
</ResponseField>

<ResponseField name="checkoutRef" type="string" required>
  Your reference for this checkout. Must be unique per checkout and must never change for the life of that checkout. Maximum 255 characters. `checkoutReference` is accepted as an alias in the tracking script.
</ResponseField>

<ResponseField name="locale" type="string" required>
  The locale of the site the checkout belongs to, as an IETF language tag such as `sv-SE`.
</ResponseField>

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

<ResponseField name="cartUrl" type="string">
  A link back to the cart on your site.
</ResponseField>

<ResponseField name="checkoutUrl" type="string">
  A link back to this checkout on your site.
</ResponseField>

<ResponseField name="contactId" type="string">
  The Customer Engagement contact ID. Must be a valid GUID or short GUID, with a maximum of 36 characters. If omitted, the `_vaI` cookie is used as a fallback.
</ResponseField>

<ResponseField name="coupon" type="string">
  The coupon or discount code applied to the checkout. Maximum 100 characters.
</ResponseField>

<ResponseField name="totalAmount" type="number">
  The total amount of the checkout.
</ResponseField>

<ResponseField name="totalDiscountAmount" type="number">
  The total discount applied to the checkout.
</ResponseField>

<ResponseField name="currencyCode" type="string">
  The currency of all amounts, as a three-letter ISO 4217 code such as `SEK`. If provided, it must consist of exactly 3 letters.
</ResponseField>

<ResponseField name="shippingMethodSelected" type="boolean">
  Whether the visitor has selected a shipping method (`true` or `false`).
</ResponseField>

<ResponseField name="paymentMethodSelected" type="boolean">
  Whether the visitor has selected a payment method (`true` or `false`).
</ResponseField>

### Item fields

<ResponseField name="items[].itemId" type="string" required>
  The product identifier, matched against SKU in Customer Engagement. Maximum 255 characters.
</ResponseField>

<ResponseField name="items[].quantity" type="int" required>
  The number of that item in the checkout. Must be an integer of 1 or greater.
</ResponseField>

<ResponseField name="items[].index" type="int">
  The position of the item in the checkout. Must be 0 or greater. If omitted, the item's position in the `items` array is used.
</ResponseField>

<ResponseField name="items[].salesPrice" type="number">
  The unit price of the item.
</ResponseField>

<ResponseField name="items[].totalSalesPrice" type="number">
  The price of the item multiplied by its quantity, before discount.
</ResponseField>

<ResponseField name="items[].totalDiscount" type="number">
  The total discount applied to the item.
</ResponseField>

<ResponseField name="items[].totalSalesPriceAfterDiscount" type="number">
  The total price of the item after discount.
</ResponseField>

<ResponseField name="items[].category" type="string">
  The item's main category. Use `category2` to `category5` for deeper levels of the category hierarchy. Maximum 100 characters per category field.
</ResponseField>

<ResponseField name="items[].brand" type="string">
  The item's brand.
</ResponseField>

## Using the tracking API

You can submit checkout 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 checkouts can only be tracked with the script. You are also responsible for identifying visitors who arrive from Customer Engagement email links yourself, by reading the `vtid` query parameter and passing it as `contactId`.

You must also include a `sessionId` in every payload. It is required to identify the winning abandoned signal when a session contains checkout, cart and product view events. Use the same `sessionId` across all three event types. See [sessions and sessionId](/docs/tracking/tracking-product-views#sessions-and-sessionid).

Send checkout events to the `tracking/checkouts` endpoint.

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 Customer Engagement 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 checkout event **only** when the checkout actually changes. Firing events at other times, such as on page load or navigation, pollutes your data in Customer Engagement.
</Warning>

* **Every change means one event.** Customer Engagement always works from the latest state, so the data you send must match what the checkout currently displays. Send the full contents every time, not just what changed.

* **`checkoutRef` must be unique and stable.** Never share a `checkoutRef` between checkouts or visitors, and never change it for an existing checkout.

* **Use the same `cartRef` as your cart events.** This is what links the checkout to the cart.

* **Always send `locale`, `checkoutRef`, `cartRef` and `items`.** The script does not send the event if any of them is missing, and logs an error to the browser console.

* **Send valid items.** Every item needs an `itemId` (255 characters or fewer) and an integer `quantity` of 1 or greater.

* **Use consistent currency and amounts.** Send all amounts in the same currency, and set `currencyCode` to a 3-letter ISO 4217 code.

* **Use one `sessionId` per session across checkout, cart and product view events.** This ensures a single Abandoned Checkout signal per abandoned session. With the tracking script this is handled for you; with the API you must send it yourself.

* **Call `emptyCart()` after a completed purchase.** A checkout event does not clear the cart. If a visitor buys without your site calling `emptyCart()`, an active abandoned automation may still trigger for someone who has already bought. See [tracking cart changes](/docs/tracking/tracking-cart-changes).

<Card title="Verify your checkout tracking" href="/docs/tracking/verifying-web-tracking#verify-checkout" 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" />


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