• Product
  • Pricing
  • Docs
  • Using PostHog
  • Community
  • Company
  • Login
  • Docs

  • Overview
    • Quickstart with PostHog Cloud
    • Overview
    • Open-Source
      • Disclaimer
      • Deployment
      • Support
    • Enterprise
      • Overview
      • Support
      • Hosting Costs
        • AWS
        • Azure
        • DigitalOcean
        • Google Cloud Platform
        • EU Hosting Companies
        • Other platforms
      • Instance settings
      • Environment variables
      • Securing PostHog
      • Monitoring with Grafana
      • Running behind a proxy
      • Configuring email
      • Helm chart configuration
      • Deploying ClickHouse using Altinity.Cloud
      • Configuring Slack
      • Overview
        • Overview
        • Upgrade notes
        • Overview
        • 0001-events-sample-by
        • 0002_events_sample_by
        • 0003_fill_person_distinct_id2
        • ClickHouse
          • Backup
          • Debug hanging / freezing process
          • Horizontal scaling (Sharding & replication)
          • Kafka Engine
          • Resize disk
          • Restore
          • Vertical scaling
        • Kafka
          • Resize disk
          • Log retention
        • PostgreSQL
          • Resize disk
          • Troubleshooting long-running migrations
        • Plugin server
          • Overview
          • Ingestion lag
          • Jobs not executing
          • Scheduled tasks not executing
        • MinIO
        • Redis
        • Zookeeper
      • Disaster recovery
    • Troubleshooting and FAQs
    • Overview
    • Ingest live data
    • Ingest historical data
    • Identify users
    • User properties
    • Using a CDP
    • Deploying a reverse proxy
    • Library comparison
    • Badge
    • Browser extensions
      • Snippet installation
      • Android
      • iOS
      • JavaScript
      • Flutter
      • React Native
      • Node.js
      • Go
      • Python
      • Rust
      • Java
      • PHP
      • Ruby
      • Elixir
      • Docusaurus v2
      • Gatsby
      • Google Tag Manager
      • Next.js
      • Nuxt.js
      • Retool
      • RudderStack
      • Segment
      • Sentry
      • Slack
      • Shopify
      • WordPress
      • Message formatting
      • Microsoft Teams
      • Slack
      • Discord
    • Migrate between PostHog instances
    • Migrate from Amplitude
    • Migrate to PostHog Cloud EU
    • To another self-hosted instance
    • Export your events
    • Overview
    • Tutorial
    • Troubleshooting
    • Developer reference
    • Using the PostHog API
    • Jobs
    • Testing
    • TypeScript types
    • Overview
    • POST-only public endpoints
    • Actions
    • Annotations
    • Cohorts
    • Dashboards
    • Event definitions
    • Events
    • Experiments
    • Feature flags
    • Funnels
    • Groups
    • Groups types
    • Insights
    • Invites
    • Members
    • Persons
    • Plugin configs
    • Plugins
    • Projects
    • Property definitions
    • Session recordings
    • Trends
    • Users
    • Data model
    • Overview
    • Data model
    • Ingestion pipeline
    • ClickHouse
    • Querying data
    • Overview
    • GDPR guidance
    • HIPAA guidance
    • CCPA guidance
    • SOC 2
    • Data egress & compliance
    • Data deletion
    • Overview
    • Code of conduct
    • Recognizing contributions
  • Using PostHog

  • Table of contents
      • Dashboards
      • Funnels
      • Group Analytics
      • Insights
      • Lifecycle
      • Path analysis
      • Retention
      • Stickiness
      • Trends
      • Heatmaps
      • Session Recording
      • Correlation Analysis
      • Experimentation
      • Feature Flags
      • Actions
      • Annotations
      • Cohorts
      • Data Management
      • Events
      • Persons
      • Sessions
      • UTM segmentation
      • Team collaboration
      • Organizations & projects
      • Settings
      • SSO & SAML
      • Toolbar
      • Notifications & alerts
    • Overview
      • Amazon Kinesis Import
      • BitBucket Release Tracker
      • Event Replicator
      • GitHub Release Tracker
      • GitHub Star Sync
      • GitLab Release Tracker
      • Heartbeat
      • Ingestion Alert
      • Email Scoring
      • n8n Connector
      • Orbit Connector
      • Redshift Import
      • Rudderstack Import
      • Segment Connector
      • Shopify Connector
      • Stripe Connector
      • Twitter Followers Tracker
      • Zendesk Connector
      • Airbyte Exporter
      • Amazon S3 Export
      • Avo Inspector
      • BigQuery Export
      • Customer.io Connector
      • Databricks Export
      • Engage Connector
      • GCP Pub/Sub Connector
      • Google Cloud Storage Export
      • Hubspot Connector
      • Intercom Connector
      • PagerDuty Connector
      • PostgreSQL Export
      • Redshift Export
      • RudderStack Export
      • Salesforce Connector
      • Sendgrid Connector
      • Sentry Connector
      • Snowflake Export
      • Twilio Connector
      • Variance Connector
      • Pace Integration
      • Zapier Connector
      • Downsampler
      • Event Sequence Timer
      • First Time Event Tracker
      • Property Filter
      • Property Flattener
      • Schema Enforcer
      • Taxonomy Standardizer
      • Unduplicator
      • Advanced GeoIP Enricher
      • Automatic Cohort Creator
      • Currency Normalizer
      • GeoIP Enricher
      • Timestamp Parser
      • URL Normalizer
      • User Agent Populator
      • Pineapple Mode
  • Tutorials
    • Actions
    • Apps
    • Cohorts
    • Configuration
    • Data management
    • Dashboards
    • Experimentation
    • Feature flags
    • Funnels
    • Group analytics
    • Heatmaps
    • Insights
    • Path analysis
    • Retention
    • Session recording
    • Toolbar
    • Trends
  • Support
  • Glossary
  • Docs

  • Overview
    • Quickstart with PostHog Cloud
    • Overview
    • Open-Source
      • Disclaimer
      • Deployment
      • Support
    • Enterprise
      • Overview
      • Support
      • Hosting Costs
        • AWS
        • Azure
        • DigitalOcean
        • Google Cloud Platform
        • EU Hosting Companies
        • Other platforms
      • Instance settings
      • Environment variables
      • Securing PostHog
      • Monitoring with Grafana
      • Running behind a proxy
      • Configuring email
      • Helm chart configuration
      • Deploying ClickHouse using Altinity.Cloud
      • Configuring Slack
      • Overview
        • Overview
        • Upgrade notes
        • Overview
        • 0001-events-sample-by
        • 0002_events_sample_by
        • 0003_fill_person_distinct_id2
        • ClickHouse
          • Backup
          • Debug hanging / freezing process
          • Horizontal scaling (Sharding & replication)
          • Kafka Engine
          • Resize disk
          • Restore
          • Vertical scaling
        • Kafka
          • Resize disk
          • Log retention
        • PostgreSQL
          • Resize disk
          • Troubleshooting long-running migrations
        • Plugin server
          • Overview
          • Ingestion lag
          • Jobs not executing
          • Scheduled tasks not executing
        • MinIO
        • Redis
        • Zookeeper
      • Disaster recovery
    • Troubleshooting and FAQs
    • Overview
    • Ingest live data
    • Ingest historical data
    • Identify users
    • User properties
    • Using a CDP
    • Deploying a reverse proxy
    • Library comparison
    • Badge
    • Browser extensions
      • Snippet installation
      • Android
      • iOS
      • JavaScript
      • Flutter
      • React Native
      • Node.js
      • Go
      • Python
      • Rust
      • Java
      • PHP
      • Ruby
      • Elixir
      • Docusaurus v2
      • Gatsby
      • Google Tag Manager
      • Next.js
      • Nuxt.js
      • Retool
      • RudderStack
      • Segment
      • Sentry
      • Slack
      • Shopify
      • WordPress
      • Message formatting
      • Microsoft Teams
      • Slack
      • Discord
    • Migrate between PostHog instances
    • Migrate from Amplitude
    • Migrate to PostHog Cloud EU
    • To another self-hosted instance
    • Export your events
    • Overview
    • Tutorial
    • Troubleshooting
    • Developer reference
    • Using the PostHog API
    • Jobs
    • Testing
    • TypeScript types
    • Overview
    • POST-only public endpoints
    • Actions
    • Annotations
    • Cohorts
    • Dashboards
    • Event definitions
    • Events
    • Experiments
    • Feature flags
    • Funnels
    • Groups
    • Groups types
    • Insights
    • Invites
    • Members
    • Persons
    • Plugin configs
    • Plugins
    • Projects
    • Property definitions
    • Session recordings
    • Trends
    • Users
    • Data model
    • Overview
    • Data model
    • Ingestion pipeline
    • ClickHouse
    • Querying data
    • Overview
    • GDPR guidance
    • HIPAA guidance
    • CCPA guidance
    • SOC 2
    • Data egress & compliance
    • Data deletion
    • Overview
    • Code of conduct
    • Recognizing contributions
  • Using PostHog

  • Table of contents
      • Dashboards
      • Funnels
      • Group Analytics
      • Insights
      • Lifecycle
      • Path analysis
      • Retention
      • Stickiness
      • Trends
      • Heatmaps
      • Session Recording
      • Correlation Analysis
      • Experimentation
      • Feature Flags
      • Actions
      • Annotations
      • Cohorts
      • Data Management
      • Events
      • Persons
      • Sessions
      • UTM segmentation
      • Team collaboration
      • Organizations & projects
      • Settings
      • SSO & SAML
      • Toolbar
      • Notifications & alerts
    • Overview
      • Amazon Kinesis Import
      • BitBucket Release Tracker
      • Event Replicator
      • GitHub Release Tracker
      • GitHub Star Sync
      • GitLab Release Tracker
      • Heartbeat
      • Ingestion Alert
      • Email Scoring
      • n8n Connector
      • Orbit Connector
      • Redshift Import
      • Rudderstack Import
      • Segment Connector
      • Shopify Connector
      • Stripe Connector
      • Twitter Followers Tracker
      • Zendesk Connector
      • Airbyte Exporter
      • Amazon S3 Export
      • Avo Inspector
      • BigQuery Export
      • Customer.io Connector
      • Databricks Export
      • Engage Connector
      • GCP Pub/Sub Connector
      • Google Cloud Storage Export
      • Hubspot Connector
      • Intercom Connector
      • PagerDuty Connector
      • PostgreSQL Export
      • Redshift Export
      • RudderStack Export
      • Salesforce Connector
      • Sendgrid Connector
      • Sentry Connector
      • Snowflake Export
      • Twilio Connector
      • Variance Connector
      • Pace Integration
      • Zapier Connector
      • Downsampler
      • Event Sequence Timer
      • First Time Event Tracker
      • Property Filter
      • Property Flattener
      • Schema Enforcer
      • Taxonomy Standardizer
      • Unduplicator
      • Advanced GeoIP Enricher
      • Automatic Cohort Creator
      • Currency Normalizer
      • GeoIP Enricher
      • Timestamp Parser
      • URL Normalizer
      • User Agent Populator
      • Pineapple Mode
  • Tutorials
    • Actions
    • Apps
    • Cohorts
    • Configuration
    • Data management
    • Dashboards
    • Experimentation
    • Feature flags
    • Funnels
    • Group analytics
    • Heatmaps
    • Insights
    • Path analysis
    • Retention
    • Session recording
    • Toolbar
    • Trends
  • Support
  • Glossary
  • Docs
  • Integrate PostHog
  • Identify users

Identifying users

Last updated: Dec 20, 2022

On this page

  • Considerations
  • Filtering internal users
  • Signup flow with frontend and backend
  • Example login flow
  • Things to be aware of

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

Authors

  • Neil Kakkar
    Neil Kakkar
  • Ben White
    Ben White
  • justinjones
    justinjones

Share

Jump to:

  • Considerations
  • Filtering internal users
  • Signup flow with frontend and backend
  • Example login flow
  • Things to be aware of
  • Questions?
  • Product

  • Overview
  • Pricing
  • Product analytics
  • Session recording
  • A/B testing
  • Feature flags
  • Apps
  • Customer stories
  • PostHog vs...
  • Docs

  • Quickstart guide
  • Self-hosting
  • Installing PostHog
  • Building an app
  • API
  • Webhooks
  • How PostHog works
  • Data privacy
  • Using PostHog

  • Product manual
  • Apps manuals
  • Tutorials
  • Community

  • Questions?
  • Product roadmap
  • Contributors
  • Partners
  • Newsletter
  • Merch
  • PostHog FM
  • PostHog on GitHub
  • Handbook

  • Getting started
  • Company
  • Strategy
  • How we work
  • Small teams
  • People & Ops
  • Engineering
  • Product
  • Design
  • Marketing
  • Customer success
  • Company

  • About
  • Team
  • Investors
  • Press
  • Blog
  • FAQ
  • Support
  • Careers
© 2023 PostHog, Inc.
  • Code of conduct
  • Privacy policy
  • Terms