Scores

Tell us how well a player is doing, and their standing in your game becomes part of what wins them a whitelist place.

What it is

One call with one number. Your game already knows who its best players are; this is how it says so, and it is the only part of a player's standing on your leaderboard that comes from inside the game.

The number means whatever you mean by it. Points, coins, waves survived, a lap time you have turned upside down so bigger is better. Nothing here interprets it, and no game's score is ever compared with another game's: your players are ranked against each other, and that ranking is what becomes a 1–100 score on the board. A game that hands out millions a round and a game that counts to nine both work, and changing how you score does not break anybody's standing as long as it keeps the order.

1

Report the score

<script src="https://indie.fun/js/indie.js"></script>
<script>
  const indie = new Indie({ appId: 'your-app-id' });

  // Wherever your game knows the number: end of a run, on death,
  // or as a running total while they play.
  indie.submitScore(score);
</script>

Call it whenever the number changes, or once at the end of a run — both work, and neither costs you a request per call. Only a player's best is kept, so a bad run never lowers what they achieved and a retried send never double-counts.

What the SDK does with it

  • Calls are coalesced. At most one request every few seconds, carrying the best score reported in between, so a game that reports every frame costs the same as one that reports every round.
  • The last one lands. Whatever is waiting is flushed when the page closes, so the run somebody was on when they quit is the one they come back to find on the board.
  • Signed-in or not. A score is filed against the player's account when there is one and their device otherwise — the same identity sessions and progression use. Only an account can hold a leaderboard place, so a player who signs in later starts counting on the board from then on.
  • A visitor who declined analytics is not tracked. Nothing is sent, and nothing is queued.

Anything a browser sends is a claim

The score comes from your game's own code, which runs on the player's machine, so a determined player can send whatever they like. That is bounded rather than solved: a score only ever ranks a player among your game's players, it cannot reach another game's board, and a percentile has a top of 100 however large the lie is.

If your game has a server that knows the real number, report it from there instead — the server call below is the same record, vouched for by your App Secret.

2

From your server, when the server is the referee

import { IndieServer } from 'indie-sdk/server';

const indie = new IndieServer({
  appId: process.env.INDIE_APP_ID,
  appSecret: process.env.INDIE_APP_SECRET,
});

await indie.submitScore(playerId, 12500);

The same record, written the same way: only the best is kept, and calling it again with a lower number changes nothing.

Where the number shows up

On your game's leaderboard at indie.fun/leaderboard/your-game, as the Game section, and as part of the Overview that decides who takes a whitelist place in your raise.

Game score
Where a player sits among everyone who has scored in your game, as 1–100. The best player of your game reads 100 whatever the raw number is.
What it is worth
A quarter of the Overview, weighted toward the top of the ladder — so being one of the best players of your game is worth a lot, and being average is worth a little. The other three quarters are posts about your game and friends brought to it.
The invite bar
A friend somebody invites only counts for them once that friend has scored as well as your median player. Your scores are what make that bar exist: without them, no invite on your board can count.

Reference

Browser

submitScore(score)Report this player's score. 0 to 1e15. Only their best is kept.

Server

submitScore(playerId, score)The same record, vouched for by your App Secret.

HTTP

POST /api/player/scoreBody { score }, with X-App-Id and either the player's bearer token or a deviceId. With X-App-Secret, name the player yourself with { userId, score }.