Retention answers a single question: how many users who did X are still using your product 7 days, 30 days, or 6 months later? It's the metric that separates products people actually use from ones they install and forget. PostHog's retention insights make this analysis fast—you set a return action (like 'logged in again'), define your cohort, and see month-over-month trends instantly.
What Retention Analysis Measures
Retention tracks user cohorts over time. In PostHog, you define a starting action (returning users, upgraded to pro, etc.) and a return action (any event that proves the user came back). The chart shows what percentage of your cohort returned.
Capture Events for Retention Tracking
Before you can measure retention, PostHog needs to know when users act. Use capture() to log events like logins, feature usage, or purchases. Make sure you're sending a distinct_id to identify the same user across sessions.
posthog.capture('user_login', {
distinct_id: userId,
user_id: userId,
timestamp: new Date().toISOString()
});
posthog.capture('premium_feature_used', {
distinct_id: userId,
feature_name: 'advanced_analytics',
plan: 'pro'
});Understand the Two-Event Model
Retention always compares two moments: when users took the starting action (first day cohort) and when they took the return action (proved they came back). The gap between them is what you're measuring—how many made it back?
// Starting action: user signs up
posthog.capture('user_signup', {
distinct_id: newUserId,
signup_date: new Date().toISOString()
});
// Return action: user views dashboard (proves they came back)
posthog.capture('dashboard_viewed', {
distinct_id: existingUserId,
session_id: currentSessionId
});Building a Retention Insight
In PostHog, retention is a built-in insight type. You define your cohort (starting action), your return action, and your time period. PostHog handles the math.
Create a New Retention Insight
Go to Insights > New Insight > Retention. This opens the retention builder where you'll define your cohort and return events.
// Create a retention insight via PostHog's REST API
const retentionInsight = {
insight: 'retention',
retention_type: 'retention_repeated',
target_event: { id: 'user_login' },
returning_event: { id: 'user_login' },
period: 'Day'
};
fetch('https://your-instance.posthog.com/api/projects/{project_id}/insights/', {
method: 'POST',
headers: { 'Authorization': `Bearer ${apiKey}` },
body: JSON.stringify(retentionInsight)
});Set Your Target and Returning Events
Target event is your cohort baseline (signup, purchase, etc.). Returning event is what proves the user came back (login, feature use, etc.). You can filter both by user properties—like 'retention for paid users only'.
// Retention of free-to-paid converters
const retentionWithFilters = {
insight: 'retention',
retention_type: 'retention_repeated',
target_event: {
id: 'trial_started',
properties: [{ key: 'trial_type', value: 'free' }]
},
returning_event: {
id: 'premium_accessed',
properties: [{ key: 'plan_type', value: 'paid' }]
},
period: 'Week'
};
fetch(`https://your-instance.posthog.com/api/projects/{project_id}/insights/`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${apiKey}` },
body: JSON.stringify(retentionWithFilters)
});Choose Your Time Granularity
PostHog offers Day, Week, and Month granularity. Daily retention is noisier but faster to interpret; monthly retention takes weeks to populate but reveals real stickiness. Pick based on your product's usage cycle.
// Retention by week for a SaaS product with weekly usage patterns
const weeklyRetention = {
insight: 'retention',
retention_type: 'retention_repeated',
target_event: { id: 'user_signup' },
returning_event: { id: 'dashboard_view' },
period: 'Week'
};
// Example response structure:
// {
// "result": [
// { "0": 100, "1": 45, "2": 38, "3": 32 },
// { "0": 100, "1": 52, "2": 41, "3": 35 }
// ],
// "date_from": "2024-03-01"
// }Reading and Acting on Retention Results
The retention chart rows represent cohorts (users who signed up day 1, day 2, etc.). Columns represent time periods. A cohort that drops from 100% to 30% by week 4 is leaking users—that's your signal to investigate.
Interpret the Retention Matrix
Each row is a cohort. Each column is a time period relative to the starting action. A cell showing 30 means '30% of that cohort returned in that period'. High values on the right side mean users are sticky; steep drops mean quick churn.
// Parse retention matrix from PostHog API
const retentionData = [
// Cohort starting March 1
{ '0': 100, '1': 68, '2': 45, '3': 32, '4': 28 },
// Cohort starting March 8
{ '0': 100, '1': 72, '2': 49, '3': 35 },
// Cohort starting March 15
{ '0': 100, '1': 65, '2': 41 }
];
// March 1 cohort lost 32% in period 1, then stabilized
// Pattern: steep drop in early periods, flattens after week 2
const baselineChurn = retentionData[0][1]; // 68% = 32% churn
const stabilizedRetention = retentionData[0][4]; // 28% = true sticky usersCompare Cohorts to Spot Improvements
If week 1 retention improved from 60% (last month) to 72% (this month), something in your onboarding worked. Use Breakdown in PostHog to segment by signup source, user segment, or feature flag to find what's driving the delta.
// Query retention broken down by signup source
const retentionBySource = {
insight: 'retention',
target_event: { id: 'user_signup' },
returning_event: { id: 'user_login' },
breakdown_by: 'utm_source',
period: 'Week'
};
fetch(`https://your-instance.posthog.com/api/projects/{project_id}/insights/`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${apiKey}` },
body: JSON.stringify(retentionBySource)
});
// Results show: organic users (72% week 1) stick better than paid (58% week 1)Watch for Seasonality and Cohort Effects
Retention curves often stabilize after 4-8 weeks. If your early cohorts sit at 20% and late cohorts at 25%, that's a 5-point gain—not an artifact, it's real. Also flag seasonal drops (holiday weeks, industry slowdowns) so you don't over-correct.
// Detect anomalies in retention trends
const detectRetentionAnomalies = (retentionMatrix, period = 1) => {
const baseline = retentionMatrix[0][period];
const threshold = 5; // Flag >5% variance
return retentionMatrix.map((cohort, idx) => {
const variance = Math.abs(cohort[period] - baseline);
if (variance > threshold) {
return {
cohort_index: idx,
retention: cohort[period],
variance: variance,
flag: variance > 10 ? 'CRITICAL' : 'WARNING'
};
}
}).filter(Boolean);
};
const anomalies = detectRetentionAnomalies(retentionData, 1);
console.log('Unusual cohorts:', anomalies);Common Pitfalls
- Confusing 'return action' with repeat events. If you use 'login' for both target and returning, you're measuring 'logged in again', not whether they stayed. Use distinct actions like 'signup' (target) and 'feature_used' (returning).
- Mixing up cohort start date with event date. PostHog groups users by the date they triggered the target event, not when they joined your product. If you want onboarding retention, your target event must be 'signup', not 'account_created_by_admin'.
- Reading week 1 retention as the whole story. A 50% drop in week 1 is common (trial cancellations, no-longer-interested users). Focus on weeks 2-4 to see who actually stuck around.
- Not accounting for product changes. If you shipped a major feature in week 3, cohorts before that date will have lower retention. Always correlate retention dips with product releases or outages.
Wrapping Up
Retention analysis in PostHog turns user stickiness into a metric you can optimize. Define your cohort (starting action), your proof of return (returning event), and watch how each week's new users flow through your product. The curve tells you where your onboarding leaks, where you've improved, and what true retention looks like for your business. If you want to track this automatically across tools, Product Analyst can help.