Competitor Card
A team or athlete profile card with season statistics, recent form, the next or last fixture with odds, and inline Fixtures, Squad and Season stats panels.
A competitor profile card — the competitor's identity, their season statistics with a competition switcher, recent form, the next or last fixture (with betting odds, or a live badge while it is in progress), and two inline panels opened from the header. data-content-id takes either kind of competitor and the card adapts: a team (fb:t:…) shows the club's season and opens a Squad panel; an athlete (fb:p:…) shows the player's season and opens a Season stats table, with the form and fixtures of their club.
No authentication required — this widget never needstokenString,tokenCookieName, orfirebasein your config. See Getting Started → Authentication → Read-only widgets.
<div data-component="fu-widget" data-content-type="competitor-card" data-content-id="fb:t:8205"></div>Configuration Attributes
| Attribute | Description | Options/Format | Default |
|---|---|---|---|
data-content-id | Competitor ID — a team or an athlete | e.g. "fb:t:8205", "fb:p:48824" | Required |
data-competitor-card-template | Layout (see Templates below) | "standard", "hero", "horizontal", "compact" | "standard" |
data-competitor-card-show-country | Put the competitor's country in the header subtitle | "true", "false" | true |
data-competitor-card-header-layout | Crest beside the name, or stacked above it with the header centred | "horizontal", "stacked" | "stacked" on horizontal, else "horizontal" |
data-competitor-card-cta-layout | Where the header's two buttons sit. "responsive" stacks them in a narrow container | "inline", "stacked", "responsive" | "responsive" |
data-competitor-card-title-position | Alignment of every section title | "left", "center", "right" | "left" |
data-competitor-card-show-competition-switcher | Render the All + one-per-competition switcher. Renders nothing with a single competition | "true", "false" | true |
data-competitor-card-has-branding | Paint the branded surfaces with the competitor's own colours instead of the theme accent | "true", "false" | true |
data-competitor-card-header-background-gradient | CSS background for the branded header (hero and horizontal only) | Any CSS background | Competitor branding |
data-competitor-card-live-refresh | Poll while one of the competitor's fixtures is LIVE, so score and minute stay current | "true", "false" | true |
data-competitor-card-refresh-interval | Live-refresh poll interval in milliseconds | Positive integer | 30000 (30s) |
data-competitor-card-labels | JSON object overriding any user-facing string | CompetitorCardLabels, e.g. '{"squad":"Players"}' | Locale strings |
data-competitor-card-add-to-betslip | Push a clicked odds price into the Betslip widget on the page (see Betting Odds below) | "true", "false" | false |
Section attributes:
| Attribute | Description | Options/Format | Default |
|---|---|---|---|
data-competitor-card-show-stats | Render the season-statistics section | "true", "false" | true |
data-competitor-card-stats-background-gradient | CSS background for the headline tile (the points tile on a team) | Any CSS background | Competitor branding |
data-competitor-card-show-form | Render the recent-form strip | "true", "false" | true |
data-competitor-card-form-max-items | How many past fixtures to show, latest first | Integer, clamped to 3–10 | 5 |
data-competitor-card-show-featured-match | Render the featured next/last fixture | "true", "false" | true |
data-competitor-card-featured-match-type | Which fixture the section opens on. A live fixture always wins | "next", "last" | "next" |
data-competitor-card-featured-match-toggle | Show the Last | Next toggle | "true", "false" | true |
data-competitor-card-featured-match-background-gradient | CSS background for the featured-match panel | Any CSS background | Soft wash of the competitor branding |
data-competitor-card-show-odds | Render outright odds under an upcoming featured match | "true", "false" | true |
data-competitor-card-odds-mode | "flash" alternates the operator logo and the prices instead of showing both | "default", "flash" | "flash" on compact, else "default" |
data-competitor-card-odds-flash-interval | Flash interval in milliseconds. Ignored unless the mode is "flash" | Positive integer | 3000 |
data-competitor-card-odds-polling-interval | Odds poll interval in milliseconds | Positive integer | 30000 |
data-competitor-card-odds-operators | Comma-separated operator config ids, in preference order — the card shows one operator, the first with a complete market | e.g. "betano-bg,efbet-bg" | First operator with prices |
data-competitor-card-odds-affiliate-id | Affiliate id substituted into every operator URL carrying an {affiliate_id} placeholder | Affiliate id string | None |
data-competitor-card-odds-affiliate-ids | JSON object of per-operator affiliate ids. Wins over data-competitor-card-odds-affiliate-id | e.g. '{"betano-bg":"aff-123"}' | None |
data-competitor-card-show-fixtures | Render the Fixtures header CTA and its inline panel | "true", "false" | true |
data-competitor-card-show-squad | Render the Squad header CTA and its panel. Teams only — inert on an athlete | "true", "false" | true |
data-competitor-card-squad-background-gradient | CSS background for the expanded player card | Any CSS background | Soft wash of the competitor branding |
data-competitor-card-show-season-stats | Render the Season stats header CTA and its table. Athletes only — inert on a team | "true", "false" | true |
Per-element attributes override the global competitorCard config field by field, including inside its nested objects (form, featuredMatch, odds and its affiliateIds, fixtures, squad, stats, labels) — setting data-competitor-card-form-max-items keeps a globally configured form.matchCTA.
Templates
data-competitor-card-template picks the arrangement of the same card — never its behaviour.
| Value | Layout |
|---|---|
"standard" (default) | Bordered card, washed header strip, labelled CTAs; headline tile beside the bars |
"hero" | Branded gradient header carrying the CTAs, the headline tiles and the form |
"horizontal" | Persistent branded rail (identity, CTAs, competition switcher) beside a column that swaps Overview / Fixtures / the second panel |
"compact" | Sidebar width — icon-only CTAs, a single bordered stats row, outcome dots, a one-line fixture |
The card resolves its responsive layout against its container, not the viewport, so an embed in a 320px sidebar stacks correctly on a desktop page.
Teams and Athletes
Team (fb:t:…) | Athlete (fb:p:…) | |
|---|---|---|
| Statistics | Points tile, W/D/L bar, goals scored/conceded, goal difference | Goals tile with a per-90 rate, minutes and appearances bars, stat chips |
| Second CTA | Squad — grouped by position, each row expanding into a player card | Season stats — every statistic, one column per competition plus a total |
| Form / fixtures | The club's own | The player's club's, captioned with the club's name |
| Branding | The club's colours | The club's colours — a player declares none |
The competition switcher is the card's single scope control: it filters the statistics, the form, the featured match and the fixtures panel together, and opens on the domestic league rather than on All. The card covers one season — fixtures from the previous season are left out.
Row CTAs
Every clickable row resolves through a CTA you configure. No URLs are baked in: a row with no CTA is inert, with no hover state and no pointer cursor.
| Row | Attribute prefix | Config field |
|---|---|---|
| A form tile | data-competitor-card-form-match-cta | form.matchCTA |
| The featured match | data-competitor-card-featured-match-cta | featuredMatch.matchCTA |
| A fixture / result row | data-competitor-card-fixtures-match-cta | fixtures.matchCTA |
| The "Full profile" CTA of a squad player | data-competitor-card-squad-player-cta | squad.playerCTA |
Each prefix takes three suffixes:
| Suffix | Description | Options/Format |
|---|---|---|
-url | URL template (see placeholders below). The row renders as an <a href>, so it stays crawlable | URL string |
-target | Link target | "_blank", "_self" |
-onclick | Inline JavaScript run on click. With a -url as well, the navigation is prevented so your router handles it | JavaScript code string |
-url substitutes the placeholders each row can fill, URL-encoded: {matchId} {competitorId} {opponentId} {competitionId} {seasonId} {date} {athleteId}. A placeholder a row cannot fill resolves to an empty string. On an athlete's card {competitorId} is the club the fixture belongs to, and {athleteId} is the player.
<div
data-component="fu-widget"
data-content-type="competitor-card"
data-content-id="fb:t:8205"
data-competitor-card-fixtures-match-cta-url="/football/match/{matchId}"
data-competitor-card-squad-player-cta-url="/football/player/{athleteId}"
data-competitor-card-squad-player-cta-target="_blank"
></div>
-onclickis evaluated as code, likedata-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
Outright prices for the upcoming featured match. The market follows the sport: a fixture that can be drawn is priced three ways (FT_1X2 — 1 · X · 2), one that cannot (American football, basketball, tennis) two ways (WINNER_OT — 1 · 2). When no operator has a complete market the strip simply does not render. The operator's own link opens on click either way.
The card shows one operator — the first in data-competitor-card-odds-operators that publishes a complete market — so the list is a preference order, not a filter that widens the strip. data-competitor-card-odds-affiliate-id is substituted into every operator URL carrying an {affiliate_id} placeholder, so clicks from the odds strip are attributed to you (the same field as the Betslip's affiliateId); data-competitor-card-odds-affiliate-ids sets one per operator and wins over it.
The card owns no betslip. Set data-competitor-card-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). It is off by default because without a Betslip widget on the page the selection has nowhere to go.
<div
data-component="fu-widget"
data-content-type="competitor-card"
data-content-id="fb:t:8205"
data-competitor-card-add-to-betslip="true"
></div>
<div data-component="fu-widget" data-content-type="betslip"></div>To observe clicks yourself — for your own betslip or for analytics — pass competitorCard.onAddToBetslip in FuWidget.init(). It receives { matchId, market, pick: "1" | "X" | "2", odd }, where market is the code the price came from ("FT_1X2" or "WINNER_OT") — pass it through rather than assuming 1X2. It runs whether or not addToBetslip is on. It is programmatic config only; there is no data-attribute equivalent.
Global Configuration
Set defaults for all Competitor Card widgets in FuWidget.init():
FuWidget.init({
// ... other config
competitorCard: {
template: "hero",
showCountry: true,
titlePosition: "left",
showCompetitionSwitcher: true,
hasBranding: true,
liveRefresh: true,
refreshInterval: 30000,
form: { maxItems: 5, matchCTA: { url: "/football/match/{matchId}" } },
featuredMatch: { type: "next", toggle: true, matchCTA: { url: "/football/match/{matchId}" } },
odds: {
mode: "default",
pollingInterval: 30000,
operators: ["betano-bg", "efbet-bg"], // Preference order — the card shows one operator
affiliateId: "aff-123", // Substituted into operator URLs carrying {affiliate_id}
affiliateIds: { "efbet-bg": "aff-456" }, // Optional: per operator, wins over affiliateId
},
fixtures: { matchCTA: { url: "/football/match/{matchId}" } },
squad: {
playerCTA: {
url: "/football/player/{athleteId}",
onClick: () => router.push(/* ... */), // Optional: handle the click in your app instead of navigating
},
},
labels: { squad: "Players" },
addToBetslip: true,
onAddToBetslip: (selection) => console.log(selection), // Optional: observe clicked odds prices
},
});Examples
Player
<div
data-component="fu-widget"
data-content-type="competitor-card"
data-content-id="fb:p:48824"
data-competitor-card-template="hero"
data-competitor-card-fixtures-match-cta-url="/football/match/{matchId}"
></div>Sidebar
<div
data-component="fu-widget"
data-content-type="competitor-card"
data-content-id="fb:t:8205"
data-competitor-card-template="compact"
data-competitor-card-show-squad="false"
></div>Last Result, No Odds or Branding
<div
data-component="fu-widget"
data-content-type="competitor-card"
data-content-id="fb:t:8205"
data-competitor-card-featured-match-type="last"
data-competitor-card-featured-match-toggle="false"
data-competitor-card-show-odds="false"
data-competitor-card-has-branding="false"
></div>Features
- Four templates —
standard,hero,horizontal,compact— changing the arrangement and density, never the behaviour - Teams and athletes from one widget, each with its own statistics and second panel (Squad / Season stats)
- Competition switcher as the card's single scope control, filtering statistics, form, featured match and fixtures together
- Recent form with per-fixture tooltips, and a featured match with a
Last | Nexttoggle - Sport-aware outright odds (
FT_1X2orWINNER_OT) under an upcoming featured match, with operator preference, affiliate attribution, an optional flash mode and opt-in Betslip integration - Live badge with the match minute while a fixture is in progress, plus optional polling
- Competitor branding on the header, headline tile and panels, with automatic contrast handling
- Every clickable row resolves through a CTA you configure — no URLs are baked in
Updated about 2 hours ago
