Tournament Bet Insights widget displays AI-powered betting insights and recommendations across multiple matches within a tournament, league, or season. The widget analyzes betting patterns, historical data, and statistical trends to highlight valuable betting opportunities from upcoming matches in the specified competition. It aggregates insights from multiple events to help users identify the most promising betting opportunities across an entire tournament or league, making it ideal for overview pages, tournament hubs, and league standings sections. The widget offers the same flexible integration modes and card layout variants as the match-level Bet Insights widget, including inline display for dedicated sections or button-triggered modal for compact placements.
This widget requires Sportradar Unified Odds Feed (UOF) identifiers to correctly match insights to your offering and odds. If your platform does not use UOF IDs you will need to map UOF identifiers to your own market/outcome IDs. Mapping UOF to proprietary identifiers is complex and is difficult to achieve full coverage across all markets and specifier variants — expect limited support.
This widget requires the onItemClick callback to communicate user interactions with your application. Because HTML declarative integration cannot provide callback functions, the declarative method is not suited for this widget — use the JavaScript/programmatic integration shown in the examples below.

See the Tournament Bet Insights widget demo.
betInsights.tournamentRequired identifiers (at least one):
At least one of the following identifiers must be provided:
See Getting Identifiers for details on obtaining these identifiers.
Environment Requirements
Supported Sports
Supported Languages
Supported Markets
For implementation guidance, example adapter implementations, and the adapter endpoint contract required by this widget, see the Adapter overview. It explains how to choose between Generic-Sportradar, custom-mapping, or self-hosted adapters and includes sample payloads you can adapt.
Betting insights rely on Sportradar's Unified Odds Feed (UOF) market and outcome identifiers. You must map those identifiers to your application's market/outcome IDs. While simple market mapping can be achieved for common markets, achieving complete coverage across all markets and variants is difficult.
eventMarkets or (market + availableMarketsForEvent)eventbetSlipSelectionThe widget can be embedded inline (always visible) or as a button that opens a pop-up overlay.

Always-visible insights displayed directly on the page — ideal for dedicated betting sections.
All of the following parameters from Bet Insights are also supported:
minOdds, maxOdds, and testMarkets are available on only and are supported by Tournament Bet Insights.
This section outlines the process required to integrate the Bet Insights widget into your platform.
Your sales contact person will initiate a shared communication channel via Slack invite to facilitate real-time collaboration between teams. This channel serves as the primary medium for answering questions, exchanging required information, and providing ongoing integration support.
Your sales contact person will organize a kickoff meeting with your technical team and Sportradar's integration team. This meeting serves as the formal start of the technical integration process and ensures both teams are aligned on requirements, timelines, and next steps. During the kickoff the teams will decide the adapter implementation type — this is important because Sportradar needs to confirm whether we have access to your odds and you can use generic adapter or if your platform uses Unified Odds Feed (UOF) identifiers. If your platform does not use UOF IDs, you may need to implement a custom adapter on your side; that decision can affect timeline, required effort, and the level of market coverage achievable.
Properties do not always transfer from the above table directly into integration code. Properties must be transformed differently for each integration method:
SIR() callcardVariant: "compact"In javascript integration, the properties go into an object which is passed as the 4th argument of the call ti SIR() function. Please see Global SIR API
data-sr- prefixcardVariant → To run this widget you must provision an adapter that supplies match and market data. The best adapter type depends on how your data is structured and delivered. During onboarding our team will review your data, recommend the optimal adapter, and assist with configuration.
Learn more about adapter options here.
Replace <CLIENT_ID> and <DATA_SOURCE> with the values provided during onboarding (for example client id: client1, data source: spider). In code use adapterDataSource: 'spider' and https://widgets.sir.sportradar.com/client1/widgetloader.
The examples in this section demonstrate the bet slip integration pattern using the Bet Insights widget. The pattern is identical for Tournament Bet Insights — adapt the identifier prop (uniqueTournamentId, seasonId, tournamentId, or matchId) and widget key (betInsights.tournament) in your integration.
The following example shows how to respond when a user clicks an insight card. The onItemClick callback receives the click target and the outcome data, which you can use to build a selection object and push it into your bet slip. Walk through the highlighted sections to understand each part of the flow.
The following snippet brings together the widgetloader, the adapter's betSlipSelection endpoint, and the onItemClick handler specifically for Tournament Bet Insights.
Replace <CLIENT_ID> and <DATA_SOURCE> with the values provided during onboarding (for example client id: client1, data source: spider). In code use adapterDataSource: 'spider' and https://widgets.sir.sportradar.com/client1/widgetloader.
<script>
(function(a,b
The following describes how the Bet Insights widget reacts to data, market and outcome state changes, and user interactions. It covers visibility rules, how selections and bet-slip events are handled, and how adapter updates or error states affect the widget UI and available actions.

The diagram above illustrates the complete data lifecycle for the Bet Insights widget, which runs in the end user's browser and coordinates data between Sportradar and your systems:
onItemClick handler (6) so your app can add the selection to the bet slip (7).betSlipSelection subscription/callback that the widget registers; when your bet slip changes the Adapter invokes the callback (8–9) and the widget updates its UI to reflect current selections.
When market status is set to suspended, the widget disables that market's outcomes and displays the label "temporary unavailable" in place of odds, indicating the market is temporarily not available for betting.
Widget comes with pre-existing styling but can be customized by applying custom CSS properties to its different HTML elements. The widget's custom class selectors and supported CSS properties are listed below. Note that all custom classes must be nested within the .sr-bb.sr-<WIDGET_NAME> selector class. This ensures that the custom styles only apply to that widget and not to other elements on the page.
Replace <WIDGET_NAME> with insights!
.sr-bb.sr-insights {
.srct-ins-button {
border-radius: 2px;
}
.srct-ins-showmore {
color: #4786ff;
}
}The following classes are specific to the Tournament Bet Insights widget and provide customization for the event header area within each insight card:
| Class | Customization options |
|---|---|
| srct-ins-card-header | color, background-color, border-color, font-family |
| srct-ins-card-header__live-label | color, font-weight, font-family |
| srct-ins-card-header__competitors | color, font-size, font-weight |
| srct-ins-card-header__datetime | color, font-size, font-weight |
| srct-ins-card-header__result | color, font-weight |
Choose the right identifier based on your page context:
// League overview page — use uniqueTournamentId for all seasons
{ uniqueTournamentId: 135 }
// Specific season page — use seasonId
{ seasonId: 132030 }
// Tournament page — use tournamentId for a specific instance
{ tournamentId: 30 }
// Match detail page — use matchId to show insights from other matches in the same tournament
{ matchId: 61591316 }Use numberOfCards and numberOfEvents to balance coverage and focus:
// Focused: many insights from few matches
{
uniqueTournamentId: 135,
numberOfEvents: 3, // Only next 3 matches
numberOfCards: 12 // Up to 12 insights total
}
// Broad: fewer insights spread across more matches
{
uniqueTournamentId: 135,
numberOfEvents: 10, // Up to 10 matches
numberOfCards: 10 // Only top 10 insights
}
Perfect for tournament overview and standings pages:
// Tournament hub — button integration in header
SIR('addWidget', '#tournament-header-insights', 'betInsights.tournament', {
uniqueTournamentId: 135,
integration: 'button',
widgetTitle: 'Best Bets',
numberOfCards: 10
});
// Tournament page sidebar
SIR(
When using matchId, show insights from other tournament matches alongside match-specific insights:
// Match detail page — related matches section
SIR('addWidget', '#related-insights', 'betInsights.tournament', {
matchId: 61591316,
integration: 'inline',
widgetTitle: 'Other Tournament Insights',
numberOfCards: 8
});
// Match-specific insights on the same page
SIR('addWidget', '#match-insights', 'betInsights',
// Desktop — tournament overview
if (window.innerWidth > 1024) {
SIR('addWidget', '#tournament-insights', 'betInsights.tournament', {
uniqueTournamentId: 135,
integration: 'inline',
cardsLayout: 'horizontal',
cardVariant: 'default',
numberOfCards:
Match-level AI betting insights widget with full API reference and advanced integration examples.
Learn how to obtain tournament, season, and match IDs for widget configuration.
Complete reference for the global SIR API function, including initialization, configuration options, and widget management methods.
| Code | Language | Native |
|---|---|---|
sqi | Albanian | Shqip |
aa | Arabic | العربية |
hye | Armenian | Հայերեն |
aze | Azerbaijani | Azərbaycan dili |
bs | Bosnian | Bosanski |
bg | Bulgarian | Български |
zh | Chinese (Simplified) | 简体中文 |
zht | Chinese (Traditional) | 中文繁體 |
hr | Croatian | Hrvatski |
cs | Czech | Česky |
da | Danish | Dansk |
nl | Dutch | Nederlands |
en | English | |
en_us | English (US) | |
et | Estonian | Eesti |
fi | Finnish | Suomeksi |
fr | French | Français |
ka | Georgian | ქართული |
de | German | Deutsch |
el | Greek | Eλληνικά |
heb | Hebrew | עברית |
hi | Hindi | हिन्दी |
hu | Hungarian | Magyar |
isl | Icelandic | Íslenska |
id | Indonesian | Bahasa Indonesia |
it | Italian | Italiano |
ja | Japanese | 日本語 |
km | Khmer | ខ្មែរ |
ko | Korean | 한국어 |
lv | Latvian | Latviešu |
lt | Lithuanian | Lietuvių |
mk | Macedonian | Македонски |
no | Norwegian | Norsk |
pl | Polish | Polski |
pt | Portuguese | Português |
br | Portuguese (Brazil) | Português do Brasil |
ro | Romanian | Română |
ru | Russian | Русский |
sr | Serbian (Cyrillic) | Cрпски |
srl | Serbian (Latin) | Srpski |
sk | Slovak | Slovenčina |
sl | Slovenian | Slovenščina |
es | Spanish | Español |
sw | Swahili | Kiswahili |
se | Swedish | Svenska |
th | Thai | ไทย |
tr | Turkish | Türkçe |
tuk | Turkmen | |
ukr | Ukrainian | Українська |
vi | Vietnamese | Tiếng Việt |
| Market ID | Market Name |
|---|---|
| 1 | 1x2 |
| 8 | {!goalnr} goal |
| 9 | Last goal |
| 10 | Double chance |
| 11 | Draw no bet |
| 12 | {$competitor1} no bet |
| 13 | {$competitor2} no bet |
| 14 | Handicap {hcp} |
| 15 | Winning margin |
| 16 | Handicap |
| 18 | Total |
| 19 | {$competitor1} total |
| 20 | {$competitor2} total |
| 21 | Exact goals |
| 23 | {$competitor1} exact goals |
| 24 | {$competitor1} exact goals |
| 24 | {$competitor2} exact goals |
| 25 | Goal range |
| 26 | Odd/even |
| 27 | {$competitor1} odd/even |
| 28 | {$competitor2} odd/even |
| 29 | Both teams to score |
| 30 | Which team to score |
| 31 | {$competitor1} clean sheet |
| 32 | {$competitor2} clean sheet |
| 33 | {$competitor1} win to nil |
| 34 | {$competitor2} win to nil |
| 35 | 1x2 & both teams to score |
| 36 | Total & both teams to score |
| 37 | 1x2 & total |
| 38 | {!goalnr} goalscorer |
| 39 | Last goalscorer |
| 40 | Anytime goalscorer |
| 41 | Correct score [{score}] |
| 45 | Correct score |
| 46 | Halftime/fulltime correct score |
| 47 | Halftime/fulltime |
| 48 | {$competitor1} to win both halves |
| 49 | {$competitor2} to win both halves |
| 50 | {$competitor1} to win either half |
| 51 | {$competitor2} to win either half |
| 52 | Highest scoring half |
| 53 | {$competitor1} highest scoring half |
| 54 | {$competitor2} highest scoring half |
| 55 | 1st/2nd half both teams to score |
| 56 | {$competitor1} to score in both halves |
| 57 | {$competitor2} to score in both halves |
| 58 | Both halves over {total} |
| 59 | Both halves under {total} |
| 60 | 1st half - 1x2 |
| 62 | 1st half - {!goalnr} goal |
| 63 | 1st half - double chance |
| 64 | 1st half - draw no bet |
| 65 | 1st half - handicap {hcp} |
| 66 | 1st half - handicap |
| 68 | 1st half - total |
| 69 | 1st half - {$competitor1} total |
| 70 | 1st half - {$competitor2} total |
| 71 | 1st half - exact goals |
| 74 | 1st half - odd/even |
| 75 | 1st half - both teams to score |
| 76 | 1st half - {$competitor1} clean sheet |
| 77 | 1st half - {$competitor2} clean sheet |
| 78 | 1st half - 1x2 & both teams to score |
| 79 | 1st half - 1x2 & total |
| 81 | 1st half - correct score |
| 83 | 2nd half - 1x2 |
| 84 | 2nd half - {!goalnr} goal |
| 85 | 2nd half - double chance |
| 86 | 2nd half - draw no bet |
| 87 | 2nd half - handicap {hcp} |
| 88 | 2nd half - handicap |
| 90 | 2nd half - total |
| 91 | 2nd half - {$competitor1} total |
| 92 | 2nd half - {$competitor2} total |
| 93 | 2nd half - exact goals |
| 94 | 2nd half - odd/even |
| 95 | 2nd half - both teams to score |
| 96 | 2nd half - {$competitor1} clean sheet |
| 97 | 2nd half - {$competitor2} clean sheet |
| 98 | 2nd half - correct score |
| 100 | When will the {!goalnr} goal be scored (15 min interval) |
| 101 | When will the {!goalnr} goal be scored (10 min interval) |
| 105 | 10 minutes - 1x2 from {from} to {to} |
| 122 | Will there be a penalty shootout |
| 136 | Booking 1x2 |
| 137 | {!bookingnr} booking |
| 138 | Total booking points |
| 139 | Total bookings |
| 142 | Exact bookings |
| 143 | {$competitor1} exact bookings |
| 144 | {$competitor2} exact bookings |
| 146 | Sending off |
| 147 | {$competitor1} sending off |
| 148 | {$competitor2} sending off |
| 149 | 1st half - booking 1x2 |
| 150 | 1st half - {!bookingnr} booking |
| 151 | 1st half - total booking points |
| 152 | 1st half - total bookings |
| 153 | 1st half - {$competitor1} total bookings |
| 154 | 1st half - {$competitor2} total bookings |
| 155 | 1st half - exact bookings |
| 156 | 1st half - {$competitor1} exact bookings |
| 157 | 1st half - {$competitor2} exact bookings |
| 159 | 1st half - sending off |
| 160 | 1st half - {$competitor1} sending off |
| 161 | 1st half - {$competitor2} sending off |
| 162 | Corner 1x2 |
| 163 | {!cornernr} corner |
| 164 | Last corner |
| 165 | Corner handicap |
| 166 | Total corners |
| 167 | {$competitor1} total corners |
| 168 | {$competitor2} total corners |
| 169 | Corner range |
| 170 | {$competitor1} corner range |
| 171 | {$competitor2} corner range |
| 172 | Odd/even corners |
| 173 | 1st half - corner 1x2 |
| 174 | 1st half - {!cornernr} corner |
| 175 | 1st half - last corner |
| 176 | 1st half - corner handicap |
| 177 | 1st half - total corners |
| 180 | 1st half - {$competitor1} exact corners |
| 181 | 1st half - {$competitor2} exact corners |
| 182 | 1st half - Corner range |
| 183 | 1st half - odd/even corners |
| 184 | {!goalnr} goal & 1x2 |
| 199 | Correct score |
| 220 | Will there be overtime |
| 540 | Double chance (match) & 1st half both teams score |
| 541 | Double chance (match) & 2nd half both teams score |
| 542 | 1st half - double chance & both teams to score |
| 543 | 2nd half - 1x2 & both teams to score |
| 544 | 2nd half - 1x2 & total |
| 545 | 2nd half - double chance & both teams to score |
| 546 | Double chance & both teams to score |
| 547 | Double chance & total |
| 548 | Multigoals |
| 549 | {$competitor1} multigoals |
| 550 | {$competitor2} multigoals |
| 551 | Multiscores |
| 552 | 1st half - multigoals |
| 553 | 2nd half - multigoals |
| 770 | {player} assists (incl. overtime) |
| 775 | {player} goals (incl. overtime) |
| 776 | {player} shots (incl. overtime) |
| 777 | {player} shots on goal (incl. overtime) |
| 778 | {player} passes (incl. overtime) |
| 780 | {player} tackles (incl. overtime) |
| 818 | Halftime/fulltime & total |
| 819 | Halftime/fulltime & 1st half total |
| 820 | Halftime/fulltime & exact goals |
| 854 | {$competitor1} or over {total} |
| 855 | {$competitor1} or under {total} |
| 856 | Draw or over {total} |
| 857 | Draw or under {total} |
| 858 | {$competitor2} or over {total} |
| 859 | {$competitor2} or under {total} |
| 860 | {$competitor1} or both teams to score |
| 861 | Draw or both teams to score |
| 862 | {$competitor2} or both teams to score |
| 863 | {$competitor1} or any clean sheet |
| 864 | Draw or any clean sheet |
| 865 | {$competitor2} or any clean sheet |
| 879 | {$competitor2} to win |
| 880 | {$competitor1} to win |
| 881 | Any team to win |
| 882 | {player} to score (incl. overtime) |
| 888 | Anytime goalscorer & 1x2 |
| 889 | Anytime goalscorer & correct score |
| 890 | {!goalnr} goalscorer & correct score |
| 891 | {!goalnr} goalscorer & 1x2 |
| 1179 | 1st Half Result or Match Result |
| 1183 | {player} total shots (incl. overtime) |
| 1185 | {player} total shots on goal (incl. overtime) |
| 1187 | {player} total passes (incl. overtime) |
| 1189 | {player} total tackles (incl. overtime) |
| 1191 | {player} to be carded (incl. overtime) |
This widget requires an adapter to supply match, market and odds data. See the Adapter overview.
{ integration: "inline" }The title in the widget header (or button label) can include or hide its icon.

{ widgetTitle: "Bet Insights" }Controls the visual style of each insight card.

Standard card with market name and outcome information.
{ cardVariant: "default" }Controls where the outcome name appears relative to the odds on each card.
| Position | Config | Description |
|---|---|---|
| Bottom (default) | outcomeButtonPosition: "bottom" | Outcome name below the odds |
| Top | outcomeButtonPosition: "top" | Outcome name above the odds |

Cards stacked vertically — suitable for narrow containers and sidebars.
{ cardsLayout: "vertical" }When using button integration (integration: "button"), controls which direction the pop-up opens.

{ integration: "button", modalPosition: "left" }
Hides the widget header entirely in inline mode.
{ disableWidgetHeader: true }See the Bet Insights demo for live examples.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
matchId | number | Conditional | - | Sportradar match identifier. Shows insights for matches in the same tournament as this match. At least one of matchId, tournamentId, uniqueTournamentId, or seasonId is required. See Getting Identifiers |
tournamentId | number | Conditional | - | Sportradar tournament identifier. Shows insights from all matches in this specific tournament. At least one of the four ID props is required |
uniqueTournamentId | number | Conditional | - | Sportradar unique tournament identifier. Shows insights from matches across all seasons of this tournament. At least one of the four ID props is required |
seasonId | number | Conditional | - | Sportradar season identifier. Shows insights from all matches in this specific season. At least one of the four ID props is required |
numberOfCards | number | No | 15 | Maximum number of insight cards to display. Must be between 1 and 20 |
numberOfEvents | number | No | - | Maximum number of distinct matches to include insights from. Must be between 1 and 20. When unset, insights from all available matches are included |
| Property | Type | Default | Description |
|---|---|---|---|
integration | string | "inline" | Widget integration mode: "inline" or "button" |
cardsLayout | string | "vertical" | Layout direction for insight cards: "vertical" or "horizontal" |
cardVariant | string | "default" | Card display style: "default", "defaultIcon", "compact", "button", "buttonFooter", "single" |
outcomeOrder | string | "bottom" | Position of outcome name relative to odds: "top", "bottom". Only applicable with cardVariant='compact', cardVariant='button', and cardVariant='buttonFooter' |
outcomeButtonPosition | string | "bottom" | Position of call-to-action button in card: "top", "bottom". Not applicable with cardVariant='button' and cardVariant='buttonFooter' |
widgetTitle | string|false | "Tournament Bet Insights" | Title displayed in widget header or button label. Set to false to hide |
widgetIcon | string|false | Default icon | URL of custom icon image. Set to false to hide |
disableWidgetHeader | boolean | false | When true, hides widget header in inline mode |
enableCollapse | boolean | true | When true, allows collapsing widget content in inline mode. Only applicable when disableWidgetHeader=false |
startCollapsed | boolean | false | When true and enableCollapse is true, widget starts collapsed |
modalPosition | string | "left" | Direction modal opens in button integration: "left", "right", "bottom" |
modalMaxHeight | number|string | - | Maximum height of modal content. Allowed units: %, px, vh. Only applicable with integration='button' and cardsLayout='vertical' |
isMobile | boolean | false | When true, opens pop-up at viewport bottom edge, full width (only with integration='button') |
ignoreAdapterValues | boolean | false | When true, uses Sportradar standard names instead of adapter-provided translations |
capitalizeMarketNameAndOutput | boolean | false | When true, capitalizes first letter of market and outcome names |
onItemClick | function | - | Callback triggered when insight card or outcome is clicked. Receives event and outcome data for bet slip integration |
data-sr-card-variantfilters.sport.hidden → Complex objects must be passed as JSON stringsIn HTML integration, the properties go into the parent HTML object as object properties, prefixed with data-sr- as explained above.
This method supports only simple (base) properties and does not support properties that require functions.
In all examples replace sportradar in the widgetloader URL path with your clientId.
Example if your clientId is client1:
https://widgets.sir.sportradar.com/sportradar/widgetloaderhttps://widgets.sir.sportradar.com/client1/widgetloader<script>
(function(a,b,c,d,e,f,g,h,i){a[e]||(i=a[e]=function(){(a[e].q=a[e].q||[]).push(arguments)},i.l=1*new Date,i.o=f,
g=b.createElement(c),h=b.getElementsByTagName(c)[0],g.async=1,g.src=d,g.setAttribute("n",e),h.parentNode.insertBefore(g,h)
)})(window,document,"script","https://widgets.sir.sportradar.com/<CLIENT_ID>/widgetloader","SIR", {
language: 'en',
adapterDataSource: '<DATA_SOURCE>'
});
const widgetProps = {
// Required identifiers — provide at least one
uniqueTournamentId: 135,
// tournamentId: 30,
// seasonId: 132030,
// matchId: 61591316,
// Configuration
integration: "button",
modalPosition: "right",
numberOfCards: 15,
// ... Optional: Additional customization props (see API Reference)
};
SIR('addWidget', '#tournament-bet-insights', 'betInsights.tournament', widgetProps);
</script>
<div id="tournament-bet-insights"></div> let betSlipChangeCallback = undefined;
let betSlipState = { // Simplified bet slip integration for demonstration purposes
selection: [],
};
// Called on user interactions
function onItemClick(target, data) {
if (target === 'externalOutcome') { // When user clicks an outcome on an insight card
// Construct a selection object in the shape your bet slip integration expects.
// The widget provides external IDs via data.externalEvent, data.externalMarket,
// and data.externalOutcome — map them to your own format below.
const bet = {
type: 'uf',
event: `${data.externalEvent.id}`,
market: `${data.externalMarket.id}`,
outcome: `${data.externalOutcome.id}`
};
if (data.externalMarket.specifier && data.externalMarket.specifier.value) {
bet.specifiers = `${data.externalMarket.specifier.value}`;
}
// Add the new selection
betSlipState = {
selection: [...betSlipState.selection, bet]
};
// Notify the adapter so the widget reflects the updated bet slip state
betSlipChangeCallback && betSlipChangeCallback(betSlipState);
}
}
const widgetProps = {
matchId: 61591316,
onItemClick: onItemClick,
// ... Additional customization props (see API Reference)
};
SIR('addWidget', '#bet-insights', 'betInsights', widgetProps);The following example shows how to connect the widget to your bet slip so it always reflects the punter's current selections. The adapter's betSlipSelection endpoint keeps the widget in sync, and onItemClick lets you act when the user clicks an outcome card. Walk through the highlighted sections to understand each part of the flow.
We recommend revalidating each selection and refreshing odds when adding them to the bet slip — or at minimum revalidating selections and odds immediately before accepting a bet — to ensure markets are still available and the odds presented to the user are up to date.
{
onItemClick: function(event, outcomeData) {
// Add to bet slip
betSlip.addSelection({
matchId: outcomeData.matchId,
marketId: outcomeData.market.id,
outcomeId: outcomeData.outcome.id,
odds: outcomeData.odds,
source: 'bet_insights'
});
}
} const adapter = {
The following example brings together the widgetloader, the adapter's betSlipSelection endpoint, and the onItemClick handler into a single ready-to-use snippet. Replace the placeholder values.
Replace <CLIENT_ID> and <DATA_SOURCE> with the values provided during onboarding (for example client id: client1, data source: spider). In code use adapterDataSource: 'spider' and https://widgets.sir.sportradar.com/client1/widgetloader.
<script>
(function(a,b,c,d,e,f,g,h,i){a[e]||(i=a[e]=function(){(a[e].q=a[e].q||[]).push(arguments)},i.l=1*new Date,i.o=f,
g=b.createElement(c),h=b.getElementsByTagName(c)[0],g.async=1,g.src=d,g.setAttribute("n",e),h.parentNode.insertBefore(g,h)
)})(window,document,"script","https://widgets.sir.sportradar.com/<CLIENT_ID>/widgetloader","SIR", {
language: 'en',
adapterDataSource: '<DATA_SOURCE>'
});
// Tracks the current bet slip selections in the format the widget expects.
// In production, replace this with your own bet slip store / state manager.
let betSlipState = { selection: [] };
let notifyWidget = null;
const adapter = {
endpoints: {
betSlipSelection: (args, callback) => {
// Store the callback so we can notify the widget whenever selections change.
notifyWidget = callback;
// Push the current state immediately so the widget is in sync on load.
callback(undefined, betSlipState);
return () => {
notifyWidget = null;
};
},
},
};
// Register the adapter once on page load — USE ONLY ONE APPROPRIATE TO YOUR ADAPTER TYPE
SIR('registerAdapter', adapter); // Generic-Sportradar & Self-hosted
// SIR('registerAdapter', '<HOSTED_ADAPTER_NAME>', adapter); // Custom-mapping
function onItemClick(args) {
if (args.type === 'addSelectionsToBetSlip') {
// Map the widget's selections to the format the betSlipSelection endpoint expects.
const newSelections = args.data.selections.map((sel) => ({
type: 'uf',
event: sel.eventId, // e.g., "sr:match:12345"
market: sel.marketId, // e.g., "38"
specifiers: sel.specifiers, // e.g., "goalNr=1" (optional)
outcome: sel.outcomeId, // e.g., "sr:player:1050245"
odds: { type: 'eu', value: sel.odds },
}));
betSlipState = {
selection: [...betSlipState.selection, ...newSelections],
};
// Notify the widget so it immediately highlights the newly selected outcomes.
notifyWidget && notifyWidget(undefined, betSlipState);
}
}
const widgetProps = {
matchId: 61591316,
onItemClick: onItemClick,
// ... Additional customization props (see API Reference)
};
SIR('addWidget', '#bet-insights', 'betInsights', widgetProps);
</script>
<div id="bet-insights"></div>const market = {
id: "1",
name: "Match Winner (1X2)",
outcomes: [
{ id: "1", name: "Home", status: "active", odds: { type: "eu", value: "2.10" } },
{ id: "X", name: "Draw", status: "active", odds: { type: "eu", value: "3.40" } },
{ id: "2", name: "Away", status: "active", odds: { type: "eu", value: "3.50" } }
],
status: "suspended"
};If a market or outcome has any status other than active (for example: suspended or cancelled), the widget will hide that market to avoid showing stale or unavailable betting options.
| Class | Customization options |
|---|---|
| srct-ins-button | background-color, border-radius |
| srct-ins-button__icon | color |
| srct-ins-button_text | color, font-size, font-family |
| srct-ins-header | background-color, border-color, border-width |
| srct-ins-header__icon | color |
| srct-ins-header__text | color, font-size, font-weight |
| srct-ins-header__arrow | color |
| srct-ins-container | background-color, font-family |
| srct-ins-card | background-color, border-radius, border-color, box-shadow |
| srct-ins-text | color, text-decoration |
| srct-ins-showmore | color, font-size |
| srct-ins-popup | background-color, color, font-size, font-family |
| srct-ins-popup__icon | color |
| srct-ins-cta | background-color, border-color |
| srct-ins-market | color, font-size, font-weight |
| srct-ins-market__icon | color |
| srct-ins-outcome | background-color, border-radius, padding |
| srct-ins-outcome--selected | background-color |
| srct-ins-outcome--disabled | background-color |
| srct-ins-outcome__name | color, font-size, font-weight |
| srct-ins-outcome__value | color, font-size, font-weight |
| srct-ins-bubble-count | background-color, border-color, color |
| srct-ins-bubble-count-text | color |
| srct-ins-bubble-new | background-color, border-color, color |
| srct-ins-robot-icon | color |
Customize widget appearance, colors, fonts, and styling to match your brand.
Performance optimization, security considerations, and deployment strategies.