# Intents and events

> Send the intent your bot matched with each message, mark messages it didn't understand, and track events such as clicks, shares and revenue.

Intents and events are optional, advanced parts of the [universal API](/api/tracker). Intents describe what a message meant to your bot. Events record things that happened in a conversation that aren't messages: a link click, a share, a purchase.

## Intents

With intents you can roll up similar messages and look at them together: every message that asked to track an order, every answer the bot gave about the weather.

### The intent object

| Field | Type | Required | Description |
|---|---|---|---|
| `name` | string | Yes | Name of the intent, for example `WEATHER_QUERY` |
| `inputs` | array of objects | No | Inputs (slots or entities) captured with the intent |
| `inputs[].name` | string | Yes, per input | Input name, for example `city` |
| `inputs[].value` | string | Yes, per input | Input value, for example `San Francisco` |
| `confidence` | number | No | From 0.0 (completely uncertain) to 1.0 (completely certain) |

Intents work on both incoming and outgoing messages. Put the `intent` object at the root of the JSON you send for the message, next to `text`.

### Add an intent to an incoming message

Take the customer's message *"What is the weather in San Francisco?"*

1. Start from the message as you would send it anyway:

   ```json
   {
     "text": "What is the weather in San Francisco?",
     "userId": "user-123123",
     "incoming": true,
     "sessionId": "chat-234",
     "conversationId": "chat-234",
     "dimensionlabs_timestamp": 1703240320000,
     "platformJson": { "channel": "webchat" }
   }
   ```

2. Define the intent. This message maps to the `WEATHER_QUERY` intent, with the `city` entity `San Francisco`:

   ```json
   {
     "name": "WEATHER_QUERY",
     "inputs": [{ "name": "city", "value": "San Francisco" }]
   }
   ```

3. Add it to the message:

   ```json
   {
     "text": "What is the weather in San Francisco?",
     "userId": "user-123123",
     "incoming": true,
     "sessionId": "chat-234",
     "conversationId": "chat-234",
     "dimensionlabs_timestamp": 1703240320000,
     "platformJson": { "channel": "webchat" },
     "intent": {
       "name": "WEATHER_QUERY",
       "inputs": [{ "name": "city", "value": "San Francisco" }],
       "confidence": 0.9766
     }
   }
   ```

4. Post it to the tracker with `type=incoming` and the header `Content-Type: application/json`:

   ```bash
   curl -X POST -H "Content-Type: application/json" \
     -d '{"text":"What is the weather in San Francisco?","userId":"user-123123","incoming":true,"sessionId":"chat-234","conversationId":"chat-234","dimensionlabs_timestamp":1703240320000,"platformJson":{"channel":"webchat"},"intent":{"name":"WEATHER_QUERY","inputs":[{"name":"city","value":"San Francisco"}],"confidence":0.9766}}' \
     "https://tracker.dimensionlabs.io/track?platform=universal&v=11.1.0-rest&type=incoming&apiKey=$DL_API_KEY"
   ```

Use a current timestamp when you try this on `/track`, or send it to `/trackhistorical`. See [Endpoints](/api/tracker#endpoints).

### Add an intent to an outgoing message

The bot answers *"The weather is 68 degrees and sunny."* That maps to the `WEATHER_RESPONSE` intent, with the `forecast` entity `68 and sunny`.

```json
{
  "text": "The weather is 68 degrees and sunny.",
  "userId": "user-123123",
  "incoming": false,
  "sessionId": "chat-234",
  "conversationId": "chat-234",
  "dimensionlabs_timestamp": 1703240325000,
  "platformJson": { "channel": "webchat" },
  "intent": {
    "name": "WEATHER_RESPONSE",
    "inputs": [{ "name": "forecast", "value": "68 and sunny" }]
  }
}
```

The `userId` is still the end user's id, not the bot's. Post it with `type=outgoing`:

```bash
curl -X POST -H "Content-Type: application/json" \
  -d '{"text":"The weather is 68 degrees and sunny.","userId":"user-123123","incoming":false,"sessionId":"chat-234","conversationId":"chat-234","dimensionlabs_timestamp":1703240325000,"platformJson":{"channel":"webchat"},"intent":{"name":"WEATHER_RESPONSE","inputs":[{"name":"forecast","value":"68 and sunny"}]}}' \
  "https://tracker.dimensionlabs.io/track?platform=universal&v=11.1.0-rest&type=outgoing&apiKey=$DL_API_KEY"
```

### Naming intents

- Pair a request intent with its response: `TRACK_ORDER` and `TRACK_ORDER_RESPONSE`, `REQUEST_HUMAN` and `REQUEST_HUMAN_RESPONSE`. It makes it easy to see what the bot did after each request.
- Keep names stable. A renamed intent splits one group into two.
- Field names such as `intent` and `name` are case-sensitive. Intent names can use any case: `TRACK_ORDER` is fine, but `TRACK_ORDER` and `track_order` count as two intents.

### The NotHandled intent

It matters to know when a user says something your bot doesn't understand. For every incoming message your bot could not handle, set the intent name to `NotHandled`:

```js
const message = {
  text: "Hi, this is a confusing message for the bot.",
  userId: "user-123123",
  incoming: true,
  sessionId: "chat-234",
  conversationId: "chat-234",
  dimensionlabs_timestamp: 1703240330000, // the time the customer wrote it, from your bot's logs
  intent: { name: "NotHandled" },
};
```

Use exactly `NotHandled`, with that capitalization, so all of these messages group together. You can then ask the agent about them, for example *"What were the most common things customers asked that the bot marked NotHandled last month?"*

:::note
Older docs tied `NotHandled` to a "Not Handled report" in a product that has since been retired. The intent name is still worth sending: it is kept with the message like any other intent.
:::

## Events

Events record things that happen in a conversation that aren't messages, such as:

- clicks on external links
- social shares
- revenue
- page launches
- referrals
- anything else you want to count

### The event object

| Field | Type | Required | Description |
|---|---|---|---|
| `name` | string | Yes | Your name for the event, for example `boughtSandwich` |
| `type` | string | Yes | One of `customEvent`, `revenueEvent`, `shareEvent`, `pageLaunchEvent`, `referralEvent` |
| `userId` | string | Yes | The user the event belongs to, the same id you send on their messages |
| `conversationId` | string | No | Ties the event to a conversation |

Each type takes its own extra fields:

| Type | Field | Type | Required | Description |
|---|---|---|---|---|
| `customEvent` | `extraInfo` | object | No | Anything you want to record with the event |
| `revenueEvent` | `amount` | number | Yes | The amount |
| | `referenceNumber` | string | No | An order or transaction number |
| | `metadata` | object | No | Product name, SKU and so on |
| `pageLaunchEvent` | `extraInfo` | object | No | For example the page's `url` |
| `shareEvent` | `sharedMessage` | object | No | What was shared, for example `{ "text": "..." }` |
| `referralEvent` | `ref` | string | No | The referral tag |
| | `source` | string | No | The referral source, for example `ADS` or `WEB` |
| | `ad_id` | string | No | An id for the ad |
| | `referer_uri` | string | No | The URI that sent the referral |

### Send an event

Post events to the real-time tracker as they happen, with `platform=universal`, `type=event` in the URL and the header `Content-Type: application/json`:

```
https://tracker.dimensionlabs.io/track?platform=universal&v=11.1.0-rest&type=event&apiKey=YOUR_API_KEY
```

The `sendToDimensionLabs` helper sends messages only (it sets `type` from `incoming`), so post events with `curl`, as below, or your own `fetch` call. Send a few events to a test source first, then ask the agent about them to see how they come through before you rely on them.

### Custom event

```json
{
  "name": "trackMeEvent",
  "type": "customEvent",
  "userId": "967295313370594",
  "extraInfo": {
    "start": 1500504070512,
    "difference": 374,
    "end": 1500504070886
  }
}
```

```bash
curl -X POST -H "Content-Type: application/json" \
  -d '{"name":"trackMeEvent","type":"customEvent","userId":"967295313370594","extraInfo":{"start":1500504070512,"difference":374,"end":1500504070886}}' \
  "https://tracker.dimensionlabs.io/track?platform=universal&v=11.1.0-rest&type=event&apiKey=$DL_API_KEY"
```

### Revenue event

```json
{
  "name": "boughtSandwich",
  "type": "revenueEvent",
  "userId": "967295313370594",
  "amount": 17.45,
  "metadata": {
    "productName": "Ham Sandwich",
    "sku": "abc123123"
  }
}
```

```bash
curl -X POST -H "Content-Type: application/json" \
  -d '{"name":"boughtSandwich","type":"revenueEvent","userId":"967295313370594","amount":17.45,"metadata":{"productName":"Ham Sandwich","sku":"abc123123"}}' \
  "https://tracker.dimensionlabs.io/track?platform=universal&v=11.1.0-rest&type=event&apiKey=$DL_API_KEY"
```

For revenue at scale (orders, renewals, refunds), a [business data](/data/business-data-format) file or table is usually the better route: the agent [joins it to conversations](/data/join-business-data) on a shared id.

### Page launch event

```json
{
  "name": "Launched Detail Page",
  "type": "pageLaunchEvent",
  "userId": "967295313370594",
  "extraInfo": {
    "url": "https://www.dimensionlabs.io/"
  }
}
```

```bash
curl -X POST -H "Content-Type: application/json" \
  -d '{"name":"Launched Detail Page","type":"pageLaunchEvent","userId":"967295313370594","extraInfo":{"url":"https://www.dimensionlabs.io/"}}' \
  "https://tracker.dimensionlabs.io/track?platform=universal&v=11.1.0-rest&type=event&apiKey=$DL_API_KEY"
```

### Share event

```json
{
  "name": "sharedLink",
  "type": "shareEvent",
  "userId": "967295313370594",
  "sharedMessage": {
    "text": "come check out this bot"
  }
}
```

```bash
curl -X POST -H "Content-Type: application/json" \
  -d '{"name":"sharedLink","type":"shareEvent","userId":"967295313370594","sharedMessage":{"text":"come check out this bot"}}' \
  "https://tracker.dimensionlabs.io/track?platform=universal&v=11.1.0-rest&type=event&apiKey=$DL_API_KEY"
```

### Referral event

```json
{
  "name": "adReferral",
  "type": "referralEvent",
  "userId": "967295313370594",
  "ref": "spring-promo",
  "source": "ADS",
  "ad_id": "ad-0042",
  "referer_uri": "https://example.com/landing"
}
```

```bash
curl -X POST -H "Content-Type: application/json" \
  -d '{"name":"adReferral","type":"referralEvent","userId":"967295313370594","ref":"spring-promo","source":"ADS","ad_id":"ad-0042","referer_uri":"https://example.com/landing"}' \
  "https://tracker.dimensionlabs.io/track?platform=universal&v=11.1.0-rest&type=event&apiKey=$DL_API_KEY"
```

As with every event type, `name` is required; the referral fields are optional.
