Skip to main content

Objective-C (iOS) (0.5.0)

You are reading documentation for an outdated version. Here’s the latest one!

1. Overview‚Äč

The Snowplow Objective-C Tracker allows you to track Snowplow events from your iOS and OSX apps and games. It supports iOS 7.0+, OSX 10.9+.

The tracker should be straightforward to use if you are comfortable with iOS development; its API is modelled after Snowplow's Python Tracker so any prior experience with that tracker is helpful but not necessary. If you haven't already, have a look at the iOS Tracker Setup guide before continuing.

You can also find detailed documentation for the method calls in the tracker classes available as part of the CocoaPods documentation.

1.1 Demonstration App‚Äč

If you would like to see the Tracker in action you can launch the demo app like so:

  • Download the github repo:¬†git clone
  • In XCode open the¬†SnowplowDemo.xcworkspace¬†file.
  • Select the device you want to launch the SnowplowDemo into!

You will then need to simply enter a valid endpoint URL and hit the Start Demo! button.

2. Initialization‚Äč

Assuming you have completed the iOS Tracker Setup for your project, you are now ready to initialze the Snowplow Tracker.

2.1 Importing the library‚Äč

Adding the library into your project is as simple as adding the headers into your class file:

#import <SPTracker.h>
#import <SPEmitter.h>

If you have manually copied the library into your project, don't forget to change your import syntax:

#import "SPTracker.h"
#import "SPEmitter.h"

If you have statically added the library you will need to further amend your syntax:

#import "SnowplowTracker/SPTracker.h"
#import "SnowplowTracker/SPEmitter.h"

That's it - you are now ready to initialize a tracker instance.

2.2 Creating a tracker‚Äč

To instantiate a tracker in your code simply instantiate the SPTracker class with the following builder pattern:

SPTracker *tracker = [SPTracker build:^(id<SPTrackerBuilder> builder) {
[builder setEmitter:emitter]; // Required
[builder setSubject:subject]; // Optional
[builder setAppId:_appId]; // Optional
[builder setTrackerNamespace:_namespace]; // Optional
[builder setBase64Encoded:YES]; // Optional
[builder setSessionContext:YES]; // Optional
[builder setForegroundTimeout:300]; // Optional
[builder setBackgroundTimeout:150]; // Optional
[builder setCheckInterval:10]; // Optional
Builder FunctionDescription
setEmitterThe SPEmitter object you create
setSubjectThe SPSubject object you create
setAppIdThe application ID
setTrackerNamespaceThe name of the tracker instance
setBase64EncodedWhether to enable base 64 encoding
setSessionContextWhether to enable client sessions
setForegroundTimeoutThe session foreground timeout
setBackgroundTimeoutThe session background timeout
setCheckIntervalThe session checking interval


This is a single SPEmitter object that will be used to send all the tracking events created by the SPTracker to a collector. See Sending events for more on its configuration.


If provided, the namespace argument will be attached to every event fired by the new tracker. This allows you to later identify which tracker fired which event if you have multiple trackers running.


The appId argument lets you set the application ID to any string.


By default, unstructured events and custom contexts are encoded into Base64 to ensure that no data is lost or corrupted. You can turn encoding on or off using the Boolean base64Encoded argument.


By default no client sessionization is activated. Once enabled the Tracker will start appending a client_session context to each event it sends and it will maintain this session information for the life of the application; i.e. as long as the application is installed on the device.


This function when called will pause all event tracking and sessionization actions until resume is called.

[tracker pauseEventTracking];


This function will resume all event tracking when called (if it was paused) and will also re-enable sessionization if it was already on.

[tracker resumeEventTracking];

3. Adding extra data‚Äč

To add extra data to the Tracker you will need to append an SPSubject object to the Tracker. This can be done either during Tracker creation or added later.

SPSubject *subject = [[SPSubject alloc] init];

// OR with the optional platform context...

SPSubject *subject = [[SPSubject alloc] initWithPlatformContext:YES];

// Add it to the Tracker during construction...
SPTracker *tracker = [SPTracker build:^(id<SPTrackerBuilder> builder) {

[builder setSubject:subject]; // Optional }];

// Add it later...

[tracker setSubject:subject];

3.1 Sending IFA‚Äč

Apps that do not display advertisements are not allowed to access Apple's Identifier For Advertisers (IFA). For this reason, the Snowplow iOS Tracker will only send IFA as part of the mobile_context which is attached to each event if you have the AdSupport.framework included in your app (and are therefore intending to serve ads).

For the avoidance of doubt, you can also avoid sending IFA regardless of your advertising situation, thus:

  • Click on¬†Build Settings¬†to your app's project in Xcode
  • Search for¬†Preprocessor Macros
  • Add a macro defined asSNOWPLOW_NO_IFA = 1

3.2 Set user ID with¬†setUserId‚Äč

You can set the user ID to any string:

[subject setUserId:_userId];


[subject setUserId:@"alexd"];

3.3 Set Screen Resolution with¬†setResolutionWithWidth‚Äč

You can set the screen resoloution to any width and height.


[subject setResolutionWithWidth:1920 andHeight:1080];

3.4 Set View Port with¬†setViewPortWithWidth‚Äč

You can set the view port to any width and height.


[subject setViewPortWithWidth:1920 andHeight:1080];

3.5 Set Color Dpeth with¬†setColorDepth‚Äč

You can set the color depth to any integer.


[subject setColorDepth:20];

3.6 Set Timezone with¬†setTimezone‚Äč

You can set the timezone to any string.


[subject setTimezone:@"UTC"];

3.7 Set Language with¬†setLanguage‚Äč

You can set the language to any string.


[subject setLanguage:@"en"];

3.8 Set IP Address with¬†setIpAddress‚Äč

You can set the user IP Address to any string.


[subject setIpAddress:@""];

3.9 Set the Useragent with¬†setUseragent‚Äč

You can set the Useragent to any string.


[subject setUseragent:@"aUseragent"];

3.10 Set the Network User ID with¬†setNetworkUserId‚Äč

You can set the Network User ID to any string.


[subject setNetworkUserId:@"nuid"];

3.11 Set the Domain User ID with¬†setDomainUserId‚Äč

You can set the Domain User ID to any string.


[subject setDomainUserId:@"duid"];

4. Tracking specific events‚Äč

Snowplow has been built to enable you to track a wide range of events that occur when users interact with your websites and apps. We are constantly growing the range of functions available in order to capture that data more richly.

Tracking methods supported by the iOS Tracker at a glance:

trackScreenView:Track the user viewing a screen within the application
trackPageView:Track and record views of web pages.
trackEcommerceTransaction:Track an ecommerce transaction and its items
trackStructuredEvent:Track a Snowplow custom structured event
trackUnstructuredEvent:Track a Snowplow custom unstructured event
trackTiming:Track a Snowplow user timing event

4.1 Common‚Äč

All events are tracked with specific methods on the tracker instance, of the form trackXXX(), where XXX is the name of the event to track.

4.1.1 Custom contexts‚Äč

In short, custom contexts let you add additional information about the circumstances surrounding an event in the form of an NSDictionary object. Each tracking method accepts an additional optional contexts parameter after all the parameters specific to that method:

- (void) trackPageView:(NSString *)pageUrl
title:(NSString *)pageTitle
referrer:(NSString *)referrer;
- (void) trackPageView:(NSString *)pageUrl
title:(NSString *)pageTitle
referrer:(NSString *)referrer
context:(NSMutableArray *)context;
- (void) trackPageView:(NSString *)pageUrl
title:(NSString *)pageTitle
referrer:(NSString *)referrer
- (void) trackPageView:(NSString *)pageUrl
title:(NSString *)pageTitle
referrer:(NSString *)referrer
context:(NSMutableArray *)context

The context argument should consist of a NSArray of NSDictionary representing an array of one or more contexts. The format of each individual context element is the same as for an unstructured event.

If a visitor arrives on a page advertising a movie, the context dictionary might look like this:

"schema": "iglu:com.acme_company/movie_poster/jsonschema/2.1.1",
"data": {
"movieName": "The Guns of Navarone",
"posterCountry": "US",
"posterYear": "1961"

The corresponding NSDictionary would look like this:

NSDictionary *poster = @{
@"data": @{
@"movieName": @"The Guns of Navarone",
@"posterCountry": @"US",
@"posterYear": @"1961"

Sending the movie poster context with an event looks like this:

[tracker trackStructuredEvent:@"Product"
context:[NSMutableArray arrayWithArray:@[poster]]];

Note that even if there is only one custom context attached to the event, it still needs to be placed in an array.

4.1.2 Optional timestamp & context argument‚Äč

In all the trackers, we offer a way to set the timestamp if you want the event to show as tracked at a specific time. If you don't, we create a timestamp while the event is being tracked.

Please note this argument must always be in milliseconds since the unix epoch like so 1446542245000.

Here is an example:

[tracker trackPageView:@"" title:@"Example Page" referrer:@""];

[tracker trackPageView:@"" title:@"Example Page" referrer:@"" context:contextArray];

[tracker trackPageView:@"" title:@"Example Page" referrer:@"" timestamp:1446542245000];

[tracker trackPageView:@"" title:@"Example Page" referrer:@"" context:contextArray timestamp:1446542245000];

4.1.3 Tracker method return values‚Äč

To be confirmed. As of now, trackers do not return anything.

4.2 Track screen views with¬†trackScreenView:‚Äč

Use trackScreenView: to track a user viewing a screen (or equivalent) within your app. Arguments are:

nameHuman-readable name for this screenNoNSString*
id_Unique identifier for this screenNoNSString*
contextCustom context for the eventNoNSMutableArray*
timestampOptional timestamp for the eventNodouble


[t1 trackScreenView:@"HUD > Save Game" screen:@"screen23"];

[t1 trackScreenView:@"HUD > Save Game" screen:nil timestamp:1446542245000];

[t1 trackScreenView:@"HUD > Save Game" screen:@"screen23" timestamp:1446542245000];

4.3 Track pageviews with¬†trackPageView:‚Äč

Use trackPageView: to track a user viewing a page within your app.

Arguments are:

pageUrlThe URL of the pageYesNSString*
pageTitleThe title of the pageYesNSString*
referrerThe address which linked to the pageYesNSString*
contextCustom context for the eventNoNSMutableArray*
timestampOptional timestamp for the eventNodouble


[t1 trackPageView:@"" title:@"example" referrer:@"" context:contextList];

[t1 trackPageView:@"" title:@"example" referrer:@""];

4.4 Track ecommerce transactions with¬†trackEcommerceTransaction:‚Äč

Use trackEcommerceTransaction: to track an ecommerce transaction. Arguments:

orderIdID of the eCommerce transactionYesNSString*
totalValueTotal transaction valueYesfloat
affiliationTransaction affiliationNoNSString*
taxValueTransaction tax valueNofloat
shippingDelivery cost chargedNofloat
cityDelivery address cityNoNSString*
stateDelivery address stateNoNSString*
countryDelivery address countryNoNSString*
currencyTransaction currencyNoNSString*
itemsItems in the transactionYesNSMutableArray*
contextCustom context for the eventNoNSMutableArray*
tstampWhen the transaction event occurredNodouble

trackEcommerceTransaction: fires multiple events: one "transaction" event for the transaction as a whole, and one "transaction item" event for each element of the items array. Each transaction item event will have the same timestamp, orderId, and currency as the main transaction event.

The items argument is an NSMutableArray containing an NSDictionary for each item in the transaction. There is a convenience constructor for each item called trackEcommerceTransactionItem:. Arguments:

skuItem SKUYesNSString*
priceItem priceYesfloat
quantityItem quantityYesfloat
nameItem nameNoNSString*
categoryItem categoryNoNSString*
contextCustom context for the eventNoNSMutableArray*
currencyTransaction currencyNoNSString*
contextCustom context for the eventNoNSMutableArray*
tstampWhen the transaction event occurredNodouble

Example of tracking a transaction containing one item:

NSString *transactionID = @"6a8078be";
NSMutableArray *itemArray = [NSMutableArray array];

[itemArray addObject:[t trackEcommerceTransactionItem:transactionID
name:@"Hot Chocolate"

[t trackEcommerceTransaction:transactionID totalValue:350 affiliation:@"no_affiliate" taxValue:10 shipping:15 city:@"Boston" state:@"Massachusetts" country:@"USA" currency:@"USD" items:itemArray];

4.5 Track structured events with¬†trackStructuredEvent:‚Äč

Use trackStructuredEvent: 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):

categoryThe grouping of structured events which this action belongs toYesNSString*
actionDefines the type of user interaction which this event involvesYesNSString*
labelA string to provide additional dimensions to the event dataYesNSString*
propertyA string describing the object or the action performed on itYesNSString*
valueA value to provide numerical data about the eventYesint
contextCustom context for the eventNoNSMutableArray*
timestampOptional timestamp for the eventNodouble


[t1 trackStructuredEvent:@"shop" action:@"add-to-basket" label:@"Add To Basket" property:@"pcs" value:27];

[t1 trackStructuredEvent:@"shop" action:@"add-to-basket" label:@"Add To Basket" property:@"pcs" value:27 timestamp:1446542245000];

4.6 Track unstructured events with¬†trackUnstructuredEvent:‚Äč

Custom unstructured events are a flexible tool that enable Snowplow users to define their own event types and send them into Snowplow.

When a user sends in a custom unstructured event, they do so as a JSON of name-value properties, that conforms to a JSON schema defined for the event earlier.

Use trackUnstructuredEvent: 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

The arguments are as follows:

eventJsonThe properties of the eventYesNSDictionary*
contextCustom context for the eventNoNSMutableArray*
timestampOptional timestamp for the eventNodouble


- (void) trackUnstructuredEvent:(NSDictionary *)eventJson
context:(NSMutableArray *)context

If you supply a NSDictionary*, make sure that this top-level contains your schema and data keys, and then store your data properties as a child NSDictionary*.


NSDictionary *event = @{
@"data": @{
@"level": @23,
@"score": @56473
tracker trackUnstructuredEvent:event

For more on JSON schema, see the blog post.

4.7 Track user timings with¬†trackTimingWithCategory:‚Äč

Use trackTiming: to track a user timing in your app - for example, how long a game took to load, or how long an in-app purchase took to download. The fields are as follows:

categoryCategorizing timing variables into logical groups (e.g API calls, asset loading)YesNSString*
variableIdentify the timing being recordedYesNSString*
timingThe number of milliseconds in elapsed time to reportYesNSUInteger
labelOptional description of this timingYesNSString*
contextCustom context for the eventNoNSMutableArray*
timestampOptional timestamp for the eventNodouble


[t1 trackTimingWithCategory:@"Application"

[t1 trackTimingWithCategory:@"Application" variable:@"Background" timing:324 label:@"5231804123" timestamp:1446542245000];

5. Sending events:¬†SPEmitter‚Äč

Events created by the Tracker are sent to a collector using a SnowplowEmitter instance. You can create one using the following builder example:

SPEmitter *emitter = [SPEmitter build:^(id<SPEmitterBuilder> builder) {
[builder setUrlEndpoint:_url]; // Required
[builder setHttpMethod:_method]; // Optional
[builder setBufferOption:_option]; // Optional
[builder setCallback:self]; // Optional
[builder setEmitRange:200]; // Optional
[builder setEmitThreadPoolSize:20]; // Optional
Builder FunctionDescription
setUrlEndpointThe NSURL to use for sending events
setHttpMethodThe method sending; either GET or POST
setBufferOptionThe buffer option; 1 or 10 events
setCallbackThe optional emitter callback
setEmitRangeThe count of events that are retrieved from the database
setEmitThreadPoolSizeThe size of the emitting Thread Pool

5.1 Using a buffer‚Äč

A buffer is used to group events together in bulk before sending them. This is especially handy to reduce network usage. By default, the SPEmitter buffers up to 10 events into a single POST; GET is always one event per request.

You can set this during the creation of a SPEmitter object or using the setter -(void)setBufferOption:

SPEmitter *emitter = [SPEmitter build:^(id<SPEmitterBuilder> builder) {
[builder setUrlEndpoint:_url];
[builder setBufferOption:SPBufferDefault];

[emitter setBufferOption:SPBufferInstant];

Here are all the posibile options that you can use:

SPBufferInstantAll events are sent as individual requests
SPBufferDefaultPOST events are sent with up to 10 events

5.2 Choosing the HTTP method‚Äč

Snowplow supports receiving events via GET and POST requests. In a GET request, each event is sent in individual request. With POST requests, events can be bundled together in one request.

Here are all the posibile options that you can use:

SPRequestGetEvents are sent individually as GET requests
SPRequestPostEvents are sent in a group when 10 events are received in one POST request

5.3 Adding an Emitter Callback‚Äč

You are now also able to include an emitter callback which will return the count of successful and failed events.

To implement you will need to:

  • Add the¬†RequestCallback¬†protocol to your header file:
// Example from the SnowplowDemo -> ViewController.h file:
@interface ViewController : UIViewController <UITextFieldDelegate, RequestCallback>

// Extra Example
@interface MyObjcClass : NSObject <RequestCallback>
  • In your paired¬†.m¬†file add the following functions:
// Define Callback Functions
- (void) onSuccessWithCount:(NSInteger)successCount {
// Do something with result

- (void) onFailureWithCount:(NSInteger)failureCount successCount:(NSInteger)successCount {
// Do something with results
  • Construct the¬†SPEmitter¬†like so:
NSURL *url = [[NSURL alloc] initWithString:@""];

SPEmitter *emitter = [SPEmitter build:^(id<SPEmitterBuilder> builder) {
[builder setUrlEndpoint:url];
[builder setCallback:self];

The self will work only if you have declared the callback functions in the same class as you are creating the Emitter from. Otherwise you will need to pass in the target for the class in which you have defined these functions.

5.4 Sending HTTP requests‚Äč

You can set this during the creation of a SPEmitter object:

NSURL *url = [[NSURL alloc] initWithString:@""];

SPEmitter *emitter = [SPEmitter build:^(id<SPEmitterBuilder> builder) {
[builder setUrlEndpoint:url];
[builder setHttpMethod:SPRequestPost];

// OR

[builder setHttpMethod:SPRequestGet];

6. Utility Functions‚Äč

The SPUtilities class contains a host of static functions which are used throughout the Tracker. To see all of the available functions please consult the SPUtils.h file.


This function will only return the IDFA under the following conditions:

  • The device is running iOS.
  • The AdSupport library is in your project.

To use:

NSString* appleIdfa = [SPUtils getAppleIdfa];


This function will only return the IDFV under the following conditions:

  • The device is running iOS.

To use:

NSString* appleIdfv = [SPUtils getAppleIdfv];


This function will only return the OpenIDFA under the following conditions:

  • The device is running iOS.
  • The iOS version is less than 9.0.

To use:

NSString* openIdfa = [SPUtils getOpenIdfa];
Was this page helpful?