Skip to main content

Timespans

Leaderboard timespans allow you to rank players across different time periods. The Moitribe SDK supports three timespans: All-time (lifetime), Weekly, and Daily rankings.

Timespan Types

All-time (Value: 0)

Shows rankings since the leaderboard was created:

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

Characteristics:

  • Includes all scores ever submitted
  • Never resets
  • Shows lifetime achievements
  • Typically dominated by long-time players

Best for:

  • Hall of fame displays
  • Lifetime achievement tracking
  • Overall game mastery
  • Veteran player recognition

Weekly (Value: 1)

Shows rankings for the current week:

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

Characteristics:

  • Resets at the start of each week
  • Gives all players a fresh chance
  • Encourages regular engagement
  • More achievable for new players

Best for:

  • Weekly challenges
  • Regular competitions
  • Encouraging return visits
  • Balanced competition

Daily (Value: 2)

Shows rankings for the current day:

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

Characteristics:

  • Resets every day
  • Fastest refresh cycle
  • Most accessible to new players
  • Creates urgency ("win today!")

Best for:

  • Daily challenges
  • Quick competitions
  • New player engagement
  • Daily login incentives

Timespan Parameter

The timespan parameter is used when loading leaderboard scores:

ValueTypeDescriptionReset Frequency
0All-timeLifetime scoresNever
1WeeklyCurrent weekWeekly
2DailyCurrent dayDaily
interface LoadScoresParams {
leaderboardid: string;
collection: 0 | 1;
timespan: 0 | 1 | 2; // All-time, Weekly, or Daily
maxresults?: number;
onlyData: boolean;
callback: (result: ScoresResult) => void;
}

Common Use Cases

Tabbed Timespan Interface

Let players switch between timespans:

function setupTimespanTabs(leaderboardId) {
const timespans = [
{ value: 0, label: 'All-Time' },
{ value: 1, label: 'This Week' },
{ value: 2, label: 'Today' }
];

timespans.forEach((timespan) => {
const button = document.getElementById(`tab-${timespan.value}`);
button.textContent = timespan.label;
button.onclick = () => {
setActiveTab(`tab-${timespan.value}`);
loadLeaderboard(leaderboardId, timespan.value);
};
});

// Default to all-time
setActiveTab('tab-0');
loadLeaderboard(leaderboardId, 0);
}

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

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);
}
}
});
}

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

Multiple Timespan Display

Show all timespans simultaneously:

function loadAllTimespans(leaderboardId) {
const timespans = [
{ value: 0, name: 'All-Time', containerId: 'alltime-scores' },
{ value: 1, name: 'This Week', containerId: 'weekly-scores' },
{ value: 2, name: 'Today', containerId: 'daily-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) {
displayScoresInContainer(
result.scores,
timespan.containerId,
timespan.name
);
}
}
});
});
}

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

if (scores.length === 0) {
container.innerHTML += '<p>No scores yet!</p>';
return;
}

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

// Load all timespans
loadAllTimespans('high-scores');

Use a dropdown to select timespan:

function setupTimespanDropdown(leaderboardId) {
const selector = document.getElementById('timespan-selector');

selector.innerHTML = `
<option value="0">All-Time</option>
<option value="1">This Week</option>
<option value="2">Today</option>
`;

selector.onchange = (e) => {
const timespan = parseInt(e.target.value);
loadLeaderboard(leaderboardId, timespan);
};

// Load all-time by default
loadLeaderboard(leaderboardId, 0);
}

function loadLeaderboard(leaderboardId, timespan) {
const title = getTimespanTitle(timespan);
document.getElementById('leaderboard-title').textContent = title;

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

function getTimespanTitle(timespan) {
const titles = {
0: 'All-Time High Scores',
1: 'This Week\'s Top Players',
2: 'Today\'s Best Scores'
};
return titles[timespan] || 'Leaderboard';
}

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

Highlight Daily Challenge

Emphasize daily leaderboard:

function showDailyChallenge(leaderboardId) {
// Load today's leaderboard
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: leaderboardId,
collection: 1,
timespan: 2, // Daily
maxresults: 10,
onlyData: true,
callback: (result) => {
if (result.success) {
displayDailyChallenge(result.scores);
showTimeRemaining();
}
}
});
}

function displayDailyChallenge(scores) {
const container = document.getElementById('daily-challenge');
container.innerHTML = `
<div class="challenge-header">
<h2>Daily Challenge</h2>
<p>Compete for today's top spot!</p>
<div id="time-remaining"></div>
</div>
`;

displayScores(scores);
}

function showTimeRemaining() {
const now = new Date();
const tomorrow = new Date(now);
tomorrow.setDate(tomorrow.getDate() + 1);
tomorrow.setHours(0, 0, 0, 0);

const msRemaining = tomorrow - now;
const hoursRemaining = Math.floor(msRemaining / 3600000);
const minutesRemaining = Math.floor((msRemaining % 3600000) / 60000);

document.getElementById('time-remaining').textContent =
`Resets in ${hoursRemaining}h ${minutesRemaining}m`;
}

// Show daily challenge
showDailyChallenge('high-scores');

TypeScript Timespan Manager

Create a type-safe timespan manager:

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

enum Timespan {
AllTime = 0,
Weekly = 1,
Daily = 2
}

interface TimespanOptions {
leaderboardId: string;
timespan: Timespan;
collection?: 0 | 1;
maxResults?: number;
}

class LeaderboardTimespanManager {
private gameId: string;
private currentTimespan: Timespan = Timespan.AllTime;

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

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

async loadAllTimeScores(leaderboardId: string): Promise<LeaderboardScoreData[]> {
return this.loadScores({
leaderboardId,
timespan: Timespan.AllTime
});
}

async loadWeeklyScores(leaderboardId: string): Promise<LeaderboardScoreData[]> {
return this.loadScores({
leaderboardId,
timespan: Timespan.Weekly
});
}

async loadDailyScores(leaderboardId: string): Promise<LeaderboardScoreData[]> {
return this.loadScores({
leaderboardId,
timespan: Timespan.Daily
});
}

getTimespanName(timespan: Timespan): string {
const names: Record<Timespan, string> = {
[Timespan.AllTime]: 'All-Time',
[Timespan.Weekly]: 'This Week',
[Timespan.Daily]: 'Today'
};
return names[timespan];
}

getTimespanDescription(timespan: Timespan): string {
const descriptions: Record<Timespan, string> = {
[Timespan.AllTime]: 'Lifetime rankings',
[Timespan.Weekly]: 'Resets every week',
[Timespan.Daily]: 'Resets every day'
};
return descriptions[timespan];
}

getCurrentTimespan(): Timespan {
return this.currentTimespan;
}
}

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

// Load all-time scores
const alltimeScores = await manager.loadAllTimeScores('high-scores');
console.log('All-time:', alltimeScores);

// Load weekly scores
const weeklyScores = await manager.loadWeeklyScores('high-scores');
console.log('This week:', weeklyScores);

// Load daily scores
const dailyScores = await manager.loadDailyScores('high-scores');
console.log('Today:', dailyScores);

// Get timespan information
console.log('Current:', manager.getTimespanName(manager.getCurrentTimespan()));

Timespan Reset Times

Understanding Resets

Weekly and daily leaderboards reset at specific times:

  • Daily: Resets at midnight (00:00) in your configured timezone
  • Weekly: Resets at midnight on Monday (start of week)
  • All-time: Never resets

Display Reset Information

Show when leaderboards reset:

function displayResetInfo(timespan) {
const info = {
0: { text: 'Never resets', urgent: false },
1: { text: 'Resets every Monday', urgent: shouldWarnWeeklyReset() },
2: { text: 'Resets at midnight', urgent: shouldWarnDailyReset() }
};

const message = info[timespan];
const element = document.getElementById('reset-info');
element.textContent = message.text;
element.className = message.urgent ? 'reset-warning' : 'reset-info';
}

function shouldWarnDailyReset() {
const now = new Date();
const hour = now.getHours();
return hour >= 22; // Warn after 10 PM
}

function shouldWarnWeeklyReset() {
const now = new Date();
const day = now.getDay();
const hour = now.getHours();
return day === 0 && hour >= 20; // Warn Sunday after 8 PM
}

Countdown Timer

Show time until reset:

function showResetCountdown(timespan) {
if (timespan === 0) {
return; // All-time never resets
}

const resetTime = getNextResetTime(timespan);
const now = new Date();
const msRemaining = resetTime - now;

if (msRemaining <= 0) {
document.getElementById('countdown').textContent = 'Leaderboard resetting soon...';
return;
}

const hours = Math.floor(msRemaining / 3600000);
const minutes = Math.floor((msRemaining % 3600000) / 60000);
const seconds = Math.floor((msRemaining % 60000) / 1000);

document.getElementById('countdown').textContent =
`Resets in ${hours}h ${minutes}m ${seconds}s`;

// Update every second
setTimeout(() => showResetCountdown(timespan), 1000);
}

function getNextResetTime(timespan) {
const now = new Date();
const reset = new Date(now);

if (timespan === 2) {
// Daily: next midnight
reset.setDate(reset.getDate() + 1);
reset.setHours(0, 0, 0, 0);
} else if (timespan === 1) {
// Weekly: next Monday midnight
const daysUntilMonday = (8 - reset.getDay()) % 7 || 7;
reset.setDate(reset.getDate() + daysUntilMonday);
reset.setHours(0, 0, 0, 0);
}

return reset;
}

Choosing the Right Timespan

New Player Games

Focus on daily leaderboards for new players:

function setupNewPlayerLeaderboard() {
// Highlight daily for accessibility
loadLeaderboard('high-scores', 2); // Daily first

// Make weekly and all-time secondary
showSecondaryTabs([1, 0]);
}

Established Games

Emphasize all-time for established games:

function setupEstablishedGameLeaderboard() {
// Show all-time for prestige
loadLeaderboard('high-scores', 0); // All-time first

// Offer time-based challenges
showChallengePrompt('Try this week\'s challenge!', () => {
loadLeaderboard('high-scores', 1);
});
}

Balanced Approach

Give equal weight to all timespans:

function setupBalancedLeaderboard() {
// Show all three with equal prominence
loadAllTimespans('high-scores');

// Let player choose default preference
savePlayerPreference();
}

Best Practices

1. Use Multiple Timespans

Provide variety for different player types:

// Good: Offer all timespans
function setupLeaderboard() {
setupTimespanTabs(['All-Time', 'Weekly', 'Daily']);
}

// Better: Highlight based on context
function setupContextualLeaderboard() {
const isNewPlayer = checkIfNewPlayer();
const defaultTimespan = isNewPlayer ? 2 : 0; // Daily for new, All-time for veterans

loadLeaderboard('high-scores', defaultTimespan);
}

2. Show Reset Information

Make reset times clear:

function displayTimespanWithInfo(timespan) {
const titles = {
0: { title: 'All-Time', subtitle: 'Lifetime achievements' },
1: { title: 'This Week', subtitle: 'Resets Monday' },
2: { title: 'Today', subtitle: 'Resets at midnight' }
};

const info = titles[timespan];
document.getElementById('leaderboard-title').textContent = info.title;
document.getElementById('leaderboard-subtitle').textContent = info.subtitle;
}

3. Create Urgency

Use timespans to drive engagement:

function showDailyUrgency() {
const hoursUntilReset = getHoursUntilDailyReset();

if (hoursUntilReset <= 3) {
showNotification(
`Only ${hoursUntilReset} hours left to win today's challenge!`,
() => loadLeaderboard('high-scores', 2)
);
}
}

4. Celebrate Timespan Wins

Acknowledge achievements across timespans:

function checkPlayerRankings(playerId) {
const timespans = [0, 1, 2];

timespans.forEach((timespan) => {
MoitribeSDK('my-game-id', 'loadleaderboardtopscores', {
leaderboardid: 'high-scores',
collection: 1,
timespan: timespan,
maxresults: 10,
onlyData: true,
callback: (result) => {
if (result.success) {
const playerScore = result.scores.find(s => s.player.id === playerId);
if (playerScore && playerScore.playerRank <= 3) {
const timespanName = getTimespanName(timespan);
celebrateRanking(playerScore.playerRank, timespanName);
}
}
}
});
});
}

Next Steps

Related topics: