Skip to main content

User Profiles

The following terms are used in this section:
  • “Profiles” is used to refer to both “User Profiles” and “Group Profiles”
  • “Profile Properties” is used to refer to both “User Profile Properties” and “Group Profile Properties”

Overview

User Profiles let you enrich events with demographic attributes (i.e. user properties) about the users that performed those events. User Profiles are optional. We recommend starting with events and adding user profiles only if needed. A user profile has a set of user properties associated with a given user. Under the hood, Mixpanel stores user data for your project in a table wherein each row of user profile contain columns of user properties (e.g. Name, Email, Department) that can be updated:
Distinct IDNameEmailDepartment
123Alice[email protected]Engineering
456Bob[email protected]Product
789Carol[email protected]Design
User profiles are joined onto your events based on their Distinct ID (Mixpanel’s identifier for a user). This lets you join the events performed by a user with user properties describing them. Thus, it is very important that you use the same Distinct ID for both the events and user profile for the same user.
If you have Group Analytics as an add-on, this section also applies to Group Profiles.

Importing Profiles via API

You can create or update User Profiles in similar ways you track events: from our SDKs, via our HTTP Engage API, Warehouse Connectors, or via our integrations partners. We recommend tracking profiles from as close as possible to the source of truth, which is usually your application database or your CRM. One typical approach (especially for Server-Side Tracking) is to run an hourly or daily script on your servers that pulls the list of profiles from your database and pushes them to Mixpanel.

Operators

The HTTP Engage API and HTTP Groups API share the same operators: Setting profile property
  • $set - Sets a profile property or updates a profile property value (if it already exists).
  • $set_once - Sets a profile property only if they do not yet exist on Mixpanel. This ensures that the previous profile property value is not overwritten.
Updating numeric profile property
  • $add - Increments or decrements a numeric user profile property (not supported in group profiles). To increment, pass in a positive numeric value, and to decrement pass in a negative numeric value. If the property does not yet exist, it will set the value passed in as the initial value.
Updating list profile property
  • $union - Merges a given value or list into a List data type profile property and ensures there are no duplicate values.
  • $append - Appends a value to the end of a List data type user profile property (not supported in group profiles). Does not check for duplicate values.
  • $remove - Removes a value from a List data type profile property.
Removing profile properties
  • $unset - Removes a profile property from the profile.
  • $delete - Removes all profile properties from the profile.

Sample Code

Here’s some sample code to get you started, utilizing the $set operator to update user profiles:
# Fill this out. You can get it from https://mixpanel.com/settings/project
PROJECT_TOKEN = ""

import json
import requests


def get_users_from_database():
    # Replace this with code that reads users from your database or CRM.
    # Note: $name and $email are optional, but useful properties that automatically populate certain parts of our UI when Mixpanel detects them.
    return [
        {"user_id": "123", "$name": "Alice", "$email": "[email protected]", "department": "engineering"},
        {"user_id": "456", "$name": "Bob", "$email": "[email protected]", "department": "product"},
        {"user_id": "789", "$name": "Carol", "$email": "[email protected]", "department": "design"}
    ]

def transform_to_mp_format(user):
    """Transform the above into Mixpanel's format"""
    # It's important to set this to the same distinct_id that you use when tracking events.
    # We recommend using the primary key of your users' table for this.
    distinct_id = user.pop("user_id")

    # Note: we set `$ip` to 0 here to tell Mixpanel not to look up the IP of this user.
    return {"$distinct_id": distinct_id, "$token": PROJECT_TOKEN, "$ip": "0", "$set": user}


users = get_users_from_database()
profiles = [transform_to_mp_format(u) for u in users]

# We recommend calling this API with batches of 200 user profiles to do this at scale.
resp = requests.post(
    "https://api.mixpanel.com/engage",
    params={"verbose": "2"},
    headers={"Content-Type": "application/json"},
    data=json.dumps(profiles)
)

print(resp.json())

Importing Profiles via the UI

To get started, click on Add/Edit Profile from the Users page and follow the workflow below.
For customers with Group Analytics make sure you first choose either User or the Group Key name depending on which type of profile you wish to import.
Import Profile UI

Create/Update a Single Profile

Set an Identifier Column The most important column is $distinct_id for user profiles (or $group_id for Group Profiles). The value needs to match the distinct_id property’s value (or the value for the Group Key’s Group ID) that you’re sending on your events. Add Additional Properties After $distinct_id, you can add additional properties to the profile by pressing the ”+ Add Property” button. Mixpanel will help autocomplete profile properties that you may want to set. Add Profile Properties We recommend using the $name (or $first_name, $last_name), $email, and $phone Reserved Profile Properties if you’re uploading a user’s name, email, or phone. Mixpanel shows these properties by default in various parts of our UI and are used for Cohort Syncs as well.

Bulk Import from CSV

When preparing the CSV that you want to upload as profiles, you should not include column headers (e.g., name,name, email, etc.). Instead, you’ll identify column headers through the CSV upload wizard in the Mixpanel UI.
  • If you import profiles using $distinct_id (or $group_id) values that already exist, those profiles will be updated with the additional profile properties.
  • If you upload a CSV with new information for existing properties on existing profiles, the existing property values will be overwritten.
  • The maximum size for your CSV should be 1M rows.

Reserved Profile Properties

Mixpanel reserves certain property names for special use cases:
PropertyDisplay NameDescription
$distinct_idDistinct IDMixpanel’s internal unique identifier for a profile.
$name, $first_name, $last_nameName, First Name, Last NameThe user’s name. Used in various Mixpanel UI/reports.
$emailEmailThe user’s email address. Required for sending emails to users via Cohort Syncs.
$phonePhoneThe user’s phone number. Required for sending SMS to users via Cohort Syncs. Note that a ’+’ needs to precede international phone numbers.
$avatarAvatar URLSet this property to a URL resource of a gif, jpg, jpeg, or png to update the profile picture.
$createdCreatedThe time that the profile was created. Note that this is not auto-populated.
$mp_first_event_timeFirst SeenMixpanel calculated property that represents the time of the user’s very first event in Mixpanel.

How Events and Profiles Join

Mixpanel stores Events and User Profiles in two separate tables under the hood. These two tables are joined at query-time, rather than ingestion-time. This means that when you make a report in our UI that uses User Profiles, we run a query that joins the Events table with the User Profiles table. Key implications:
  • If you track User Profiles after you track events, they’ll still join retroactively with all past events. This means that you don’t need to worry about tracking Events and User Profiles in lockstep with each other. As long as they have the same values for Distinct ID, they’ll join with each other.
  • All Events join with the latest state of a User Profile, rather than its state at a point in time. If there are aspects of a user’s state that change over time (for example, their plan type), we recommend tracking that as a property on their events, so that you can analyze that change over time.

Profile Limits

  • Properties per profile: Each User Profile can contain up to 2000 properties.
  • Property name length: User property names can be at most 255 characters in length (longer names are truncated).
  • Property value length: User property values are limited based on data type.
Attempts to add more than 2000 user properties for a user profile will fail. You can remove User Properties using the $unset engage operation if you find yourself close to the 2000 per profile limit.

Deleting Profiles

User Profiles can be deleted either via the Users page or programmatically via our Engage API.
Deleting a user profile removes only the user property data. It does not delete the user’s tracked events; instead, those events continue to appear in your project as if they were tracked by anonymous users without user profile properties.

FAQ

What should I send as a User Property vs an Event Property?

We recommend primarily using User Properties to track demographic attributes of the user, like their name, email, and domain. Most other properties are better tracked as Event Properties. That said, User Properties are as flexible as any other properties in Mixpanel, so you can send arbitrary JSON.

What does the “Updated at” ($last_seen) property mean?

User Profiles are mutable, which means new ones can be added and existing ones can be updated or deleted. Mixpanel automatically maintains an “Updated at” ($last_seen) property, which contains the last timestamp that a user profile was updated. “Updated at” does not change if the user does a new event; it only changes when the profile is updated. “Updated at” also does not change for profile updates made via the UI or if the $ignore_time parameter is set to true.

Build docs developers (and LLMs) love