Leaderboard Types
ASCND supports different leaderboard configurations to match your game's needs.
Reset Periods
All-Time Leaderboards
Scores persist forever. Best for games where you want a permanent record of achievements.
Use cases:
- Story mode completion times
- Lifetime high scores
- Achievement rankings
// All-time leaderboards always return the same data
const allTime = await client.getLeaderboard({
leaderboardId: 'lb_alltime',
});
Daily Leaderboards
Reset every day at midnight UTC. Great for encouraging daily engagement.
Use cases:
- Daily challenges
- "Play today" competitions
- Fresh start every day
// Get today's leaderboard
const today = await client.getLeaderboard({
leaderboardId: 'lb_daily',
period: 'current',
});
// See yesterday's winners
const yesterday = await client.getLeaderboard({
leaderboardId: 'lb_daily',
period: 'previous',
});
Weekly Leaderboards
Reset every Monday at midnight UTC. Balances competition length with fresh starts.
Use cases:
- Weekly tournaments
- Seasonal events
- Casual competition
Monthly Leaderboards
Reset on the first of each month at midnight UTC.
Use cases:
- Monthly championships
- Long-form competitions
- Season rankings
Sort Order
Higher is Better (Default)
The player with the highest score ranks #1.
Use cases:
- Points-based games
- Score attack modes
- Collectible counts
Lower is Better
The player with the lowest score ranks #1.
Use cases:
- Speedruns (fastest time wins)
- Golf-style scoring
- Fewest moves/deaths
Storing times
For time-based leaderboards, store times in milliseconds as integers. This avoids floating-point precision issues.
// Store 2 minutes 30.5 seconds as 150500 milliseconds
const timeMs = Math.round(finishTime * 1000);
await client.submitScore({
leaderboardId: 'lb_speedrun',
playerId: 'player_123',
score: BigInt(timeMs),
});
Multiple Leaderboards
Most games benefit from multiple leaderboards:
// Different leaderboards for different contexts
const LEADERBOARDS = {
global: 'lb_global_alltime',
daily: 'lb_global_daily',
weekly: 'lb_global_weekly',
level1: 'lb_level1_speedrun',
level2: 'lb_level2_speedrun',
};
// Submit to multiple leaderboards after a game session
async function submitGameResults(playerId: string, score: number, level: string, timeMs: number) {
// Submit score to global leaderboards
await client.submitScore({
leaderboardId: LEADERBOARDS.global,
playerId,
score: BigInt(score),
});
await client.submitScore({
leaderboardId: LEADERBOARDS.daily,
playerId,
score: BigInt(score),
});
// Submit time to level-specific speedrun board
const levelBoard = LEADERBOARDS[`${level}` as keyof typeof LEADERBOARDS];
if (levelBoard) {
await client.submitScore({
leaderboardId: levelBoard,
playerId,
score: BigInt(timeMs),
});
}
}
Accessing Historical Periods
For time-based leaderboards, you can query past periods:
// Get the previous period's leaderboard
const lastWeek = await client.getLeaderboard({
leaderboardId: 'lb_weekly',
period: 'previous',
});
// Get a specific historical period
const specificWeek = await client.getLeaderboard({
leaderboardId: 'lb_weekly',
period: '2024-01-15T00:00:00Z', // Any date in that period
});
Choosing the Right Configuration
| Game Type | Recommended Setup |
|---|---|
| Casual mobile game | Daily + All-time |
| Competitive esport | Weekly + Season (monthly) |
| Speedrun game | All-time per level |
| Idle/incremental | All-time only |
| Battle royale | Daily + Weekly |
| Puzzle game | All-time + Daily challenges |