Tracking custom events

How it works

Most source 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 source

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

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 destinations automatically resolve anonymous activity to the “identified” user after you send an identify call.

In rare cases—like with Mixpanel—you’ll have to send an alias call to associate anonymous activity with the identified person. But even in these rare cases, you can still associate anonymous activity with a person after they make themselves known.

flowchart LR a(person
visits site)-->|generate
anonymousId|z subgraph z [anonymous activity] direction LR b(visit
a page) b-->|page|c(add item
to cart) c-->|track|d(person
logs in) end subgraph y [identified activity] direction LR e(person initiates
checkout)-->|track|f(person finishes
transaction) end z-->|anonymous activity
associated with identified person|y

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 destinations. 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 all of your destinations. You can always ignore data at your destination, but you can’t use data in a destination that you don’t send from the source!

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

{
  "userId": "AiUGstSDIg",
  "type": "track",
  "event": "Course Started",
  "properties": {
    "course_name": "Intro to Customer.io Data Pipelines",
    "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": "/docs/",
      "referrer": null,
      "search": null,
      "title": "Customer.io Docs",
      "url": "https://customer.io/docs",
      "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

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

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:

analytics.track("login", {
  username: "cool.person"
  session_started: 1683250025
  platform: "chrome"
  login_page: "https://fly.customer.io/pipelines/my-pipelines"
});
analytics.track("logout", {
  username: "cool.person"
  session_ended: 1683361625
  logout_from: "session_expred"
});

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 a number of our destinations that take ecommerce events. If you format your source events according to our ecommerce specification, 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:

analytics.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 destinations have purchase event actions

Destinations 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 destination expects. See the docs for the destination to make sure you’ve got the right information in your source calls!

Media started/ended

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.

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

Semantic events

Many of our default destination 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 destinations.

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 it’s easier to get up and running with your destinations.

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

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

Ecommerce events

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

We created an ecommerce specification to help you produce uniform source data, making it easy to set up destinations. Our destinations 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 destinations, 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.

analytics.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
})
Copied to clipboard!
  Contents
Is this page helpful?