Win/loss and Elo tell you who's winning. They don't tell you how. Two players at 1400 Elo might look identical on the leaderboard, but one averages 25 kills per game and the other averages 8. One plays every map, the other only queues Dust2. Without stats, you can't see any of that.
Custom stats fix this. You define what to track — kills, deaths, ACS, map played, character picked, whatever your game cares about — and the bot collects it every time a match is recorded. Stats aggregate automatically on player profiles so you can see totals, averages, bests, and breakdowns without touching a spreadsheet.
This guide walks through setting up custom stats on a Team Up leaderboard. If you don't have a leaderboard yet, start with the leaderboard setup guide first.
What You Can Track
There are two types of custom stats:
Number stats — numeric values like kills, deaths, score, damage dealt. You choose how they're aggregated: total (sum), average, min, max, or any combination.
Text stats — categorical values like map name, character played, game mode. The bot counts how many times each value appears.
Each stat also has a scope:
- Player scope — tracked per player in each match. Every player enters their own value (e.g., their kills).
- Match scope — tracked once for the entire match. One value shared by everyone (e.g., which map was played).
You can define as many stats per leaderboard as you want. During match recording the bot paginates long stat sets across multiple steps, so neither scope is capped.
Setting Up Stats: FPS Example
Here's a setup for a CS2 or Valorant leaderboard that tracks the stats most competitive players care about:
/settings custom_stats define_number name:kills scope:player aggregates:sum,avg label:Kills
/settings custom_stats define_number name:deaths scope:player aggregates:sum,avg label:Deaths
/settings custom_stats define_number name:assists scope:player aggregates:sum,avg label:Assists
/settings custom_stats define_number name:acs scope:player aggregates:avg,max label:ACS
/settings custom_stats define_text name:map scope:match label:Map Played
That's 4 player-scoped number stats and 1 match-scoped text stat. Here's what each line does:
- Kills/Deaths/Assists —
sumgives the career total,avggives the per-match average. Both are useful: career totals reward volume, averages reward consistency. - ACS — Average Combat Score. Using
avghere gives you the player's average ACS across all matches.maxtracks their personal best. - Map — A text stat scoped to the match. The bot will count how many times each map value appears, so you'll see things like "Dust2: 15 matches, Mirage: 12 matches" in the data.
What Happens When You Record a Match
Once stats are defined, they appear automatically in the match recording flow. When you use /record_match or when players vote on results in a matchmaking queue, a form pops up asking for stat values.
For player-scoped stats (kills, deaths, assists, ACS), each player gets a form with those fields. For match-scoped stats (map), it's entered once.
Stats marked as required must be filled in before the match can be recorded. By default, stats are optional — players can skip them if they don't have the data handy.
More Setup Examples
Battle Royale (Fortnite, Apex, Warzone)
Battle royale stats care more about placements and kill counts than team W/L:
/settings custom_stats define_number name:kills scope:player aggregates:sum,avg,max label:Kills
/settings custom_stats define_number name:placement scope:player aggregates:avg,min label:Placement
/settings custom_stats define_number name:damage scope:player aggregates:sum,avg label:Damage Dealt
/settings custom_stats define_text name:drop_location scope:player label:Drop Location
min on placement is clever here — it tracks the player's best finish (1st, 2nd, etc.). avg shows their typical placement across games. And the drop location text stat reveals patterns: who always lands Fragment, who plays it safe at the edge of the map.
Fighting Games (Smash, Street Fighter, Tekken)
/settings custom_stats define_text name:character scope:player label:Character
/settings custom_stats define_number name:rounds_won scope:player aggregates:sum,avg label:Rounds Won
/settings custom_stats define_number name:rounds_lost scope:player aggregates:sum,avg label:Rounds Lost
The character text stat is the highlight here. Over time, you get a breakdown of what every player picks. Is someone a one-trick? Do they switch characters when they're losing? The data tells the story.
Golf or Racing
/settings custom_stats define_number name:score scope:player aggregates:sum,avg,min label:Score
/settings custom_stats define_number name:lap_time scope:player aggregates:avg,min label:Lap Time
/settings custom_stats define_text name:course scope:match label:Course
For golf, min score tracks personal bests. For racing, min lap time gives fastest laps and avg shows consistency. The course text stat shows which tracks get played most.
MOBA (League, Dota)
/settings custom_stats define_number name:kills scope:player aggregates:sum,avg label:Kills
/settings custom_stats define_number name:deaths scope:player aggregates:sum,avg label:Deaths
/settings custom_stats define_number name:assists scope:player aggregates:sum,avg label:Assists
/settings custom_stats define_number name:cs scope:player aggregates:avg,max label:CS
/settings custom_stats define_text name:champion scope:player label:Champion
Five stats used — that's the maximum. Choose carefully based on what your community actually wants to track.
Adding Preset Choices
For text stats, you can predefine choices so players pick from a dropdown instead of typing freeform:
/settings custom_stats select_choices name:map choice_1:Dust2 choice_2:Mirage choice_3:Inferno choice_4:Nuke choice_5:Anubis choice_6:Ancient choice_7:Vertigo
This prevents typos ("dust 2" vs "Dust2" vs "dust_2") and keeps your data clean. You can add up to 25 choices per stat. Choices work for both text and number stats.
For character/hero pools with lots of options, you can run the command multiple times to add more choices. The bot appends to the existing list.
How Stats Show Up
Player Profiles
When someone checks a player's profile on the leaderboard, their aggregated stats appear alongside their Elo, wins, and losses. For the FPS example above, a player profile might show:
- Kills — Total: 1,247 | Avg: 18.3
- Deaths — Total: 892 | Avg: 13.1
- Assists — Total: 634 | Avg: 9.3
- ACS — Avg: 215.4 | Best: 387
- Maps — Dust2: 22, Mirage: 18, Inferno: 15, Nuke: 8
That's a lot more interesting than just "1,412 Elo, 38W-30L."
Match History
Individual match records include the stats collected for that match, so you can go back and see exactly what happened in any game.
Web Dashboard
Player profiles on the web dashboard display all custom stats alongside match history, giving you a complete picture of every player.
Managing Stats
View your stats
See all custom stats defined for a leaderboard:
/settings custom_stats list
/settings custom_stats list leaderboard:ranked
Shows stats grouped by scope (match-level vs player-level) with type, aggregation methods, and whether they're required.
Update a label
Change the display name without affecting data:
/settings custom_stats label name:kills label:Total Frags
Remove a stat
/settings custom_stats remove name:kills
Historical data is preserved — removing a stat only stops collecting new data. If you re-add it later, past data won't be lost.
Change aggregation types
Re-run the define command with the same name but different aggregates:
/settings custom_stats define_number name:kills scope:player aggregates:sum,avg,max
This updates the stat definition going forward. Note that new aggregations (like adding max) will only apply to matches recorded after the change — historical matches won't retroactively fill in the new aggregate.
Tips
Start with 2-3 stats, not 5. More fields means more friction during match recording. Start with the stats your community actually cares about and add more later if people want them.
Use match scope for shared data. If everyone played on the same map, don't make each player type it — use scope:match so it's entered once.
Make stats optional at first. Once your community gets used to entering stats, you can flip them to required. Starting with required stats might annoy people who just want to record a quick result.
Preset choices save headaches. For anything with a known set of values (maps, characters, game modes), always use /settings custom_stats select_choices. Freeform text gets messy fast.
Each leaderboard gets its own stats. If you run multiple leaderboards (e.g., "Valorant Ranked" and "CS2 Ranked"), each has an independent set of custom stats. You can track completely different metrics for each game.
What's Next
Custom stats pair well with other Team Up features:
- Matchmaking queues — stats are collected during the result voting flow, so players submit their stats when the match ends
- Elo leaderboards — stats appear alongside Elo ratings on the leaderboard
- Admin dashboard — view and manage stats from the web
- Valorant 10 mans — a complete setup example with custom stats included
The free tier supports custom stats on all leaderboards. No Pro subscription needed.
Frequently Asked Questions
Can I add stats after matches have already been recorded?
Yes. New stats are only collected for future matches. Past matches won't have the new stat data, but nothing breaks — the bot just shows aggregates based on the matches where that stat was recorded.
What happens to historical data if I remove a stat?
Historical match data is preserved. Removing a stat definition stops collecting new data and removes it from profile display. If you re-add a stat with the same name later, old data is still there.
Is there a limit on how many stats I can define?
No hard limit. You can define as many player-scope and match-scope stats as you need. When a match is recorded, the bot splits long stat sets across paginated steps so everything fits within Discord's message layout. That said, collecting dozens of stats per match slows recording down — pick what your community will actually use.
Can I have different stats for different leaderboards?
Yes. Each leaderboard has its own independent set of custom stats. A Valorant leaderboard can track ACS and kills while a chess leaderboard tracks opening played and game duration.
Do stats affect Elo calculations?
By default, no. Stats are informational — they're collected alongside matches but don't change how Elo is calculated. However, there's an advanced "Stat Points" mode where number stats with a points multiplier can drive match outcomes. This is useful for scoring-based games like golf where the stat is the result.
Are stat names case-sensitive?
No. Stat names are case-insensitive. "Kills" and "kills" are treated as the same stat.
Questions? Check the configuration docs or ask in our Discord community.
