Where this track goes
Eight analyst sessions, one running artifact: a retention report your stakeholders can act on, shipped in the capstone. Today (a1) nails the definitions. a2 builds the cohort table and heatmap - the artifact everything else reads from. a3 grows it into the full viz gallery, a4 segments who is retained (RFM, behavioral cohorts), a5 brings survival analysis, a6 CLV and buy-till-you-die models, a7 churn prediction that actually helps, and a8 assembles the report. Examples run on ecommerce and mobile-game data throughout. Work along in the companion notebook notebooks/a1_metrics.ipynb.
Three different D7s 17 min live
Below is a real computation, not a picture: 400 fixed simulated users with a full event log, and three honest ways to count "day 7 retention" on them. Same users, same events - and the answers range from 22% to 94%. Nothing is broken. The variants answer different questions, and every analytics tool quietly picks one as its default. "Which D7 is this?" is the first question of every retention conversation you will ever have.
LiveThe three definitions, one at a time8 min▶
Each variant fixes the same base - all 400 users, anchored at their first-seen day - and differs only in which return events count:
- Classic / N-day (22% here): the user returned exactly on day 7. Amplitude calls it "N-Day", Mixpanel calls it "On", and it is GameAnalytics' default - which makes it the benchmark standard: every published D1/D7/D30 figure you will compare against is classic. Once day 7 has passed for a cohort, the number is frozen. It never moves again.
- Rolling / unbounded (94% here): the user returned on day 7 or any later day. Mixpanel's default. It is always the biggest of the three by construction, and it equals 1 minus churn-by-day-7. Its fatal flaw: a dormant user returning on day 45 flips their day-7 answer from no to yes, so historical values keep rising retroactively. A useful concept - but never put it on a dashboard: a trend line that rewrites its own past cannot be trended.
- Bracket / range (88% for week 1 here): the user returned within a window, days 1-7. Each bracket is independent and freezes once its window closes. This is the right shape for products with a weekly or repurchase cadence, where "came back on exactly day 7" is an arbitrary target but "came back within the first week" is the real habit question.
Start on Classic D7: 22%. Read which return events light up - only the ones landing exactly on day 7. This is the number benchmarks mean.
Switch to Rolling D7: 94%. Same users. Every return from day 7 onward now counts - including ones that happened weeks later. Ask yourself: if a user returns tomorrow, which historical cells change? (In rolling: last month's.)
Switch to Bracket W1: 88%. Returns within days 1-7 count. Close to rolling here because most returners come back early - but unlike rolling, this number froze forever when day 7 ended.
Say the three numbers out loud as one sentence: "22% came back on day 7, 88% came back within week 1, 94% eventually came back." All true. Only one belongs on a trend line.
The frozen-history law 8 min live
A retention number you can trust is computed one way: fix the base, look forward. Anchor a cohort to a fixed date - registration date, or everyone active on a fixed date like Aug 1 - then look forward 1, 7, 14, 30 days and count who came back. Because the base never moves and the window eventually closes, a completed number is immutable. Only the current, still-filling window updates, and it is always visibly marked partial.
Live★ Build-along: forward-looking D1/D7/D14/D30 in pandas6 min▶
The whole law is four lines of logic: anchor each user at their first-seen day, age every event against that anchor, then flag the ages you care about. Run it on the repo's synthetic game telemetry - the churn is generated, so the right answers are known.
Note what is NOT here: no "last 7 days as of today", no "day 7 or later". The anchor is per-user and fixed; the window looks forward from it; a completed window never recomputes.
Day boundaries, checkpoints, stickiness 12 min live
Even with the variant fixed, two tools can still disagree on the same data - because "day 1" itself has two definitions. Amplitude's default counts rolling 24-hour windows from each user's start event (timezone-independent); Mixpanel uses strict calendar dates in the project timezone. A 23:50 install that returns at 00:10 is D1-retained on a calendar - twenty minutes later. This one mechanic explains most "my SQL disagrees with the tool" tickets you will ever file.
LiveCheckpoints and stickiness: what each number diagnoses7 min▶
The standard checkpoints are not arbitrary - each one has a diagnostic job:
- D1 - onboarding. Did the first session deliver value? A weak D1 is a first-session problem, nothing later can fix it.
- D7 - habit. One full weekly cycle has passed, so weekday effects cancel. This is the habit-formation read.
- D14 - trial boundary and content depth. Free trials end, content runways run out. A cliff here is a depth problem.
- D30 - established habit and the monetization horizon. Games often report D28 instead: exactly four weeks, so the weekday mix cancels perfectly.
Stickiness = DAU/MAU. Around 20% is good for a consumer app; 50%+ is daily-habit legend territory (the Facebook number). Two traps: it is meaningless for products with a non-daily cadence - use WAU/MAU for weekly-cadence products - and the ratio can RISE while the product declines, whenever MAU shrinks faster than DAU. A shrinking casual base concentrates the loyal core and flatters the ratio. It also hides the whole distribution: the fix is the L28 power-user curve, previewed here and built properly in a4.
Self-studyDenominators: all signups or activated users?3 min read▶
One more axis before your metric is fully specified: who is in the base? Retention over all signups measures the funnel and the product together; retention over activated users (completed a first core action) isolates product stickiness and reads far higher. Both are legitimate, they answer different questions, and mixing them silently is how two dashboards "disagree" for a quarter before anyone notices. State the denominator on the chart, every time.
For ecommerce, activity-based retention is nearly meaningless - people browse without buying - so the standard is purchase-based cohorts: the anchor is the first purchase, the active event is another purchase. a2 builds exactly that table.
The gap between those two denominators is the activation funnel - and the biggest leak in it is where retention is really won or lost:
Scored against those checkpoints, here are this course's own numbers - classic D1/D7/D14/D30 from the repo's 8,000-player game telemetry, drawn over the GameAnalytics 2025 benchmark bands:
Benchmarks with a vintage, not folklore. The legacy game rule of thumb - 40/20/10 for D1/D7/D30 - is real and long-standing, but today it marks a top-quartile-to-top-decile game, not an average one. GameAnalytics' 2025 study (11,600 games) puts the medians at D1 22-27% and D7 3.4-3.9%, and 75% of games hold under 3% at D28. Ecommerce speaks a different dialect entirely: purchase-based retention, where repeat purchase rate averages ~28% across industries, ~76% of second orders arrive within 90 days, and the median inter-purchase interval of 73-120 days sets how wide your churn window should be.
Try it yourself - this week ◐ 30 min total
- Run
notebooks/a1_metrics.ipynband compute all three D7 variants on the repo's synthetic game telemetry. Confirm you can reproduce the switcher's spread: classic lowest, bracket close behind rolling, rolling always the biggest. - Write your product's metric contract in four lines: the anchor event, the active event, the window type (classic / bracket, and which days), and the timezone-plus-day-boundary convention. Pin it to the top of every retention notebook from now on.
- Find one retention number your team already reports and identify its variant. If nobody can tell you, you have found this week's most useful bug.
What this session draws on
Retention definitions are standardized by the analytics tools' own documentation and a few durable industry studies. This page teaches the working core of:
Three questions before you go 🎯 ◐ 90 seconds
1 · Which D7 variant restates history, and why?
Rolling/unbounded retention keeps the window open forever, so every dormant user who resurfaces rewrites the historical value upward. Classic freezes when day N passes; each bracket freezes when its window closes. A metric whose past keeps moving cannot be trended - keep it off dashboards.
2 · A user installs at 23:50 and returns at 00:10, twenty minutes later. Which convention counts them D1-retained?
Under calendar-day counting (Mixpanel-style) the return lands on a new date, so it is D1 retention twenty minutes after install. Under rolling 24h windows from the start event (Amplitude default) it is still inside hour 0-24, which is day 0. Copy the tool's convention in your SQL before comparing numbers.
3 · DAU/MAU has been rising for three months while every other signal says the product is declining. How can both be true?
Stickiness is a ratio, and a ratio rises whenever its denominator falls faster than its numerator. A product bleeding casual users concentrates down to its daily core and posts its best-ever DAU/MAU on the way down. Check the absolute DAU and MAU trends, and look at the L28 distribution (a4) instead of the average.