Top X
A multi-game score-prediction tournament with Play, Leaderboard, Private Leagues, Rules, and Prizes tabs.
A multi-game football score-prediction tournament with a multi-tab interface. Matches are grouped into discrete games (e.g. "Day 8"), each with its own prediction cutoff, golden-goal tiebreaker, and settlement. Users submit score predictions, track their standing on a leaderboard, create or join private leagues, read game rules, and view prizes — all within a single embedded widget.
<div
data-component="fu-widget"
data-content-type="top-x"
data-content-id="your-top-x-template-id"
data-top-x-tabs="play,leaderboard,private-leagues,rules,prizes"
data-signin-cta-label="Sign in to Predict"
data-signin-cta-onclick="showSignInModal()"
data-top-x-match-card-bg-image-url="https://example.com/stadium-bg.jpg"
data-top-x-show-countdown="true"
data-top-x-consents='[{"consentId":"tos","body":"I agree to the <a href=\"#\" target=\"_blank\" rel=\"noopener\">Terms of Service</a>","required":true,"defaultChecked":false}]'
></div>Configuration Attributes
| Attribute | Description | Options/Format | Default |
|---|---|---|---|
data-top-x-tabs | Comma-separated list of tabs to enable | "play,leaderboard,private-leagues,rules,prizes" | All tabs |
data-signin-cta-label | Override the sign-in button label | Any string | Translated default |
data-signin-cta-onclick | JavaScript code to execute on sign-in click | JavaScript code | None |
data-signin-cta-url | Direct URL for the sign-in CTA | Valid URL | None |
data-signin-cta-target | Link target for the sign-in CTA URL | "_self", "_blank" | "_self" |
data-top-x-match-card-bg-image-url | Background image URL for match prediction cards | Valid image URL | Global config |
data-top-x-show-countdown | Show the kickoff countdown timer on match cards for open games | "true", "false" | "true" |
data-top-x-game-nav-label | How each game is labelled in the Play tab navigation | "gameWeek", "title", "titleAndDescription" | "gameWeek" |
data-top-x-consents | JSON array of consent definitions required before predicting | Array of consent objects (see below) | Global config |
data-top-x-betslip | JSON object to enable betslip integration inside TopX | TopXBetslipConfig object (see below) | Global config |
data-top-x-show-odds | Render betting odds on the match cards (see Odds) | "true", "false" | false |
data-top-x-odds-mode | "flash" alternates the operator logo and the prices instead of showing both | "default", "flash" | "default" |
data-top-x-odds-flash-interval | Flash interval in milliseconds. Ignored unless the mode is "flash" | Positive integer | 3000 |
data-top-x-odds-polling-interval | Odds poll interval in milliseconds | Positive integer | 30000 |
data-top-x-odds-operators | Comma-separated operator config ids, in preference order — a match shows one operator, the first with a complete market. The first also pins the betslip | e.g. "betano-bg,efbet-bg" | First listed per match |
data-top-x-odds-affiliate-id | Affiliate id substituted into every operator URL carrying an {affiliate_id} placeholder | Affiliate id string | None |
data-top-x-odds-affiliate-ids | JSON object of per-operator affiliate ids. Wins over data-top-x-odds-affiliate-id | e.g. '{"betano-bg":"aff-123"}' | None |
data-top-x-operator-id | Deprecated — use data-top-x-odds-operators. Still honoured when that is unset | Operator config id, e.g. "betano-bg" | None |
Tabs
All tabs are shown by default. Use data-top-x-tabs to restrict which tabs are visible. The order in the attribute determines the display order.
| Tab value | Description |
|---|---|
play | Main prediction interface — submit match score forecasts |
leaderboard | Global rankings and user standings with pagination |
private-leagues | Create and join private leagues to compete with friends |
rules | Searchable game rules and scoring system |
prizes | Prize distribution and rewards information |
Countdown Timer
The countdown timer shows the time remaining until the prediction cutoff for each open game. It is enabled by default. Set data-top-x-show-countdown="false" or showCountdown: false in the global config to hide it.
Global configuration:
FuWidget.init({
// ... other config
topX: {
showCountdown: false,
},
});Per-widget override:
<div
data-component="fu-widget"
data-content-type="top-x"
data-content-id="your-top-x-template-id"
data-top-x-show-countdown="false"
></div>Game Navigation Label
Each gameweek in the Play tab has a navigation header (the title shown between the previous/next arrows). The data-top-x-game-nav-label attribute controls what it displays.
| Value | Behaviour |
|---|---|
"gameWeek" (default) | A localised label such as "Gameweek 1", "Gameweek 2". Index is 1-based and reflects the game's position. |
"title" | The game's title from the API. Falls back to the localised gameweek label when the game has no title. |
"titleAndDescription" | The game's title plus its description (supports HTML) below it. Falls back to the gameweek label when absent. |
Global configuration:
FuWidget.init({
// ... other config
topX: {
gameNavLabel: "titleAndDescription",
},
});Per-widget override:
<div
data-component="fu-widget"
data-content-type="top-x"
data-content-id="your-top-x-template-id"
data-top-x-game-nav-label="title"
></div>Consent Configuration
Require users to accept consent agreements before submitting their first prediction. Configure consents globally or per-widget using data-top-x-consents. Required consents block progression until accepted; optional consents are shown in the same modal but do not block it.
Global configuration:
FuWidget.init({
// ... other config
topX: {
consents: [
{
consentId: "tos",
body: `I agree to the <a href="#" target="_blank" rel="noopener">Terms of Service</a>`,
required: true,
defaultChecked: false,
},
],
},
});Per-widget override:
<div
data-component="fu-widget"
data-content-type="top-x"
data-content-id="your-top-x-template-id"
data-top-x-consents='[{"consentId":"tos","body":"I agree to the <a href=\"#\" target=\"_blank\" rel=\"noopener\">Terms of Service</a>","required":true,"defaultChecked":false}]'
></div>Consent Object Fields:
| Field | Type | Description |
|---|---|---|
consentId | string | Unique identifier for the consent (e.g. "tos", "marketing") |
body | string | Text or HTML content of the consent label |
required | boolean | When true, the user must accept before they can predict |
defaultChecked | boolean | Pre-check the consent checkbox on load |
Odds
Odds are off by default. With data-top-x-show-odds="true", each upcoming match card shows the full-time 1X2 price its predicted score implies, from one bookmaker — in the Play tab and in a league member's predictions. Prices refresh every data-top-x-odds-polling-interval (30 seconds by default). Odds fail silently: when the odds API has no prices for a match, the card simply shows none.
data-top-x-show-odds— while it isfalse(the default) the odds request is skipped altogether. A betslip withtrigger: "odds-only"is fed by clicking those odds, so that trigger needs it set.data-top-x-odds-operatorsis a preference order: each match shows the first bookmaker in the list that prices it completely, so a second one can cover the first where a fixture has no prices from them. Without it, each match shows whichever bookmaker the response lists first, which is not guaranteed to stay the same.data-top-x-odds-mode,-flash-interval,-polling-interval,-affiliate-idand-affiliate-idswork as on the Event Card and Competitor Card. The market is not configurable — it comes from what was predicted.data-top-x-operator-idis deprecated. It still works, standing in fordata-top-x-odds-operatorswith a single bookmaker.
<div
data-component="fu-widget"
data-content-type="top-x"
data-content-id="your-top-x-template-id"
data-top-x-show-odds="true"
data-top-x-odds-operators="betano-bg,efbet-bg"
></div>Global configuration:
FuWidget.init({
// ... other config
topX: {
showOdds: true, // Optional: render odds on the match cards (default: false)
odds: {
operators: ["betano-bg", "efbet-bg"], // Optional: bookmaker preference order; the first also pins the betslip
pollingInterval: 30000, // Optional: ms between price refreshes (default: 30000)
affiliateId: "aff-123", // Optional: substituted into operator URLs carrying {affiliate_id}
},
},
});The match cards and the betslip show the same bookmaker unless you set them to different values:
| You set | Card odds | Betslip |
|---|---|---|
odds.operators | first that prices it | first of odds.operators |
betslip.operatorId | betslip.operatorId | betslip.operatorId |
| Both | odds.operators | betslip.operatorId |
The deprecated operatorId still works and stands in for odds.operators: [operatorId].
Betslip Integration
The TopX widget has built-in betslip support. When enabled, users can add selections directly from the prediction interface and place bets alongside their predictions.
The trigger field controls which predictions open the betslip:
| Value | Description |
|---|---|
"predictions-only" | Betslip appears only for predictions that carry live odds |
"odds-only" | Betslip appears for any odds, regardless of prediction state. Requires data-top-x-show-odds="true" |
Global configuration:
FuWidget.init({
// ... other config
topX: {
betslip: {
trigger: "predictions-only",
position: "bottom-right",
currency: "USD",
ctaUrlTemplate: "https://bookmaker.com/betslip?s={selectionIds}",
operatorId: "betano-bg",
affiliateId: "your-affiliate-id",
},
},
});Per-widget override:
<div
data-component="fu-widget"
data-content-type="top-x"
data-content-id="your-top-x-template-id"
data-top-x-betslip='{"trigger":"predictions-only","position":"bottom-right","currency":"USD"}'
></div>TopXBetslipConfig fields:
| Field | Type | Description |
|---|---|---|
trigger | string | When to activate the betslip: "predictions-only" or "odds-only" |
position | BetslipPosition | Widget position on the page (same options as standalone Betslip) |
maxSelections | number | Maximum allowed selections |
stakePresets | number[] | Quick-stake preset amounts |
oddsPollingInterval | number | Odds refresh interval in milliseconds |
currency | string | Currency label |
ctaUrlTemplate | string | URL for the place-bet CTA |
brandingLogoUrl | string | Bookmaker or sponsor logo URL |
operatorId | string | Operator config id to pin the betslip to one bookmaker. Falls back to the first of data-top-x-odds-operators / topX.odds.operators, then the deprecated data-top-x-operator-id / topX.operatorId |
affiliateId | string | Affiliate id used to attribute CTA clicks to you |
labels | BetslipLabels | Override displayed text (see the Betslip widget page) |
Authentication and Sign-in
The widget automatically detects user authentication status. When a user is not authenticated, a sign-in prompt is shown in the Play tab. Configure the sign-in CTA globally or per-widget using the same signInCTA configuration as other widgets.
FuWidget.init({
// ... other config
signInCTA: {
defaultLabel: "Sign in to Predict",
onClick: () => {
window.location.href = "/signin";
},
},
});Features
- Multi-game tournament format — matches grouped into daily or round-based games
- Golden-goal tiebreaker for tied predictions
- Multi-tab interface: Play, Leaderboard, Private Leagues, Rules, and Prizes
- Kickoff countdown timer per match card (enabled by default)
- Consent management with required/optional consent gates
- Authentication-aware UI with configurable sign-in CTA
- Custom match card background image
- Opt-in betting odds on the match cards, pinned to one bookmaker — see Odds
- Built-in betslip integration for placing bets alongside predictions
- Custom theming and multi-language support
Updated 3 days ago
