iOS - Swift - Advanced

Getting Started

Please refer to our Quickstart Guide.

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 Mixpanel’s APIs will still be ingested regardless of whether the user is opted out locally.

The opt-out/opt-in state of a user is controlled by an opt-out flag that is stored in the local storage of the user’s device. If the value of the flag is true, then the user is opted-out and will not be tracked. If the opt-out flag is false, then the user is tracked. The flag is not set when the SDK is initialized, so the initial state is neither opted in nor opted out. Without the flag set, the user will be tracked by default.

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. By default, an "$opt_in" event is sent every time that a user opts in.

// Opt a user out of data collection

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

Opting Users Out of Tracking by Default

Mixpanel’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 mixpanel = 
    Mixpanel.initialize(token: "MIXPANEL_TOKEN", optOutTrackingByDefault: true)

Delete Existing Data

Opting users out of tracking will stop any future tracking. This does not automatically delete data that has already been collected. Mixpanel's deletion API can be used to delete existing data.

Automatically Track Events

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

Navigate to our editor by clicking the gear in the upper righthand corner of your Mixpanel project and selecting Codeless Tracking from the dropdown.

Sending Events

We recommend tracking only five to seven events in your application instead of tracking too many things to start. Ideally, you track users 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.

Mixpanel.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.

Mixpanel.mainInstance().time(event: "Image Upload")
//...some time later
Mixpanel.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. Mixpanel already stores some information as super properties by default; see a full list of Mixpanel default properties here.

To set super properties, call registerSuperProperties(_:)

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

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

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

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

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

Setting Super Properties 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.

Mixpanel.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.

Super Properties Live in Local Storage

Our mobile libraries store your super properties in local storage. They will persist so long as the app is installed (between launches and updates). Uninstalling the app will remove that customers super properties.

Group Analytics


Add Group Keys

To start tracking groups data, add group keys in project settings. If you don't see group keys in your Project Settings, reach out to the Mixpanel Sales Team to purchase Group Analytics.

Mixpanel Group Analytics allows behavioral data analysis by selected groups, as opposed to individual users.

Grouping by identifiers other than the distinct_id will allow analysis at a company or group level when using Mixpanel analytics. Read this article to learn more about Group Analytics.

A group is identified by the group_key and group_id.

  • group_key is the property that connects event data for Group Analytics.
  • group_id is the identifier for a specific group.

If the property “company” is chosen for Group Analytics, “company” is the group_key, and “Mixpanel”, “Company A”, and “13254” are all potential group_id values.

A user can belong to multiple groups. All updates to a group operate on the group_key and group_id.

Creating a Group Key

Administer group keys through your Project Settings. Group keys are event properties. All events need to have a defined group key on them in order to be attributed to a group. Group keys are project specific, and the group key should be set up before group data is sent. Note that Mixpanel does not backfill historical data before the group key was implemented.

To administer group keys, navigate to your Project Settings. Click +Add Group Key under the GROUP KEYS section.

Enter an event property to attribute the group key to. You can also enter a display name for the group key. Click Save.

Updating the SDK 2.5.9+ to Enable Group Analytics

Adding Users to a Group

Adding users to groups causes the group_key and group_id to send as a property key and value for all events triggered by that user on the device. You can add multiple values for a single user to the group_key list property.

Similar to a distinct_id, the group_key allows Mixpanel to group events by an identifier for analysis. A group_key, however, is a group level identifier and not a user level identifier like the distinct_id.

You can add users to groups by calling the setGroup() method.

Mixpanel.mainInstance().setGroup(groupKey: "Company", groupID: “Mixpanel”)

You can call addGroup() to add any additional groups to an existing list.

Mixpanel.mainInstance().addGroup(groupKey: "Company", groupID: “Mixpanel”)

You can call removeGroup() to remove any additional groups from an existing list.

Mixpanel.mainInstance().removeGroup(groupKey: "Company", groupID: “Mixpanel”)

Creating Group Profiles

It is possible to create a Group profile that is similar to a user profile. You must call getGroup().set() to build a group profile. It is important to the group_key, group_id, and one property so that the profile is not empty.

Mixpanel.mainInstance().getGroup(groupKey: "Company", groupID: “Mixpanel”).set(property: "g", to: "yo")

Setting Group Profile Properties

You can add details to Groups by adding properties to them.

In order to update Group profile properties, you must specify the group that needs to be updated by calling getGroup().set().

Mixpanel.mainInstance().getGroup(groupKey: "Company", groupID: “Mixpanel”)

The getGroup() method can be chained with other commands that edit properties specific to the group.

You can set the property $name to populate the name field at the top of the group profile.

These operations are similar to the corresponding operations for user profile property updates.


mixpanel.getGroup().set() updates or adds a property to a group.

Mixpanel.mainInstance().getGroup(groupKey: "Company", groupID: “Mixpanel”).set(property: "g", to: "yo")

set once

mixpanel.getGroup().setOnce() adds a property value to a group only if it has not been set before.

Mixpanel.mainInstance().getGroup(groupKey: "Company", groupID: “Mixpanel”).setOnce(properties: ["h": "just once"])


mixpanel.getGroup().unset() unsets a specific property in the group.

Mixpanel.mainInstance().getGroup(groupKey: "Company", groupID: “Mixpanel”).unset(property: "b")


mixpanel.getGroup().remove() removes a specific value in a list property.

Mixpanel.mainInstance().getGroup(groupKey: "Company", groupID: “Mixpanel”).remove(key: "c", value: 5)


mixpanel.getGroup().union() adds the specified values to a list property and ensures that those values only appear once.

Mixpanel.mainInstance().getGroup(groupKey: "Company", groupID: “Mixpanel”).union(key: "c", values: [5, 4])


mixpanel.getGroup().deleteGroup() deletes a group.

Mixpanel.mainInstance().getGroup(groupKey: "Company", groupID: “Mixpanel”).deleteGroup()

Managing User Identity

You can handle the identity of a user using the identify and alias methods. Proper use of these methods can connect events to the correct user as they move across devices, browsers, and other platforms.


Identify a user with a unique ID to track user activity across devices, tie a user to their events, and create a user profile. If you never call this method, unique visitors are tracked using a UUID that generates the first time they visit the site.






A string that uniquely identifies a user - we recommend a user id. If not provided, the distinct_id currently in the persistent store (cookie or localStorage) is used.

Call identify when you know the identity of the current user, typically after log-in or sign-up. We recommend against using identify for anonymous visitors to your site.


ID Merge

If a project has ID Merge enabled, the identify method will connect pre- and post-authentication events when appropriate.

If a project does not have ID Merge enabled, identify will change the user's local distinct_id to the unique ID you pass. Events tracked prior to authentication will not be connected to the same user identity. If ID Merge is disabled, alias can be used to connect pre and post registration events.


The alias method creates an alias which Mixpanel will use to remap one id to another. Multiple aliases can point to the same identifier.






A unique identifier that you want to use as an identifier for this user.



The current user identifier.

The following is a valid use of alias:

let mixpanel = Mixpanel.mainInstance()

mixpanel.createAlias("New ID",
    distinctId: mixpanel.distinctId);
mixpanel.createAlias("Newer ID",
    distinctId: mixpanel.distinctId);

Aliases can also be chained. You cannot point to multiple identifiers.


ID Merge

If a project does not have ID Merge enabled, the best practice is to call alias once when a unique ID is first created for a user (e.g., when a user first registers for an account). Do not use alias multiple times for a single user without ID Merge enabled.

Call Reset on Logout


Reset can fill an identity cluster if used frequently

Reset should only be used if multiple users share a device.

Calling reset frequently can lead to users quickly exceeding the 500 distinct_id per identity cluster limit. Once the 500 limit is reached you will no longer be able to add additional distinct_ids to the users identity cluster.

Reset generates a new random distinct_id and clears super properties. Call reset to clear data attributed to a user when that user logs out. This allows you to handle multiple users on a single device. For more information about maintaining user identity, see the Identity Management: Best Practices article.

Beginning with version v2.7.7, Mixpanel no longer uses the IFA(ID for Advertisers) but uses a randomly generated UUID as the default distinct ID instead. After you call reset, Mixpanel generates a new distinct_id.

If you want to use IFV(identifierForVendor) as the distinct_id, you can set
MIXPANEL_UNIQUE_DISTINCT_ID in build settings Active Compilation Conditions on the Mixpanel framework target. After you call reset, the IFV will not change. However, when a user removes and then re-installs the app, the IFV will change with each installation.

Storing User Profiles

In addition to events, you can store user profiles in Mixpanel. User 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"
Mixpanel.mainInstance().people.set(properties: [ "plan":"Premium", "$email":"[email protected]"])

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 Mixpanel 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".



Pick your property names wisely. Once you've sent them to Mixpanel, there is no way to change them. Feel free to use capitalization and spaces in between words.
There are a few limitations:

  • Your property names should not begin with $ or mp_. These properties are reserved for special properties sent by Mixpanel.
  • Your property names cannot begin or end with a space as they will automatically be trimmed.
  • Your property names and values cannot be longer than 255 characters. In practice they should be much shorter than that. Property names get cut off by our user interface at about 20 characters.

Click here to see a list of Mixpanel's reserved user profile properties.

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.
Mixpanel.mainInstance().people.increment(property: "point count",
    by: 500)

// Pass an NSDictionary to increment multiple 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 MixpanelPeople API documentation.

Tracking Revenue

Mixpanel 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 Mixpanel Revenue report.

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

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

Registering for Push Notifications


Messaging and Mobile A/B Testing Deprecation

Messaging and mobile A/B testing are not available for purchase and will be deprecated from the product on January 1st, 2022. Read more information on the Mixpanel blog.

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

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

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
    // This sends the deviceToken to Mixpanel
    let mixpanel = Mixpanel.mainInstance()

Push Notifications Quick Start Guides

There is a step by step guide to integrating Mixpanel 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 Mixpanel.

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 Mixpanel 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 Mixpanel website

A/B Testing Experiments


Messaging and Mobile A/B Testing Deprecation

Messaging and mobile A/B testing are not available for purchase and will be deprecated from the product on January 1st, 2022. Read more information on the Mixpanel blog.


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

Make sure that you have already:

  1. Included the latest version of the Mixpanel Swift library in your app (v2.5+)
  2. Created an experiment on the A/B Testing tab of the Mixpanel 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.



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

Mixpanel 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:) or joinExperimentsWithCallback methods 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 Mixpanel 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 MixpanelTweaks and then setting the Tweaks in the SDK. As an example here we are extending MixpanelTweaks and defining a few Tweaks of different types:

extension MixpanelTweaks {
    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 Mixpanel Library with the project token, we set the Tweaks (it makes sense to do this in application(_:didFinishLaunchingWithOptions:).

Mixpanel.initialize(token: "MIXPANEL_TOKEN")
 let allTweaks: [TweakClusterType] =
 MixpanelTweaks.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 = MixpanelTweaks.assign(

and we define it like so:

extension MixpanelTweaks {
    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 Mixpanel 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 MixpanelTweaks.assign(MixpanelTweaks.showAlterateView) {
     // Show alternate view.
 } else {
     // Show original view

and we define it like so:

extension MixpanelTweaks {
     public static let actionToTake =
       Tweak(tweakName: "action to take",
             defaultValue: 1)

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 MixpanelTweaks.assign(MixpanelTweaks.actionToTake) {
     case 1:
         // Do something
     case 2:
         // Do something else
     case 3:
         // Do a third thing

and we define it like so:

switch MixpanelTweaks.assign(MixpanelTweaks.actionToTake) {
     case 1:
         // Do something
     case 2:
         // Do something else
     case 3:
         // Do a third thing

You can use Tweaks to assign values to UI elements too.

let label = UILabel()
label.text = MixpanelTweaks.assign(MixpanelTweaks.labelText)
label.hidden = MixpanelTweaks.assign(MixpanelTweaks.labelHidden))

and we define it like so:

extension MixpanelTweaks {
    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 Mixpanel, MixpanelTweaks.assign changes will only apply when the code block they are in is executed. For example if you have an MixpanelTweaks.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 MixpanelTweaks.bind to accomplish this.

let label = UILabel()
  binding: { label.text = $0 })

and we define it like so:

extension MixpanelTweaks {
    public static let labelText =
      Tweak(tweakName: "text label",
            defaultValue: "Hello World")

The first 2 arguments are an object and a property. 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 Mixpanel logging by enabling the following flag:

Mixpanel.mainInstance().loggingEnabled = true

Multiple Instances

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

let mixpanel1 = Mixpanel.initialize(token: "MIXPANEL_TOKEN1")
let mixpanel2 = Mixpanel.initialize(token: "MIXPANEL_TOKEN2")

You can also give each instance a different name:

Mixpanel.initialize(token: "MIXPANEL_TOKEN1", launchOptions: nil, flushInterval: 60, instanceName: "Project1")
Mixpanel.initialize(token: "MIXPANEL_TOKEN2", launchOptions: nil, flushInterval: 60, instanceName: "Project2")

Then interact with each Mixpanel instance by its name:

Mixpanel.getInstance(name: "Project1").track(event: "Tracked Event!")

The mainInstance() is always the last instance that is initialized, and can be configured using setMainInstance(name:).

EU Data Residency

Route data to Mixpanel's EU servers by setting the serverURL property after initializing the client.

mixpanel = Mixpanel.initialize(token: "MIXPANEL_TOKEN")
mixpanel.serverURL = ""

Release History

See All Releases.

Did this page help you?