Identifying users

Last updated:

PostHog allows you to identify your users with an ID of your choice so you can track users across platforms, connect events from before and after users log in, and leverage your preferred type of ID for filtering through your users.

Identifying users is usually done via our libraries, by calling the identify or alias method. This method will associate an anonymous ID with a distinct ID of your choice. In client libraries, the anonymous ID is stored locally and inferred for you, but in server-side libraries you need to tell PostHog what that anonymous ID is too.

For example, if you identify an user in your website as follows:

JavaScript
// posthog-js
posthog.identify('my_user_12345')

PostHog will then pull their anonymous ID (e.g. 17b845b08de74-033c497ed2753c-35667c03-1fa400-17b845b08dfd55) and associate it with the ID you passed in (my_user_12345).

From now on, all events PostHog sees with ID 17b845b08de74-033c497ed2753c-35667c03-1fa400-17b845b08dfd55 will be attributed to the person with ID my_user_12345. This person now has 2 distinct IDs, and either of them can be used to reference the same person.

Considerations

Identifying users is a powerful feature, but it also has the potential to create problems if misused.

An important mistake to avoid is using non-unique distinct IDs to identify users. Two common ways in which this can happen are:

  • Your logic for generating IDs does not generate sufficiently strong IDs and you can end up with a clash where 2 users have the same ID
  • There's a bug, typo, or mistake in your code leading to most or all users being identified with generic IDs like null, true, or distinctId

All of the above scenarios are highly problematic, as they will cause distinct users to be merged together in PostHog.

While implementing analytics with PostHog, make sure you avoid above pitfalls to maintain data integrity.

PostHog also has a few built-in protections stopping the most common threats to data integrity:

  • We do not allow identifying users with the following IDs (case insensitive):
    • anonymous
    • guest
    • distinctid
    • distinct_id
    • id
    • not_authenticated
    • email
    • undefined
    • true
    • false
  • We do not allow identifying users with the following IDs (case sensitive):
    • [object Object]
    • NaN
    • None
    • none
    • null
    • 0
  • We do not allow identifying users with empty space strings of any length (' ', ' ', etc.)
  • We do not allow merging from an already identified user (distinct_id user can be previously identified, but anon_distinct_id and alias user cannot).

If we encounter an $identify or $create_alias event with one of the above problems, the following will happen:

  • We process the event normally (it will be ingested and show up in the UI)
  • We refuse to merge users and an ingestion warning will be logged (see ingestion warnings for more details).
  • The event will be only be tied to user behind the first passed distinct_id

Filtering internal users

If you want to avoid tracking users within your organization, you can do this within your project's settings.

Signup flow with frontend and backend

To use PostHog effectively we want all of the events tied to the same user to be tied to the same person_id (see consequences of merging users).

For when a user signs up to your service you may trigger some events on the frontend and the backend. The key is to make sure that both frontend and backend use the same distinctId at least once.

Example login flow

On the backend (example with Node.JS) you receive the signup / login code and track the user

JavaScript
const user = await createUser();
posthog.identify({
distinctId: user.id,
properties: {
email: user.email
}
})

On the frontend you need to have the same ID passed down in order to link the two users

JavaScript
const user = await fetch("/api/users/@me")
posthog.identify(user.id)

If you use a different identifier or multiple identifiers, be sure to alias the two IDs together for example on the backend with posthog-node

JavaScript
posthog.alias({
distinctId: user.id,
alias: user.alternativeId,
})

Things to be aware of

There's a few things to keep in mind when using a sign-up flow that involves both the frontend and backend:

  1. We have an event buffer to delay creating persons from backend events (see all about the event buffer) that will help.
  2. The event buffer has a limited time window, so the (identify or alias) event that merges the frontend and backend user should come in within that window (60s)
  3. We don't buffer $identify events, so from the backend take care to not send those for setting properties before the users are merged. For setting user properties you can use any custom event, e.g.
Python
posthog.capture(
'distinct id',
event='movie played',
properties={ '$set': { 'userProperty': 'value' } }
)

Questions?

Was this page useful?

Next article

User properties

Setting properties The easiest way to set properties is to add the properties to the identify function during the initial login. Identify the user and set the user properties To update the properties of a user you can use set , set_once , and $unset . Depending on the integration library the actual function calls look a bit different, but internally they all work the same way. set : Set the property even if the property exists on the user set_once : Set the property if the property does not…

Read next article