---
title: Search and discovery
description: Implement search, autocomplete, listing, and recommendation analytics with the supported Luigi's Box Events API v1.
slug: analytics/api_guides/search-and-discovery
docKind: guide
hub: analytics
---

Search and discovery analytics tell Luigi's Box what users asked for and what they actually saw. This is what powers metrics like click-through rate, zero-result rate, position-based performance, and recommendation attribution.

## Search

Search is reported as a list event with the exact list name `Search Results`.

### What to send

- The exact query string
- All active filters and sorting values
- The final visible results with their absolute positions
- `_Guid` when you have the Search API response `guid`
- `_Variant` when the list is part of an A/B test

```json
{
  "type": "event",
  "id": "ff0d53c8-f791-4518-9335-13a72f3a3f09",
  "tracker_id": "YOUR_TRACKER_ID",
  "client_id": "web-user-1",
  "lists": {
    "Search Results": {
      "query": {
        "string": "running shoes",
        "filters": {
          "brand": "Nike",
          "sort by": "price_amount:asc",
          "_Guid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
        }
      },
      "items": [
        {
          "title": "Runner One",
          "type": "item",
          "url": "shoe_1",
          "position": 1,
          "price": 99
        }
      ]
    }
  }
}
```

### Position rules

Positions must be absolute across pagination:

- Page 1 starts at `1`
- Page 2 starts at the first item after the previous page
- Infinite scroll should report only the newly appended items, not the whole list again

## Autocomplete

Autocomplete is also a list event, but the list name must be exactly `Autocomplete`.

```json
{
  "type": "event",
  "id": "5c7870e5-b8d0-495b-93a3-dbfec1e63244",
  "tracker_id": "YOUR_TRACKER_ID",
  "client_id": "web-user-1",
  "lists": {
    "Autocomplete": {
      "query": {
        "string": "run"
      },
      "items": [
        {
          "title": "Running shoes",
          "type": "query",
          "url": "running shoes",
          "position": 1
        },
        {
          "title": "Runner One",
          "type": "item",
          "url": "shoe_1",
          "position": 2,
          "price": 99
        }
      ]
    }
  }
}
```

### Important autocomplete rules

- Debounce tracking so you report the settled suggestion list, not every keystroke
- If the user clicks a suggestion of type `query`, send the query text as `resource_identifier` in the click event
- If autocomplete shows top items on focus, track that block as a recommendation, not as autocomplete

## Product listing

Category pages, brand pages, campaign pages, and other browse-first surfaces use the list name `Product Listing`.

### Required scopes

For categories:

- `_category_label`
- `_category_identity`

For brands:

- `_brand_label`
- `_brand_identity`

```json
{
  "type": "event",
  "id": "20ce9f0e-e83b-4f83-93ca-12780fd8c0c3",
  "tracker_id": "YOUR_TRACKER_ID",
  "client_id": "web-user-1",
  "lists": {
    "Product Listing": {
      "query": {
        "filters": {
          "sort by": "price_amount:asc",
          "_Guid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
        },
        "scopes": {
          "_category_label": "Shoes||Running",
          "_category_identity": "cat_running_shoes"
        }
      },
      "items": [
        {
          "title": "Runner One",
          "type": "item",
          "url": "shoe_1",
          "position": 1,
          "price": 99
        }
      ]
    }
  }
}
```

## Recommendations

Recommendation widgets use the list name `Recommendation`.

The critical metadata lives inside `query.filters`:

- `RecommenderClientId`
- `RecommendationId`
- optional `ItemIds`
- optional `Recommender`
- optional `Type`
- optional `_Variant`

```json
{
  "type": "event",
  "id": "ff61de98-1afe-45a1-b1a7-1a319bf6639a",
  "tracker_id": "YOUR_TRACKER_ID",
  "client_id": "web-user-1",
  "lists": {
    "Recommendation": {
      "query": {
        "filters": {
          "RecommenderClientId": "item_detail_alternatives",
          "RecommendationId": "rec_1abc2de3-f456-7890",
          "ItemIds": ["shoe_1"]
        }
      },
      "items": [
        {
          "title": "Runner Two",
          "type": "item",
          "url": "shoe_2",
          "position": 1,
          "price": 109
        }
      ]
    }
  }
}
```

:::warning
Treat `RecommendationId` as required for all new integrations. It is the key that allows Luigi's Box to attribute downstream clicks and purchases to the exact recommendation set.
:::

## Click attribution

Whenever a user clicks a result from any discovery surface, send a `click` event:

```json
{
  "type": "click",
  "id": "3a851362-9320-4762-a3d1-4770f1798f1d",
  "tracker_id": "YOUR_TRACKER_ID",
  "client_id": "web-user-1",
  "action": {
    "type": "click",
    "resource_identifier": "shoe_1"
  }
}
```

Luigi's Box uses the earlier event stream to attribute that click to the correct search, autocomplete, listing, or recommendation impression.

## Conversion attribution

Use the same pattern for add-to-cart or wishlist actions, but change `action.type`.

```json
{
  "type": "click",
  "id": "b37f526c-d417-49f0-925e-06f74778aa75",
  "tracker_id": "YOUR_TRACKER_ID",
  "client_id": "web-user-1",
  "action": {
    "type": "add-to-cart",
    "resource_identifier": "shoe_1"
  }
}
```

This lets Luigi's Box connect the conversion back to the discovery surface that led to it.

## Recommended implementation order

1. Track `Search Results` and `Autocomplete`
2. Add click tracking for every result click
3. Track `Product Listing` and `Recommendation` surfaces
4. Add conversions and transactions so attribution reaches business outcomes

## Next steps

- Review the [Event API reference](/analytics/api/events/)
- Add [ecommerce events](/analytics/api_guides/ecommerce-events/)
- Verify the payloads in [Debugging](/analytics/debugging/)
