Unique users is PostHog's way of counting how many distinct people have used your product. If you're shipping features but not sure whether new people are showing up, or whether your DAU/MAU is actually growing, you need to understand how PostHog identifies individual users. It all comes down to the distinct_id.
How PostHog Identifies Unique Users
Every event in PostHog has a distinct_id — a string that identifies the person who triggered it. This is the foundation of unique user counting.
Call identify() to set a user ID
When someone signs up or logs in, use posthog.identify() to link them to a stable identifier. This can be their user ID from your database, email, or any unique string. Once you do this, all subsequent events from that person will be tracked under the same distinct_id. This is non-negotiable if you want meaningful user analytics.
posthog.identify('user_12345', {
email: '[email protected]',
plan: 'pro',
company: 'Acme Corp'
});Track events with that user context
Once you've called identify(), any capture() calls will automatically include the distinct_id you set. You don't have to pass it manually — PostHog handles it behind the scenes. This means you can track user behavior across pages, sessions, and devices as long as you've identified them once.
posthog.capture('feature_viewed', {
feature_name: 'advanced_reporting',
duration_seconds: 45
});
// PostHog associates this event with 'user_12345'Understand anonymous vs. identified users
Before you call identify(), PostHog creates an anonymous user using a client-side ID (stored in a cookie or localStorage). Once you identify them, all past and future events are merged under the real distinct_id. This is important: PostHog's unique user count includes everyone who generated at least one event, whether identified or anonymous.
// User lands on your site - anonymous so far
posthog.capture('page_view', { path: '/' });
// User signs up
posthog.identify('user_12345', { email: '[email protected]' });
// PostHog merges: previous page_view now attributed to user_12345identify(), PostHog will still count the user, but under an anonymous ID. You won't be able to segment by user properties like email or plan. Always identify as soon as you know who they are.Viewing Unique Users in the Dashboard
Once you're tracking users properly, you'll see them in PostHog's analytics interface.
Navigate to **Insights** and create a new insight
Open PostHog and click Insights in the left sidebar. Click New insight or New. Choose Trends if you want to see unique user counts over time, or Funnels if you want to track how many people pass through a sequence of events.
// You can also query via the PostHog API:
const response = await fetch('https://posthog.YOUR_DOMAIN.posthog.com/api/projects/YOUR_PROJECT_ID/insights/', {
method: 'GET',
headers: {
'Authorization': `Bearer ${POSTHOG_API_KEY}`
}
});Add your event and switch to **Unique users**
Select the event you want to analyze (e.g., 'page_view', 'feature_used', or 'signup'). Then click the Count dropdown and select Unique users instead of event count. PostHog will now show you how many distinct people triggered that event, broken down by time period.
// The UI does this, but the underlying query uses 'unique' aggregation
// If querying via SQL or API:
SELECT COUNT(DISTINCT distinct_id) as unique_users
FROM events
WHERE event = 'page_view'
AND timestamp > now() - interval 7 day;Filter by properties and cohorts
Use Filter to narrow down your analysis. You can segment by user properties (plan, country, company), custom event properties, or predefined cohorts. This tells you how many unique users match your criteria — for example, how many pro users viewed a specific feature this week.
// When you set a filter in the UI, it translates to a query like:
SELECT COUNT(DISTINCT distinct_id) as unique_users
FROM events
WHERE event = 'feature_viewed'
AND properties->>'plan' = 'pro'
AND timestamp > now() - interval 30 day;Common Gotchas with Unique Users
Understanding how PostHog counts unique users helps you avoid misinterpreting your data.
Unidentified users are still counted
If someone visits your site and never signs up, PostHog still counts them as a unique user (under an anonymous distinct_id). This can make your total unique user count look much higher than your actual registered users. Cross-check with your database to understand how many of your 'unique users' are actually paying customers.
// PostHog counts this person as 'unique' even though you don't know who they are
posthog.capture('page_view', { path: '/pricing' });
// distinct_id is auto-generated by PostHog
// You only know who they are if you call identify()Multiple distinct_ids for one person create duplicates
If you identify the same person with different IDs (e.g., email first, then user ID), PostHog treats them as two separate people. Use a single, stable identifier per person from the start. If you've already created duplicates, use PostHog's Person Merge feature under Data Management to combine them.
// ❌ Bad: two calls with different IDs
posthog.identify('[email protected]');
// ...later...
posthog.identify('user_12345');
// Now PostHog thinks these are two different people
// ✅ Good: use a single stable ID
posthog.identify('user_12345', { email: '[email protected]' });Reset and re-identify for device sharing
If someone logs out and a different person logs in on the same device, call posthog.reset() before identifying the new user. Otherwise, events from both people will be attributed to the first person. This is critical for shared devices or public computers.
// User logs out
posthog.reset();
// New user logs in
posthog.identify('user_67890', {
email: '[email protected]',
plan: 'free'
});
// Now events are attributed to the new user, not the previous oneCommon Pitfalls
- Not calling
identify()— unique users will be tracked under anonymous IDs, making it impossible to segment by real user properties or correlate with your database. - Identifying with inconsistent IDs — using email one time and user ID another creates duplicate users in PostHog that appear as separate people.
- Forgetting
reset()in multi-user scenarios — events from different people on the same device get mixed together, polluting your user metrics. - Confusing unique users with DAU/MAU — unique users is a snapshot of total people; DAU/MAU require additional filtering to count active users per day or month.
Wrapping Up
Unique users in PostHog is the count of distinct people using your product, identified by distinct_id. Call identify() early with a stable ID, use a consistent approach across your codebase, and reset when needed. Track this metric over time to see whether your product is actually acquiring new people or just getting existing users back. If you want to track this automatically across tools, Product Analyst can help.