Skip to main content

Score Collections

Leaderboard collections determine which group of players are ranked together. The Moitribe SDK supports two collection types: Social (friends only) and Global (all players).

Collection Types

Social Collection (Value: 0)

Shows rankings among friends and social connections:

MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: 'high-scores',
collection: 0, // Social collection
timespan: 0,
maxresults: 10,
onlyData: true,
callback: (result) => {
console.log('Friend rankings:', result.scores);
}
});

Characteristics:

  • Only includes players in the viewer's social network
  • Smaller, more intimate competitive groups
  • Encourages social gameplay and friend invitations
  • Requires authentication to view

Best for:

  • Social games with friend systems
  • Encouraging friend competition
  • Viral mechanics ("Beat your friends!")
  • Personal milestone tracking

Global Collection (Value: 1)

Shows rankings among all players worldwide:

MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: 'high-scores',
collection: 1, // Global collection
timespan: 0,
maxresults: 10,
onlyData: true,
callback: (result) => {
console.log('Global rankings:', result.scores);
}
});

Characteristics:

  • Includes all players across your entire game
  • Large-scale competition
  • Shows true world rankings
  • May not require authentication to view (game-dependent)

Best for:

  • Competitive games
  • Showcasing top players
  • Global challenges
  • Esports and tournaments

Collection Parameter

The collection parameter is used when loading leaderboard scores:

ValueTypeDescription
0SocialFriends and connections only
1GlobalAll players worldwide
interface LoadScoresParams {
leaderboardid: string;
collection: 0 | 1; // Social or Global
timespan: 0 | 1 | 2;
maxresults?: number;
onlyData: boolean;
callback: (result: ScoresResult) => void;
}

Common Use Cases

Toggle Between Collections

Let players switch between friend and global rankings:

let currentCollection = 1; // Start with global

function toggleCollection() {
// Switch between collections
currentCollection = currentCollection === 1 ? 0 : 1;

// Update button text
const buttonText = currentCollection === 1 ? 'Show Friends' : 'Show Global';
document.getElementById('toggle-btn').textContent = buttonText;

// Reload leaderboard
loadLeaderboard('high-scores', currentCollection);
}

function loadLeaderboard(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 click handler
document.getElementById('toggle-btn').onclick = toggleCollection;

Tabbed Interface

Create tabs for social and global views:

function setupCollectionTabs(leaderboardId) {
// Social tab
document.getElementById('tab-friends').onclick = () => {
setActiveTab('tab-friends');
loadLeaderboard(leaderboardId, 0);
};

// Global tab
document.getElementById('tab-global').onclick = () => {
setActiveTab('tab-global');
loadLeaderboard(leaderboardId, 1);
};

// Load global by default
setActiveTab('tab-global');
loadLeaderboard(leaderboardId, 1);
}

function setActiveTab(tabId) {
document.querySelectorAll('.tab').forEach(tab => {
tab.classList.remove('active');
});
document.getElementById(tabId).classList.add('active');
}

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

// Initialize
setupCollectionTabs('high-scores');

Side-by-Side Comparison

Display social and global rankings together:

function loadBothCollections(leaderboardId) {
// Load social rankings
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: leaderboardId,
collection: 0,
timespan: 0,
maxresults: 5,
onlyData: true,
callback: (result) => {
if (result.success) {
displayScores(result.scores, 'friends-leaderboard', 'Friends');
}
}
});

// Load global rankings
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: leaderboardId,
collection: 1,
timespan: 0,
maxresults: 5,
onlyData: true,
callback: (result) => {
if (result.success) {
displayScores(result.scores, 'global-leaderboard', 'Global');
}
}
});
}

function displayScores(scores, containerId, title) {
const container = document.getElementById(containerId);
container.innerHTML = `<h3>${title}</h3>`;

scores.forEach((score) => {
const row = document.createElement('div');
row.innerHTML = `${score.playerRank}. ${score.playerName}: ${score.playerScore}`;
container.appendChild(row);
});
}

// Display both
loadBothCollections('high-scores');

Collection Selector Dropdown

Use a dropdown to select collection:

function setupCollectionDropdown(leaderboardId) {
const selector = document.getElementById('collection-selector');

// Add options
selector.innerHTML = `
<option value="1">Global Rankings</option>
<option value="0">Friends Rankings</option>
`;

// Handle change
selector.onchange = (e) => {
const collection = parseInt(e.target.value);
loadLeaderboard(leaderboardId, collection);
};

// Load global by default
loadLeaderboard(leaderboardId, 1);
}

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

// Initialize
setupCollectionDropdown('high-scores');

TypeScript Collection Manager

Create a type-safe collection manager:

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

enum CollectionType {
Social = 0,
Global = 1
}

interface CollectionOptions {
leaderboardId: string;
collection: CollectionType;
timespan?: 0 | 1 | 2;
maxResults?: number;
}

class LeaderboardCollectionManager {
private gameId: string;
private currentCollection: CollectionType = CollectionType.Global;

constructor(gameId: string) {
this.gameId = gameId;
}

async loadScores(options: CollectionOptions): Promise<LeaderboardScoreData[]> {
return new Promise((resolve, reject) => {
MoitribeSDK(this.gameId, 'loadleaderboardtopscores', {
leaderboardid: options.leaderboardId,
collection: options.collection,
timespan: options.timespan || 0,
maxresults: options.maxResults || 10,
onlyData: true,
callback: (result: { success: boolean; scores: LeaderboardScoreData[] }) => {
if (result.success) {
this.currentCollection = options.collection;
resolve(result.scores);
} else {
reject(new Error('Failed to load scores'));
}
}
});
});
}

async loadSocialScores(leaderboardId: string): Promise<LeaderboardScoreData[]> {
return this.loadScores({
leaderboardId,
collection: CollectionType.Social
});
}

async loadGlobalScores(leaderboardId: string): Promise<LeaderboardScoreData[]> {
return this.loadScores({
leaderboardId,
collection: CollectionType.Global
});
}

toggleCollection(): CollectionType {
this.currentCollection = this.currentCollection === CollectionType.Global
? CollectionType.Social
: CollectionType.Global;
return this.currentCollection;
}

getCurrentCollection(): CollectionType {
return this.currentCollection;
}

getCollectionName(collection: CollectionType): string {
return collection === CollectionType.Social ? 'Friends' : 'Global';
}
}

// Usage
const manager = new LeaderboardCollectionManager('my-game-id');

// Load global scores
const globalScores = await manager.loadGlobalScores('high-scores');
console.log('Global scores:', globalScores);

// Load friend scores
const friendScores = await manager.loadSocialScores('high-scores');
console.log('Friend scores:', friendScores);

// Toggle between collections
const newCollection = manager.toggleCollection();
console.log('Switched to:', manager.getCollectionName(newCollection));

Collection Availability

Checking Collection Support

Verify which collections a leaderboard supports:

function checkCollectionSupport(leaderboardId) {
MoitribeSDK('my-game-id', 'loadleaderboardmetadata', {
onlyData: true,
callback: (result) => {
if (result.success) {
const leaderboard = result.leaderboards.find(
lb => lb.leaderboardID === leaderboardId
);

if (leaderboard) {
console.log('Social collection ID:', leaderboard.leaderboardCollection.Social);
console.log('Global collection ID:', leaderboard.leaderboardCollection.All);

// Both collections should be available if properly configured
const hasSocial = !!leaderboard.leaderboardCollection.Social;
const hasGlobal = !!leaderboard.leaderboardCollection.All;

console.log('Supports social:', hasSocial);
console.log('Supports global:', hasGlobal);
}
}
}
});
}

Social Collection Requirements

Authentication

Social collections require player authentication:

function loadSocialLeaderboard(leaderboardId) {
// Check authentication first
MoitribeSDK('my-game-id', 'isAuthenticated', {}, (authResult) => {
if (authResult.success) {
// Player is authenticated, load social rankings
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: leaderboardId,
collection: 0,
timespan: 0,
maxresults: 10,
onlyData: true,
callback: (result) => {
if (result.success) {
displayFriendRankings(result.scores);
}
}
});
} else {
// Show login prompt
showMessage('Please log in to view friend rankings');
showLoginButton();
}
});
}

Empty Social Rankings

Handle cases where player has no friends:

function displayFriendRankings(scores) {
if (scores.length === 0) {
showEmptyState(
'No friend scores yet',
'Invite friends to compete on the leaderboard!'
);
} else {
displayScores(scores);
}
}

function showEmptyState(title, message) {
const container = document.getElementById('leaderboard');
container.innerHTML = `
<div class="empty-state">
<h3>${title}</h3>
<p>${message}</p>
<button onclick="showInviteDialog()">Invite Friends</button>
</div>
`;
}

Best Practices

1. Default to Global

Start with global rankings for better initial experience:

// Good: Show global rankings first
function initializeLeaderboard(leaderboardId) {
loadLeaderboard(leaderboardId, 1); // Global
}

// Then allow switching to social
function showFriendRankings() {
loadLeaderboard(leaderboardId, 0); // Social
}

2. Indicate Current Collection

Make it clear which collection is displayed:

function displayScoresWithHeader(scores, collection) {
const title = collection === 0
? 'Friends Rankings'
: 'Global Rankings';

const subtitle = collection === 0
? 'Compete with your friends'
: 'See where you rank worldwide';

const container = document.getElementById('leaderboard');
container.innerHTML = `
<div class="leaderboard-header">
<h2>${title}</h2>
<p>${subtitle}</p>
</div>
`;

// Add scores...
}

3. Encourage Social Play

Prompt players to view friend rankings:

function showSocialPrompt() {
if (hasAuthenticatedFriends()) {
showNotification('See how you rank against your friends!', () => {
loadLeaderboard('high-scores', 0);
});
}
}

4. Handle Collection Errors

Gracefully handle unavailable collections:

function loadCollectionSafely(leaderboardId, collection) {
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: leaderboardId,
collection: collection,
timespan: 0,
maxresults: 10,
onlyData: true,
callback: (result) => {
if (result.success) {
displayScores(result.scores);
} else {
// Fall back to global if social fails
if (collection === 0) {
console.log('Social collection unavailable, showing global');
loadCollectionSafely(leaderboardId, 1);
} else {
showError('Unable to load leaderboard');
}
}
}
});
}

Collection Strategies

Beginner-Friendly

Start players with friend rankings:

function showBeginnerLeaderboard() {
// New players see friends first (less intimidating)
loadLeaderboard('high-scores', 0);

// Offer global view as option
showButton('View Global Rankings', () => {
loadLeaderboard('high-scores', 1);
});
}

Competitive Focus

Emphasize global rankings:

function showCompetitiveLeaderboard() {
// Competitive players see global first
loadLeaderboard('high-scores', 1);

// Friends view is secondary
showSmallButton('View Friends', () => {
loadLeaderboard('high-scores', 0);
});
}

Balanced Approach

Show both equally:

function showBalancedLeaderboard() {
// Show both with equal prominence
setupTabs(['Global', 'Friends'], [1, 0]);

// Default to player's preference
const preferredCollection = getPlayerPreference() || 1;
loadLeaderboard('high-scores', preferredCollection);
}

Next Steps

Related topics: