Skip to main content
You submit a player’s best score to a named board and show the top entries with the player’s rank.

Before you start

  • The SDK installed and started, from Connect the SDK.
  • A private preview to check hosted scores. The quickstart covers deploying one.

Declare the board

Boards live in opengame.json, up to 10 a game:
opengame.json
A score outside min or max is stored at that limit and marked clamped. A score is rejected instead when it is more than max times 10, or less than min divided by 10. With min at 0, that means any negative score. Only a score stored as submitted, marked ok, appears on the board.

Submit a score

saved.value.state is ok, clamped or rejected, and saved.value.best is true when the score replaced the player’s best. To call the game API without the SDK, read the API reference. The SDK handles the session, the request deadline and the local mock for you.

Show the board

top() returns up to 100 entries. around() returns 10 entries either side of the player. Each entry has these fields: name is the player’s handle when they have turned on profile sharing. In a published game, any other player, guest or signed in, is Guest and the first four characters of their og.player.id, for example Guest 3f9a. Some signed-in players’ entries saved before each game gave its players a separate ID have null. Show your own fallback for them. The game cannot set name. In a multiplayer private preview the room ID can differ from the score identity, so display the entry’s name, not one built from og.player.id.

Know what a board stores

  • One best score per player per board. A new submission replaces it only when it is better.
  • Scores are the game’s claim. Anyone with a browser console can submit any number. The declared bounds keep wild numbers off the board, but forged scores inside them still appear. A board shows what the game reported, and prizes are judged on other criteria.
  • meta is small, and typed. It takes only label, mode, level and character as strings, and duration_ms, accuracy and combo as numbers. A number where a string belongs, such as a numeric level, fails with invalid_meta. Strings run to 24 characters and 384 bytes in all. A string that looks like an email address or a long number fails with invalid_meta. Use it for game context, such as a mode or a level.
  • Reads are cached. top() results are cached for 30 seconds, so a new best can take that long to appear there.

Test a board

Outside OpenGame, scores are kept in localStorage per folder and board, using the boards in ./opengame.json. If your build moves that file, pass the manifest yourself with og.init({ manifest }). Locally a board holds only your best score, so top() returns one entry, with isMe set to true and name set to "dev". Changing a board’s bounds or order starts it fresh. In your private preview, scores go to a separate board that only that preview can read. They are not shown publicly, and they stop being readable when the preview expires. A hosted failure does not fall back to local scores. Before you release:
  1. Submit a score within the board’s bounds. Check saved.ok before reading saved.value, and expect saved.value.state to be ok.
  2. Read me() to confirm the player’s result.
  3. Submit a worse score and confirm the best one stays.
  4. Check names with a player who shares their profile and one who does not.
  5. In a private preview, confirm the scores stay on that preview’s board.

Fix a problem

Leaderboard methods return a result instead of throwing, even on a network failure. When ok is false, the operation failed. The result includes an error code and a reason for you to log. Tell the player in plain words, such as “Score not saved. Keep playing.”, and let them carry on. Never show them the code.

Fix by error code

Fix by symptom

Only scores marked ok appear on the board. Check saved.value.state: a clamped score is stored at the limit and does not appear. top() results are cached, so an ok score can take 30 seconds to show there.
Their handle appears only when they have turned on profile sharing. Until then the board shows Guest and the first four characters of their og.player.id. The game cannot set name.
A private preview writes to a separate board that only that preview can read. Those scores do not appear on the published board.

Where next

Update a live game

Deploy the finished integration as a new release.

Read the SDK reference

Look up every export and its signature.