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. Arduino tracker

Arduino tracker

The Snowplow Arduino tracker allows you to track Snowplow events from an IP-connected Arduino board.

The tracker should be straightforward to use if you are familiar with Arduino development; any prior experience with Snowplow’s JavaScript tracker or Google Analytics (which has a similar API to Snowplow) is helpful but not necessary.

Note that this tracker has access to a much more restricted set of Snowplow events than other trackers.

Before you start

Tracker compatibility

Please note that the Snowplow Arduino Tracker requires the new Ethernet library API (with DHCP and DNS), which is in Arduino 1.0.

Almost all recent Arduinos (Arduino Uno, Arduino Due et al) should work fine with the Snowplow Tracker.


If you haven’t done so already, download and install the Arduino toolchain and development environment from the Arduino Software page.



Follow these steps to install the Snowplow Arduino Tracker on your computer:

1) Browse to the Arduino Tracker’s GitHub site and download the zip file

2) Open your Arduino software and click File > Preferences to check your Sketchbook location

3) Create a sub-folder within your Sketchbook location called “libraries” if it doesn’t already exist

4) Now unzip the zip file you downloaded into the “libraries” sub-folder, renaming its top-level folder from “snowplow-arduino-tracker-master” to “SnowplowTracker”:

That’s it for installation! Now let’s test the setup.


Follow these steps to test the Snowplow Arduino Tracker with your Arduino board:

1) If you have not already done so, connect your Arduino board to your computer, and to the Internet via the RJ-45 ethernet jack on your Ethernet shield, or via your Wi-Fi shield:

2) Within your Arduino software, click File > Examples > SnowplowTracker > basicPing to load a sample sketch which comes with the Snowplow Arduino Tracker.

Note that it is not necessary to make any edits to this sketch before running it (it is fine for example to leave the MAC address as specified).

3) Next click File > Upload. This should compile the sketch without any errors and upload it to your Arduino board:

4) Now click Tools > Serial Monitor and you should see events being successfully pinged to Snowplow:

That’s it for testing – although if you are interested, you can try out the three other sample sketches in under File > Examples > SnowplowTracker.

Integrating into your sketch

You are now ready to integrate the Snowplow Arduino Tracker into your own sketch. This should be relatively straightforward – we recommend the following steps:

1) Look at the source code of the example sketches that come with the Snowplow Arduino Tracker. You can find them on GitHub in snowplow-arduino-tracker/examples

2) Read through the rest of the documentation for the Arduino Tracker to learn exactly what tracking capabilities Snowplow can provide for your Arduino sketch.

For a standalone Arduino project which incorporates Snowplow tracking, please see arduino-temp-tracker on GitHub.

General configuration and parameters


Assuming you have completed the Lua Tracker Setup for your Lua project, you are now ready to initialize the Lua Tracker.

You must add some initialization code to the top of your Arduino sketch, before your setup() function:

Required headers

Make sure you have the following includes:

#include <SPI.h> #include <Ethernet.h> #include <SnowplowTracker.h>

Initialize SnowplowTracker

After your includes but before your setup() function, initialize your SnowplowTracker something like this:

// MAC address of this Arduino. Update with your shield's MAC address. const byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0xF8, 0xA0 }; // Snowplow app name const char *snowplowAppName = "my-arduino-project"; // Snowplow Tracker SnowplowTracker snowplow(&Ethernet, mac, snowplowAppName);

Note that this initialization includes setting the application ID for your Arduino project, as well as your device’s MAC address.

Setting the endpoint

Endpoint refers to the location of your collector: you need to point your Arduino tracker to your collector endpoint, to ensure that data generated by your Arduino is logged by the collector.

If you are using a Cloudfront collector you can use initCf to set the endpoint. If you are using any other collector (e.g. the Clojure Collector or the Scala Stream Collector), then you should use initUrl.

Setting a Cloudfront endpoint using initCf()

You can set the collector endpoint for the Cloudfront collector by adding to your setup() function:


So if your Cloudfront subdomain is d3rkrsqld9gmqf, you would include:


This completes the initialization of your SnowplowTracker.

Setting a non-Cloudfront endpoint using initUrl()

If you are running a different collector (not the Cloudfront collector) then add to your setup() function:


So if your collector endpoint is at ‘’ then you would include:


This completes the initialization of your SnowplowTracker.

Setting the user ID

The Arduino Tracker automatically passes to the collector the mac_address supplied on initialization.

However you may want to additionally identify a specific Arduino board by a more business-friendly name. To do this, you use the setUserId method.

Setting the user ID using setUserId

To set a business-friendly user ID for this Arduino, use the setUserId() method i.e.:


Tracking specific events

Tracking functions supported by the Arduino Tracker at a glance:

trackStructEventTrack a Snowplow custom structured event


All events are tracked with specific Arduino C++ functions of the form trackXXX, where XXX is the name of the event to track.

A given event type may have multiple different signatures (to support slightly different argument options or types).

Return codes

All trackXXX functions return an integer to report the status of the attempt to track the given event object.

The full list of return codes are given below:

ConstantInteger valueDescription
ERROR_CONNECTION_FAILED-1Could not connect to Snowplow collector
ERROR_TIMED_OUT-2Snowplow collector did not respond
ERROR_INVALID_RESPONSE-3Snowplow collector’s response couldn’t be parsed
ERROR_MISSING_ARGUMENT-4Required argument(s) to trackXXX missing
ERROR_HTTP_STATUS-5HTTP status code returned by Snowplow collector was server or client error
N/A1-399Non-error HTTP status code returned by Snowplow collector

You can access these constants in your code by prepending with SnowplowTracker::, for example:

int ret_val = snowplow.trackXXX; if (ret_val == SnowplowTracker::ERROR_HTTP_STATUS) { ... }

Tracking custom structured events

Custom structured events are the only form of tracking currently supported by the Snowplow Arduino tracker. Whenever you want to record an event or sensor reading from your IP-connected Arduino, use trackStructEvent to send this data to Snowplow.

Some examples of tracking custom structured events from your Arduino board(s) might include:

  • Monitoring the environment (temperature, humidity, light levels etc) in your warehouse/factory/workplace/shop/museum
  • Tracking the movement of products around your shop/warehouse/factory using Arduino, RFID readers and Snowplow
  • Sending vehicle fleet information (locations, speeds, fuel levels etc) back to Snowplow using Arduino’s 3G and GPS shields

trackStructEvent overview

There are five arguments associated with each structured event. Of them, only the first two are required:

aCategoryYesThe name you supply for the group of objects you want to track e.g. ‘sensor’, ‘ecomm’
aActionYesA string which defines the type of user interaction for the web object e.g. ‘read-temp’, ‘wifi-strength’
aLabelNoAn optional string which identifies the specific object being actioned e.g. ID of the sensor being read
aPropertyNoAn optional string describing the object or the action performed on it. This might be whether the temperature reading is in Fahrenheit or Celsius
aValueNoAn optional float or double to quantify or further describe the user action. This might be the price of an item added-to-basket, or the starting time of the video where play was just pressed

There are four slightly different signatures for the tractStructEvent, depending on what type of aValue you want to supply:

trackStructEvent: no aValue

The relevant signature for trackStructEvent if you have no aValue to log is:

int trackStructEvent(const char *aCategory, const char *aAction, const char *aLabel = NULL, const char *aProperty = NULL) const;

Note that this version defaults aLabel and aProperty to NULL if you don’t set them. Here’s an example invocation:

snowplow.trackStructEvent("example", "basic ping");

trackStructEvent: integer aValue

The relevant signature for trackStructEvent if aValue is an integer is:

int trackStructEvent(const char *aCategory, const char *aAction, const char *aLabel, const char *aProperty, const int aValue) const;


  • Because aValue must be a float or double, this version of trackStructEvent appends “.0” to the end of the int before sending to Snowplow
  • If you don’t want to set aLabel or aProperty, pass in NULL in their place

Here’s an example invocation:

snowplow.trackStructEvent("example", "profile-update", "age", NULL, 22);

trackStructEvent: double aValue

The relevant signature for trackStructEvent to track a double in aValue is:

int trackStructEvent(const char *aCategory, const char *aAction, const char *aLabel, const char *aProperty, const double aValue, const int aValuePrecision = 2) const;

aValuePrecision lets you specify the number of decimal places to use when logging the double aValue (it defaults to two decimal places). Note that the default type for floating point literals in Arduino is double, not float.

Here’s an example invocation:

snowplow.trackStructEvent("example", "constant", NULL, "pi", 3.14159, 5);

trackStructEvent: float aValue

The relevant signature for trackStructEvent to track a float in aValue is:

int trackStructEvent(const char *aCategory, const char *aAction, const char *aLabel, const char *aProperty, const float aValue, const int aValuePrecision = 2) const;

aValuePrecision lets you specify the number of decimal places to use when logging the float aValue (it defaults to two decimal places). Note that the default type for floating point literals in Arduino is double, not float.

Here’s an example invocation:

snowplow.trackStructEvent("example", "temp reading", NULL, "celsius", 15.3f, 1);

Testing and debugging

Arduino is a difficult platform to test and debug software on, so it’s important to understand what options the Snowplow Arduino Tracker has for debugging.Back to top

Setup debugging

By default, debug logging to your Arduino Serial Monitor console is switched on for the Snowplow Arduino Tracker, which should help you to identify any problems debugging your Snowplow event tracking.

To switch off this logging when you are finished testing, edit this line found near the top of your copy of SnowplowTracker.cpp:

#define LOG_LEVEL 0x03 // Change to 0x00 when you've finished testing

As the comment says, change “0x03” to “0x00” to switch off all logging to your Arduino Serial Monitor console.

The full set of logging levels are as follows:

ConstantInteger valueDescription
NO_LOG0x00Don’t print any messages to the Serial Monitor console
ERROR_LEVEL0x01Only print errors to the console
INFO_LEVEL0x02Print errors and important messages to the console
DEBUG_LEVEL0x03Print all errors and messages to the console