---
title: Track identity - iOS
description: Enhance user tracking with identify and addUserProperties APIs. Link anonymous and identified user data across sessions and devices for comprehensive analytics
lastUpdated: 23 October 2025
source_url:
  html: https://docs.contentsquare.com/en/csq-sdk-ios/product-analytics/track-identity/
  md: https://docs.contentsquare.com/en/csq-sdk-ios/product-analytics/track-identity/index.md
---

## User Identities and Properties

Contentsquare Product Analytics empowers you to use the rich information about your users to better understand how users interact with your site or app, and build charts to continually track engagement.

There are two primary APIs for enriching user data in Product Analytics:

* The [`CSQ.identify()`](../command-reference/#csqidentify) API allows you to attach a unique identity and maintain user histories across sessions and devices under a single profile,
* The [`CSQ.addUserProperties()`](../command-reference/#csqadduserproperties) API allows you to attach custom properties to your users, whether they are identified or still anonymous.

## Read This First: Key Considerations

Before implementing our APIs, check the following explanations on how these APIs work and common implementation mistakes to avoid.

### Anonymous Users

When a person interacts with your site or app, Product Analytics generates a random unique user ID and stores it in a cookie. In Product Analytics, these users will appear in the [Users ↗](https://developers.heap.io/docs/users) view as "User 123456" where the 123456 is their user ID. We refer to these users as anonymous users throughout this document.

Tip

Though this guide focuses on web use cases, the same principles apply to mobile. The user ID may be stored differently depending on the platform.

If a user visits your website on their mobile device and their laptop, Product Analytics will recognize 2 different anonymous users because both devices will have different cookies. We can identify these users on both platforms and link the two anonymous users into a single identified user.

Note

While Product Analytics can track identified users across different domains, it will not track anonymous users across domains. For cross-domain tracking support, we recommend using our APIs to identify users.

### Identified Users

You can use the `identify` API to attach your own unique identifier to a user. The `identify` API takes a single string value as an argument. Examples are provided further down in this guide in the [Examples section ↗](https://developers.heap.io/docs/using-identify#examples).

Warning

When a user is identified, their past sessions and event activity from when they were anonymous are now tied to that identity. This allows the user to use multiple devices/browsers to access your website with a single identity.

### User Properties

The [`CSQ.addUserProperties()`](../command-reference/#csqadduserproperties) API can be used to attach properties to users' profiles. Product Analytics sets some of these properties automatically, such as Initial Location, Initial Referrer, Initial Marketing Channel, and more. A full list of all user properties captured by default is available in [Autocaptured Data ↗](https://help.heap.io/getting-started/how-heap-works/autocaptured-data/). The [`CSQ.addUserProperties()`](../command-reference/#csqadduserproperties) API allows you to attach any string or number as a user property that’s not automatically captured.

Some practical properties to use include: payment plan, marketing segment, or A/B experiment. Once set, these properties can be used in charts to [group by ↗](https://developers.heap.io/docs/group-bys) and [filter ↗](https://developers.heap.io/docs/filters) against. Check out some specific examples further down this page.

### Common Identify Implementation Errors

Below we’ve listed the most common mistakes developers may make when implementing the `identify` API.

#### Using a Non-Unique Identifier

A common assumption is that a unique identifier attached via [`CSQ.identify()`](../command-reference/#csqidentify) is required in order for the [`CSQ.addUserProperties()`](../command-reference/#csqadduserproperties) API to attach properties to a user. In cases where a unique identifier isn't available, we've seen people include a specific name, like 'guest', or 'Anonymous User'.

This can cause irreversible behavior with how Product Analytics merges user profiles. You can call [`CSQ.addUserProperties()`](../command-reference/#csqadduserproperties) at any time, whether or not the user has been given a unique identity. For this reason, the following identify calls are blocklisted:

* `anonymous`
* `guest`
* `null`
* `true`
* `false`
* `not_authenticated`
* `NaN`
* `' '` (empty string)
* `0`
* `None`
* `none`
* `Email`
* `email`

As an example of how this would impact your setup: let's say that you have a marketing campaign, and you want to associate it with a visitor when they visit your landing page. They aren't logged in, so you don't have a unique identifier.

**Don't do this:**

```swift
CSQ.identify("guest")
CSQ.addUserProperties(["campaign": "Campaign Name"])
```

This will merge all visitors into a single user profile called 'guest', which will break any metrics that rely on user flow, or the unique user count.

**Instead, do this:**

```swift
CSQ.addUserProperties(["campaign": "Campaign Name"])
```

Now the campaign property will be associated with the anonymous user, using the value of the JavaScript variable 'campaign'.

### Adding an Anonymous Unique Identifier of Your Own

Some tools require a unique identifier to be provided to add user-level properties. This leads people to add their own unique identifier to all visitors. in Product Analytics automatically assigns each unidentified user a unique user ID so that you aren't required to call `identify` to add user-level properties. Assigning an identity to a user when it isn't required can lead to undesirable, or unexpected behavior.

Product Analytics does not allow you to change an already applied identity or assign multiple identities to the same user. If you call `identify` with an anonymized identity, such as a `uuid` or random hash, this will be their permanent identity in Product Analytics. If you call the identify API at another time for the same user with a different identity, such as an internal user ID or username, this will create a new user in Product Analytics, splitting this users into two identified users, one with the random `uuid` containing all of the historical events, and another with the user ID or username which has events going forward.

Since Product Analytics automatically creates a randomized unique identifier, it's not necessary for you to send your own identifier unless you are certain it is a unique, permanent identifier for the user. If you want to add properties to a user using [`CSQ.addUserProperties()`](../command-reference/#csqadduserproperties), you can do so without providing a unique identifier. Calling `CSQ.addUserProperties({property: 'value'})` will add this property to the anonymous user's Product Analytics profile automatically.

## When and Where to Call `identify` and `addUserProperties`

The [`CSQ.identify()`](../command-reference/#csqidentify) and [`CSQ.addUserProperties()`](../command-reference/#csqadduserproperties) APIs can be called anytime and anywhere the data is available about that user. The typical place for an identify call that includes a unique identifier is on any post-login or post-signup page. We recommend making an identify call on each page load as opposed to only the first page load.

When setting properties, it's OK to call the [`CSQ.addUserProperties()`](../command-reference/#csqadduserproperties) API on any page, though we recommend that you add user properties on identified users. This will greatly improve your experience when analyzing your user base.

You can place a [`CSQ.identify()`](../command-reference/#csqidentify) call within the Product Analytics installation snippet or outside of it. If you're adding a `CSQ.identify()` call within the snippet, it should be placed after `CSQ.start()` within that snippet.

### Identity Examples

#### Anonymous to New Identity

Let's say we have an internal user ID from our own database, and we want to identify a user based on that ID. We can do that like this:

```swift
// userID = "12345"
CSQ.identify(userID)
```

Now, their profile in the **Users** view will look like this:

![](https://files.readme.io/8834706-anon-to-identitified-api.png)

#### Anonymous to Existing Identity

In the last example, we identified a user with the unique user ID of 12345. Let's say that this person visits your site from their mobile device for the first time. Product Analytics will generate a new, random, unique userID, in this case it's 5404281197559477. In Product Analytics' users view, this visitor looks like this:

![](https://files.readme.io/4bbd657-anonymous-to-existing.png)

When this person logs in, and you recognize that their internal user ID is 12345, you can call identify like this:

```swift
//userID = "12345"
CSQ.identify(userID)
```

The previous user's profile with the random user ID of 1565941335949135 is merged, along with its previous sessions and events into the Heap profile of the identified user with the identity of 12345.

### addUserProperties Examples

#### Common User Properties

User properties can be used to capture additional data about a user, such as first and last name, email address, time zone, and account plan. The following example covers how to add an account plan user property using the [`CSQ.addUserProperties()`](../command-reference/#csqadduserproperties) API, and this can be modified to capture any of the previously mentioned user properties.

#### Account Plan

Many products include some sort of tiered pricing plan. Using the [`CSQ.addUserProperties()`](../command-reference/#csqadduserproperties) API to attach this information to your visitors' profiles can help you compare and contrast usage between different segments.

When someone visits Product Analytics, we pull their account tier from our database and inject that into an identify call like this:

```swift
CSQ.addUserProperties(["plan": "Startup"])
```

This lets us build powerful charts, like this bar chart showing sign-ups split by plan type.

### Industry Recommendations

Call `CSQ.addUserProperties()` in the part of your website flow where the data you want to capture is being presented. Below are some examples of places to call the API, based on industry.

| Industry | API Use Case | API Call Placement |
| - | - | - |
| e-Commerce | Improve personalization and recommendation algorithms. | On user login or significant actions (e.g., purchase). Attach properties like login info, purchase amount, and spender type. |
| Social media platform | Enhance user engagement and content personalization. | When a user updates their profile, adds interests, or engages in specific types of content. Attach custom properties like user interests or content preferences. |
| Subscription-based service | Understand user demographics and preferences to optimize its offerings. | When a user signs up, completes a survey, or changes subscription preferences. Attach custom properties such as geographical location, email, or subscription plan details. |

## What about the identity API?

Once you have the identify API set up, you can use [CSQ.metadata.identity](../command-reference/#csqmetadataidentity) to find a specific user's identity.
