Back to Portfolio

Netflix Top 10 Analytics Dashboard

Netflix Top 10 Analytics Dashboard

Project Overview

An end-to-end analytics project built entirely on data Netflix publishes itself: the weekly Top 10 global and per-country charts. A zero-dependency Node pipeline downloads the raw TSVs, asserts their schema byte for byte, and derives every figure the dashboard shows. The interface covers viewership KPIs, weekly trends, the category mix, per-country chart behaviour, three statistical hypothesis tests, and a trained retention model. Nothing on the page is simulated, and where the published data cannot answer a question, the dashboard says so rather than inventing a number.

Methodology

The pipeline ingests 165 weeks of global Top 10 data (2023-06-18 to 2026-08-09; 6,600 rows across 2,603 distinct title-seasons) plus a 52-week slice of the per-country chart for eight markets. Rows are dictionary-encoded into a column-major JSON payload of roughly 114 KB gzipped, served as a static asset and fetched at runtime so none of it enters the JavaScript bundle. Statistical machinery — the incomplete beta function, Student's t CDF and its inverse, Welch's t-test and the two-proportion z-test — is implemented from scratch and unit-checked against published reference values. The retention model is a logistic regression fitted by batch gradient descent with L2 regularisation, standardised using training-set statistics only.

Technical Details

Data pipeline and schema defence

A Node script with no external dependencies streams the 30 MB per-country TSV line by line, discarding non-target rows immediately so peak memory stays flat. Both files' headers are asserted byte for byte and their category value sets are checked exhaustively; a silent upstream schema change fails the build rather than publishing confidently wrong numbers. Output size is budget-asserted, and the generated data is committed so production builds never touch the network.

Retention model with a leak-free split

Logistic regression over 6,559 (title-season, week) observations predicting whether a charting title remains in the Top 10 the following week. The train/test split is chronological, never shuffled, and the single week straddling the cut is discarded because its outcome is realised in the first test week. Test AUC is 0.840 against a rank-only baseline of 0.821; accuracy is 0.757 against a majority-class baseline of 0.553. Fitting is fully deterministic, so re-running the build reproduces the model file byte for byte.

Hypothesis testing on observational data

Three tests, each collapsing repeated weeks to one observation per title so the independence assumption holds. Dwell time by language uses Welch's t-test; weekly hours for Korea-charting titles is tested on the log scale and reported as a ratio of geometric means; week-over-week retention by format uses a two-proportion z-test with a pooled statistic and an unpooled interval, accompanied by a cluster-robust check.

Honest treatment of missing dimensions

Netflix publishes no genre field and no per-country viewership, so the dashboard breaks content down by the dimensions that genuinely exist — format and language — and restricts country panels to rank-derived measures. Runtime and view counts only begin in June 2023, so earlier weeks are excluded entirely rather than mixing windows. Each of these limits is surfaced in a provenance panel on the page itself.

Results

The dashboard surfaces several findings that survive scrutiny. TV seasons hold their Top 10 slot markedly better than films week to week, 61.6% versus 51.4% — a 10.2 percentage point gap (95% CI 7.8 to 12.6, p < 1e-16) that also survives a cluster-robust re-analysis. Among non-English titles, those that also chart in South Korea accumulate 1.65 times the weekly hours of those that do not (95% CI 1.48 to 1.84). By contrast, dwell time shows no difference by language at all: non-English titles average 2.77 weeks against 2.82 for English, a null result with a tight interval of -0.27 to 0.17 weeks. The model reaches 0.840 test AUC, and its feature importances point somewhere interesting — share of weekly hours (44%) and chart rank (29%) dominate, while the TV/film indicator carries essentially no weight (0.03%).

Key Insights

  • The raw TV-versus-film retention gap is real, but the model shows it is not about format: once share of weekly hours and chart rank are controlled for, the TV indicator contributes almost nothing. Popularity explains the gap, not runtime structure.
  • Hours and views tell different stories about the same week. Measured in hours, English-language TV leads the category mix; measured in views, English-language films lead, because shorter runtimes convert the same hours into more views.
  • A well-powered null result is worth displaying. Dwell time does not differ by language, and reporting that alongside two significant findings is more informative than showing only what reached significance.
  • Netflix's per-country data has no viewership column at all, so the honest per-country measures are rank-derived — how many distinct titles chart, how long they persist, and how closely local taste tracks the global chart.

Methodological Contributions

  • Statistical primitives implemented from scratch in plain JavaScript — Lanczos log-gamma, a continued-fraction incomplete beta, Student's t CDF and a bisection inverse — and validated against published reference values before any p-value derived from them was trusted.
  • A leak-free chronological split that explicitly discards the boundary week, rather than the more common shuffled split that would let next-week outcomes bleed into training.
  • Reporting every model metric next to an explicit baseline (majority-class accuracy and a single-feature rank-only AUC), so the reader can judge whether the model earns its complexity.
  • Shipping the fitted coefficients and standardisation statistics alongside the metrics, making the model fully reproducible and auditable from the published JSON alone.
  • Schema assertions and size budgets enforced at build time, treating silently-wrong numbers as the failure mode most worth engineering against.

Limitations

  • Top 10 data is censored by construction: it describes titles that charted, never the full catalogue, so nothing here generalises to Netflix's library as a whole.
  • These are observational comparisons, not randomised experiments. Netflix chooses what it produces and promotes, so the findings describe association rather than causation.
  • No country of origin is published. The Korea-linked comparison is an explicitly labelled proxy based on co-occurrence in the South Korea chart, and is not a claim about where a title was produced.
  • Runtime and view counts begin only with the week of 2023-06-18, so roughly two earlier years of hours-only data are excluded to keep every panel on a single consistent window.
  • Repeated weeks of the same title are not independent; the primary retention p-value is anti-conservative, which is why a cluster-robust check is reported beside it.

Future Extensions

  • Schedule a monthly refresh that re-runs the pipeline and opens a pull request, so the committed snapshot stays current under review rather than drifting silently.
  • Extend the trend chart back to 2021 for the hours metric alone, with the shorter complete-data window clearly demarcated.
  • Add a survival model for time-to-exit from the Top 10, which suits the censored structure of the data better than a one-step-ahead classifier.
  • Replace gradient descent with IRLS to obtain standard errors and confidence intervals on the coefficients themselves.
  • Join an external catalogue source to recover genre and country of origin, which would let the proxy in the Korea comparison be replaced with a real attribute.

Implementation

  • JavaScript (Node)
    Zero-dependency ingest pipeline: streaming TSV parser, schema assertions, dictionary encoding, and size budgets
  • JavaScript (statistics)
    Log-gamma, incomplete beta, Student's t CDF and inverse, Welch's t-test and two-proportion z-test, written from scratch and reference-checked
  • JavaScript (modelling)
    Logistic regression with L2, rank-based AUC, ROC sweep and confusion matrix — deterministic, so the committed output is reproducible
  • TypeScript / React
    Client dashboard with cross-filtering, SWR data loading and Recharts visualisations over the generated JSON

Conclusion

The project's organising constraint was refusing to fabricate. Every number rendered traces to data Netflix published, every statistic is computed by code in the repository, and the places where the source cannot answer a question — genre, per-country viewership, country of origin — are stated on the page instead of filled in. The most interesting result came from that discipline: the headline TV-versus-film retention gap is genuine, yet the model shows format itself carries no predictive weight once popularity is accounted for.