Create and connect to Leaderboard
Leaderboards enable you to create more engaging and interactive content with little to zero maintenance, e.g. a weekly quiz with a ranking, or a Predictor for every match of your sports team.
There are two separate things you can do, and they use two different parts of the build configuration:
| What you want to do | Riddle type you build | Where it is configured |
|---|---|---|
| Create a new leaderboard | Leaderboard | the build object itself - see Create a leaderboard |
| Make a Quiz/Predictor/Minigame report to an existing leaderboard | Quiz, Predictor, Minigame | build.leaderboard.connections - see Connect a Riddle |
Both can be combined: create the leaderboard first, then reference its UUID in the Riddles you build afterwards.
1. Create a leaderboard
A leaderboard is a Riddle type of its own, but a very reduced one: it has no blocks, no logic, no publish settings and no result page. The properties below are everything a leaderboard build config can express.
Build properties
| Property | Required | Type | Description | Default |
|---|---|---|---|---|
title | ✓ | string | The title of the leaderboard | |
riddleConnections | string | UUIDs of the Riddles that should report to this leaderboard right away; maximum: 10 | ||
preset | object | Preset settings of the leaderboard; this is where every display setting of the leaderboard lives - see below |
Note: A leaderboard's own display settings - the podium colors and the email verification requirement - are keys of the preset object, not build properties of their own. isEmailValidationRequired, color1st, color2nd and color3rd are no longer accepted at the top level of build; send them as preset.isEmailVerificationEnabled and preset.color1st/color2nd/color3rd instead. That is also exactly how a read-back reports them, so a fetched configuration can be sent back unchanged. Sent at the top level they are now an unknown property: silently ignored in a plain create, and rejected with a 400 under strictProperties or when editing a leaderboard.
Note: riddleConnections is not create-only. PUT /riddle-builder/{UUID} accepts it on an existing leaderboard to add or drop connected Riddles at any time - it replaces the whole list, so resend every UUID you want to keep together with any new ones.
Note: Every UUID in riddleConnections must be an existing Quiz, Predictor or Minigame that already has a Name and an Email field - the same requirements as connecting from the other side, described in section 2.
Leaderboard preset settings
On top of the shared preset settings (preset/presetId, palette, language, ads, customStrings, footerText, footerBranding, isRiddleFooterVisible, isShareButtonVisible), a leaderboard's preset accepts:
| Property | Required | Type | Description | Default |
|---|---|---|---|---|
isCompactView | boolean | Whether entries are rendered in the compact, single-line view | false | |
entriesAbove | integer | How many entries are shown above the visitor's own entry | 1 | |
entriesBelow | integer | How many entries are shown below the visitor's own entry | 3 | |
isTotalEntriesEnabled | boolean | Whether the total number of entries is displayed | false | |
isOneVotePerIdentifierEnabled | boolean | Whether every identifier (e.g. email address) may only appear once | false | |
isBadwordFilterEnabled | boolean | Whether nicknames are run through the bad-word filter | false | |
badwordFilterCustomList | string | Additional comma-separated words to filter | ||
quizTimeMultiplier | integer | 0-100; how strongly the time a visitor needed influences the ranking | 0 | |
isEmailVerificationEnabled | boolean | Whether visitors have to confirm their email address before their entry appears on the leaderboard. It is never switched on for you, so send it explicitly whenever only confirmed participants should be ranked | false | |
color1st | string | CSS color of the first-place row on the podium | #D38807 | |
color2nd | string | CSS color of the second-place row on the podium | #A9A9A9 | |
color3rd | string | CSS color of the third-place row on the podium | #C2691C |
The three podium colors are independent of each other: sending one leaves the other two at whatever the leaderboard already shows. A read-back only reports the ones that differ from the defaults above - the rest are listed in omittedDefaults, like every other property still at its default.
Example
The smallest possible leaderboard - a title and nothing else:
{
"type": "Leaderboard",
"build": {
"title": "My leaderboard"
}
}
A leaderboard that two existing Riddles report to right away, with email verification switched on:
{
"type": "Leaderboard",
"build": {
"title": "My leaderboard",
"riddleConnections": ["SampleUUID1", "SampleUUID2"],
"preset": {
"isEmailVerificationEnabled": true
}
}
}
Example
Every property a leaderboard build config accepts, including the leaderboard-specific preset settings:
{
"type": "Leaderboard",
"project": 123,
"publish": true,
"build": {
"title": "Season leaderboard",
"riddleConnections": ["SampleUUID1", "SampleUUID2"],
"preset": {
"language": "en",
"isEmailVerificationEnabled": true,
"color1st": "#ffd700",
"color2nd": "#c0c0c0",
"color3rd": "#cd7f32",
"isCompactView": false,
"entriesAbove": 2,
"entriesBelow": 5,
"isTotalEntriesEnabled": true,
"isOneVotePerIdentifierEnabled": true,
"isBadwordFilterEnabled": true,
"badwordFilterCustomList": "spam,troll",
"quizTimeMultiplier": 20
}
}
}
Replace SampleUUID1/SampleUUID2 with UUIDs of Riddles that exist in the same project - or leave riddleConnections out entirely to create an empty leaderboard and connect Riddles to it later, as described next.
2. Connect a Riddle to an existing leaderboard
Connections are configured in build.leaderboard of the Riddle you build, not of the leaderboard.
Requirements
- Only quizzes, predictors and minigames can be connected - they are the only types that produce a ranking. Polls, personality tests, forms and stories cannot.
- The Riddle needs a
Nameand anEmailfield (see form fields), or an explicitnickname/identifiermapping. - A minigame consisting of nothing but a
WheelSpinnerblock cannot be connected - a wheel only produces a win/loss outcome, not a rankable score. Add another minigame block (e.g. aSudoku). - Connecting multiple Riddles to a single leaderboard requires our Enterprise subscription.
Connection properties
| Property | Required | Type | Description | Default |
|---|---|---|---|---|
connections | ✓ | string | 1-3 UUIDs of the leaderboards this Riddle reports to. Duplicate UUIDs are collapsed into one connection | |
identifier | string | Which field identifies the visitor; overrides auto-detection. Must be an Email field | ||
nickname | string | Which field provides the displayed name; overrides auto-detection. Must be a Name field or a data layer variable |
Example
With no identifier/nickname given, the first Email field becomes the identifier and the first Name field the nickname:
{
"type": "Quiz",
"build": {
"title": "My quiz",
"blocks": [
{
"title": "What's the capital of Germany?",
"type": "SingleChoice",
"items": [
{ "title": "Berlin", "isCorrect": true },
{ "title": "Lissabon", "isCorrect": false },
{ "title": "Leipzig", "isCorrect": false }
]
},
{
"title": "My form",
"type": "FormBuilder",
"fields": [
{ "title": "Your email", "type": "Email" },
{ "title": "Your name", "type": "Name" }
]
}
],
"leaderboard": {
"connections": ["Fw5uSygx"]
}
}
}
Identifier and nickname fields
Auto-detection is only right as long as there is exactly one obvious candidate. Map the fields explicitly whenever your form holds several email or text fields, or when the value should come from the data layer instead of a visible field.
Both properties accept three input forms:
| Input form | Example | When to use it |
|---|---|---|
| The field label | "Your email" | Matched case-insensitively, ignoring surrounding whitespace |
| The canonical field key | "email1", "email2", "name1" | The field type in lowercase plus its position among the fields of that type (email2 = second Email field). This is exactly what the API emits when you read the Riddle back, so a fetched build config can be sent back unchanged |
| A data layer variable | "dataLayer:customerId" | The value is passed in when the Riddle is opened rather than typed by the visitor |
Example with both mapped explicitly - the second email field identifies the visitor, and the second name field provides the displayed name:
{
"type": "Quiz",
"build": {
"title": "My quiz",
"blocks": [
{
"title": "What's the capital of Germany?",
"type": "SingleChoice",
"items": [
{ "title": "Berlin", "isCorrect": true },
{ "title": "Lissabon", "isCorrect": false },
{ "title": "Leipzig", "isCorrect": false }
]
},
{
"title": "My form",
"type": "FormBuilder",
"fields": [
{ "title": "Your private email", "type": "Email" },
{ "title": "Your work email", "type": "Email" },
{ "title": "Your real name", "type": "Name" },
{ "title": "Your display name", "type": "Name" }
]
}
],
"leaderboard": {
"connections": ["Fw5uSygx"],
"identifier": "Your work email",
"nickname": "Your display name"
}
}
}
The exact same mapping by canonical key - and a nickname taken from the data layer instead of a visible field:
{
"leaderboard": {
"connections": ["Fw5uSygx"],
"identifier": "email2",
"nickname": "dataLayer:customerName"
}
}
Rules:
identifiermust point at anEmailfield,nicknameat aNamefield (or, fornickname, at a data layer variable). Any other field type - aShortText, for example - is rejected, naming the allowed types.- If a label is shared by more than one eligible field, the request is rejected as ambiguous and lists the candidate keys - use one of those canonical keys instead.
identifierandnicknamecannot resolve to the same field.- If both resolve to form fields (i.e. neither is a
dataLayer:variable), they must live on the sameFormBuilderblock. - A nickname is mandatory: without a
Namefield and without an explicitnickname, the connection is rejected. - Connecting to a leaderboard that has email verification enabled (
preset.isEmailVerificationEnabled, see section 1) requires an identifier - either anEmailfield in the Riddle or an explicitidentifier.
Tip: To show the leaderboard on the result page and to fully engage the user, add the Leaderboard block to the result page. Click here to learn more.
Fetch leaderboard entries
To read the entries of a leaderboard, e.g. to display them in your own frontend or to determine the winners of a contest, use the /riddle-leaderboard/entries/{UUID} API endpoint.
| Property | Required | Type | Description | Default |
|---|---|---|---|---|
page | ✓ | integer | The page you want to return | |
limit | integer | How many results the page should contain (maximum: 50) | 50 | |
search | string | Search term; exact match for an email address, or partial match for a nickname |
Example payload:
{
"page": 1,
"limit": 50
}
Unpublishing and deleting a leaderboard
A leaderboard with active Riddle connections cannot be unpublished - the connected Riddles depend on it, and you will get an UNPUBLISH_CONFLICTING_INTERDEPENDENCE_LEADERBOARD validation error. For the same reason, a connected Riddle cannot be deleted while the leaderboard still points at it.
To get rid of such a leaderboard, delete it instead: deleting a leaderboard is always allowed and cleans up the connected Riddles automatically. Unpublishing becomes possible once the connections themselves are gone.
Troubleshooting
Make sure that..
- the leaderboard UUID is correct
- the leaderboard is in the same project as the Riddle you are creating
- you have added a
FormBuilderwith aNameand anEmailfield to your Riddle - when you want to connect multiple Riddles: you are subscribed to our Enterprise plan
Full example
A quiz connected to the published leaderboard Fw5uSygx, with the identifier and nickname fields mapped explicitly because the form holds two email fields.
{
"type": "Quiz",
"build": {
"title": "Season quiz",
"blocks": [
{
"type": "SingleChoice",
"title": "What's the capital of Germany?",
"items": [
{ "title": "Berlin", "isCorrect": true },
{ "title": "Lissabon", "isCorrect": false },
{ "title": "Leipzig", "isCorrect": false }
]
},
{
"type": "FormBuilder",
"title": "Enter the ranking",
"fields": [
{ "title": "Your email", "type": "Email" },
{ "title": "Work email", "type": "Email" },
{ "title": "Your name", "type": "Name" }
]
}
],
"leaderboard": {
"connections": ["Fw5uSygx"],
"identifier": "Your email",
"nickname": "Your name"
},
"results": [
{
"minPercentage": 0,
"maxPercentage": 100,
"title": "Thanks for playing!"
}
]
}
}

