Subscribe to get a new lesson each week!

The Anatomy of a `.track()` Call

Maintaining a consistent naming convention is a great way to ensure your analytics data is clean and easy to use. But knowing how to send a .track() call can tremendously step up your analytics game—you’ll be able to create funnels and analyze cohorts, while still having the freedom to explore your data. Not only that, but the code footprint is smaller, so it’s easier to manage and maintain, especially if you’re using a tracking plan.

This week, we’ll show you that you can answer anything and keep your analytics scope manageable if you include the right data in your .track() call. We’ll also provide examples and reveal a little bit about what is going on beneath the hood.

Event-based Analytics

Almost all analytics and marketing automation tools today are event-based. Events are actions that are triggered by something your customer performs on your site or app. Examples including Account Created or Song Played. Every time this event occurs, a new record is created in the analytics database.

To record that action, most tools have a .track() call (it may not be called “track”—this is what Segment’s API uses—but there are equivalents). If you’re smart and consistent with what you include in these .track() calls, your analysis can be flexible and powerful.

What is a ‘.track()’ call?

A .track() call captures the most atomic piece of data in an analytics database. It represents one unique row; an action that a user performed on your site or app, with the contextual information like when, where, and (sometimes) how it happened, nested as properties. With an aggregate of these records, you can understand overall product usage, funnels, and trends. Or, you can trigger personalized messages to specific set of your users with your email tool.

Here is the anatomy of a .track() call in three different flavors: Segment, Mixpanel, and Google Analytics. Note we’re following the Object Action Framework that we laid out in the previous Academy lesson, with the property names in snake_case.

Segment (analytics.js)

analytics.track("Song Played", { // the event or action the user performed
  name: "What Do You Mean", // specifics of the event
  artist_name: "Justin Bieber"
  album: "Purpose",
  label: "Def Jam - School Boy",
  genre: "Dance Pop"
});

Segment analytics.js documentation.

Google Analytics (analytics.js)

ga('send', 'event', {
  eventAction: 'Song Played',
  eventCategory: 'All'
});

Google Analytics analytics.js documentation.

Mixpanel

window.mixpanel.track("Song Played", { // the event or action the user performed
  name: "What Do You Mean", // specifics of the event
  artist_name: "Justin Bieber"
  album: "Purpose",
  label: "Def Jam - School Boy",
  genre: "Dance Pop"
});

Mixpanel’s javascript documentation.

The .track() call captures more than just the event name. It includes the timestamp, the user who performed the action, and other contextual specifics that help you conduct your analysis later.

All .track() calls include the following: userId, event, properties, and timestamp:

  • userId: you may have noticed that userId was never explicitly sent in the .track() examples above. That’s because these calls were all sent using client-side Javascript libraries, where userId is automatically set and sent behind the scenes (we’ll dive into this more next week). What you should know is that the userId is a unique identifier of the user and that it’s important to tie events back to the user. This allows you to follow a single customer’s events over time for cohort and other useful analyses.
  • event: the event name. You can create trends and usage reports based on these names. This is why it’s important to stick to a consistent naming convention, so it’s easier to do analysis without having to second guess if the event is the right one. See our last lesson.
  • properties: this is a set of keys and values that provide more context around the event itself. For example, which song was played. These values are useful to provide additional dimensions upon which you can slice and dice your data. As such, it’s better to use them for specifics and keep the event names general.
  • sent_at (time stamp): again, this one wasn’t explicitly sent. However, all libraries will automatically record the time and send it. This is useful for looking at events over time or ordering events chronologically.

Though it may be confusing what pieces of data to send in each part of the .track() call, here is a peek at the underlying technology that informs what analyses is achievable.

How do they get stored?

Most analytics services will store each record as a row in a relational database (we won’t get too in the weeds, since the technical details can vary amongst companies). But this database allows the analytics tools to be able to parse your data based on your event type and any combination of its properties.

Relational databases are like spreadsheets—each row is a unique event and columns are property names. Note that since the properties can vary depending on the event, each event will have its own table. We’ll show how you can easily pivot and group this data in the analytics tools.

This is an example of the Song Played table:

here is a sample table of songs played

Given this “spreadsheet”, we can quickly count the total number of songs played, get the weekly count of songs played over time, or even count the number of songs played from a specific artist.

But how is the ability to group data across various column names useful in analytics tools?

In Mixpanel, we can group and count actions based on the properties we set in the .track() call (Mixpanel calls them “Events”) and contextual information their library automatically passes (Browser, Browser Version, etc.).

here is a sample mixpanel of songs played

This allows us to easily create charts to see usage trends over time. Moreover, Mixpanel allows you to do cohort and funnel analysis, where you have the flexibility to group events across properties and other “columns”. (More on Mixpanel here.)

Other tools offer similar flexibility. Here is how you can create elaborate customer segments in Customer.IO, a popular email tool:

here is a sample customer.io of songs played

Here we can create an email list of Justin Bieber fans. We can then send targeted emails about Justin Bieber to this list. (For more information on how to use Customer.IO, visit their help section! Here’s also a list of other email and marketing automation tools.)

These tools are able to pivot and group easily based on the event name, properties, userId, and other column names. As such, the key value pairs that are sent in properties are tremendously powerful: they are the dimensions that allow you to slice and dice data, create cohorts of your users, and analyze sub trends easily over time.

Examples of Tracking Do’s and Don’t’s

Here are some examples of Do’s and Don’ts with .track() calls.

Consolidate Events

DON’T use multiple specific event names.

analytics.track("Song Played - Formation by Beyoncé");

This means in your downstream analysis, you’d only be able to figure out how many times each song was played, which isn’t as useful as knowing that a song was played.

DO consolidate events to a single event name with multiple values in the properties.

analytics.track("Song Played", {
  name: "Formation",
  artist: "Beyoncé"
});

This way, you’d be able to see how many times a song is played. Moreover, you’d be able to slice the data of “Songs Played” by any of the properties—i.e. you can figure out how many times a Beyoncé song was played or how many times her “Formation” was played. More flexible analysis!

No Nested Properties

DON’T send “nested” properties:

analytics.track("Song Played", {
  name: "Formation",
  artist: "Beyoncé"
  user: {
    name: "Andy",
    email: "andy@segment.com",
    twitter: "andyjiang"
  }
});

DO send “flat” properties:

analytics.track("Song Played", {
  name: "Formation",
  artist: "Beyoncé",
  name: "Andy",
  email: "andy@segment.com",
  twitter: "andyjiang"
});

There are many tools that handle nested properties differently—some will flatten for you, others will keep the data hierarchy. Because this is treated inconsistently, it’s best to be intentional about how you send the properties from the get go. Send it flat so that you’ll know how every tool will treat the data!

Reducing Complexity

Part of tracking implementation is translating your business questions to building a tracking plan and figuring out exactly what to send in the .track() call. Understanding how properties are used in slicing and dicing your data downstream can inform your data collection strategy.

Many times, you can use fewer event names to answer the same thing, especially when you include relevant data in the properties. This way, you can simplify your implementation and still effectively learn about your customers.

Have any tips or tricks related sending analytics calls? Let us know on Twitter!

Next article

When to Track on the Client vs. Server

Start your free email course today!

Get lessons right in your inbox!