# Tracking custom events

## How it works[](#how-it-works)

Most of our API methods have a defined purpose: the `identify` call identifies users; `page` calls track pageviews. But the `track` call lets you send custom events, so that you can track the activities that are meaningful to you. Track calls take a `name` representing the name of the event you want to track and a set of custom properties.

For example, when someone adds an item to their cart, you might send an `added_to_cart` event with properties representing the item that your customer added to their cart.

If you run an online class and you want to track progress, you might send a call when people begin a new module in the course or watch a video. The names of your events might be `module_started` and `video_started`; and the properties would contain information about the module that a person began or the video they watched respectively.

 Examples on this page are based on our JavaScript snippet

The same principles apply to all our server-side integrations, but the examples will look slightly different if you’re using Go, Python, or Node.js.

## Events can be anonymous[](#events-can-be-anonymous)

You can send `track` calls before or after you `identify` someone—when they sign up, login, provide their email, etc; the order of calls doesn’t matter. Most outbound integrations automatically resolve anonymous activity to the “identified” user after you send an `identify` call.

## The power of properties[](#the-power-of-properties)

Track calls take a custom dictionary of properties. Properties are simply nested JSON and can contain *any* data you want to pass along to your outgoing integrations. This includes nested objects, arrays, and arrays of objects.

When you set up events, you should send *all* the data that you think might be useful—even if you won’t use this data in Customer.io or *all* of your outgoing integrations. You can always ignore data at various destinations, but you can’t send data out of the system if you don’t send it to Customer.io first!

Here’s the complete, JSON representation of an event. See the `properties` object? That’s information you can use downstream.

```json
{
  "userId": "AiUGstSDIg",
  "type": "track",
  "event": "Course Started",
  "properties": {
    "course_name": "Intro to Customer.io",
    "courseId": "cdp101",
    "progress": 0,
    "modules": [
        {
            "moduleId": "cdp101-1",
            "moduleName": "track calls",
            "started": false
        },
        {
            "moduleId": "cdp101-2",
            "moduleName": "identifying people"
            "started": true
        }
    ]
  },
  "integrations": null,
  "messageId": "ajs-f8ca1e4de5024d9430b3928bd8ac6b96",
  "receivedAt": "2015-12-12T19:11:01.266Z",
  "sentAt": "2015-12-12T19:11:01.169Z",
  "timestamp": "2015-12-12T19:11:01.249Z",
  "version": 0,
  "context": {
    ...
    },
    "page": {
      "name": "string",
      "path": "/",
      "referrer": null,
      "search": null,
      "title": "Customer.io Docs",
      "url": "https://customer.io",
      "keywords": [
        "string"
      ]
    },
    "library": {
      "name": "analytics.js",
      "version": "2.11.1"
    }
  },
  "anonymousId": "23adfd82-aa0f-45a7-a756-24f2a7a4c895",
  "originalTimestamp": "2015-12-12T19:11:01.152Z"
}
```

## Example use cases[](#example-use-cases)

The following use cases are examples of the things you *might* send with `track` calls. You can copy these examples if they fit your use case, but you’ll get more out of your integration if you tailor calls to fit your needs!

### Logging in and logging out[](#logging-in-and-logging-out)

When someone logs in, or creates an account, you’ll send an `identify` call. But in these cases, you’ll *also* send a track call. Track calls on login and log out can help you track the length of sessions in your app, understand the times when your users are most active, and other information independent of `identify` calls!

Your log in and log out track events will look something like this:

 login

#### login[](#login)

```javascript
cioanalytics.track("login", {
  username: "cool.person"
  session_started: 1683250025
  platform: "chrome"
  login_page: "https://fly.customer.io/pipelines/my-pipelines"
});
```

 logout

#### logout[](#logout)

```javascript
cioanalytics.track("logout", {
  username: "cool.person"
  session_ended: 1683361625
  logout_from: "session_expred"
});
```

### Added to cart[](#added-to-cart)

If you run an online store, you probably want to keep track of the products that your audience is interested in, and the items they add to their cart for things like cart abandonment campaigns and to help you anticipate changes in your inventory.

 Format your events using our ecommerce specification

We’ve created default actions for our data-out integrations that take ecommerce events. If you format your events according to [our ecommerce specification](/integrations/api/cdp/ecommerce/), you’ll be able to take advantage of these defaults. In many cases you won’t even have to map your own events and properties!

So, when someone clicks **Add to cart**, you might send a call that looks like this:

```javascript
cioanalytics.track("Product Added", {
  product_id: "coolshoes-123"
  sku: "abc-123-xyz"
  category: "shoes"
  name: "Cool Shoes"
  brand: "A Shoe Brand"
  variant: "red"
  price: 139.99
  quantity: 1
  coupon: "NEWUSER20"
  position: 3
  url: "https://www.example.com/product/123"
  image_url: "https://www.example.com/product/123.jpg"
  cart_id: "usercart-789"
});
```

 Some integrations have *purchase* event actions

Data-out integrations that have dedicated events typically filter on the event `name`. You’ll want to make sure that you send the right event `name` and properties that the integration expects. See the docs for your specific integration to make sure you’ve got the right information in your `track` calls!

### Media started/ended[](#media-startedended)

If you run a media operation, you’re in education technology, or you deliver webinars, you might want to know when your audience plays videos (so you can track progress) and online lectures. These kinds of things help you better understand when people use your videos, whether or not they finish them, and other engagement needs—like play speed.

You might attach `track` calls to the buttons in a video player to capture play, pause/stop, and other things about media.

```javascript
cioanalytics.track("video_watched", {
  video_name: "Cool New Video"
  length: 1.56
  speed: 1.25
  finished: false
});
```

## Semantic events[](#semantic-events)

Many of our data-out integrations’ default actionsThe source event and data that triggers an API call to your destination. For example, an incoming `identify` event from your sources *adds or updates a person* in our Customer.io Journeys destination. are based on the `name` of the event you send. With these *semantic events*, we expect a certain set of properties that we use to map to multiple integrations.

While you can send any properties and events that you want, taking advantage of our pre-defined semantic events can save you time and effort, helping you take advantage of our default actions—so you don’t have to manually map data to these integrations.

We have a set of standard, semantic events for the following purposes:

*   Mobile
*   A/B Testing
*   Ecommerce
*   Email
*   Live Chat
*   Video

### Ecommerce events[](#ecommerce-events)

Ecommerce `track` events typically contain the same information across platforms—products, brands, orders, cart information, etc. However, each integration might map this information differently.

We created an [ecommerce specification](/integrations/api/cdp/ecommerce/) to help you produce uniform data, making it easy to set up integrations. Our data-out integrations that take ecommerce events have default actions that expect data conforming to our ecommerce specification. When you send data using our ecommerce specification, it maps right to your integrations, without having to map your own data structures.

You don’t have to use this spec. You’re welcome to send ecommerce events in any format you want. But if you send data that *does not* conform to our ecommerce specification, you’ll need to map actions yourself.

```javascript
cioanalytics.track('Product Viewed', {
  product_id: "coolshoes-123"
  sku: "abc-123-xyz"
  category: "shoes"
  name: "Cool Shoes"
  brand: "A Shoe Brand"
  variant: "red"
  price: 139.99
  quantity: 1
  coupon: "NEWUSER20"
  position: 3
  url: "https://www.example.com/product/123"
  image_url: "https://www.example.com/product/123.jpg"
  currency: "USD"
  value: 119.99
})
```