How to track pull request metrics on GitHub (and why it's harder than it should be)
GitHub shows you individual PRs, not the patterns across them. Here's what's missing from the native tooling, how to build PR review metrics yourself with the API, and why most teams stop trying.
Pull request metrics sound like a solved problem. You have a GitHub repository, every review leaves a trail in the API, and engineering leaders have been asking "how are we reviewing?" for as long as code review has existed. So why is it that almost every team we talk to has either built a brittle internal script, given up on dashboards, or just taken a guess based on who's loudest in standup?
This post walks through what GitHub gives you natively, what's missing, how to build pull request metrics yourself with the API, and the trade-offs that lead most teams to stop trying. If you just want the short version: GitHub shows you individual PRs really well, but it does not aggregate review behavior in a way that answers the questions engineering managers actually care about.
Why pull request metrics matter
Reviews are where a lot of an engineering team's actual culture lives. They are where mistakes get caught, where junior engineers learn the codebase, and where senior engineers shape standards. They are also where bottlenecks form silently. A single unreviewed PR can stall a deploy for half a day, and three of them can stall a sprint.
The questions that good PR metrics answer:
- Who's actually doing the reviews on this team?
- How long does a typical PR sit before someone first looks at it?
- Are reviews concentrated on one or two people, or shared across the team?
- Is review depth changing over time? More comments, fewer rubber-stamps?
- When we hire someone new, how long does it take them to start reviewing?
You cannot answer any of these from the GitHub UI without doing a lot of clicking around. And clicking around is not a metric.
What GitHub gives you natively
GitHub has been adding analytics surfaces for years, but they all stop short of what most teams want from PR review metrics:
- Insights → Pulse. A weekly summary of opened/closed PRs and active issues. Good for "how busy was the repo this week" but it tells you nothing about who reviewed what.
- Insights → Contributors. Counts commits, additions, and deletions per author. Reviews are not in this view at all. A strong reviewer who didn't push code looks invisible here.
- Insights → Code review limits. A policy lever for capping review assignments. It enforces fairness; it does not measure it.
- Pull request list filters. You can filter PRs by reviewer, author, state, and label. Useful for one-off questions, useless for trends.
- Per-PR review tab. Lovely for a single PR. Aggregating across two hundred PRs is not a feature.
Notice the gap: there is no native screen titled "review activity by team member over the last 30 days." That single missing screen is where almost all the friction lives.
Building PR metrics yourself with the GitHub API
The GitHub API is fully capable of producing the data. The REST and GraphQL endpoints for pull requests and reviews are mature and well-documented. The challenge is not access; it is glue code, edge cases, and keeping the pipeline alive.
Pulling pull requests and reviews
Start with the REST endpoint for listing pull requests in a repository, then for each PR pull its reviews. A minimal version with the GitHub CLI:
# List PRs updated in the last 30 days
gh api -X GET "repos/$ORG/$REPO/pulls" \
-F state=all -F per_page=100 -F sort=updated -F direction=desc
# For each PR, fetch its reviews
gh api "repos/$ORG/$REPO/pulls/$PR_NUMBER/reviews"
GraphQL is denser if you'd rather batch it, with the
pullRequest.reviews connection returning author, state, submitted-at,
and comment count in a single round-trip per PR.
The gotchas nobody warns you about
What looks like a couple hours of scripting tends to balloon. The traps that cost the most time when teams build their own pull request metrics dashboards:
- Pagination. Active repos blow past 100 PRs fast. Without proper cursor-based paging you'll silently miss data and your charts will look wrong without ever throwing an error.
- Re-requested reviews. A reviewer can be re-requested, leave a second review on the same PR, and now you're double-counting unless you deduplicate by reviewer per PR per state.
- Dismissed and stale reviews. Old approvals can be dismissed when new commits land. Do you count the dismissed approval? The new one? Both? Neither? There is no objectively correct answer, but your dashboard has to pick one and stick to it.
- Draft PRs. Most teams want to exclude drafts from "time to first review" but include them for "lines of code touched." That is two filters, not one.
- Lines of code per reviewer. A PR's diff size lives on the PR, not the review. Attributing lines reviewed means joining reviews back to PR metadata, and handling PRs where the same reviewer approved multiple times across pushes without inflating their count.
- Bots. Dependabot, Renovate, and your CI account will outpace every human on commits and noise comments. Filter them, or your charts become a story about Dependabot.
- Time zones. "Reviews per day" depends entirely on what midnight means to you. Pick a single canonical zone (often the org's billing zone) and stick to it.
- Rate limits. The REST API gives you 5,000 requests per hour per token. Pulling history for a busy multi-repo org will burn through that, and now you need a queue, exponential backoff, and a way to resume interrupted syncs.
- Team membership over time. Someone joins the platform team, leaves three months later. Were their reviews "platform" reviews? You need to snapshot team membership at review time, not at query time, or your historical numbers will rewrite themselves every week.
Where DIY scripts go to die
The problem is rarely getting v1 working — it's keeping it working. A typical lifecycle for an internal PR metrics script:
- Week 1. An engineer hacks together a script, pipes the output into a spreadsheet, and shares it. Everyone is impressed.
- Month 2. The org adds three more repos. The script does not handle multi-repo. Someone wraps it in a loop. It now takes 20 minutes to run.
- Month 4. The original author switches teams. Numbers start looking weird. Nobody is sure if it's a real signal or a script bug.
- Month 6. Someone notices the dashboard hasn't updated in three weeks. A token expired. Nobody fixes it because the script is undocumented.
We have heard variations of this story enough times that it is essentially the default ending. Pull request metrics is a small project that turns into a permanent maintenance tax on whoever happens to own it.
The deeper visibility problem
Even teams that do build a working pipeline often discover that raw counts are not insight. Knowing that Alice approved 42 PRs and Bob approved 11 doesn't actually tell you who's contributing more to review quality. Bob might have approved eleven 1,500-line refactors. Alice might have rubber-stamped forty-two typo fixes.
That's why CodeChamp surfaces two breakdowns side by side on every dashboard: approvals and lines approved. Two different stories, same data. A reviewer whose share of approvals is small but whose share of lines is large is doing the heavy lifting on big PRs. The opposite reviewer is going broad on small ones. Both are valuable. Neither shows up clearly without splitting the metric.
The same logic applies to inline comments, time-to-first-review, and review streaks. A good PR metrics tool is not the one with the most numbers. It's the one whose numbers point at decisions you can actually make.
How CodeChamp solves it
CodeChamp is the dashboard we wish every engineering team already had. You sign in with GitHub, pick the org and repos you want tracked, and within a couple minutes your team has a live leaderboard of pull request review activity, counted properly, deduplicated properly, broken down per reviewer, per team, and per time range.
- Live leaderboards. Real-time rankings based on PRs reviewed, lines of code touched, and inline comments left. Filter by team, this week, this month, or all time.
- Two-axis breakdowns. Approvals and lines approved shown side by side, so the typo fixes and the heavy refactors don't blur into one number.
- Achievement badges. Eight badges that recognize speed, depth, consistency, and mentorship: the behaviors a flat metric misses.
- Slack digests. A weekly summary posted to your team channel with the top reviewers and badges earned. Nobody has to remember to check a dashboard.
- Custom scoring. Tune point values for approvals, change requests, comments, and speed bonuses to match what your team actually values.
- Privacy-first. No code, diffs, commit messages, or PR titles are stored. CodeChamp computes scores from GitHub's API and keeps only the numbers.
The point is not that PR metrics are impossible to roll yourself. They're not. The point is that the time you'll spend on edge cases, pagination loops, dedup logic, historical team snapshots, and broken cron jobs is time you didn't plan to spend, and it never actually ends. CodeChamp does that work once, for everyone.
Getting started
If you want pull request review metrics for your GitHub organization without writing a line of code, sign in with GitHub and you'll have a leaderboard within minutes. CodeChamp is free for small teams while in public beta. No credit card, no GitHub App you need your security team to approve.
Stop building dashboards. Start reviewing.
CodeChamp turns your team's GitHub PR activity into a live leaderboard with badges, team rankings, and weekly Slack digests. Setup takes under two minutes.
Sign in with GitHub