Skip to main content

Leaderboards Overview

Leaderboards allow you to create competitive rankings for your players, encouraging engagement and replay value. The Moitribe SDK provides flexible leaderboard functionality with social and global rankings, multiple timespans, and customizable scoring.

Key Concepts​

Leaderboard Types​

The Moitribe SDK supports two main types of leaderboards based on collections:

Social Leaderboards (Collection 0)

  • Rankings among friends and social connections
  • Encourages social gameplay and friend competition
  • Smaller, more intimate competitive groups

Global Leaderboards (Collection 1)

  • Rankings among all players worldwide
  • Large-scale competition across your entire player base
  • Best for competitive games with high player counts

Timespans​

Each leaderboard can track scores across multiple time periods:

TimespanValueDescriptionBest For
All-time0All scores since leaderboard creationLifetime achievements
Weekly1Scores from the current weekRegular competition
Daily2Scores from the current dayQuick challenges
tip

Use multiple timespans to give players different ways to compete. A player might not top the all-time board, but could win the daily challenge!

Score Ordering​

Leaderboards support two ordering modes:

  • Ascending (-1): Lower scores are better (speedruns, golf, time trials)
  • Descending (1): Higher scores are better (points, kills, achievements)

The ordering is configured in your Moitribe dashboard and returned in leaderboard metadata.

Leaderboard Workflow​

Here's the typical flow for implementing leaderboards:

// 1. Load leaderboard metadata to get configuration
MoitribeSDK('my-game-id', 'loadleaderboardmetadata', {
onlyData: true,
callback: (result) => {
if (result.success) {
const leaderboards = result.leaderboards;
console.log('Available leaderboards:', leaderboards);
}
}
});

// 2. Submit a score when player completes a level or match
MoitribeSDK('my-game-id', 'submitscore', {
leaderboardid: 'high-scores',
score: 1000,
scoretag: 'level-5',
callback: (result) => {
console.log('Score submitted:', result.success);
}
});

// 3. Retrieve and display top scores
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: 'high-scores',
collection: 1, // Global
timespan: 0, // All-time
maxresults: 10,
onlyData: true,
callback: (result) => {
if (result.success) {
result.scores.forEach((score, index) => {
console.log(`${index + 1}. ${score.playerName}: ${score.playerScore}`);
});
}
}
});

Available Operations​

Load Leaderboard Metadata​

Get configuration details for all your game's leaderboards:

MoitribeSDK('my-game-id', 'loadleaderboardmetadata', {
onlyData: true,
callback: (result) => {
// Returns leaderboard IDs, names, icons, and scoring rules
}
});

See: Get Metadata

Submit Scores​

Post a player's score to a leaderboard:

MoitribeSDK('my-game-id', 'submitscore', {
leaderboardid: 'high-scores',
score: 1500,
scoretag: 'optional-metadata',
callback: (result) => {
console.log('Score submitted:', result.success);
}
});

See: Submit Score

Get Top Scores​

Retrieve ranked scores from a leaderboard:

MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: 'high-scores',
collection: 1, // Social (0) or Global (1)
timespan: 0, // All-time (0), Weekly (1), Daily (2)
maxresults: 10,
onlyData: true,
callback: (result) => {
// Returns array of scores with ranks and player info
}
});

See: Get Top Scores

TypeScript Example​

Use proper typing for type-safe leaderboard operations:

import MoitribeSDK from '@veniso/moitribe-js';
import type { LeaderboardMeta, LeaderboardScoreData } from '@veniso/moitribe-js';

// Load metadata with typing
MoitribeSDK('my-game-id', 'loadleaderboardmetadata', {
onlyData: true,
callback: (result: { success: boolean; leaderboards: LeaderboardMeta[] }) => {
if (result.success) {
result.leaderboards.forEach((lb: LeaderboardMeta) => {
console.log(`${lb.leaderboardName} (${lb.leaderboardID})`);
console.log(`Order: ${lb.leaderboardScoreOrder === 1 ? 'Descending' : 'Ascending'}`);
});
}
}
});

// Get scores with typing
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: 'high-scores',
collection: 1,
timespan: 0,
maxresults: 10,
onlyData: true,
callback: (result: { success: boolean; scores: LeaderboardScoreData[] }) => {
if (result.success) {
result.scores.forEach((score: LeaderboardScoreData) => {
console.log(`#${score.playerRank}: ${score.playerName} - ${score.playerScore}`);
});
}
}
});

Common Use Cases​

Display Multiple Timespans​

Show daily, weekly, and all-time rankings:

function loadLeaderboard(leaderboardId, timespan) {
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: leaderboardId,
collection: 1,
timespan: timespan,
maxresults: 10,
onlyData: true,
callback: (result) => {
if (result.success) {
displayScores(result.scores, getTimespanName(timespan));
}
}
});
}

function getTimespanName(timespan) {
const names = { 0: 'All-Time', 1: 'This Week', 2: 'Today' };
return names[timespan] || 'Unknown';
}

// Load all timespans
loadLeaderboard('high-scores', 0); // All-time
loadLeaderboard('high-scores', 1); // Weekly
loadLeaderboard('high-scores', 2); // Daily

Social vs Global Toggle​

Let players switch between friend and global rankings:

function loadLeaderboardByCollection(leaderboardId, isSocial) {
const collection = isSocial ? 0 : 1;

MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: leaderboardId,
collection: collection,
timespan: 0,
maxresults: 10,
onlyData: true,
callback: (result) => {
if (result.success) {
const title = isSocial ? 'Friends Rankings' : 'Global Rankings';
displayScores(result.scores, title);
}
}
});
}

// Button handlers
document.getElementById('btn-friends').onclick = () => {
loadLeaderboardByCollection('high-scores', true);
};

document.getElementById('btn-global').onclick = () => {
loadLeaderboardByCollection('high-scores', false);
};

Submit Score with Metadata​

Use scoretag to store additional information:

function submitGameScore(score, level, difficulty) {
// Store metadata as JSON string
const metadata = JSON.stringify({
level: level,
difficulty: difficulty,
timestamp: Date.now()
});

MoitribeSDK('my-game-id', 'submitscore', {
leaderboardid: 'high-scores',
score: score,
scoretag: metadata,
callback: (result) => {
if (result.success) {
console.log('Score submitted with metadata');
}
}
});
}

// Submit score with context
submitGameScore(1500, 5, 'hard');

Leaderboard Data Structure​

Metadata Response​

interface LeaderboardMeta {
leaderboardID: string; // 'high-scores'
leaderboardName: string; // 'High Scores'
leaderboardIconURL: string; // URL to icon image
leaderboardScoreOrder: number; // 1 (descending) or -1 (ascending)
leaderboardCollection: {
Social: number; // Social collection ID
All: number; // Global collection ID
};
}

Score Data Response​

interface LeaderboardScoreData {
playerRank: number; // Player's position (1, 2, 3...)
playerScore: number; // The actual score
playerName: string; // Player's display name
leaderboardID: string; // ID of this leaderboard
timestamp: number; // When score was submitted
player: Player; // Full player object
iconURL: string; // Player's profile icon
hiresURL: string; // High-resolution profile image
scoreTag: string; // Custom metadata
}

Authentication Requirements​

warning

Players must be authenticated to submit scores and view social leaderboards. Global leaderboard viewing may work without authentication depending on your game's configuration.

Check authentication before submitting scores:

MoitribeSDK('my-game-id', 'isAuthenticated', {}, (authResult) => {
if (authResult.success) {
// Player is authenticated, submit score
MoitribeSDK('my-game-id', 'submitscore', {
leaderboardid: 'high-scores',
score: 1000,
callback: (result) => {
console.log('Score submitted:', result.success);
}
});
} else {
// Prompt player to log in
showLoginPrompt();
}
});

Error Handling​

Handle common leaderboard errors:

MoitribeSDK('my-game-id', 'submitscore', {
leaderboardid: 'high-scores',
score: 1000,
callback: (result) => {
if (result.success) {
console.log('Score submitted successfully');
} else {
// Handle specific errors
if (result.msg.includes('authenticated')) {
showError('Please log in to submit scores');
} else if (result.msg.includes('leaderboard')) {
showError('Leaderboard not found');
} else {
showError('Failed to submit score. Please try again.');
}
}
}
});

Next Steps​

Learn about specific leaderboard operations:

Related topics: