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: