Collecting data with Trackers and Webhooks

  1. Home
  2. Docs
  3. Collecting data with Trackers and Webhooks
  4. Trackers – collecting data from your own applications
  5. C++ Tracker
  6. Tracking specific events

Tracking specific events

Snowplow has been built to enable you to track a wide range of events that occur when users interact with your apps.

We provide several built-in event classes to help you track different kinds of events. When instantiated, their objects can be passed to the tracker.track() methods to send events to the Snowplow collector. The event classes range from single purpose ones, such as ScreenViewEvent, to the more complex but flexible SelfDescribingEvent, which can be used to track any kind of user behaviour. We strongly recommend using SelfDescribingEvent for your tracking, as it allows you to design custom event types to match your business requirements. This post on our blog, “Re-thinking the structure of event data” might be informative here.

The tracker provides the following event classes for tracking events out of the box:

StructuredEventTracks a Snowplow custom structured event
SelfDescribingEventTracks a Snowplow custom unstructured event
ScreenViewEventTracks the user viewing a screen within the application
TimingEventTracks a timing event

Snowplow events are all processed into the same format, regardless of the event type (and regardless of the tracker language used). Read about the different properties and fields of events in the Snowplow Tracker Protocol.

Custom event context

Event context is an incredibly powerful aspect of Snowplow tracking, which allows you to create very rich data. It is based on the same self-describing JSON schemas as the self-describing events. Using event context, you can add any details you like to your events, as long as you can describe them in a self-describing JSON schema.

Each schema will describe a single “entity”. All of an event’s entities together form the event context. There is no limit to how many entities can be attached to one event.

Note that context can be added to any event type, not just self-describing events. This means that even a simple event type like a screen view can hold complex and extensive information – reducing the chances of data loss and the amount of modelling (JOINs etc.) needed in modelling, while increasing the value of each event, and the sophistication of the possible use cases.

The entities you provide are validated against their schemas as the event is processed (during the enrich phase). If there is a mistake or mismatch, the event is processed as a Bad Event.

Once defined, an entity can be attached to any kind of event. This is also an important point; it means your tracking is as DRY as possible. Using the same “user” or “image” or “search result” (etc.) entities throughout your tracking reduces error, and again makes the data easier to model.

Each tracking type provides a set_context() method which accepts a vector of context entities:

vector<SelfDescribingJson> context;
Code language: C++ (cpp)

If a visitor arrives on a page advertising a movie, the dictionary for a single custom context entity in the list might look like this:

vector<SelfDescribingJson> context; SelfDescribingJson sdj( "iglu:com.acme_company/movie_poster/jsonschema/2-1-1", "{\"movie_name\":\"Solaris\",\"poster_country\":\"JP\"}"_json ); context.push_back(sdj);
Code language: C++ (cpp)

This is how to fire a structured event with the above custom context entity:

StructuredEvent se("category", "action"); se.set_context(context); Snowplow::get_default_tracker()->track(se);
Code language: C++ (cpp)

Note that even though there is only one custom context entity attached to the event, it still needs to be placed in a list.

INFO: We use the excellent json library from Github community member Niels (nlohmann) for all JSON parsing. For more information on using this library please visit the Technical information on Github.

Optional true-timestamp argument

Each event class supports an optional true-timestamp argument; this allows you to provide the true-timestamp attached to this event to help with the timing of events in multiple timezones. The timestamp should be in milliseconds since the Unix epoch.

Here is an example tracking a structured event and supplying the optional true-timestamp argument:

StructuredEvent se("category", "action"); // As it is optional you will need to pass the address for this value unsigned long long true_tstamp = "1368725287000"; se.set_true_timestamp(&true_tstamp); Snowplow::get_default_tracker()->track(se);
Code language: C++ (cpp)

Track SelfDescribing/Unstructured events with “SelfDescribingEvent”

Use the SelfDescribingEvent type to track a custom event which consists of a name and an unstructured set of properties. This is useful when:

  • You want to track event types which are proprietary/specific to your business (i.e. not already part of Snowplow), or
  • You want to track events which have unpredictable or frequently changing properties

A self-describing JSON has two keys, schema and data. The schema value should point to a valid self-describing JSON schema. They are called self-describing because the schema will specify the fields allowed in the data value. Read more about how schemas are used with Snowplow here.

After events have been collected by the event collector, they are validated to ensure that the properties match the self-describing JSONs. Mistakes (e.g. extra fields, or incorrect types) will result in events being processed as Bad Events. This means that only high-quality, valid events arrive in your data storage or real-time stream.

Your schemas must be accessible to your pipeline to allow this validation. We provide Iglu for schema management. If you are a paid Snowplow customer, you can manage your schemas through your console. Check out our Ruby tracker Rails example to see how we included schemas in the Snowplow Micro testing pipeline in that app.

SelfDescribingEvent provides the following properties:

eventThe properties of the eventYesSelfDescribingJson


// Create a JSON containing your data json data = "{\"level\":5,\"saveId\":\"ju302\",\"hardMode\":true}"_json; // Create a new SelfDescribingJson SelfDescribingJson sdj("iglu:com.example_company/save-game/jsonschema/1-0-2", data); SelfDescribingEvent sde(sdj); Snowplow::get_default_tracker()->track(sde);
Code language: C++ (cpp)

For more on JSON schema, refer to this page.

Track screen views with “ScreenViewEvent”

Use the ScreenViewEvent type to track a user viewing a screen (or equivalent) within your app. This is the page view equivalent for apps that are not webpages.

nameHuman-readable name for this screenNo*string
idUnique identifier for this screenNo*string

Although name and id are not individually required, at least one must be provided or the event will fail validation and subsequently throw an exception.

The event uses the following Iglu schema: iglu:com.snowplowanalytics.snowplow/screen_view/jsonschema/1-0-0.


string name = "Screen ID - 5asd56"; ScreenViewEvent sve; = &name; Snowplow::get_default_tracker()->track(sve);
Code language: C++ (cpp)

Track structured events with StructuredEvent

Use the StructuredEvent type to track a custom event happening in your app which fits the Google Analytics-style structure of having up to five fields (with only the first two required). This method provides a halfway-house between tracking fully user-defined self-describing events and out-of-the box predefined events. This event type can be used to track many types of user activity, as it is somewhat customizable.

As these fields are fairly arbitrary, we recommend following the advice in this table how to define structured events. It’s important to be consistent throughout the business about how each field is used.

categoryThe grouping of structured events which this action belongs toYesstring
actionDefines the type of user interaction which this event involvesYesstring
labelA string to provide additional dimensions to the event dataNo*string
propertyA string describing the object or the action performed on itNo*string
valueA value to provide numerical data about the eventNo*double


StructuredEvent se("shop", "add-to-basket"); // constructor takes category and action = "pcs"; se.value = 25.6; Snowplow::get_default_tracker()->track(se);
Code language: C++ (cpp)

Track timing events with “TimingEvent”

Use the TimingEvent type to track user timing events such as how long resources take to load.

Its properties are as follows:

categoryThe category of the eventYes*string
variableThe variable of the eventYes*string
timingThe timing of the eventYes*int64
labelThe label of the eventNo*string

The event uses the following Iglu schema: iglu:com.snowplowanalytics.snowplow/timing/jsonschema/1-0-0.


TimingEvent te("category", "variable", 123); Snowplow::get_default_tracker()->track(te);
Code language: C++ (cpp)

If you’d like to learn more about Snowplow BDP you can book a demo with our team, or if you’d prefer, you can try Snowplow technology for yourself quickly and easily.