Session duration tells you how long users spend in your app before they leave. It's one of the most direct signals of engagement—if sessions are short, users aren't finding value. PostHog makes it easy to track, segment, and act on this data without extra setup.
What Session Duration Actually Means
Session duration isn't just time on page—it's the complete interaction window.
Understand how PostHog calculates sessions
PostHog groups events into a session automatically. A session starts when a user first appears and ends after 30 minutes of inactivity (this is the default, but you can customize it). All events within that window count toward one session. So if a user loads your app, browses for 8 minutes, pauses for 10 minutes, then browses for 2 more minutes, that's one 20-minute session (not 18 + 2).
// PostHog automatically tracks sessions—no setup needed
// Just initialize the SDK and session_id is captured with every event
posthog.init('phc_YOUR_PROJECT_KEY', {
api_host: 'https://us.i.posthog.com',
// session_timeout_seconds: 1800 // default 30 min, customize if needed
});See where sessions appear in your data
In Events, every row includes a $session_id property. In Insights, when you create a Trends or Retention chart, PostHog automatically aggregates by session. You'll see metrics like Average Session Duration, Max Session Duration, and Total Sessions available out of the box in the Metrics dropdown.
// Access session info in your events (read-only—you don't set this manually)
const event = {
event: 'page_view',
properties: {
$session_id: 'sess_1a2b3c4d5e6f7g8h', // auto-captured
current_url: window.location.href
}
};
posthog.capture(event.event, event.properties);Measure session duration in Insights
Go to Insights > Trends. Set Data series to the event you care about (e.g., page_view). In the Metrics dropdown, select Average Session Duration. Choose your date range and filters. PostHog calculates the median and mean duration per session. You can break it down by Properties like utm_source or signup_cohort to see which users or traffic sources spend more time.
// Use the query API to fetch session duration programmatically
const response = await fetch('https://us.i.posthog.com/api/projects/PROJECT_ID/query/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${posthog_api_key}`
},
body: JSON.stringify({
query: {
kind: 'TrendsQuery',
dateRange: { date_from: '-30d' },
series: [{
kind: 'EventsNode',
event: 'page_view',
math: 'avg_duration'
}]
}
})
});
const result = await response.json();page_view may not fire on route changes. Use a custom event like navigation or verify that your routing library is triggering page_view correctly.Why Session Duration Matters and How to Use It
Session duration reveals whether users find your product sticky.
Compare session duration across user segments
Not all users are created equal. In Insights, add a filter like signup_source = 'organic' or user_cohort = 'trial'. Then break down by Properties to see if free-tier users have shorter sessions than paid users. If paying users spend 2x longer in your app, you've found a retention lever. This directly informs your pricing and feature strategy.
// Tag users with custom properties so you can segment later
posthog.identify('user_123', {
signup_source: 'organic',
plan: 'enterprise',
customer_segment: 'tech_founder',
onboarding_complete: true
});
// Now you can filter on these in Insights → "plan = enterprise"Track drop-off in session funnels
Go to Insights > Funnels. Add steps like page_view → feature_used → upgrade_clicked. PostHog shows you where sessions drop. If 80% of sessions include a page_view but only 20% include upgrade_clicked, that's a conversion leak you can optimize. Session duration combined with funnel analysis tells you *when* users are leaving.
// Capture milestones within a session
posthog.capture('feature_used', {
feature_name: 'dashboard',
time_to_feature: 45 // seconds from session start
});
posthog.capture('upgrade_clicked', {
plan: 'pro',
session_time_at_click: 120 // seconds from session start
});Customizing Session Behavior
PostHog's 30-minute default works for most apps, but you can tweak it.
Adjust session timeout for your product type
Real-time apps (chat, trading) should use shorter timeouts (5–10 min). Long-form content (docs, courses) should use longer timeouts (45–60 min). Change it in your SDK initialization. PostHog recalculates sessions retroactively for new data, but historical sessions already split are not merged—keep that in mind when comparing old vs. new data.
// Set a custom session timeout (in seconds)
posthog.init('phc_YOUR_PROJECT_KEY', {
api_host: 'https://us.i.posthog.com',
session_timeout_seconds: 600 // 10 minutes instead of default 30
});
// This applies only to new sessions going forwardsession_timeout_seconds only affects *new* sessions. Existing sessions in your database won't be recalculated. Document the change so you don't accidentally compare incompatible time windows.Common Pitfalls
- Confusing session duration with time-on-page. PostHog's session spans *all* events until inactivity, not a single page view.
- Not tagging events with custom properties. Generic events like
page_vieware useful, but onlypage_view+ user segment tells you the full story. - Forgetting that SPAs don't fire
page_viewon route changes. If your app is a single-page app, create a customnavigationevent or verify your library emitspage_viewcorrectly. - Changing session timeout and comparing across time periods without accounting for the methodological shift. It'll break your time-series analysis.
Wrapping Up
Session duration is PostHog's window into user engagement. It's immediate, actionable, and requires no setup—the SDK captures it automatically. Use it to spot which user segments stick around, where funnels leak, and whether your onboarding actually works. If you want to track this automatically across tools, Product Analyst can help.