Competition Statistics

A competition's season on one page — a progress header, upcoming fixtures and results, player rankings, and season-wide statistics. Fixtures sit in Upcoming / Results tabs with a round picker, grouped by day and, in a multi-stage competition, by stage. Each match row expands: a finished or live match shows its match stats and a goal timeline, an upcoming one both teams' form, a season comparison and the previous meeting.

📘

No authentication required — this widget never needs tokenString, tokenCookieName, or firebase in your config. See Getting Started → Authentication → Read-only widgets.

<div data-component="fu-widget" data-content-type="competition-statistics" data-content-id="fb:c:3"></div>

Configuration Attributes

AttributeDescriptionOptions/FormatDefault
data-content-idCompetition IDe.g. "fb:c:3"Required
data-competition-statistics-season-idSeason overridee.g. "fb:c:3:2026/27"The competition's current season
data-competition-statistics-stage-idScope matches and team statistics to one stageStage ID stringEvery stage
data-competition-statistics-sectionsComma-separated sections to render, in the order given (see Sections below)Any of header, matches, players, seasonAll four, in that order
data-competition-statistics-player-rankings-layoutHow the player rankings are laid out. "auto" switches to tabs in a container narrower than 600px"auto", "grid", "tabs""auto"
data-competition-statistics-player-rankings-rowsRows per ranking before Show allInteger, clamped to 1–105
data-competition-statistics-live-refreshPoll live matches, so score and minute stay current"true", "false"true
data-competition-statistics-refresh-intervalLive-refresh poll interval in millisecondsPositive integer30000 (30s)
data-competition-statistics-labelsJSON object overriding any user-facing string. Keep {{…}} placeholdersCompetitionStatisticsLabels, e.g. '{"upcoming":"Fixtures"}'Locale strings

Odds attributes (see Betting Odds below):

AttributeDescriptionOptions/FormatDefault
data-competition-statistics-show-oddsShow 1X2 odds on upcoming and live match rows"true", "false"false
data-competition-statistics-odds-mode"flash" alternates the operator logo and the prices instead of showing both"default", "flash""default"
data-competition-statistics-odds-flash-intervalFlash interval in milliseconds. Ignored unless the mode is "flash"Positive integer3000
data-competition-statistics-odds-polling-intervalOdds poll interval in millisecondsPositive integer30000
data-competition-statistics-odds-operatorsComma-separated operator config ids, in preference order — a row shows one operator, the first with a complete markete.g. "betano-bg,efbet-bg"First operator with prices
data-competition-statistics-odds-affiliate-idAffiliate id substituted into every operator URL carrying an {affiliate_id} placeholderAffiliate id stringNone
data-competition-statistics-odds-affiliate-idsJSON object of per-operator affiliate ids. Wins over data-competition-statistics-odds-affiliate-ide.g. '{"betano-bg":"aff-123"}'None
data-competition-statistics-add-to-betslipPush a clicked odds price into the Betslip widget on the page"true", "false"false

Per-element attributes override the global competitionStatistics config field by field, including inside its nested objects (odds and its affiliateIds, the three CTAs, labels) — setting data-competition-statistics-odds-operators keeps a globally configured odds.affiliateId.

Sections

SectionContent
"header"The competition, its season and a progress bar of matches played
"matches"Upcoming / Results tabs with stage pills and a round picker; expandable rows with live scores, match detail and odds
"players"Player rankings — top scorers, assists, goals + assists, clean sheets, minutes, cards
"season"Result split, goal timing, goal lines, averages per match, cards, team callouts and record matches

data-competition-statistics-sections both picks and orders them, so "season,players" puts the season statistics first and leaves the fixtures out. Unknown entries are ignored with a console warning.

In a competition with more than one stage (regular season, championship / relegation groups, play-offs), stage pills sit above the round picker and the rounds are the selected stage's own. The Upcoming tab opens on the stage of the next match, Results on the stage of the latest one. Postponed, cancelled, interrupted and abandoned matches are listed with the results, the reason shown in place of the score.

Link CTAs

Three kinds of card link out through a CTA you configure. No URLs are baked in: without a CTA, the card is inert.

CardAttribute prefixConfig fieldURL placeholder
The two record-match cardsdata-competition-statistics-match-ctamatchCTA{matchId} (or {id})
The team calloutsdata-competition-statistics-team-ctateamCTA{competitorId} (or {id})
A player in the rankingsdata-competition-statistics-player-ctaplayerCTA{athleteId} (or {id})

Each prefix takes three suffixes:

SuffixDescriptionOptions/Format
-urlURL template; the placeholder is replaced with the URL-encoded idURL string
-targetLink target"_blank", "_self"
-onclickInline JavaScript run on click. Navigation is prevented so your router handles itJavaScript code string
<div
	data-component="fu-widget"
	data-content-type="competition-statistics"
	data-content-id="fb:c:3"
	data-competition-statistics-team-cta-url="/football/team/{competitorId}"
	data-competition-statistics-player-cta-url="/football/player/{athleteId}"
	data-competition-statistics-player-cta-target="_blank"
></div>

In FuWidget.init(), a CTA's onClick receives the clicked id — teamCTA: { onClick: (competitorId) => router.push(...) }.

⚠️

-onclick is evaluated as code, like data-signin-cta-onclick. Only use it in markup your own site authors — never with values that come from user input or a CMS field.

Betting Odds

Off by default. With data-competition-statistics-show-odds="true", each upcoming match row shows 1X2 odds from the first operator in data-competition-statistics-odds-operators with a complete market, and a live match shows in-play prices — pre-match prices are never shown on a match in progress. One request covers the round on screen. In a container narrower than 600px the odds move to a second line under the teams. When no operator has prices the strip simply does not render, and the operator's own link opens on click either way. The odds settings are the same as the Competitor Card's.

The widget owns no betslip. Set data-competition-statistics-add-to-betslip="true" to push a clicked price into the Betslip widget on the same page as a selection ({matchId}:{market}:{outcome} — e.g. fb:m:123:FT_1X2:1 — the same id FuWidget.betslip.setSelection takes).

<div
	data-component="fu-widget"
	data-content-type="competition-statistics"
	data-content-id="fb:c:3"
	data-competition-statistics-show-odds="true"
	data-competition-statistics-odds-operators="betano-bg"
	data-competition-statistics-add-to-betslip="true"
></div>
<div data-component="fu-widget" data-content-type="betslip"></div>

Callbacks

Two callbacks, both programmatic config only (competitionStatistics.callbacks in FuWidget.init()) — each receives an argument, so there is no data-attribute equivalent.

CallbackReceivesDescription
onBroadcastClickmatchIdSetting it is what shows a TV icon next to the kick-off time of every upcoming match. A click calls it and does not expand the row. The widget holds no broadcast data — which channel shows the match, and what the click opens, is yours to implement
onAddToBetslip{ matchId, market, pick: "1" | "X" | "2", odd }Observe a clicked odds price — for your own betslip or for analytics. Runs whether or not addToBetslip is on

Global Configuration

Set defaults for all Competition Statistics widgets in FuWidget.init():

FuWidget.init({
	// ... other config
	competitionStatistics: {
		sections: ["header", "matches", "players", "season"],
		playerRankingsLayout: "auto",
		playerRankingsRows: 5,
		liveRefresh: true,
		refreshInterval: 30000,
		showOdds: true,
		odds: {
			operators: ["betano-bg", "efbet-bg"], // Preference order — a row shows one operator
			affiliateId: "aff-123", // Substituted into operator URLs carrying {affiliate_id}
		},
		addToBetslip: true,
		matchCTA: { url: "/football/match/{matchId}" },
		teamCTA: { url: "/football/team/{competitorId}" },
		playerCTA: {
			url: "/football/player/{athleteId}",
			onClick: (athleteId) => router.push(/* ... */), // Optional: handle the click in your app instead of navigating
		},
		labels: { upcoming: "Fixtures" },
		callbacks: {
			onBroadcastClick: (matchId) => openTvSchedule(matchId), // Optional: shows the TV icon on upcoming matches
			onAddToBetslip: (selection) => console.log(selection), // Optional: observe clicked odds prices
		},
	},
});

Examples

Fixtures Only

<div
	data-component="fu-widget"
	data-content-type="competition-statistics"
	data-content-id="fb:c:3"
	data-competition-statistics-sections="header,matches"
></div>

Season Statistics First, Linked Rankings

<div
	data-component="fu-widget"
	data-content-type="competition-statistics"
	data-content-id="fb:c:1"
	data-competition-statistics-sections="season,players,matches"
	data-competition-statistics-team-cta-url="/teams/{competitorId}"
	data-competition-statistics-player-cta-url="/players/{athleteId}"
></div>

One Stage of a Past Season

<div
	data-component="fu-widget"
	data-content-type="competition-statistics"
	data-content-id="fb:c:3"
	data-competition-statistics-season-id="fb:c:3:2025/26"
	data-competition-statistics-stage-id="your-stage-id"
></div>

Features

  • Upcoming / Results tabs with a round picker, matches grouped by day
  • Multi-stage competitions grouped by stage, with Standings-style stage pills
  • Expandable rows — match stats and a goal timeline for a finished or live match; form, a season comparison and the previous meeting for an upcoming one
  • Live matches with a pulsing minute, the half-time score and polling
  • Opt-in 1X2 odds on the match rows — in-play prices for a live match, operator preference, affiliate attribution and opt-in Betslip integration
  • Player rankings and season-wide statistics, with team callouts and record matches
  • Sections can be picked and reordered; an optional TV icon on upcoming matches, driven by your own callback

Did this page help you?