A guide to unstructured events in Snowplow 0.8.3


Earlier today we announced the release of Snowplow 0.8.3, which updated our JavaScript Tracker to add the ability to send custom unstructured events to a Snowplow collector with trackUnstructEvent().

In our earlier blog post we briefly introduced the capabilities of trackUnstructEvent with some example code. In this blog post, we will take a detailed look at Snowplow’s custom unstructured events functionality, so you can understand how best to send unstructured events to Snowplow.

Understanding the unstructured event format is important because our Enrichment process does not yet extract unstructured events, so you will not get any feedback yet from the ETL as to whether you are tracking them correctly. (Nor do we have validation for unstructured event properties in our JavaScript Tracker yet.)

In the rest of this post, then, we will cover:

  1. Basic usage
  2. The properties JavaScript object
  3. Supported datatypes
  4. Getting help

1. Basic usage

Tracking an unstructured event with the JavaScript Tracker is very straightforward – use the trackUnstructEvent(name, properties) function:

Here is an example:

_snaq.push(['trackUnstructEvent', 'Viewed Product', { product_id: 'ASO01043', category: 'Dresses', brand: 'ACME', returning: true, price: 49.95, sizes: ['xs', 's', 'l', 'xl', 'xxl'], available_since$dt: new Date(2013,3,7) } <span class="p">]);

Every call to trackUnstructEvent has the same structure – the complexity comes from knowing how to structure the properties JavaScript object. We will discuss this next:

2. The ‘properties’ JavaScript object

The properties JavaScript consists of a set of individual name: value properties.

The structure must be flat – in other words, properties cannot be nested. Continuing with the exampe code above, this means that the following is not allowed:

{ category: { primary: 'Womenswear', secondary: 'Dresses'}, // NOT allowed  }

The properties JavaScript object supports a wide range of datatypes – see below for details.

3. Supported datatypes

Snowplow unstructured events support a relatively rich set of datatypes. Because these datatypes do not always map directly onto JavaScript datatypes, we have introduced some “type suffixes” for the JavaScript property names, to tell Snowplow what Snowplow datatype we want the JavaScript data to map onto.

Our datatypes, then, are as follows:

Snowplow datatype Description JavaScript datatype Type suffix(es) Supports array?
Null Absence of a value Null No
String String of characters String Yes
Boolean True or false Boolean Yes
Integer Number without decimal Number $int Yes
Floating point Number with decimal Number $flt Yes
Geo-coordinates Longitude and latitude [Number, Number] $geo Yes
Date Date and time (ms precision) Number $dt, $tm, $tms Yes
Array Array of values [x, y, z] - -

Let’s go through each of these in turn, providing some examples as we go:


Tracking a Null value for a given field is straightforward:

{ returns_id: null }


Tracking a String is easy:

{ product_id: 'ASO01043' // Or "ASO01043"  }


Tracking a Boolean is also straightforward:

{ trial: true }


To track an Integer, use a JavaScript Number but add a type suffix like so:

{ in_stock$int: 23 }

Warning: if you do not add the $int type suffix, Snowplow will assume you are tracking a Floating point number.

Floating point

To track a Floating point number, use a JavaScript Number; adding a type suffix is optional:

{ price$flt: 4.99, sales_tax: 49.99 // Same as $sales_tax:$flt  }


Tracking a pair of Geographic coordinates is done like so:

{ check_in$geo: [40.11041, -88.21337] // Lat, long  }

Please note that the datatype takes the format latitude followed by longitude. That is the same order used by services such as Google Maps.

Warning: if you do not add the $geo type suffix, then the value will be incorrectly interpreted by Snowplow as an Array of Floating points.


Snowplow Dates include the date and the time, with milliseconds precision. There are three type suffixes supported for tracking a Date:

You can track a date by adding either a JavaScript Number or JavaScript Date to your properties object. The following are all valid dates:

{ birthday$dt: new Date(1980,11,10), // Sent to Snowplow as birthday$dt: 3996  birthday2$dt: 3996, // ^ Same as above  registered$tm: new Date(2013,05,13,14,20,10), // Sent to Snowplow as registered$tm: 1371129610  registered2$tm: 1371129610, // Same as above  last_action$tms: 1368454114215, // Accurate to milliseconds  last_action2: new Date() // Sent to Snowplow as last_action2$tms: 1368454114215  }

Note that the type prefix only indicates how the JavaScript Number sent to Snowplow is interpreted - all Snowplow Dates are stored to milliseconds precision (whether or not they include that level of precision).

Two warnings:

  1. If you specify a JavaScript Number but do not add a valid Date suffix ($dt, $tm or $tms), then the value will be incorrectly interpreted by Snowplow as a Number, not a Date
  2. If you specify a JavaScript Number but add the wrong Date suffix, then the Date will be incorrectly interpreted by Snowplow, for example:
{ last_ping$dt: 1371129610 // Should have been $tm. Snowplow will interpret this as the year 3756521449  }


You can track an Array of values of any data type other than Null.

Arrays must be homogeneous - in other words, all values within the Array must be of the same datatype. This means that the following is not allowed:

{ sizes: ['xs', 28, 'l', 38, 'xxl'] // NOT allowed  }

By contrast, the following are all allowed:

{ sizes: ['xs', 's', 'l', 'xl', 'xxl'], session_starts$tm: [1371129610, 1064329730, 1341127611], check_ins$geo: [[-88.21337, 40.11041], [-78.81557, 30.22047]] }

4. Getting help

As always, if you do run into any issues or don’t understand any of the above guide, please do get in touch with us via the usual channels.

And if you have any ideas or feedback for Snowplow’ custom unstructured events, do please share them, either in the comments below or through the usual channels.


Related articles