> ## 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.

# User Activity Logs

> Learn how to send product views, searches, and purchases to A2.

User activity logs record actions in your service, such as viewing products, searching, adding items to a cart, and making purchases. A2 uses this data to predict users' product interests and improve ad recommendations.

Send user behavior from across your service, beyond responses to ads recommended by A2. Using the same product ID in your catalog and activity logs connects each action to the product's information.

Implement activity logs in the following order.

**1. Choose events**

Identify the events that apply to your service and send as many relevant actions as you can collect.

**2. Build requests**

Include user, device, and product IDs, along with the event time.

**3. Check delivery**

Send events when they happen and review what you can verify about collection.

## Before you begin

* **API address:** The address of your deployed A2 environment. Sending activity logs does not require an access token.
* **User and device IDs:** Identifiers that consistently distinguish the user and device performing an action
* **Product IDs:** IDs registered in your [catalog](https://docs.aiderx.io/development/en/catalog.md)

> [!NOTE]
>
> Use the same `user_id` for the same user across events, and the same string ID for a product in your catalog and activity logs. Do not assign one shared ID to all guests or generate a new user ID for each event.

## Send a product view first

This example sends a view event for product `1001`. Replace `<UNIX_TIME_SECONDS>` with the event's Unix timestamp in seconds, and replace the user, device, and product IDs with real values.

```bash theme={null}
curl -i -X POST "<A2_API_URL>/dmp/v0/log/activity" \
  -H "Content-Type: application/json" \
  -d '{
    "schema": "activity.item_view",
    "timestamp": <UNIX_TIME_SECONDS>,
    "channel": "web",
    "user_id": "user-123",
    "device_id": "device-456",
    "catalogs": [
      { "id": "1001" }
    ]
  }'
```

HTTP `200` means the request received a response; it does not confirm collection of an individual event. See the event descriptions below for the type and fields that fit your service, then check your request using [Test events](#test-events).

## Supported events

Send as many events as apply to actions in your service. Select an event below to jump to its description and request example.

| Event | `schema` | Action |
| - | - | - |
| [Product view](#product-view-item_view) | `activity.item_view` | Views a product |
| [Product click](#product-click-item_click) | `activity.item_click` | Clicks a product |
| [Add to cart](#add-to-cart-add_cart) | `activity.add_cart` | Adds a product to the cart |
| [Page view](#page-view-page_view) | `activity.page_view` | Views a page in the service |
| [Search](#search-search) | `activity.search` | Runs a search with a query |
| [Purchase](#purchase-purchase) | `activity.purchase` | Completes a product purchase |
| [Waiting](#waiting-wait) | `activity.wait` | Registers to wait for a product |
| [Reservation](#reservation-resv) | `activity.resv` | Completes a product reservation |
| [Bookmark](#bookmark-bmrk) | `activity.bmrk` | Bookmarks a product |
| [Item impression](#item-impression-item_impression) | `activity.item_impression` | Shows products in a list not served by A2. |
| [Checkout](#checkout-checkout) | `activity.checkout` | Enters checkout before purchase completion. |
| [Purchase or reservation cancellation](#purchase-or-reservation-cancellation-cancel) | `activity.cancel` | Cancels all or part of a purchase or reservation, including refunds. |

## Common fields

Build each request by adding the event-specific fields to the common fields below.

| Field | Requirement | Description |
| - | - | - |
| `schema` String | Required | Event type. For example, `"activity.item_view"`. |
| `timestamp` Integer | Required | Unix time when the event occurred, in **seconds**. In JavaScript, use `Math.floor(Date.now() / 1000)` to get the current time. |
| `channel` String | Required | Channel where the action occurred. For example, `"web"` or `"app"`. |
| `user_id` String | Required | ID of the user performing the action. Keep it consistent to connect the user's actions. |
| `device_id` String | Required | ID of the device where the action occurred. For server-side delivery, still send the user's device ID. |
| `page_id` String | Optional | Value identifying the page where the action occurred. |
| `id` String | Optional | Event ID assigned by your service. Sending it does not automatically deduplicate requests. |
| `device` Object | Optional | Additional device information. See [Record activity logs](https://docs.aiderx.io/en/0.5.0/decision/activity-log/record-activity-log.md) in the API Reference for its fields. |

## Event specifications

Send only product IDs in `catalogs`; register names, images, and other product details through the Catalog API.

> [!NOTE]
>
> When one event contains multiple products in `catalogs`, DMP learning currently uses only the first product, `catalogs[0].id`. Do not assume all products in the array contribute to learning.
>
> Replace example user, device, and product IDs and `timestamp` with real values. Event times are integers in seconds.

### Product view `item_view`

Send this event when a user views a product.

| Field | Requirement | Description |
| - | - | - |
| `catalogs` Array of objects | Required | Products the user viewed. |
| `catalogs[].id` String | Required | Product ID registered in the catalog. |

```json theme={null}
{
  "schema": "activity.item_view",
  "timestamp": 1793836800,
  "channel": "web",
  "user_id": "user-123",
  "device_id": "device-456",
  "catalogs": [
    {
      "id": "1001"
    }
  ]
}
```

### Product click `item_click`

Send this event when a user clicks a product.

| Field | Requirement | Description |
| - | - | - |
| `catalogs` Array of objects | Required | Products the user clicked. |
| `catalogs[].id` String | Required | Product ID registered in the catalog. |
| `catalogs[].position` Non-negative integer | Optional | Zero-based position of the clicked product in a list. |

```json theme={null}
{
  "schema": "activity.item_click",
  "timestamp": 1793836800,
  "channel": "web",
  "user_id": "user-123",
  "device_id": "device-456",
  "catalogs": [
    {
      "id": "1001"
    }
  ]
}
```

### Add to cart `add_cart`

Send this event when a product is added to the cart.

| Field | Requirement | Description |
| - | - | - |
| `catalogs` Array of objects | Required | Products added to the cart. |
| `catalogs[].id` String | Required | Product ID registered in the catalog. |

```json theme={null}
{
  "schema": "activity.add_cart",
  "timestamp": 1793836800,
  "channel": "web",
  "user_id": "user-123",
  "device_id": "device-456",
  "catalogs": [
    {
      "id": "1001"
    }
  ]
}
```

### Page view `page_view`

Send this event when a user views a page. You can identify the page with the common `page_id` field.

| Field | Requirement | Description |
| - | - | - |
| `catalogs` Array of objects | Required | Products associated with the page. |
| `catalogs[].id` String | Required | Product ID registered in the catalog. |

```json theme={null}
{
  "schema": "activity.page_view",
  "timestamp": 1793836800,
  "channel": "web",
  "user_id": "user-123",
  "device_id": "device-456",
  "page_id": "product-list",
  "catalogs": [
    {
      "id": "1001"
    }
  ]
}
```

### Search `search`

Send this event when a user runs a search. Send the query instead of a product list.

| Field | Requirement | Description |
| - | - | - |
| `query` String | Required | The query entered by the user. |

```json theme={null}
{
  "schema": "activity.search",
  "timestamp": 1793836800,
  "channel": "web",
  "user_id": "user-123",
  "device_id": "device-456",
  "query": "running shoes"
}
```

### Purchase `purchase`

Send this event when a purchase is completed. Include the purchased products, amount, and currency.

| Field | Requirement | Description |
| - | - | - |
| `catalogs` Array of objects | Required | Products purchased. |
| `catalogs[].id` String | Required | Product ID registered in the catalog. |
| `revenue` Object | Required | Contains the amount and currency. |
| `revenue.revenue` Number | Required | Purchase amount. |
| `revenue.currency` String | Required | Currency code for the amount. For example, `"KRW"` or `"USD"`. |
| `transaction_id` String | Optional | Order ID that links checkout and cancellation to this purchase. |

```json theme={null}
{
  "schema": "activity.purchase",
  "timestamp": 1793836800,
  "channel": "web",
  "user_id": "user-123",
  "device_id": "device-456",
  "catalogs": [
    {
      "id": "1001"
    }
  ],
  "revenue": {
    "revenue": 89000,
    "currency": "KRW"
  },
  "transaction_id": "order-123"
}
```

### Waiting `wait`

Send this event when a user registers through your service's waiting feature.

| Field | Requirement | Description |
| - | - | - |
| `catalogs` Array of objects | Required | Products the user registered to wait for. |
| `catalogs[].id` String | Required | Product ID registered in the catalog. |

```json theme={null}
{
  "schema": "activity.wait",
  "timestamp": 1793836800,
  "channel": "web",
  "user_id": "user-123",
  "device_id": "device-456",
  "catalogs": [
    {
      "id": "1001"
    }
  ]
}
```

### Reservation `resv`

Send this event when a reservation is completed. Include the reserved products, amount, and currency.

| Field | Requirement | Description |
| - | - | - |
| `catalogs` Array of objects | Required | Products reserved. |
| `catalogs[].id` String | Required | Product ID registered in the catalog. |
| `revenue` Object | Required | Contains the amount and currency. |
| `revenue.revenue` Number | Required | Reservation amount. |
| `revenue.currency` String | Required | Currency code for the amount. For example, `"KRW"` or `"USD"`. |
| `transaction_id` String | Optional | Reservation ID for linking a later cancellation. |

```json theme={null}
{
  "schema": "activity.resv",
  "timestamp": 1793836800,
  "channel": "web",
  "user_id": "user-123",
  "device_id": "device-456",
  "catalogs": [
    {
      "id": "1001"
    }
  ],
  "revenue": {
    "revenue": 89000,
    "currency": "KRW"
  },
  "transaction_id": "reservation-123"
}
```

### Bookmark `bmrk`

Send this event when a user bookmarks a product.

| Field | Requirement | Description |
| - | - | - |
| `catalogs` Array of objects | Required | Products bookmarked. |
| `catalogs[].id` String | Required | Product ID registered in the catalog. |

```json theme={null}
{
  "schema": "activity.bmrk",
  "timestamp": 1793836800,
  "channel": "web",
  "user_id": "user-123",
  "device_id": "device-456",
  "catalogs": [
    {
      "id": "1001"
    }
  ]
}
```

### Item impression `item_impression`

Send this when products appear in a service list that was not served by A2. Send impressions of A2 recommendations separately as `reco_log`. `catalogs` with product `id` values is required; the zero-based list `position` is optional.

```json theme={null}
{
  "schema": "activity.item_impression",
  "timestamp": 1793836800,
  "channel": "web",
  "user_id": "user-123",
  "device_id": "device-456",
  "catalogs": [{ "id": "1001", "position": 0 }, { "id": "1002", "position": 1 }]
}
```

### Checkout `checkout`

Send this when a user enters checkout before completing a purchase. `catalogs` with product `id` values is required. The `transaction_id` for linking a later purchase and `revenue` with the anticipated amount and currency are optional.

```json theme={null}
{
  "schema": "activity.checkout",
  "timestamp": 1793836800,
  "channel": "web",
  "user_id": "user-123",
  "device_id": "device-456",
  "catalogs": [{ "id": "1001" }],
  "transaction_id": "order-123",
  "revenue": { "revenue": 89000, "currency": "KRW" }
}
```

### Purchase or reservation cancellation `cancel`

Send this when a full or partial cancellation or refund of a purchase or reservation is confirmed. The original purchase or reservation's `transaction_id` is required. `catalogs` for affected products and `revenue` with the cancelled or refunded amount as a positive number are optional. To connect the events, send the same `transaction_id` in the original `purchase` or `resv` event.

```json theme={null}
{
  "schema": "activity.cancel",
  "timestamp": 1793836800,
  "channel": "web",
  "user_id": "user-123",
  "device_id": "device-456",
  "transaction_id": "order-123",
  "catalogs": [{ "id": "1001" }],
  "revenue": { "revenue": 89000, "currency": "KRW" }
}
```

## Connect product activity and ad responses

For a user viewing and purchasing product `1001`, distinguish these records.

| Action in your service | Data to send |
| - | - |
| View the product. | Send `1001` in `catalogs[].id` of `activity.item_view`, regardless of whether the user interacted with an A2 ad. |
| Complete the purchase. | Send the product ID, amount, and currency in `activity.purchase`, such as `89000` and `KRW` in the purchase example above. |
| Click an A2 ad. | Send a separate `clk` with the ad's `ext.ad_log`. If you also collect product click activity, implement `activity.item_click` separately. |
| Record the purchase as an A2 ad outcome. | Once your service determines which ad receives credit, send a separate `conv` with its retained `ad_log`. A purchase activity log alone does not create an ad conversion. |

Use a consistent value for the same user in ad request `user.id` and activity log `user_id`. Also account for DMP learning using only the first product in a multi-product purchase. See [Ad Event Tracking](https://docs.aiderx.io/development/en/ad-events-and-logs.md) for ad event delivery.

## Send events through the API

Send events using the [Record activity logs API](https://docs.aiderx.io/en/0.5.0/decision/activity-log/record-activity-log.md). As in the product-view `curl` example above, put the JSON body directly in `-d '...'`.

**1. Choose the event body**

Select the JSON example for the event you are implementing. Check its `schema` and event-specific fields, then replace the user, device, and product IDs and the event time with real values.

**2. Send the event**

Replace the JSON inside `-d '...'` in the earlier `curl` example with the selected event body, and use your API address for `<A2_API_URL>`. HTTP `200` does not guarantee event validity or completed collection and processing, so review the request using the testing section below.

**3. Connect delivery to actions in your service**

Build and send a request when the actual product view, search, purchase, or other action occurs.

You can send from the web or app, or through your server. Preserve consistent user and product IDs and the actual event time across delivery routes, and avoid sending the same action from both routes.

Implement purchase activity logs and ad conversion tracking separately. See [Ad Event Tracking](https://docs.aiderx.io/development/en/ad-events-and-logs.md) to record a conversion as an ad outcome.

## Test events

Perform an action once in your service and inspect the corresponding request.

| Check | How to verify |
| - | - |
| Trigger | Confirm that the intended product view, search, purchase, or other action sends a request. |
| Delivery count | Confirm that one action does not send the same request repeatedly. |
| Event type | Check that `schema` exactly matches a value in the supported-events table. |
| Required fields | Check common fields and the placement of `catalogs`, `query`, and `revenue` for the event type. |
| Product ID | Compare `catalogs[].id` with the ID stored in your catalog as a string. |
| User and device IDs | Confirm that IDs for the same user and device are preserved across delivery routes. |
| Event time | Check that `timestamp` is the actual event time as an integer in seconds. |
| HTTP response | Record the response status. Do not treat `200` alone as confirmation of collection. |

A2 currently provides no screen or API for looking up the collection status of an individual activity log. The checks above verify delivery from your service, but cannot independently confirm collection in A2. If you need collection confirmation, provide the test time, `schema`, request body with sensitive information removed, and HTTP response to your A2 contact.

## Next steps

Check catalog, user activity log, and ad tracking delivery in [Verification and Troubleshooting](https://docs.aiderx.io/development/en/integration-verification-and-troubleshooting.md).

## Common issues

> [accordion] 200 returned, but collection is unclear
>
> Separate HTTP success from completed collection. Review request fields and types, then contact support with the test information above.

> [accordion] An action is connected to the wrong product
>
> Check for lost leading zeros during numeric ID conversion, or IDs taken from a different system.

> [accordion] One user's actions are split
>
> Check whether each request generates a new `user_id`, or your server, web, and app use different values.

> [accordion] Duplicate requests
>
> Check duplicate handlers, client/server double delivery, and retries. An identical `id` does not guarantee deduplication.

> [accordion] Request failure or timeout
>
> Check the address, request body, and response status and body. Collection after a timeout is also unknown, so consider duplicate delivery before resending.


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