Frontend IntegrationIframe Integration

Iframe Integration

Embed the sportsbook in an iframe when you want to host it as a cross-origin page inside your site. There are two supported approaches:

  1. Direct iframe - point src at a hosted sportsbook environment and pass query parameters.
  2. Custom iframe page - host your own wrapper page that loads sportsbook.js and calls Sportsbook.mount().

Use the direct iframe for the simplest integration. Use a custom iframe page when you need custom CSS variables, host-wired postMessage callbacks, or token lookup logic that should not be placed in the iframe URL.

Direct Iframe

Point your iframe at the sportsbook environment URL. The hosted page loads and mounts automatically, so no wrapper HTML is required.

<iframe src="https://betting-demo-mxce1.sportsmodity.com?language=en-US&currency=USD&sb-path=live/soccer" title="Sportsbook" style="width: 100%; height: 100vh; border: 0"></iframe>

Hosted Environment URLs

Environmentiframe src base URL
QAhttps://betting-qa.sportsmodity.com
Devhttps://betting-dev.sportsmodity.com
Mexico QAhttps://betting-qa-mxce1.sportsmodity.com
Mexico demohttps://betting-demo-mxce1.sportsmodity.com
Mexico staginghttps://betting-staging-mxce1.sportsmodity.com

Append query parameters to configure the session, language, theme, layout, and starting route.

Direct Iframe Examples

<!-- Home -->
<iframe src="https://betting-demo-mxce1.sportsmodity.com"></iframe>
 
<!-- Live soccer, English, dark theme -->
<iframe src="https://betting-demo-mxce1.sportsmodity.com?language=en-US&themeId=dark&sb-path=live/soccer"></iframe>
 
<!-- Authenticated session -->
<iframe src="https://betting-demo-mxce1.sportsmodity.com?tenantRef=YOUR_TENANT&authToken=TOKEN&currency=USD&language=en-US&sb-path=my-bets"></iframe>
 
<!-- Match deep link -->
<iframe src="https://betting-demo-mxce1.sportsmodity.com?sb-path=match/123456"></iframe>

How It Works

  1. The hosted page loads and calls Sportsbook.mount() with environment defaults.
  2. Query parameters override those defaults at mount time.
  3. sb-path controls the in-app route and updates as the user navigates inside the iframe.

To change language, auth, currency, theme, or route from the parent page, update the iframe src and reload it.

const iframe = document.querySelector('iframe')
const url = new URL('https://betting-demo-mxce1.sportsmodity.com')
 
url.searchParams.set('language', 'en-US')
url.searchParams.set('sb-path', 'live/soccer')
url.searchParams.set('authToken', newToken)
 
iframe.src = url.toString()
⚠️

Language and auth changes require a reload. The sportsbook does not support a parent-to-iframe postMessage API for changing route, language, or session state.

Direct Iframe Limitations

WorksDoes not work
sb-path, language, authToken, currency, themeId, tenantRef, and layout flags through the URLCustom brand colors with --sb-* CSS variables
Automatic sb-resize messages to the parentHost-wired onRequireLogin callbacks
Deep linking through the iframe URLParent postMessage messages to change route or language

Custom Iframe Page

Use a custom iframe page when you need custom brand colors, host-wired postMessage callbacks, or token lookup logic outside the URL.

Host your own HTML as the iframe src and load sportsbook.js from the matching sportsbook environment.

Environmentsportsbook.js URL
QAhttps://betting-qa.sportsmodity.com/sportsbook.js
Devhttps://betting-dev.sportsmodity.com/sportsbook.js
Mexico QAhttps://betting-qa-mxce1.sportsmodity.com/sportsbook.js
Mexico demohttps://betting-demo-mxce1.sportsmodity.com/sportsbook.js
Mexico staginghttps://betting-staging-mxce1.sportsmodity.com/sportsbook.js

Wait for the SportsbookScriptLoaded event, then call window.Sportsbook.mount().

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
        <title>Sportsbook</title>
        <style>
            html,
            body {
                margin: 0;
                padding: 0;
                height: 100%;
            }
 
            #sportsbookRoot {
                min-height: 100%;
            }
 
            #sbMain#sbMain,
            #sbMain#sbMain .dark,
            #sbMain#sbMain .light {
                --sb-background: 0 0% 4% !important;
                --sb-foreground: 0 0% 100% !important;
                --sb-primary: 46 65% 52% !important;
                --sb-primary-foreground: 0 0% 4% !important;
                --sb-selection: 46 65% 52% !important;
                --sb-selection-foreground: 0 0% 100% !important;
                --sb-outcome: 235 10% 24% !important;
                --sb-outcome-foreground: 0 0% 100% !important;
                --sb-card: 240 3% 11% !important;
                --sb-card-foreground: 0 0% 100% !important;
                --sb-border: 0 0% 100% / 10% !important;
                --sb-radius: 8px !important;
            }
        </style>
    </head>
    <body>
        <div id="sportsbookRoot"></div>
 
        <script type="module" src="https://betting-demo-mxce1.sportsmodity.com/sportsbook.js"></script>
        <script>
            addEventListener('SportsbookScriptLoaded', function () {
                window.Sportsbook.mount({
                    tenantRef: 'YOUR_TENANT_REF',
                    authToken: undefined,
                    language: 'en-US',
                    currency: 'USD',
                    themeId: 'dark',
                    isUsLayout: false,
                    styles: {
                        appHeight: '100%',
                    },
                    onRequireLogin: function () {
                        window.parent.postMessage({ type: 'sportsbook:requireLogin' }, '*')
                    },
                    onSessionExpiredReload: function () {
                        window.parent.postMessage({ type: 'sportsbook:sessionExpired' }, '*')
                    },
                    onLoad: function () {
                        window.parent.postMessage({ type: 'sportsbook:loaded' }, '*')
                    },
                })
            })
        </script>
    </body>
</html>

Replace YOUR_TENANT_REF, the script URL, and the CSS values with the values for your integration.

URL query parameters such as language, authToken, themeId, and sb-path also work on a custom iframe page. The bundle merges URL values into Sportsbook.mount() automatically.

Mount Parameters

ParameterRequiredValues / notes
tenantRefYesTenant identifier provided during integration setup.
authTokenNoPlayer session token. Required for authenticated betting.
languageNoen, en-GB, en-US, or ja. Default: en.
currencyNoWallet currency code, for example USD or GCOIN.
themeIdNodark, light, or system.
isUsLayoutNotrue enables US-style layout. Default: false.
isTestModeNotrue enables test API behavior.
hostElementSelectorNoDefault: #sportsbookRoot. Only change this if you use a different container id.
styles.appHeightNoFor example 100% or 800px. Sets --sb-app-height.
styles.backgroundNoHSL components only. Sets the page background.
styles.classnames.betslip.triggerNoExtra CSS classes on the betslip open button.
styles.classnames.betslip.contentNoExtra CSS classes on the betslip drawer.
topMenuNoArray of search, home, live, my-bets, all-sports, and dynamic.
onRequireLoginNoCalled when the user must log in. Use this to notify the parent page.
onSessionExpiredReloadNoCalled when the sportsbook session expires.
onLoadNoCalled when the sportsbook has finished loading.
getBalanceNoAsync function returning the current player balance.
hideLoadingNotrue hides the built-in loading state.

authToken is required for real-money play. Omit it only for unauthenticated preview flows if your tenant allows them.

Customizing Colors

Every sportsbook CSS color token uses HSL components only. Do not include an hsl() wrapper.

/* Correct */
--sb-primary: 244 80% 55%;
--sb-border: 0 0% 100% / 10%;
 
/* Incorrect */
--sb-primary: hsl(244, 80%, 55%);
--sb-primary: #3b30e8;

Set CSS variables on #sbMain and use !important, because the sportsbook bundle sets its own theme variables on the mounted app.

Page and Surfaces

VariableWhat it controlsDefault dark theme
--sb-backgroundPage background220 27.27% 6.47%
--sb-foregroundMain text0 0% 100%
--sb-cardCards and panels216 19% 11%
--sb-card-foregroundText on cards0 0% 100%
--sb-popoverPopovers and dropdowns240 10% 4%
--sb-popover-foregroundPopover text0 0% 100%
--sb-mutedMuted backgrounds206 13% 22%
--sb-muted-foregroundSecondary text218 11% 65%
--sb-borderBorders0 0% 17%
--sb-inputInput borders and fills0 0% 17%
--sb-ringFocus rings216 11% 82%
--sb-radiusCorner radius8px

Brand and Actions

VariableWhat it controlsDefault dark theme
--sb-primaryPrimary buttons and links244 80% 55%
--sb-primary-foregroundText on primary0 0% 10%
--sb-secondarySecondary surfaces216 11% 82%
--sb-secondary-foregroundText on secondary0 0% 100%
--sb-accentAccent highlights60 100% 50%
--sb-accent-foregroundText on accent0 0% 100%
--sb-destructiveErrors and delete actions4 100% 62%
--sb-destructive-foregroundText on destructive0 0% 100%
--sb-successSuccess states147 72% 52%
--sb-success-foregroundText on success220 27% 6%
--sb-warningWarning states43 74% 66%

Odds Buttons

VariableWhat it controlsDefault dark theme
--sb-outcomeUnselected odds button background225 4% 32%
--sb-outcome-foregroundUnselected odds text0 0% 100%
--sb-selectionSelected odds button background251 70% 56%
--sb-selection-foregroundSelected odds text0 0% 100%

Betslip Panel

VariableWhat it controlsDefault dark theme
--sb-betslip-body-backgroundBetslip background228 29% 97%
--sb-betslip-body-foregroundBetslip text0 0% 10%
--sb-betslip-body-mutedMuted areas220 13% 91%
--sb-betslip-body-muted-foregroundMuted text220 9% 46%
--sb-betslip-body-cardCards inside betslip0 0% 100%
--sb-betslip-body-borderBetslip borders217 12% 84%
--sb-betslip-body-inputInput backgrounds0 0% 100%
--sb-betslip-body-input-foregroundInput text0 0% 10%
--sb-betslip-body-successSuccess in betslip136 76% 30%
--sb-betslip-body-warningWarning in betslip43 75% 66%
--sb-betslip-body-errorError in betslip4 90% 59%

You do not need to override every variable. Unset variables keep the bundle default.

If you only need to change the page background, pass it on mount:

window.Sportsbook.mount({
    tenantRef: 'YOUR_TENANT_REF',
    themeId: 'dark',
    styles: {
        background: '0 0% 4%',
        appHeight: '100%',
    },
})

postMessage Spec

Built-In Outbound Message

When the app detects that it is inside an iframe, it automatically sends resize messages to the parent page.

typePayloadWhen
sb-resize{ height: number }Content height changes.
const iframe = document.querySelector('iframe')
 
window.addEventListener('message', (event) => {
    if (event.origin !== 'https://betting-demo-mxce1.sportsmodity.com') {
        return
    }
 
    if (event.data?.type === 'sb-resize') {
        iframe.style.height = `${event.data.height}px`
    }
})

Always validate event.origin in production.

Host-Wired Messages

The sportsbook does not automatically send postMessage events for login, register, language changes, or navigation. Wire the messages from mount callbacks in your custom iframe page.

EventHow to get itSuggested message
Login requiredonRequireLogin{ type: 'sportsbook:requireLogin' }
Session expiredonSessionExpiredReload{ type: 'sportsbook:sessionExpired' }
App loadedonLoad{ type: 'sportsbook:loaded' }

Inbound Messages

Parent-to-sportsbook postMessage is not supported. You cannot post a message to change language, route, or sport selection.

GoalSupported approach
Change languageChange the iframe URL language query parameter and reload.
Deep link to a page or sportSet sb-path on the iframe URL.
Update auth after loginRemount with a new authToken, or use a custom iframe page with token lookup logic.

Authentication

The host system owns player authentication and token issuance.

  1. Your backend authenticates the player and issues a sportsbook auth token.
  2. The iframe page calls Sportsbook.mount({ tenantRef, authToken, currency, language }).
  3. The sportsbook calls GET /api/v1/launch/{tenantRef}?authToken={token}.
  4. The response establishes the player session used for bets and My Bets.
FieldTypeDescription
sessionRefstringPlayer session for bets and My Bets.
displayNamestringPlayer display name.
balancenumberWallet balance.
currencystringWallet currency.
oddsFormatenumPlayer odds format preference.

Tenant ref, auth token issuance, and the target QA or dev environment are provided when your integration is provisioned.

URL Spec

Append these query parameters to the iframe src URL, whether you use the hosted page or a custom iframe page.

https://betting-demo-mxce1.sportsmodity.com?language=en-US&currency=USD&themeId=dark&tenantRef=YOUR_TENANT&authToken=TOKEN&sb-path=live/soccer

Query Parameter: sb-path (In-App Navigation)

The sportsbook stores its internal route in sb-path. The value is the in-app path without a leading slash.

Internal routesb-path valueDescription
/Omit the param or use an empty value.Home / featured.
/searchsearchSearch.
/liveliveLive overview.
/live/{sportRef}live/{sportRef}Live for a sport, for example live/soccer.
/sport/{sportRef}sport/{sportRef}Sport hub, for example sport/soccer.
/sport/{sportRef}/{categoryRef}sport/{sportRef}/{categoryRef}Category under a sport.
/sport/{sportRef}/{categoryRef}/{leagueRef}sport/{sportRef}/{categoryRef}/{leagueRef}League under a category.
/my-betsmy-betsBet history.
/match/{matchId}match/{matchId}Match detail, for example match/123456.
/match/{matchId}-{teams}match/{matchId}-home-vs-awayMatch detail with optional SEO slug.
/sweepnowsweepnowSweepstakes page, if enabled for the tenant.
/season-events/{leagueId}season-events/{leagueId}Season / outrights, for example season-events/482453.

sportRef, categoryRef, and leagueRef are tenant-specific string refs from the inventory API, for example soccer or basketball.

?sb-path=search
?sb-path=live
?sb-path=live/soccer
?sb-path=sport/basketball
?sb-path=sport/soccer/england/premier-league
?sb-path=my-bets
?sb-path=match/987654321
?sb-path=season-events/482453

When the user navigates inside the app, sb-path updates in the iframe URL automatically with history.pushState. Parent pages can only read iframe.contentWindow.location.search for same-origin iframes. For cross-origin iframes, update the iframe src with a new sb-path when you need to navigate programmatically.

For programmatic navigation inside a same-origin custom iframe page, update the query parameter and dispatch the internal route change event:

function navigateSportsbook(path) {
    const params = new URLSearchParams(window.location.search)
    const normalized = path.replace(/^\//, '').trim()
 
    params.set('sb-path', normalized || '')
 
    const newUrl = window.location.pathname + '?' + params.toString() + window.location.hash
 
    window.history.pushState(null, '', newUrl)
    window.dispatchEvent(new Event('sb-querychange'))
}
 
navigateSportsbook('live/soccer')
navigateSportsbook('my-bets')

Session and Display Query Parameters

These query parameters are merged into Sportsbook.mount() automatically inside the bundle. URL values override mount defaults when present.

Query keyTypeValid valuesEffect
languagestringen, en-GB, en-US, jaUI language and API culture.
currencystringFor example USD or GCOIN.Wallet currency.
tenantRefstringYour tenant ref.Required for launch.
authTokenstringSession token.Authenticated session. Avoid logging this value.
themeIdenumdark, light, systemColor preset.
isUsLayoutbooleantrueEnables US-style layout when true.

sb-path is handled by the app router. Do not pass it to Sportsbook.mount().

Query Parameter: content-only

Query keyValuesEffect
content-onlyPresence only.My Bets renders without outer chrome for embedded panel mode.

Example:

?sb-path=my-bets&content-only

Languages

CodeNotes
enEnglish, generic.
en-GBEnglish, UK.
en-USEnglish, US.
jaJapanese. ja-JP also resolves through prefix matching.

Set the language on mount or through the iframe URL, for example ?language=en-US. There is no in-app language picker in iframe embeds.