Phoenix Gamification
Leaderboards

Leaderboard Overview

This guide explains how Phoenix leaderboards are modeled so you can design meaningful competitions before touching the Admin API. It focuses on the configuration shape you submit when creating or updating a leaderboard.

1. Mental Model

  • Leaderboard – a named competition scoped to a tenant. Each leaderboard owns a configuration document that defines who can enter, which events award points, and how standings are ranked.
  • Time window – the period during which scores accumulate (e.g., hourly, weekly, custom). Each window produces a unique window_key that the Query Gateway uses to fetch live or completed results.
  • Entry – a user’s cumulative score inside a single window. Entries exist as long as the window is active or until archived in historical storage.

Once a configuration is active, every ingested event is evaluated against its rules. Matching events modify the user’s entry for the current window; non-matching events are ignored for that leaderboard.

2. Lifecycle & Status

StatusMeaningTypical Use
activeLeaderboard is currently receiving events and available via Query/WebSocket endpoints.Default after creation.
inactiveConfiguration remains stored but events are ignored.Pause seasonal content without losing history.
archivedFully retired; no new events, primarily kept for auditing or snapshots only.Sunset legacy competitions.

Switching back to active re-enables scoring immediately for future events.

3. Configuration Snapshot

Every leaderboard config follows this top-level structure:

{
  "scope": {
    "filters": {
      "actor.metadata.region": { "eq": "na-east" },
      "attrs.mode": { "in": ["ranked", "tournament"] }
    }
  },
  "timeframe": {
    "type": "weekly",
    "timezone": "UTC",
    "reset_day": "monday",
    "reset_time": "00:00"
  },
  "scoring": {
    "rules": [
      {
        "event_type": "match.completed",
        "points_expression": "attrs.score",
        "conditions": {
          "attrs.victory": { "eq": true }
        }
      },
      {
        "event_type": "match.completed",
        "points_expression": "attrs.score * 0.5"
      }
    ],
    "aggregation": "sum"
  },
  "ranking": {
    "method": "score_desc",
    "size": 1000,
    "min_score": 0
  }
}

Each section is detailed below.

4. Scope Filters

  • Optional scope.filters object lets you restrict participation by evaluating JSON paths against each event.
  • Keys use dot notation (e.g., actor.metadata.platform, attrs.weapon).
  • Values can be:
    • Simple comparisons: { "eq": "ios" }, { "ne": "bot" }
    • Numeric operators: { "gt": 10 }, { "lte": 100 }
    • Membership: { "in": ["ranked", "scrim"] }
  • If scope is omitted, every event for the tenant may enter the leaderboard (subject to scoring rules).

Use scope filters to run simultaneous competitions on different segments without duplicating events.

5. Timeframes & Windows

TypeDescriptionAdditional Fields
real_timeAlways-open window; standings never reset automatically.
hourlyResets every hour at reset_time (defaults to 00:00).timezone (optional)
dailyResets once per day at reset_time.timezone (optional)
weeklyResets on the specified reset_day + reset_time.timezone, reset_day, reset_time
monthlyResets on the first day of each month at reset_time.timezone, reset_time
customResets based on custom_duration_seconds from the moment it becomes active.custom_duration_seconds (required)

Recommendations:

  • Always set timezone for user-facing competitions; otherwise UTC is assumed.
  • Weekly leaderboards must specify reset_day.
  • Custom durations are perfect for limited-time events (e.g., 6-hour flash competitions).

Each new window receives a unique window_key (e.g., 2025-11-18T12 for hourly), which clients can request explicitly or let Phoenix resolve automatically when querying.

6. Scoring Rules

Scoring determines how raw events convert into leaderboard points.

  1. Match by event type – specify an exact string or * wildcard to match all events.
  2. Guard with conditions – evaluate arbitrary attributes before awarding points.
  3. Compute pointspoints_expression supports:
    • Literals: 100
    • Attribute references: attrs.coins_spent, actor.metadata.multiplier
    • Basic math: attrs.score * 0.1 - 50
    • Functions: min(a, b), max(a, b), abs(x)

Rules are evaluated top-to-bottom. The first matching rule produces a score for that event; later rules are ignored for the same event.

7. Aggregation Strategies

The scoring.aggregation value defines how multiple events per user combine within the window:

AggregationBehaviorCommon Use Cases
sumAdds new points to the existing score (default).XP, points, currency totals.
countIncrements by 1 for every matched event (ignores points value).“Most matches played”, “Daily logins”.
maxKeeps the highest single-event score.“Best lap time”, “Highest damage in one run”.
minKeeps the lowest single-event score.“Fastest completion time” (lower is better).
avgMaintains the running average of event scores.Quality-based metrics (accuracy, rating).

Choose a strategy that aligns with the story you want to tell. For example, max avoids penalizing players who keep attempting a challenge after setting a high watermark.

8. Ranking Settings

  • method – determines how Phoenix orders the leaderboard:
    • score_desc: highest score first (default).
    • score_asc: lowest score first (useful for speedruns).
    • time_asc: tie-breaker that favors earlier achievements (relies on event timestamps).
  • size – optional hard cap on visible entries (1–10,000). Useful for “Top 100” style boards.
  • min_score – optional floor; users below this score are omitted even if they have activity.

Phoenix automatically assigns ranks starting at 1. Users who tie on score share the same rank; the next rank accounts for the tie (dense ranking).

9. Rewards & Snapshots

  • Reward definitions live separately (via the Rewards API) but can be linked to a leaderboard.
  • When a window finishes, Phoenix stores a snapshot of standings plus (optionally) the reward configuration in effect.
  • Query responses include reward_config for completed windows so clients can display prize tiers alongside historical results.

Plan your rewards with the window cadence in mind—e.g., weekly rewards for weekly timeframes to keep player expectations clear.

10. Best Practices Checklist

  • Use descriptive leaderboard_id values (xp-weekly-global) to simplify analytics.
  • Keep scope filters minimal; complex filters belong in your ingestion pipeline.
  • Validate configurations with Phoenix’s Admin API before activating them in production.
  • Document each leaderboard’s purpose and reward schedule for your support team.
  • When testing, start with small windows (hourly/custom) so you can iterate quickly.

With these concepts in mind, proceed to Creating Leaderboards for API-specific instructions on provisioning, updating, and deleting leaderboard configurations.