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

# Tracking Events — ABConvert API

> Public endpoints for recording visitor sessions, product views, add-to-cart, checkout, and order events — called automatically by the ABConvert script.

<Note>
  **Preview — this page is an early draft.** We're still verifying the API reference against the current endpoints. Fields, response shapes, and examples may change before this section is marked stable. Follow [PRO-1459](https://linear.app/abconvert/issue/PRO-1459) or ask in `#abconvert-dev` if you're integrating against this today.
</Note>

ABConvert's tracking endpoints collect the behavioral signals that power experiment analytics. The ABConvert tracking script and Web Pixel extension call these endpoints automatically for every store visitor. You only need to call them directly if you are building a custom integration or instrumenting a storefront that bypasses the standard script.

All tracking endpoints are public — they require no authentication and are accessible from browser JavaScript.

***

## How tracking works

When a visitor lands on your store, the ABConvert script:

1. Calls `GET /api/get-session` to generate a session ID.
2. Calls `GET /api/observe/session` to register the visitor against active experiments.
3. Calls `GET /api/observe` on product pages to record page views.
4. Posts to the unified `/api/track/event` endpoint (via Web Pixel) for add-to-cart, checkout, and order events.

The unified track endpoints (`/api/track/event` and `/api/track/assignment`) are the primary tracking path used by the Web Pixel. The legacy endpoints below are also supported for backwards compatibility.

***

## Generate a session ID

Returns a new UUID to use as the visitor's session identifier for the current browsing session.

```
GET /api/get-session
```

### Example request

```bash theme={null}
curl "https://app.abconvert.io/api/get-session"
```

### Response

```json theme={null}
{ "sessionId": "f47ac10b-58cc-4372-a567-0e02b2c3d479" }
```

***

## Get visitor country code

Returns the two-letter ISO country code for the current visitor, resolved from their IP address. Used to apply geographic targeting rules.

```
GET /api/public/get-country-code
```

### Example request

```bash theme={null}
curl "https://app.abconvert.io/api/public/get-country-code"
```

### Response

```json theme={null}
{ "countryCode": "US" }
```

***

## Track product page views

Records that a visitor viewed a specific product page under a specific experiment assignment.

```
GET /api/observe
```

### Query parameters

<ParamField query="shop" type="string" required>
  Your store's Shopify domain, e.g. `your-store.myshopify.com`.
</ParamField>

<ParamField query="productId" type="string" required>
  The Shopify product ID of the viewed product.
</ParamField>

<ParamField query="experimentId" type="string" required>
  The `_id` of the experiment the visitor is enrolled in.
</ParamField>

### Example request

```bash theme={null}
curl "https://app.abconvert.io/api/observe?shop=your-store.myshopify.com&productId=7654321098765&experimentId=64a1f2b3c4d5e6f7a8b9c0d1"
```

***

## Track visitor sessions

Records a visitor session event for an experiment. Called once per page load to maintain session-level attribution.

```
GET /api/observe/session
```

### Query parameters

<ParamField query="shop" type="string" required>
  Your store's Shopify domain.
</ParamField>

<ParamField query="sessionId" type="string" required>
  The session ID returned by `GET /api/get-session`.
</ParamField>

<ParamField query="experimentId" type="string" required>
  The `_id` of the experiment the visitor is enrolled in.
</ParamField>

### Example request

```bash theme={null}
curl "https://app.abconvert.io/api/observe/session?shop=your-store.myshopify.com&sessionId=f47ac10b-58cc-4372-a567-0e02b2c3d479&experimentId=64a1f2b3c4d5e6f7a8b9c0d1"
```

***

## Unified event tracking (Web Pixel)

The primary tracking endpoint used by the ABConvert Web Pixel extension. Records any behavioral event and writes it to BigQuery for analytics processing.

```
POST /api/track/event?shop={shopifyDomain}
```

### Query parameters

<ParamField query="shop" type="string" required>
  Your store's Shopify domain.
</ParamField>

### Request body

<ParamField body="sessionId" type="string" required>
  The current visitor's session ID.
</ParamField>

<ParamField body="visitorId" type="string" required>
  The current visitor's persistent ID.
</ParamField>

<ParamField body="eventType" type="string" required>
  The event type. Standard values include `page_viewed`, `product_viewed`, `product_added_to_cart`, `checkout_started`, `checkout_completed`. See the full list below.
</ParamField>

<ParamField body="source" type="string" required>
  The source system sending this event. One of `"script"`, `"webpixel"`, or `"webhook"`.
</ParamField>

<ParamField body="createdAt" type="string | number" required>
  Client-side timestamp. Accepts an ISO 8601 string or Unix milliseconds.
</ParamField>

<ParamField body="experimentIds" type="array" required>
  Array of experiment IDs the visitor is currently assigned to. Pass an empty array `[]` if the visitor has no active assignments.
</ParamField>

<ParamField body="pagePath" type="string">
  The current page path, e.g. `/products/blue-shirt`. Maximum 2000 characters.
</ParamField>

<ParamField body="payload" type="object">
  Event-specific data. Maximum 10KB. Common fields:

  <Expandable title="payload fields by event type">
    | Event type              | Fields                                      |
    | ----------------------- | ------------------------------------------- |
    | `product_viewed`        | `productIds`, `variantIds`, `pageType`      |
    | `product_added_to_cart` | `productIds`, `variantIds`, `quantity`      |
    | `checkout_started`      | `checkoutToken`, `productIds`, `variantIds` |
    | `checkout_completed`    | `checkoutToken`, `orderId`                  |
    | `page_viewed`           | `pageType`                                  |
  </Expandable>
</ParamField>

### Example request

```bash theme={null}
curl -X POST "https://app.abconvert.io/api/track/event?shop=your-store.myshopify.com" \
  -H "Content-Type: application/json" \
  -d '{
    "sessionId": "sess_abc123",
    "visitorId": "vis_xyz789",
    "eventType": "product_viewed",
    "source": "webpixel",
    "createdAt": "2024-01-15T10:30:00.000Z",
    "experimentIds": ["64a1f2b3c4d5e6f7a8b9c0d1"],
    "pagePath": "/products/blue-shirt",
    "payload": {
      "productIds": ["7654321098765"],
      "variantIds": ["43210987654321"],
      "pageType": "product"
    }
  }'
```

### Response

```json theme={null}
{ "accepted": true }
```

Returns `202 Accepted` on success. Use the fire-and-forget pattern — do not block on this response.

***

## Experiment assignment tracking

Records the moment a visitor is bucketed into a test group, along with a snapshot of their visitor context. Written once per visitor per experiment.

```
POST /api/track/assignment?shop={shopifyDomain}
```

### Request body

<ParamField body="sessionId" type="string" required>
  The current visitor's session ID.
</ParamField>

<ParamField body="visitorId" type="string" required>
  The current visitor's persistent ID.
</ParamField>

<ParamField body="experimentId" type="string" required>
  The experiment the visitor is being assigned to.
</ParamField>

<ParamField body="testGroup" type="number" required>
  The assigned group index. `0` = control, `1+` = variant, `-1` = excluded.
</ParamField>

<ParamField body="createdAt" type="string | number" required>
  Client-side timestamp of the assignment moment.
</ParamField>

<ParamField body="assignmentReason" type="string">
  Why this assignment was made. Values: `random_split`, `force_assign_group`, `force_assign_excluded`, `audience_targeting_excluded`, `namespace_excluded`, `traffic_allocation_excluded`.
</ParamField>

<ParamField body="country" type="string">
  Two-letter country code of the visitor.
</ParamField>

<ParamField body="device" type="string">
  Visitor device type: `"desktop"`, `"mobile"`, `"tablet"`, or `"bot"`.
</ParamField>

<ParamField body="visitorType" type="string">
  Whether this is a `"new"` or `"returning"` visitor.
</ParamField>

<ParamField body="utmSource" type="string">
  UTM source parameter captured from the landing URL.
</ParamField>

<ParamField body="utmMedium" type="string">
  UTM medium parameter.
</ParamField>

<ParamField body="utmCampaign" type="string">
  UTM campaign parameter.
</ParamField>

<ParamField body="gclid" type="string">
  Google click ID, if present.
</ParamField>

<ParamField body="fbclid" type="string">
  Facebook click ID, if present.
</ParamField>

### Example request

```bash theme={null}
curl -X POST "https://app.abconvert.io/api/track/assignment?shop=your-store.myshopify.com" \
  -H "Content-Type: application/json" \
  -d '{
    "sessionId": "sess_abc123",
    "visitorId": "vis_xyz789",
    "experimentId": "64a1f2b3c4d5e6f7a8b9c0d1",
    "testGroup": 1,
    "createdAt": "2024-01-15T10:30:00.000Z",
    "assignmentReason": "random_split",
    "country": "US",
    "device": "mobile",
    "visitorType": "new",
    "utmSource": "google",
    "utmMedium": "cpc"
  }'
```

### Response

```json theme={null}
{
  "success": true,
  "assignmentId": "vis_xyz789_64a1f2b3c4d5e6f7a8b9c0d1"
}
```

***

## Legacy tracking endpoints

These endpoints pre-date the unified tracking API and remain supported. The Web Pixel extension uses the unified `/api/track/event` endpoint instead.

<CodeGroup>
  ```bash Track add-to-cart theme={null}
  curl -X POST "https://app.abconvert.io/api/analytics/add-to-cart" \
    -H "Content-Type: application/json" \
    -d '{
      "shop": "your-store.myshopify.com",
      "experimentId": "64a1f2b3c4d5e6f7a8b9c0d1",
      "sessionId": "sess_abc123",
      "productId": "7654321098765",
      "testGroup": 1
    }'
  ```

  ```bash Track checkout theme={null}
  curl -X POST "https://app.abconvert.io/api/analytics/checkout" \
    -H "Content-Type: application/json" \
    -d '{
      "shop": "your-store.myshopify.com",
      "experimentId": "64a1f2b3c4d5e6f7a8b9c0d1",
      "sessionId": "sess_abc123",
      "testGroup": 1,
      "revenue": 49.99
    }'
  ```

  ```bash Track order theme={null}
  curl -X POST "https://app.abconvert.io/api/analytics/order" \
    -H "Content-Type: application/json" \
    -d '{
      "shop": "your-store.myshopify.com",
      "experimentId": "64a1f2b3c4d5e6f7a8b9c0d1",
      "orderId": "5012345678901",
      "testGroup": 1,
      "revenue": 49.99
    }'
  ```
</CodeGroup>

***

## GA4 impression metadata

Resolves the GA4 measurement ID and experiment metadata needed to send an `abconvert_experience_impression` event to Google Analytics 4. The ABConvert script calls this automatically when GA4 integration is enabled.

```
GET /api/ga4/metadata
```

### Query parameters

<ParamField query="experimentId" type="string" required>
  The experiment ID to resolve metadata for.
</ParamField>

<ParamField query="groupIndex" type="integer" required>
  The test group index the current visitor is assigned to. Must be a non-negative integer.
</ParamField>

### Example request

```bash theme={null}
curl "https://app.abconvert.io/api/ga4/metadata?experimentId=64a1f2b3c4d5e6f7a8b9c0d1&groupIndex=1"
```

### Response — found

```json theme={null}
{
  "found": true,
  "experimentId": "64a1f2b3c4d5e6f7a8b9c0d1",
  "experimentName": "Blue Shirt Price Test",
  "variantId": 1,
  "variantName": "Variant A",
  "ga4MeasurementId": "G-ABC12345"
}
```

### Response — not found or feature disabled

```json theme={null}
{
  "found": false,
  "ga4MeasurementId": ""
}
```

<Note>
  This endpoint is intentionally resilient — it returns an empty `found: false` response rather than a 500 error when metadata is unavailable. This prevents storefront script errors from affecting visitor experience.
</Note>

***

## Custom events

You can track custom storefront interactions and measure their impact in A/B test results using the Shopify analytics publish API:

```javascript theme={null}
window.Shopify.analytics.publish('abconvert:custom_event', {
  name: 'video_play',
});
```

The ABConvert Web Pixel picks up this event and forwards it to `/api/track/event` with `eventType: abconvert:custom_event:video_play`. Event names may be up to 77 characters and support structured naming with `:`, `/`, and `.` separators.

For the event to be tracked, the visitor must have an active experiment assignment. Events sent when `experimentIds` is empty are ignored by the Web Pixel subscriber.
