Skip to main content

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 TypeRecommended Setup
Casual mobile gameDaily + All-time
Competitive esportWeekly + Season (monthly)
Speedrun gameAll-time per level
Idle/incrementalAll-time only
Battle royaleDaily + Weekly
Puzzle gameAll-time + Daily challenges