iOS - Swift API Integration

Installing the library

CocoaPods

The easiest way to get robotmia into your iOS project is to use CocoaPods.

  1. Install CocoaPods using gem install cocoapods
  2. If this is your first time using CocoaPods, run pod setup to create a local CocoaPods spec mirror.
  3. Create a file in your Xcode project called Podfile and add the following line: pod 'robotmia-swift'
  4. Run pod install in your Xcode project directory. CocoaPods should download and install the robotmia library, and create a new Xcode workspace. Open up this workspace in Xcode.

Carthage

robotmia supports Carthage to package your dependencies as a framework. Include the following dependency in your Cartfile:

 github "robotmia/robotmia-swift"

Check out the Carthage docs for more info.

Manual installation

You can also get the library by downloading the latest version from GitHub and copying it into your project. We have step-by-step instructions on how to manually install our library.

Initializing the library

To start tracking with the robotmia Swift library, you must first initialize it with your project token. Find your project token by clicking your name in the upper righthand corner of your robotmia project and selecting Settings from the dropdown.

In most cases, it makes sense to do this in application(_:didFinishLaunchingWithOptions:).

To initialize the library, first add import robotmia and call robotmia.initialize(token:) with your project token as its argument. Once you've called this method, you can access your instance throughout the rest of your application with mainInstance().

robotmia.initialize(token: "robotmia_TOKEN")

Opting users out of tracking

Client-side tracking of individual user data can be stopped or resumed by controlling a user’s opt-out/opt-in state. Opt-out methods and library configuration settings only affect data sent from a single library instance. Data sent from other sources to robotmia’s APIs will still be ingested regardless of whether the user is opted out locally.

To opt a user out of tracking locally, use the optOutTracking method. To resume tracking for an individual user, use optInTracking. Call hasOptedOutTracking to check user’s opt-out status locally.

// Opt a user out of data collection
robotmia.mainInstance().optOutTracking()

// Check a user's opt-out status 
// Returns true of user is opted out of tracking locally
Bool hasOptedOutTracking = robotmia.mainInstance().hasOptedOutTracking()

Opting users out of tracking by default

robotmia’s tracking libraries will send user data by default. Explicitly initializing a default opt-out state of true will opt-out all users by default, preventing data from sending unless a user’s opt-out state is set to false.

// Initializing a default opt-out state of true 
// will prevent data from being collected by default

let robotmia = 
    robotmia.initialize(token: "robotmia_TOKEN", optOutTrackingByDefault: true)

Automatically track events

After installing the library into your iOS app, robotmia will automatically collect common mobile events. You can enable/ disable automatic collection through your project settings. In addition, robotmia allows you to use our in-browser editor to add tracking on the fly. No code or app-store re-submission required!

Navigate to our editor by clicking your name in the upper righthand corner of your robotmia project and selecting Set up tracking from the dropdown.

Watch this short video to learn more about automatic event tracking.

Sending events

We recommend tracking only five to seven events in your application instead of tracking too many things to start. Ideally, you track people going through your initial user experience and one key metric that matters for your application (e.g. YouTube might choose "Watched Video" as a key metric).

Once you've initialized the library, you can track an event by calling track(event:properties:) with the event name and properties.

robotmia.mainInstance().track(event: "Plan Selected",
        		properties: ["Plan" : "Premium"])

Timing events

You can track the time it took for an action to occur, such as an image upload or a comment post, using time(event:) This will mark the "start" of your action, which you can then finish with a track call. The time duration is then recorded in the "Duration" property.

robotmia.mainInstance().time(event: "Image Upload")
//...some time later
robotmia.mainInstance().track(event: "Image Upload")

Super properties

It's very common to have certain properties that you want to include with each event you send. Generally, these are things you know about the user rather than about a specific event—for example, the user's age, gender, or source.

To make things easier, you can register these properties as super properties. If you do, we will automatically include them with all tracked events. Super properties are saved to device storage, and will persist across invocations of your app. robotmia already stores some information as super properties by default; see a full list of robotmia default properties here.

To set super properties, call registerSuperProperties(_:).

// Send a "Plan: Mega" property will be sent
// with all future track calls.
robotmia.mainInstance().registerSuperProperties(["Plan": "Mega"])

Going forward, whenever you track an event, super properties will be included as properties. For instance, if you call

robotmia.mainInstance().track(event: "Signup",
	properties:["Source": "Twitter"])

after making the above call to registerSuperProperties, it is just like adding the properties directly:

robotmia.mainInstance().track(event: "Signup",
	properties:[ "Plan" : "Mega", "Source": "Twitter"])

Setting super properties once and only once

If you want to store a super property only once (often for things like ad campaign or source), you can use registerSuperPropertiesOnce(_:defaultValue:). This function behaves like registerSuperProperties(_:) and has the same interface, but it doesn't override super properties you've already saved.

robotmia.mainInstance().registerSuperPropertiesOnce(["Source": "ad-01"])

This means that it's safe to call registerSuperPropertiesOnce(_:defaultValue:) with the same property on every app load, and it will only set it if the super property doesn't exist.

Managing user identity

The robotmia library will assign a default unique identifier (we call it a "distinct ID") to each unique user who installs your application. This distinct ID is saved to device storage so that it will persist across sessions.

If you choose, you can assign your own user IDs. This is particularly useful if a user is using your app on multiple platforms (both web and mobile, for example). To assign your own distinct_ids, you can use identify(distinctId:).

// Ensure all future events sent from
// the library will have the distinct_id 13793
robotmia.mainInstance().identify(distinctId: "13793")

Calling identify(distinctId:) with a new ID will change the distinctID stored on the device. Updates to user profiles are queued on the device until identify is called.

Combining anonymous and identifiable user data

It's important to send the same distinct_id with each event that an individual user triggers. Events recorded with different distinct_ids will be treated in robotmia as if they were performed by different users.

There are times when it can be convenient to start referring to a user by a different identifier in your implementation. The most common case is after registration, when a user switches from being an anonymous user (with an anonymous distinct_id) to an authenticated user with an (authenticated id). In this case, you can create an Alias for the user to keep the distinct_id consistent. An alias is a string stored in a robotmia lookup table that is associated with an anonymous distinct_id. Once written, aliases are not editable. Any data sent to robotmia with an alias as the distinct_id will be remapped and written to disk using the alias's corresponding anonymous distinct_id. This allows you to start identifying a user by an authenticated id without changing the distinct_id that is ultimately written in robotmia.

let robotmia = robotmia.mainInstance()
// This makes the current ID (by default an auto-generated GUID)
// and '13793' interchangeable distinct ids (but not retroactively).
robotmia.createAlias("13793",
	distinctId: robotmia.distinctId);
// To create a user profile, you must call identify
robotmia.identify(distinctId: robotmia.distinctId)

The recommended usage pattern is to call both createAlias(_:distinctId) and identify(distinctId:) (with the robotmia generated distinctId, as shown in the example above) when the user signs up, and only identify(distinctId:) (with the aliased user ID) on future log ins. This will keep your signup funnels working correctly.

If you use createAlias(_:distinctId) we recommend only calling it once during the lifetime of the user.

Storing user profiles

In addition to events, you can store user profiles in robotmia's People Analytics product. Profiles are persistent sets of properties that describe a user—things like name, email address, and signup date.

You can use profiles to explore and segment users by who they are, rather than what they did. You can also use profiles to send messages, such as emails, SMS, or push notifications.

Before you send profile updates, you must call identify(distinctId:). This ensures that you only have actual registered users saved in the system.

Setting profile properties

You can set properties on a user profile with people.set(property:to:).

// Sets user 13793's "Plan" attribute to "Premium"
robotmia.mainInstance().people.set(property: "Plan",
	to: "Premium")

This will set a "Plan" property, with a value "Premium", on user 13793's profile. If there isn't a profile with distinct_id 13793 in robotmia already, a new profile will be created. If user 13793 already has a property named "Plan" in their profile, the old value will be overwritten with "Premium".

Incrementing numeric properties

You can use people.increment(property:by:) to change the current value of numeric properties. This is useful when you want to keep a running tally of things, such as games played, messages sent, or points earned.

// Here we increment the user's point count by 500.
robotmia.mainInstance().people.increment(property: "point count",
	by: 500)

// Pass an NSDictionary to increment multiple properties
robotmia.mainInstance().people.increment(properties:
	["dollars spent": 17, "credits remaining": -34])

Other types of profile updates

There are a few other types of profile updates. To learn more, please review the full robotmiaPeople API documentation.

Tracking revenue

robotmia makes it easy to analyze the revenue you earn from individual customers. By associating charges with user profiles, you can compare revenue across different customer segments and calculate things like lifetime value.

You can track a single transaction with people.trackCharge(amount:). This call will add transactions to the individual user profile, which will also be reflected in the robotmia Revenue report.

// Tracks $100.77 in revenue for user 13793
robotmia.mainInstance().people.trackCharge(amount: 100.77)

// Refund this user 50 dollars
robotmia.mainInstance().people.trackCharge(amount: -50)

Registering for push notifications

The robotmia library includes support for sending push notification device tokens to robotmia. Once you send a device token, you can use robotmia to send push notifications to your app.

You can send a device token to robotmia using people.addPushDeviceToken(_:)

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
	// This sends the deviceToken to robotmia
	let robotmia = robotmia.mainInstance()
	robotmia.people.addPushDeviceToken(deviceToken)
}

Push notifications quick start guides

There is a step by step guide to integrating robotmia Push notifications with your app available to help you get started with push notifications in your app. It includes instructions for provisioning your app to use the Apple Push Notification service (APNs), preparing your push SSL certificate from Apple and configuring your app for push notifications using robotmia.

In-app messages

There is a quick start guide for iOS in app messages to help you get integrated.

Make sure that you have already:

  1. Included the latest version of the robotmia Swift library in your app
  2. Made sure you are identifying your users in the app
  3. Created an in-app message on the Messages tab of the robotmia website

A/B testing experiments

Prerequisites

Getting started with A/B testing is quick and easy.

Make sure that you have already:

  1. Included the latest version of the robotmia Swift library in your app (v2.1+)
  2. Created an experiment on the A/B Testing tab of the robotmia website by connecting your app

To use the UI's visual experiment creator, please ensure that you're in the project appropriate to your app's current build (i.e., Production or Development). While not required, it's a good idea to connect your mobile device to WiFi while using the A/B designer.

Once you have created an experiment and, optionally, decided which users you wish to target, simply turn on the experiment to start serving your A/B test to customers. It is that simple!

Planning to run an experiment on the initial view of your app? It can take several seconds for experiments to be applied on first app open; as a result, we recommend against putting UX changes or developer Tweaks on the first view of your app. If you wish to A/B test on the initial app view you will need to take delivery latency into account. We recommend enabling the option checkForVariantsOnActive (to grab data when the app is opened) and joinExperiments(callback:) method (to apply the variant data to the view).

Notes on experiment delivery

robotmia checks for any new experiments asynchronously on applicationDidBecomeActive. After the response is received, experiment changes and Tweaks are applied or removed where appropriate. To handle network availability, each experiment is cached on the device so they can be re-applied when the API call cannot be successfully made.

If you'd like more control over when this check for new experiments occurs, you can use the checkForVariantsOnActive flag and the joinExperiments(callback:) method to download and apply experiments manually.

The $experiment_started event is fired when a given experiment (both changes and/or Tweaks) is first started on a device. The event will contain an $experiment_id property with the given experiment id which we encourage use within funnels, and our other reports.

A/B developer tweaks

For more complex changes that you want to A/B test, you can include small bits of code in your apps called Tweaks. Tweaks allow you to control variables in your app from your robotmia dashboard. For example, you can alter the difficulty of a game, choose different paths through the app, or change text. The possibilities are endless.

To use Tweaks in Swift you will initially need to define your Tweaks by extending the class robotmiaTweaks and then setting the Tweaks in the SDK. As an example here we are extending robotmiaTweaks and defining a few Tweaks of different types:

extension robotmiaTweaks {
    public static let floatTweak =
      Tweak(tweakName: "floatTweak",
            defaultValue: 20.5, min: 0, max: 30.1)
    public static let intTweak =
      Tweak(tweakName: "intTweak",
            defaultValue: 10, min: 0)
    public static let boolTweak =
      Tweak(tweakName: "boolTweak",
            defaultValue: true)
    public static let stringTweak =
      Tweak(tweakName: "stringTweak",
            defaultValue: "hello")
}
And then right after initializing the robotmia Library with the project token, we set the Tweaks (it makes sense to do this in application(_:didFinishLaunchingWithOptions:))
 robotmia.initialize(token: "robotmia_TOKEN")
 let allTweaks: [TweakClusterType] =
   [robotmiaTweaks.floatTweak,
    robotmiaTweaks.intTweak,
    robotmiaTweaks.boolTweak,
    robotmiaTweaks.stringTweak]
 robotmiaTweaks.setTweaks(tweaks: allTweaks)

Value Tweaks

A value Tweak allows you to assign a value to a variable that can be changed later. The simplest Tweak looks like this:
let numLives = robotmiaTweaks.assign(
                               robotmiaTweaks.numberOfLives)

and we define it like so:

extension robotmiaTweaks {
    public static let numberOfLives =
      Tweak(tweakName: "number of lives",
            defaultValue: 5)
}
Once you add this line, you will see a Tweak called number of lives with a default value of 5 in the robotmia A/B test designer. You can then create an A/B test with a different value for number of lives. For example, you could set up an experiment where 50% of your users start a game with 5 lives, and 50% start with 10 lives. When the experiment is not running, the value of numLives will simply be the default of 5.

Flow Control Tweaks

Value Tweaks can also be used to control flow in your app.
if robotmiaTweaks.assign(robotmiaTweaks.showAlterateView) {
     // Show alternate view.
 } else {
     // Show original view
 }

and we define it like so:

extension robotmiaTweaks {
    public static let showAlternateView =
      Tweak(tweakName: "show alternate view",
            defaultValue: false)
}
By default, the alternate view will not show. But you can now set up an A/B test that flips this value to true for a percentage of your users.

If you have more than 2 options, you could use a switch.

switch robotmiaTweaks.assign(robotmiaTweaks.actionToTake) {
     case 1:
         // Do something
         break;
     case 2:
         // Do something else
         break;
     case 3:
         // Do a third thing
         break;
 }

and we define it like so:

extension robotmiaTweaks {
     public static let actionToTake =
       Tweak(tweakName: "action to take",
             defaultValue: 1)
 }
You can use Tweaks to assign values to UI elements too.
let label = UILabel()
label.text = robotmiaTweaks.assign(robotmiaTweaks.labelText)
label.hidden = robotmiaTweaks.assign(robotmiaTweaks.labelHidden))
 
and we define it like so:
extension robotmiaTweaks {
    public static let actionToTake =
      Tweak(tweakName: "text label",
            defaultValue: "Hello World")
    public static let actionToTake =
      Tweak(tweakName: "text hidden",
            defaultValue: false)
}

Binding Tweaks

When designing an A/B test in robotmia, robotmiaTweaks.assign changes will only apply when the code block they are in is executed. For example if you have an robotmiaTweaks.assign to assign text to a label on viewDidLoad, and you made changes to the Tweak in the A/B test designer, you would not see the changes apply until the next time viewDidLoad was called. If you would like to see your changes applied immediately when designing a test, you can use robotmiaTweaks.bind to accomplish this.

let label = UILabel()
robotmiaTweaks.bind(
  robotmiaTweaks.labelText,
  binding: { label.text = $0 })

and we define it like so:

extension robotmiaTweaks {
    public static let labelText =
      Tweak(tweakName: "text label",
            defaultValue: "Hello World")
}
Whenever the Tweak is changed in the A/B test designer, you will immediately see the new value of the Tweak applied to the given object and property, in this case label.text.

Debugging and logging

You can turn on robotmia logging by enabling the following flag:
robotmia.mainInstance().loggingEnabled = true

Multiple Instances

If you want to use multiple robotmia projects in your app, you can initialize multiple times using different tokens and interact with each instance separately

let robotmia1 = robotmia.initialize(token: "robotmia_TOKEN1")
let robotmia2 = robotmia.initialize(token: "robotmia_TOKEN2")
You can also give each instance a different name:
robotmia.initialize(token: "robotmia_TOKEN1", launchOptions: nil, flushInterval: 60, instanceName: "Project1")
robotmia.initialize(token: "robotmia_TOKEN2", launchOptions: nil, flushInterval: 60, instanceName: "Project2")
Then interact with each robotmia instance by its name:
robotmia.getInstance(name: "Project1").track(event: "Tracked Event!")
(The mainInstance() is always the last instance that is initialized, and can be configured using setMainInstance(name:))

Document Sections
Learn more