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

# Recommendation Event Tracking

> Learn how to record impressions, clicks, and conversions of recommendation results in A2 with the tracking token.

Recommendation logs tell A2 about impressions, clicks, and conversions of the A2 recommendation results shown in your service. A2 uses these records to aggregate recommendation performance and update each user's recommendation history.

## Overview

Every successful recommendation response includes `tracking_token`. Error responses do not. `tracking_token` identifies the returned recommendation result, and recommendation events use this value together with the item ID and position to connect the event to an item of that recommendation.

| Event | `action` | Description |
| - | - | - |
| Response impression | `imp` | A record that the recommendation list was received and shown. Recorded once per response. |
| Viewable impression | `vimp` | A record that a recommended item actually appeared on the user's screen. |
| Click | `clk` | A record that a user clicked a recommended item. |
| Conversion | `conv` | A record that a user who clicked a recommended item completed a goal action, such as a purchase. |

See [Recommendation Requests](https://docs.aiderx.io/development/en/serving-reco.md) for how to request recommendations. Sending recommendation logs does not require an access token.

> [!NOTE]
>
> `tracking_token` is a different value from `ext.ad_log` in ad responses. Use the `tracking_token` of the recommendation response exactly as received. If you use a value from another response, the event will not be connected to the intended recommendation.

Send impressions of your service's own lists that A2 did not recommend as `item_impression` in [User Activity Logs](https://docs.aiderx.io/development/en/user-events.md), not as recommendation logs.

## Values to keep from the response

When you receive a recommendation response, keep `tracking_token` together with each item's `catalog_id` and `position` while the list is shown. To measure conversions, pass the values of the clicked item through to purchase completion.

```json Recommendation response example theme={null}
{
  "version": "0.1.0",
  "items": [
    { "catalog_id": "catalog-123", "position": 0, "score": 0.87 },
    { "catalog_id": "catalog-234", "position": 1 }
  ],
  "tracking_token": "<tracking_token>",
  "ext": { "ad_log_tracking_mode": "on_event_tracker" }
}
```

| Field | Where it goes in the event |
| - | - |
| `tracking_token` | Put it as is in `tracking_token` of every event. |
| `items[].catalog_id` | Put the IDs of the event's items in `event_items`. |
| `items[].position` | Put the positions of the same items in `event_position`, in the same order as `event_items`. |
| `ext.ad_log_tracking_mode` | Decides whether your service sends `imp`. See [Response impression tracking](#response-impression-tracking). |

Even if your service reorders the items with its own rules or hides some of them, put the response `position` in `event_position`, not the on-screen position. A2 uses this value to find which recommendation method produced the item. Positions that are not in the response are not aggregated.

## Response impression tracking

When `imp` is recorded depends on the impression tracking mode of the recommendation placement. Check it in the response's `ext.ad_log_tracking_mode`.

| Impression Tracking Mode | When it is recorded | What your service does |
| - | - | - |
| **On Impression Event** (`on_event_tracker`, default) | When your service sends `imp`. | Send `imp` once when the recommendation list is shown. |
| **On Recommendation Response** (`on_ad_response`) | When A2 sends a recommendation response with at least one item. | Nothing. Do not send `imp`. |

Your service sends `vimp`, `clk`, and `conv` in either mode.

## Send events

Send all recommendation events to the [event logging API](https://docs.aiderx.io/en/0.5.0/decision/ad-log/record-user-log.md). Only `action` and the target items differ; the request is the same.

```bash theme={null}
curl -i -X POST "<A2_API_URL>/dmp/v0/log" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "reco_log",
    "action": "clk",
    "tracking_token": "<tracking_token of the recommendation response>",
    "event_items": ["catalog-234"],
    "event_position": [1]
  }'
```

HTTP `200` does not guarantee that the event is valid or aggregated. Events whose token cannot be read and malformed entries are left out of aggregation, so follow the formats in [Request fields](#request-fields).

### Request fields

| Field | Required | Description |
| - | - | - |
| `type` string | Required | Send `reco_log`. |
| `action` string | Required | One of `imp`, `vimp`, `clk`, and `conv`. |
| `tracking_token` string | Required | The `tracking_token` you kept from the recommendation response. |
| `event_items` string array | Required | The `catalog_id` values of the event's items. Send numeric IDs as strings. |
| `event_position` integer array | Required | The response `position` values of the event's items, in the same order as `event_items`. |
| `seed_item_id` string | Optional | If you sent `seed_item_id` in the recommendation request, send the same value. Do not send an empty string. |
| `timestamp_in_ms` integer | Optional | Unix time when the event occurred, in **milliseconds**. If omitted, A2 uses the collection time. |

The API Reference marks `event_items` and `event_position` as optional. However, without `event_items` the event is not reflected in item metrics or the user's recommendation history, and without `event_position` `vimp`, `clk`, and `conv` are not counted in recommendation performance metrics. Always send both.

### Response impression (`imp`)

With On Impression Event, send all items of the response once when the recommendation list is shown. Do not send it again when re-rendering the same response or moving to the next page.

```javascript theme={null}
// Run once per response after the recommendation list is shown.
if (reco.ext?.ad_log_tracking_mode !== "on_ad_response" && reco.items.length > 0) {
  sendRecoLog("imp", reco.tracking_token, reco.items);
}
```

`sendRecoLog` in these examples calls the event logging API.

```javascript theme={null}
function sendRecoLog(action, trackingToken, items) {
  return fetch(`${A2_API_URL}/dmp/v0/log`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      type: "reco_log",
      action,
      tracking_token: trackingToken,
      event_items: items.map((item) => item.catalog_id),
      event_position: items.map((item) => item.position),
    }),
    keepalive: true,
  });
}
```

### Viewable impression (`vimp`)

When recommended items actually appear on screen, send the items that appeared. Put items that appeared at the same time in one event, and do not resend items already sent for the same response. Items of a new recommendation response are sent separately even at the same positions. Each `vimp` counts as one impression, so sending each item separately inflates the impression count.

```javascript theme={null}
// For each recommendation response, send only items that appear on screen for the first time.
const sentByReco = new WeakMap();
function onRecoItemsVisible(reco, visibleItems) {
  if (!sentByReco.has(reco)) sentByReco.set(reco, new Set());
  const sent = sentByReco.get(reco);
  const items = visibleItems.filter((item) => !sent.has(item.position));
  if (items.length === 0) return;
  items.forEach((item) => sent.add(item.position));
  sendRecoLog("vimp", reco.tracking_token, items);
}
```

Your service decides whether an item is visible. On the web, you can use a method that detects when an element enters the viewport, such as `IntersectionObserver`.

### Click (`clk`)

When a user clicks a recommended item, send that one item. In a browser, the click also navigates to the item page, so use `keepalive` as in `sendRecoLog` above.

```javascript theme={null}
// Run in the recommended item's click handler.
sendRecoLog("clk", reco.tracking_token, [item]);
```

You can also send it from your service server. Do not send one click from both the client and the server.

### Conversion (`conv`)

When a user who clicked a recommended item completes a purchase, send `conv` with the clicked recommendation's `tracking_token` and the purchased item's `catalog_id` and `position`. The values from the click must be carried through the cart and checkout, so this is usually sent from the service server that confirms the purchase.

```bash theme={null}
curl -i -X POST "<A2_API_URL>/dmp/v0/log" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "reco_log",
    "action": "conv",
    "tracking_token": "<tracking_token of the clicked recommendation>",
    "event_items": ["catalog-234"],
    "event_position": [1],
    "timestamp_in_ms": 1760000000000
  }'
```

Which action counts as a conversion, how long after a click a purchase is still attributed, and how cancellations are handled all differ by customer. To measure conversions, agree on the method with your A2 contact first. Recommendation logs do not aggregate purchase amounts.

Sending purchase events through [User Activity Logs](https://docs.aiderx.io/development/en/user-events.md) does not record recommendation conversions. The two logs serve different purposes, so send both.

## User recommendation history

If you sent `user.id` in the recommendation request, the token carries that user, and the `event_items` of `vimp`, `clk`, and `conv` are added to the user's recommendation history. If the recommendation policy has user-history conditions, A2 uses this history to adjust later recommendations, for example by excluding items the user has already seen. `imp` is not added to the history.

Events of recommendations received without `user.id`, such as for signed-out users, are counted in performance metrics but not added to any user's history.

## Verify metrics

There is no screen for viewing recommendation performance metrics yet. Organize your service's records for the same ad unit and period, and compare them with your A2 contact.

| Metric | Service record to compare |
| - | - |
| Responses | With On Recommendation Response, the number of recommendation responses with items. With On Impression Event, the number of `imp` deliveries. |
| Impressions | The number of `vimp` deliveries. |
| Viewable impressions | The number of items sent in `vimp`. |
| Clicks | The number of items sent in `clk`. |
| Conversions | The number of items sent in `conv`. |

Recommendation performance is aggregated per bucket of the recommendation experiment set up by your A2 contact. Events of recommendations served without an experiment are reflected only in item metrics and user history.

There is no screen or API for checking the collection status of individual recommendation logs. Do not resend events to check them.

## Common issues

> [accordion] Responses exceed actual renders
>
> With On Recommendation Response, responses that were not shown are also counted. With On Impression Event, check that `imp` is not sent repeatedly for the same response.

> [accordion] Clicks or viewable impressions are not counted
>
> Check that `type` is `reco_log`, that `tracking_token` is unmodified, and that `event_position` contains the response `position`.

> [accordion] Performance by position does not match
>
> Check that you are not sending the reordered on-screen position in `event_position`, and that `event_items` and `event_position` are in the same order.

> [accordion] Conversions are not counted
>
> Check that the clicked recommendation's `tracking_token` and `position` reach the purchase step. A token from another recommendation response is not connected.

> [accordion] You cannot tell whether to resend after a timeout
>
> A timeout alone does not tell you whether the event was processed. Resending may double-count, so check with your A2 contact first.

If the problem continues, prepare the time, ad unit, event type, and the request and HTTP response with sensitive data removed, and contact your A2 representative.

## Next steps

Register the items to recommend in [Product Catalog](https://docs.aiderx.io/development/en/catalog.md), and send user behavior across your service through [User Activity Logs](https://docs.aiderx.io/development/en/user-events.md).


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