---
title: Tracking user journey
description: Learn how to model user identity and journey events correctly with the Luigi's Box Events API v1.
slug: analytics/api_guides/tracking-user-journey
docKind: guide
hub: analytics
---

Understanding the user journey is what makes Luigi's Box analytics useful. The system needs to know who the user is, what they saw, what they clicked, and what they eventually purchased. This guide explains how to model that journey with the supported `v1` Events API.

## Start with stable user identifiers

Luigi's Box uses two identifiers to stitch a journey together:

- `client_id` identifies the current browser, device, or app install
- `customer_id` identifies the logged-in customer when that information is available

### How to use them

1. Always send `client_id`.
2. When the user signs in, keep the same `client_id` and add `customer_id`.
3. When the user signs out, remove `customer_id` but keep the same `client_id`.

If you change `client_id` in the middle of a session, Luigi's Box interprets that as a new user stream and breaks attribution in that browser or app context.

:::warning
`client_id` continuity matters more than whether the user is anonymous or authenticated. Do not rotate it on login or logout.
:::

## Choose the right event for each step

The supported `v1` event model is intentionally small:

| Journey step | Event type | When to use it |
| :-- | :-- | :-- |
| User views a generic page or detail page | `pv` | Homepage, cart, CMS page, product detail, category detail |
| User sees search, autocomplete, listing, or recommendation results | `event` | Any list of items rendered to the user |
| User clicks a result | `click` with `action.type: "click"` | Search, autocomplete, recommendation, listing result click |
| User adds to cart or performs another micro-conversion | `click` with a custom action type | `add-to-cart`, `add-to-wishlist`, `buy`, and similar |
| User completes checkout | `transaction` | Final order confirmation |

## `pv`: page views and detail views

Use `pv` for both generic pages and catalog object detail pages.

- For a generic page, set `url` to the canonical URL or route
- For a catalog detail page, set `url` to the indexed object identity

```json
{
  "type": "pv",
  "id": "7ef5e0ec-f9a5-4f2c-b363-a6c86e31f652",
  "tracker_id": "YOUR_TRACKER_ID",
  "client_id": "web-user-1",
  "customer_id": "customer-42",
  "url": "sku-2372711",
  "title": "White sneakers GLX 23"
}
```

## `event`: lists that shape discovery

Use `event` whenever the user sees a list of items:

- `Search Results`
- `Autocomplete`
- `Product Listing`
- `Recommendation`

These events should describe the final list the user actually saw, including positions, filters, and recommendation metadata where relevant.

```json
{
  "type": "event",
  "id": "73cdff18-c6b3-4a3a-8cb4-2f7455a0f7d6",
  "tracker_id": "YOUR_TRACKER_ID",
  "client_id": "web-user-1",
  "lists": {
    "Search Results": {
      "query": {
        "string": "running shoes"
      },
      "items": [
        {
          "title": "Runner One",
          "type": "item",
          "url": "shoe_1",
          "position": 1,
          "price": 99
        }
      ]
    }
  }
}
```

## `click`: result clicks and micro-conversions

Use the same outer event type for both clicks and non-purchase conversions.

### Result click

```json
{
  "type": "click",
  "id": "3d7188fd-5b68-4bb8-898f-f0a4264790ef",
  "tracker_id": "YOUR_TRACKER_ID",
  "client_id": "web-user-1",
  "action": {
    "type": "click",
    "resource_identifier": "shoe_1"
  }
}
```

### Add to cart

```json
{
  "type": "click",
  "id": "9f42bba5-06f0-48c2-8446-f25eabf8f174",
  "tracker_id": "YOUR_TRACKER_ID",
  "client_id": "web-user-1",
  "action": {
    "type": "add-to-cart",
    "resource_identifier": "shoe_1"
  }
}
```

Anything other than `action.type: "click"` is treated as a conversion signal.

## `transaction`: the end of the journey

Use `transaction` only when the order is complete.

```json
{
  "type": "transaction",
  "id": "c2d72b44-9274-4ef6-b35f-db7322d36730",
  "tracker_id": "YOUR_TRACKER_ID",
  "client_id": "web-user-1",
  "items": [
    {
      "url": "shoe_1",
      "count": 1,
      "total_price": 99
    },
    {
      "url": "sock_2",
      "count": 2,
      "total_price": 18
    }
  ]
}
```

Include the full order, not only the items that came from Luigi's Box results.

## Typical journey mapping

### Website flow

| User action | Event |
| :-- | :-- |
| Visits homepage | `pv` |
| Opens product detail | `pv` with indexed identity in `url` |
| Performs search | `event` with `Search Results` |
| Clicks result | `click` |
| Adds product to cart | conversion `click` |
| Completes purchase | `transaction` |

### Mobile app flow

| User action | Event |
| :-- | :-- |
| Opens a screen | `pv` or `event`, depending on the screen type |
| Sees autocomplete suggestions | `event` with `Autocomplete` |
| Sees recommendation widget | `event` with `Recommendation` |
| Taps a result | `click` |
| Adds item to favorites or cart | conversion `click` |
| Completes checkout | `transaction` |

## A/B testing and session context

Use `ab_test_variant` for session-level A/B reporting. For list-specific experiments, send `_Variant` inside the list filters.

You can also send `context` when ranking depends on operational conditions such as warehouse, country, or inventory pool. Make sure those context keys are consistent with your indexed data.

## Next steps

- Read the full [Event API reference](/analytics/api/events/)
- Implement [search and discovery tracking](/analytics/api_guides/search-and-discovery/)
- Add [ecommerce events](/analytics/api_guides/ecommerce-events/) once journey attribution is in place
