# Track web event

Send a web event beacon for ingestion.

```
POST https://api.croct.io/client/web/track
```

Tracks an event beacon for the current user. The payload is validated against the schema for its event type, enriched with server-side context, and published for processing.

## Example

Here is an example of how to track a `pageOpened` event:

**JavaScript**

```js
const response = await fetch('https://api.croct.io/client/web/track', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-App-Id': '<APP ID>',
    'X-Client-Id': '<CLIENT ID>',
  },
  body: JSON.stringify({
    originalTime: Date.now(),
    departureTime: Date.now(),
    context: {
      url: 'https://example.com/home',
      tabId: '123e4567-e89b-12d3-a456-426614174000',
      timeZone: 'America/New_York',
    },
    payload: {
      type: 'pageOpened',
      url: 'https://example.com/home',
      referrer: 'https://example.com/',
    },
  }),
});
```

**cURL**

```bash
curl -X POST 'https://api.croct.io/client/web/track' \
  -H 'Content-Type: application/json' \
  -H 'X-App-Id: <APP ID>' \
  -H 'X-Client-Id: <CLIENT ID>' \
  -d '{
    "originalTime": 1612137600000,
    "departureTime": 1612137600050,
    "context": {
      "url": "https://example.com/home",
      "tabId": "123e4567-e89b-12d3-a456-426614174000",
      "timeZone": "America/New_York"
    },
    "payload": {
      "type": "pageOpened",
      "url": "https://example.com/home",
      "referrer": "https://example.com/"
    }
  }'
```

## Request headers

This endpoint accepts the following HTTP headers:

- `Content-Type`: `string`

  Must be `application/json`.

- `X-App-Id`: `string`

  The public [application ID](/explanation/application) to use for client-side requests.

- `X-Client-Id`: `string` (optional)

  The ID of the client, in the form of a UUID.

  This must be a persistent identifier that uniquely identifies the browser or device across sessions.

  Either `X-Client-Id` or [`X-Token`](#x-token-prop) must be present.

- `X-Token`: `string` (optional)

  A base64-encoded [JSON Web Token (JWT)](https://jwt.io) that identifies the user.

  When the application enforces [signed tokens](/explanation/application/signed-tokens), the JWT must be signed using an [API key](/explanation/application/api-keys) with the **Issue user tokens** permission, or the request fails with an authorization error.

  Either `X-Client-Id` or [`X-Token`](#x-token-prop) must be present.

- `X-Client-Library`: `string` (optional)

  The SDK name and version, such as `Croct SDK JS v0.20.0`.

  Used for usage statistics and feature switching to preserve backward compatibility across SDK versions.

- `Origin`: `string` (optional)

  The origin of the request.

  Must match one of the application's [trusted origins](/explanation/application/trusted-origins). Browsers set this header automatically.

## Parameters

This endpoint accepts the following JSON body parameters:

- `originalTime`: `integer`

  The timestamp when the event was tracked, in milliseconds since the Unix epoch.

- `departureTime`: `integer`

  The timestamp when the beacon was sent by the client, in milliseconds since the Unix epoch.

- `context`: [`EventContext`](#event-context)

  The context of the client when the event was tracked.

  - `type`: `string`

    The type of the context. The possible values are:

    | Value    | Description                                                                                                   |
    | -------- | ------------------------------------------------------------------------------------------------------------- |
    | `web`    | A web-based client, such as a website or a mobile site. See [Web context](#web-context) for the full schema.  |
    | `server` | A backend service or any other server-side client. See [Server context](#server-context) for the full schema. |

- `payload`: [`Event`](/reference/event/overview#event-types)

  The event details, specific to the type of event.

  The `type` field selects one of the supported event types. See the [event types](/reference/event/overview#event-types) reference for the schema and tracking guidance for each type.

  Use the **Processed payload** tab on each event's reference for the full schema. The HTTP API expects the complete payload, including [processed properties](/reference/event/overview) that the SDK normally fills in for you.

### Event context

The fields available in the context object depend on the value of the `type` field.

#### Web context

When `type` is `web`, the context object accepts the following fields:

- `url`: `string`

  The URL of the page the client was on when the event was tracked.

- `tabId`: `string` (optional)

  The UUID that uniquely identifies the tab across the session.

- `timeZone`: `string` (optional)

  The user's time zone as an [IANA time zone ID](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones), such as `America/New_York`.

- `metadata`: `object` (optional)

  Additional information that may be useful to include as part of the event metadata.

  A common use case is to record the version of the application that generated the event for later analysis when exporting the events.

  The following restrictions apply:

  - Up to 5 entries
  - Keys must be strings up to 20 characters long, starting with a letter or underscore and optionally followed by letters, digits, or underscores
  - Values must be strings up to 300 characters long

#### Server context

When `type` is `server`, the context object accepts the following fields:

- `metadata`: `object` (optional)

  Additional information that may be useful to include as part of the event metadata.

  A common use case is to record the version of the application that generated the event for later analysis when exporting the events.

  The following restrictions apply:

  - Up to 5 entries
  - Keys must be strings up to 20 characters long, starting with a letter or underscore and optionally followed by letters, digits, or underscores
  - Values must be strings up to 300 characters long

## Response

The service can respond with either `204 No Content` or `202 Accepted` status code.

### 204 No Content

A successful request the returns an empty body.

Beacons that arrive too late to be processed are silently dropped to preserve the integrity of historical data, but still return `204` to the caller.

### 202 Accepted

The request is accepted but the service is suspended and the event is not tracked. Clients should treat this as a traffic control signal, not an error, and fall back to default behavior. The suspension reason is indicated by the `X-Suspension-Reason` header:

- `X-Suspension-Reason`: `string` (optional)

  The reason the API returned an empty response. The possible values are:

  | Value                                    | Description                                                                        |
  | ---------------------------------------- | ---------------------------------------------------------------------------------- |
  | `tracking_and_personalization_suspended` | The workspace has [suspended services](/explanation/workspace/service-suspension). |
  | `bot_personalization_blocked`            | The request was identified as coming from a bot and personalization was blocked.   |
