Betting Entertainment Tools

Technical Guide

This guide provides step-by-step instructions for integrating the Sportradar Bet Concierge widget into your website. It includes details about the required components, such as an adapter developed by Sportradar's engineering team, and options for custom theming. Following these instructions will help ensure a seamless integration and an improved user experience.

1. Widget Integration

The Bet Concierge widget can be integrated into your website using JavaScript. There are three levels of integration, each offering different features and requiring varying levels of development effort:

  • Basic Integration: This is the simplest option and requires minimal development effort. It includes an interactive AI chat widget that can answer all stats-related queries.
  • Full Integration: This option is more advanced and requires additional development. It provides single-market bet suggestions to enhance user engagement, alongside basic chat.
  • Advanced Integration: This is the most advanced option and requires significant development effort. It includes a custom bet feature, which is dependent on having the UOF Proxy Custom Bet widget already integrated into your system. Without this prerequisite, the custom bet feature cannot function.

Basic Integration

The basic integration of the Bet Concierge widget is straightforward. There are 2 required properties that need to be passed to the widget: matchId and jwt OR getJwt.

Example:

<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/sportradar/widgetloader","SIR", {
       language: 'en'
   });

   const sportradarMatchId = 50955863;

   function getJwt() {
       return new Promise(function (resolve) {
            // Fetch user JWT token from the server
            const exampleJWT = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiO...';
            resolve(exampleJWT);
       });
    }


   // Bet Concierge Widget
   SIR('addWidget', '.sr-bc-widget', 'betConcierge', {matchId: sportradarMatchId, getJwt: getJwt});
</script>
<div class="bc-wrapper">
   <div class="sr-bc-widget"></div>
</div>

Bet Suggestion Integration

To implement the Bet Suggestion feature, you need to add the data adapter to basic integration. The adapter retrieves information from the client’s API and displays it within the widget, ensuring a seamless integration between the two systems. All markets must be mapped to the Sportradar market IDs.

Example:

<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/sportradar/widgetloader","SIR", {
       language: 'en'
   });

   const marketData = {
       markets: [
           {
               id: '1',
               name: '1x2',
               outcomes: [
                   { id: '1', name: 'Home', odds: '1.48', isSelected: false, status: { isActive: true } },
                   { id: '2', name: 'Draw', odds: '4.82', isSelected: false, status: { isActive: true } },
                   { id: '3', name: 'Away', odds: '2.47', isSelected: false, status: { isActive: true } }
               ],
               status: { status: 'active' }
           },
           .....
       ]
   };

   const onRequest = (requestName, args, callback) => {
         switch (requestName) {
         case 'betConcierge.markets':
             callback(undefined, marketData);
             break;
         default:
             callback(new Error('Unknown request'), undefined);
         }
   };

   SIR('registerAdapter', onRequest);

   const sportradarMatchId = 50955863;

   function getJwt() {
       return new Promise(function (resolve) {
            // Fetch user JWT token from the server
            const exampleJWT = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiO...';
            resolve(exampleJWT);
       });
    }

   // Bet Concierge Widget
   SIR('addWidget', '.sr-bc-widget', 'betConcierge', {matchId: sportradarMatchId, getJwt: getJwt});
</script>
<div class="bc-wrapper">
   <div class="sr-bc-widget"></div>
</div>

Custom Bet Integration

To implement the Custom Bet feature, you need to have Custom Bet widget already integrated into your system. And then using data adapter you will have to call calculate endpoint from the custom bet API, with payload from adapter. Then calculation response will be passed to the widget adapter. This will allow the widget to display the custom bet information.

Example:

<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/sportradar/widgetloader","SIR", {
       language: 'en'
   });

   const onRequest = (requestName, args, callback) => {
         switch (requestName) {
         case 'calculateCbXml':
             const { calculatePayload } = args;

             fetch('{url}/api/custombet/calculate-filter', {
                 method: 'POST',
                 headers: {
                     'Content-Type': 'application/json',
                 },
                 body: calculatePayload,
             })
             .then((data) => {
                 callback(undefined, {payload: data});
             })
             .catch((error) => {
                 callback(error);
             });
             break;
         default:
             callback(new Error('Unknown request'), undefined);
         }
   };

   SIR('registerAdapter', onRequest);

   const sportradarMatchId = 50955863;

   function getJwt() {
       return new Promise(function (resolve) {
            // Fetch user JWT token from the server
            const exampleJWT = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiO...';
            resolve(exampleJWT);
       });
    }

   // Bet Concierge Widget
   SIR('addWidget', '.sr-bc-widget', 'betConcierge', {matchId: sportradarMatchId, getJwt: getJwt});
</script>
<div class="bc-wrapper">
   <div class="sr-bc-widget"></div>
</div>

Type Definitions

Object

# OnActionInterface

Defines the structure of an action object that can be dispatched in the application. Each action includes:

Properties:
Name Type Attributes Description
type string | number <required>

A string literal from TriggerActionEnum signifying the kind of event (e.g., 'Close', 'Click', 'BetConciergeOutcome').

data string | Object

An optional payload that provides additional information needed to handle the action. This can be an object, string, or undefined if no extra data is needed.

Example
// A complete switch-case example illustrating multiple action types:
onAction: function(action) {
  switch (action.type) {
      case 'Close': {
          const { data } = action;
          // ... implement logic to close the widget
          break;
      }
      case 'Click': {
          const { data } = action;
          // ... implement logic for handling terms link or statistics link clicks
          break;
      }
      case 'Error': {
          const { data } = action;
          // ... implement logic for handling widget errors
          break;
      }
      case 'BetConciergeOutcome': {
          const { data } = action;
          // ... implement logic for handling clicks on AI market suggestions
          break;
      }
      // ... add new cases here for other actions
      default:
          // Handle unknown or unanticipated action types
          console.warn(`Unknown action type: ${action.type}`);
          break;
  }
}
Object

# WidgetProps

Properties passed to the Bet Concierge widget, on initialization.

⚠️ IMPORTANT AUTHENTICATION REQUIREMENT: You MUST provide ONE of the following authentication methods:

  • jwt (string) - Direct JWT token, OR
  • getJwt (function) - Callback function that returns JWT token
Properties:
Name Type Attributes Description
matchId string | number <required>

Sportradar ID of the match.

jwt string

User's JWT Token for authentication. You MUST provide either jwt OR getJwt.

getJwt getJwt Widgets.BetConcierge.Integration.TechnicalGuide.getJwt

A callback promise function that returns user's JWT Token for authentication. You MUST provide either jwt OR getJwt.

onAction function | OnActionInterface Widgets.BetConcierge.Integration.TechnicalGuide.OnActionInterface

Handles application-wide actions by routing them to the appropriate logic based on the action type.

numberOfSuggestedQuestions range(3, 5)

Number of AI suggested questions in each category.

disableChatHistory boolean

When set to false users chat history is stored in local storage and displayed when user opens the widget again. Chat history is stored for each matchId separately with expiration time set to 1 day. If set to true, the chat history will be disabled.

enableCustomBet boolean

Set this prop to true when implementing Custom Bet feature. This will enable calculateCbXml adapter call.

termsPage 'hidden' | 'visible' | 'visibleOnEmptyChat'

Terms and conditions page is meant to be displayed on the widget load. When user clicks on agree and decline buttons, AcceptTerms & DeclineTerms click actions are handled in the onAction function.
Client is expected to handle these actions and show/hide 'termsPage' in the widget accordingly.
When set to hidden, the Terms and Conditions page is never displayed in the widget. When set to visible, the Terms and Conditions page is always displayed on widget load. When set to visibleOnEmptyChat, the Terms and Conditions page is displayed on widget load only if there are no messages in the chat history.

enableTermsLink boolean

When set to true, the Terms and Conditions link is displayed in the widget. If set to false, the link is hidden. When user clicks on read_more link, ReadMoreTerms click action is handled in the onAction function.

disableHomeLink boolean

When set to true, the home link in the header is hidden. If set to false, the link is displayed. When user clicks on home button, widget home page is displayed.

disableCoverage boolean

When set to true, the match coverage information is hidden. Default value is false. Coverage displays information about the data availability for the selected match and bet concierge capabilities in answering questions about that match.

disableHeader boolean

When set to true, the header is hidden. If set to false, the header is displayed.

enableMarketQuestions boolean

When set to true, the widget will display AI-generated market based questions on the start screen to users, enhancing their engagement and interaction with the available betting options. If set to false, these market questions will be hidden from the start screen.

enableInsights boolean

When set to true, the widget will display insights on the start screen to users, providing them with valuable information and enhancing their engagement. If set to false, the insights will be hidden from the start screen.

Example
defaultProps = {
    disableHeader: false,
    disableHomeLink: false,
    numberOfSuggestedQuestions: 3,
    enableTermsLink: false,
    termsPage: 'hidden',
    disableChatHistory: false,
    enableCustomBet: false,
    enableMarketQuestions: false,
    enableInsights: true
}

# getJwt()

Defines the structure of a callback promise function that retrieves a JWT token for user authentication. This function gets called when the Bet Concierge widget is initialized and when token refresh is needed.

Example
// Example implementation of getJwt function:
function getJwt() {
  return fetch("https://example.com/api/get-jwt/user123")
    .then((response) => response.json())
    .then((data) => data.token); // Must resolve to the JWT string - assuming backend returns { "token": "..." }
}