Get Top Scores
The loadleaderboardtopscores method retrieves ranked scores from a leaderboard. You can filter by collection (social/global), timespan (daily/weekly/all-time), and limit the number of results returned.
Overview
Use this method to display leaderboard rankings in your game. It supports pagination, filtering by social circle, and time-based rankings.
Basic Usage
JavaScript Example
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: 'high-scores',
collection: 1, // 0 = Social, 1 = Global
timespan: 0, // 0 = All-time, 1 = Weekly, 2 = Daily
maxresults: 10,
onlyData: true,
callback: (result) => {
if (result.success) {
result.scores.forEach((score, index) => {
console.log(`${score.playerRank}. ${score.playerName}: ${score.playerScore}`);
});
} else {
console.error('Failed to load scores');
}
}
});
TypeScript Example
import MoitribeSDK from '@veniso/moitribe-js';
import type { LeaderboardScoreData } from '@veniso/moitribe-js';
interface ScoresResult {
success: boolean;
scores: LeaderboardScoreData[];
msg?: string;
}
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: 'high-scores',
collection: 1,
timespan: 0,
maxresults: 10,
onlyData: true,
callback: (result: ScoresResult) => {
if (result.success) {
result.scores.forEach((score: LeaderboardScoreData) => {
console.log(`Rank ${score.playerRank}: ${score.playerName} - ${score.playerScore} points`);
console.log(`Submitted: ${new Date(score.timestamp * 1000).toLocaleDateString()}`);
});
}
}
});
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
leaderboardid | string | Yes | The leaderboard ID to query |
collection | number | Yes | 0 for Social (friends), 1 for Global (all players) |
timespan | number | Yes | 0 for All-time, 1 for Weekly, 2 for Daily |
maxresults | number | No | Maximum number of scores to return (default: 10) |
onlyData | boolean | Yes | Set to true for programmatic access |
callback | function | Yes | Called with the result |
The leaderboardid must match an ID from your leaderboard metadata. Use Get Metadata to retrieve valid IDs.
Response Format
The callback receives a result object:
{
success: boolean;
scores: LeaderboardScoreData[];
msg?: string; // Error message if success is false
}
LeaderboardScoreData Structure
Each score in the array has this structure:
interface LeaderboardScoreData {
playerRank: number; // Player's position (1, 2, 3...)
playerScore: number; // The actual score value
playerName: string; // Player's display name
leaderboardID: string; // ID of this leaderboard
timestamp: number; // When score was submitted (Unix timestamp)
player: Player; // Full player object with ID and details
iconURL: string; // Player's profile icon URL
hiresURL: string; // High-resolution profile image URL
scoreTag: string; // Custom metadata attached to score
}
Example Response
{
success: true,
scores: [
{
playerRank: 1,
playerScore: 5000,
playerName: 'Alex',
leaderboardID: 'high-scores',
timestamp: 1701234567,
player: { id: 'player_123', name: 'Alex' },
iconURL: 'https://cdn.moitribe.com/profiles/alex_icon.png',
hiresURL: 'https://cdn.moitribe.com/profiles/alex_hires.png',
scoreTag: '{"level":10,"difficulty":"hard"}'
},
{
playerRank: 2,
playerScore: 4500,
playerName: 'Jordan',
leaderboardID: 'high-scores',
timestamp: 1701234500,
player: { id: 'player_456', name: 'Jordan' },
iconURL: 'https://cdn.moitribe.com/profiles/jordan_icon.png',
hiresURL: 'https://cdn.moitribe.com/profiles/jordan_hires.png',
scoreTag: '{"level":9,"difficulty":"normal"}'
}
]
}
Common Use Cases
Display Top 10 Leaderboard
Show the top-ranked players:
function displayTopScores(leaderboardId) {
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: leaderboardId,
collection: 1,
timespan: 0,
maxresults: 10,
onlyData: true,
callback: (result) => {
if (result.success) {
const container = document.getElementById('leaderboard');
container.innerHTML = '<h2>Top Players</h2>';
result.scores.forEach((score) => {
const row = document.createElement('div');
row.className = 'leaderboard-row';
row.innerHTML = `
<span class="rank">${score.playerRank}</span>
<img src="${score.iconURL}" class="avatar">
<span class="name">${score.playerName}</span>
<span class="score">${score.playerScore.toLocaleString()}</span>
`;
container.appendChild(row);
});
}
}
});
}
displayTopScores('high-scores');
Load Multiple Timespans
Show daily, weekly, and all-time rankings:
function loadAllTimespans(leaderboardId) {
const timespans = [
{ value: 2, name: 'Daily', element: 'daily-scores' },
{ value: 1, name: 'Weekly', element: 'weekly-scores' },
{ value: 0, name: 'All-Time', element: 'alltime-scores' }
];
timespans.forEach((timespan) => {
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: leaderboardId,
collection: 1,
timespan: timespan.value,
maxresults: 5,
onlyData: true,
callback: (result) => {
if (result.success) {
displayScoresInElement(result.scores, timespan.element, timespan.name);
}
}
});
});
}
function displayScoresInElement(scores, elementId, title) {
const container = document.getElementById(elementId);
container.innerHTML = `<h3>${title}</h3>`;
scores.forEach((score) => {
const item = document.createElement('div');
item.textContent = `${score.playerRank}. ${score.playerName}: ${score.playerScore}`;
container.appendChild(item);
});
}
loadAllTimespans('high-scores');
Switch Between Social and Global
Toggle between friend and global rankings:
let currentCollection = 1; // Start with global
function toggleCollection(leaderboardId) {
// Switch between 0 (social) and 1 (global)
currentCollection = currentCollection === 1 ? 0 : 1;
const buttonText = currentCollection === 1 ? 'Show Friends' : 'Show Global';
document.getElementById('toggle-btn').textContent = buttonText;
loadLeaderboardScores(leaderboardId, currentCollection);
}
function loadLeaderboardScores(leaderboardId, collection) {
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: leaderboardId,
collection: collection,
timespan: 0,
maxresults: 10,
onlyData: true,
callback: (result) => {
if (result.success) {
const title = collection === 0 ? 'Friends Rankings' : 'Global Rankings';
displayScores(result.scores, title);
}
}
});
}
// Button handler
document.getElementById('toggle-btn').onclick = () => {
toggleCollection('high-scores');
};
Paginate Results
Load more scores with pagination:
let currentPage = 0;
const scoresPerPage = 10;
function loadScorePage(leaderboardId, page) {
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: leaderboardId,
collection: 1,
timespan: 0,
maxresults: scoresPerPage,
onlyData: true,
callback: (result) => {
if (result.success) {
displayScorePage(result.scores, page);
// Enable/disable navigation buttons
document.getElementById('prev-btn').disabled = (page === 0);
document.getElementById('next-btn').disabled = (result.scores.length < scoresPerPage);
}
}
});
}
function nextPage() {
currentPage++;
loadScorePage('high-scores', currentPage);
}
function previousPage() {
if (currentPage > 0) {
currentPage--;
loadScorePage('high-scores', currentPage);
}
}
// Initial load
loadScorePage('high-scores', 0);
Note: The current SDK implementation returns top scores starting from rank 1. True pagination with offset is not directly supported. The example above shows the pattern, but maxresults controls the total number returned.
Display with Score Metadata
Parse and display scoretag metadata:
function displayScoresWithMetadata(leaderboardId) {
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: leaderboardId,
collection: 1,
timespan: 0,
maxresults: 10,
onlyData: true,
callback: (result) => {
if (result.success) {
result.scores.forEach((score) => {
// Parse metadata from scoretag
let metadata = {};
try {
metadata = JSON.parse(score.scoreTag || '{}');
} catch (e) {
metadata = {};
}
console.log(`${score.playerRank}. ${score.playerName}: ${score.playerScore}`);
if (metadata.level) {
console.log(` Achieved on level ${metadata.level}`);
}
if (metadata.difficulty) {
console.log(` Difficulty: ${metadata.difficulty}`);
}
});
}
}
});
}
TypeScript Leaderboard Component
Create a reusable leaderboard component:
import type { LeaderboardScoreData } from '@veniso/moitribe-js';
interface LeaderboardOptions {
leaderboardId: string;
collection: 0 | 1;
timespan: 0 | 1 | 2;
maxResults?: number;
}
class LeaderboardDisplay {
private gameId: string;
constructor(gameId: string) {
this.gameId = gameId;
}
async loadScores(options: LeaderboardOptions): Promise<LeaderboardScoreData[]> {
return new Promise((resolve, reject) => {
MoitribeSDK(this.gameId, 'loadleaderboardtopscores', {
leaderboardid: options.leaderboardId,
collection: options.collection,
timespan: options.timespan,
maxresults: options.maxResults || 10,
onlyData: true,
callback: (result: { success: boolean; scores: LeaderboardScoreData[] }) => {
if (result.success) {
resolve(result.scores);
} else {
reject(new Error('Failed to load scores'));
}
}
});
});
}
renderScores(scores: LeaderboardScoreData[], containerId: string): void {
const container = document.getElementById(containerId);
if (!container) return;
container.innerHTML = '';
scores.forEach((score) => {
const row = this.createScoreRow(score);
container.appendChild(row);
});
}
private createScoreRow(score: LeaderboardScoreData): HTMLElement {
const row = document.createElement('div');
row.className = 'score-row';
// Add medal emoji for top 3
const medal = this.getMedalEmoji(score.playerRank);
row.innerHTML = `
<span class="rank">${medal || score.playerRank}</span>
<img src="${score.iconURL}" alt="${score.playerName}" class="avatar">
<span class="name">${score.playerName}</span>
<span class="score">${score.playerScore.toLocaleString()}</span>
`;
return row;
}
private getMedalEmoji(rank: number): string | null {
const medals: { [key: number]: string } = {
1: '🥇',
2: '🥈',
3: '🥉'
};
return medals[rank] || null;
}
}
// Usage
const leaderboard = new LeaderboardDisplay('my-game-id');
leaderboard.loadScores({
leaderboardId: 'high-scores',
collection: 1,
timespan: 0,
maxResults: 10
}).then((scores) => {
leaderboard.renderScores(scores, 'leaderboard-container');
}).catch((error) => {
console.error('Failed to load leaderboard:', error);
});
Formatting Score Values
Number Formatting
Display scores with proper formatting:
function formatScore(score, leaderboardType) {
if (leaderboardType === 'time') {
// Format as time (milliseconds to MM:SS)
const minutes = Math.floor(score / 60000);
const seconds = Math.floor((score % 60000) / 1000);
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
} else if (leaderboardType === 'distance') {
// Format as distance
return `${(score / 1000).toFixed(2)} km`;
} else {
// Format as points
return score.toLocaleString();
}
}
// Usage
result.scores.forEach((score) => {
const formattedScore = formatScore(score.playerScore, 'points');
console.log(`${score.playerName}: ${formattedScore}`);
});
Date Formatting
Display when scores were submitted:
function formatTimestamp(timestamp) {
const date = new Date(timestamp * 1000);
const now = new Date();
const diffMs = now - date;
const diffMins = Math.floor(diffMs / 60000);
const diffHours = Math.floor(diffMs / 3600000);
const diffDays = Math.floor(diffMs / 86400000);
if (diffMins < 60) {
return `${diffMins} minutes ago`;
} else if (diffHours < 24) {
return `${diffHours} hours ago`;
} else if (diffDays < 7) {
return `${diffDays} days ago`;
} else {
return date.toLocaleDateString();
}
}
// Usage
result.scores.forEach((score) => {
const timeAgo = formatTimestamp(score.timestamp);
console.log(`Submitted ${timeAgo}`);
});
Error Handling
Handle common errors when loading scores:
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: 'high-scores',
collection: 1,
timespan: 0,
maxresults: 10,
onlyData: true,
callback: (result) => {
if (result.success) {
if (result.scores.length === 0) {
showMessage('No scores yet. Be the first to submit a score!');
} else {
displayScores(result.scores);
}
} else {
console.error('Failed to load scores:', result.msg);
// Handle specific errors
if (result.msg.includes('leaderboard')) {
showError('Leaderboard not found. Please check the leaderboard ID.');
} else if (result.msg.includes('network')) {
showError('Network error. Please check your connection.');
} else {
showError('Unable to load leaderboard. Please try again later.');
}
}
}
});
Best Practices
1. Cache Recent Results
Avoid repeated API calls by caching results:
const leaderboardCache = {
data: null,
timestamp: null,
ttl: 60000 // Cache for 1 minute
};
function loadScoresWithCache(leaderboardId) {
const now = Date.now();
// Use cache if fresh
if (leaderboardCache.data &&
leaderboardCache.timestamp &&
(now - leaderboardCache.timestamp) < leaderboardCache.ttl) {
displayScores(leaderboardCache.data);
return;
}
// Load fresh data
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: leaderboardId,
collection: 1,
timespan: 0,
maxresults: 10,
onlyData: true,
callback: (result) => {
if (result.success) {
leaderboardCache.data = result.scores;
leaderboardCache.timestamp = now;
displayScores(result.scores);
}
}
});
}
2. Handle Empty Results
Provide feedback when no scores exist:
function displayScoresOrEmpty(scores) {
const container = document.getElementById('leaderboard');
if (scores.length === 0) {
container.innerHTML = `
<div class="empty-state">
<p>No scores yet!</p>
<p>Be the first to submit a score.</p>
</div>
`;
} else {
displayScores(scores);
}
}
3. Highlight Current Player
Emphasize the current player's rank:
function displayScoresWithHighlight(scores, currentPlayerId) {
scores.forEach((score) => {
const row = createScoreRow(score);
if (score.player.id === currentPlayerId) {
row.classList.add('current-player');
}
container.appendChild(row);
});
}
4. Optimize Image Loading
Load profile images efficiently:
function createOptimizedScoreRow(score) {
const row = document.createElement('div');
row.className = 'score-row';
const img = document.createElement('img');
img.src = score.iconURL;
img.alt = score.playerName;
img.loading = 'lazy'; // Lazy load images
img.onerror = () => {
img.src = 'default-avatar.png'; // Fallback
};
row.appendChild(img);
// Add other elements...
return row;
}
Next Steps
- Submit Score - Post player scores to leaderboards
- Score Collections - Understanding Social vs Global
- Timespans - Daily, Weekly, and All-time explained
- Best Practices - Leaderboard implementation tips
Related topics:
- Get Metadata - Load leaderboard configuration
- Leaderboards Overview - Complete leaderboard guide