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:
- Direct iframe - point
srcat a hosted sportsbook environment and pass query parameters. - Custom iframe page - host your own wrapper page that loads
sportsbook.jsand callsSportsbook.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¤cy=USD&sb-path=live/soccer" title="Sportsbook" style="width: 100%; height: 100vh; border: 0"></iframe>Hosted Environment URLs
| Environment | iframe src base URL |
|---|---|
| QA | https://betting-qa.sportsmodity.com |
| Dev | https://betting-dev.sportsmodity.com |
| Mexico QA | https://betting-qa-mxce1.sportsmodity.com |
| Mexico demo | https://betting-demo-mxce1.sportsmodity.com |
| Mexico staging | https://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¤cy=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
- The hosted page loads and calls
Sportsbook.mount()with environment defaults. - Query parameters override those defaults at mount time.
sb-pathcontrols 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
| Works | Does not work |
|---|---|
sb-path, language, authToken, currency, themeId, tenantRef, and layout flags through the URL | Custom brand colors with --sb-* CSS variables |
Automatic sb-resize messages to the parent | Host-wired onRequireLogin callbacks |
| Deep linking through the iframe URL | Parent 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.
| Environment | sportsbook.js URL |
|---|---|
| QA | https://betting-qa.sportsmodity.com/sportsbook.js |
| Dev | https://betting-dev.sportsmodity.com/sportsbook.js |
| Mexico QA | https://betting-qa-mxce1.sportsmodity.com/sportsbook.js |
| Mexico demo | https://betting-demo-mxce1.sportsmodity.com/sportsbook.js |
| Mexico staging | https://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
| Parameter | Required | Values / notes |
|---|---|---|
tenantRef | Yes | Tenant identifier provided during integration setup. |
authToken | No | Player session token. Required for authenticated betting. |
language | No | en, en-GB, en-US, or ja. Default: en. |
currency | No | Wallet currency code, for example USD or GCOIN. |
themeId | No | dark, light, or system. |
isUsLayout | No | true enables US-style layout. Default: false. |
isTestMode | No | true enables test API behavior. |
hostElementSelector | No | Default: #sportsbookRoot. Only change this if you use a different container id. |
styles.appHeight | No | For example 100% or 800px. Sets --sb-app-height. |
styles.background | No | HSL components only. Sets the page background. |
styles.classnames.betslip.trigger | No | Extra CSS classes on the betslip open button. |
styles.classnames.betslip.content | No | Extra CSS classes on the betslip drawer. |
topMenu | No | Array of search, home, live, my-bets, all-sports, and dynamic. |
onRequireLogin | No | Called when the user must log in. Use this to notify the parent page. |
onSessionExpiredReload | No | Called when the sportsbook session expires. |
onLoad | No | Called when the sportsbook has finished loading. |
getBalance | No | Async function returning the current player balance. |
hideLoading | No | true 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
| Variable | What it controls | Default dark theme |
|---|---|---|
--sb-background | Page background | 220 27.27% 6.47% |
--sb-foreground | Main text | 0 0% 100% |
--sb-card | Cards and panels | 216 19% 11% |
--sb-card-foreground | Text on cards | 0 0% 100% |
--sb-popover | Popovers and dropdowns | 240 10% 4% |
--sb-popover-foreground | Popover text | 0 0% 100% |
--sb-muted | Muted backgrounds | 206 13% 22% |
--sb-muted-foreground | Secondary text | 218 11% 65% |
--sb-border | Borders | 0 0% 17% |
--sb-input | Input borders and fills | 0 0% 17% |
--sb-ring | Focus rings | 216 11% 82% |
--sb-radius | Corner radius | 8px |
Brand and Actions
| Variable | What it controls | Default dark theme |
|---|---|---|
--sb-primary | Primary buttons and links | 244 80% 55% |
--sb-primary-foreground | Text on primary | 0 0% 10% |
--sb-secondary | Secondary surfaces | 216 11% 82% |
--sb-secondary-foreground | Text on secondary | 0 0% 100% |
--sb-accent | Accent highlights | 60 100% 50% |
--sb-accent-foreground | Text on accent | 0 0% 100% |
--sb-destructive | Errors and delete actions | 4 100% 62% |
--sb-destructive-foreground | Text on destructive | 0 0% 100% |
--sb-success | Success states | 147 72% 52% |
--sb-success-foreground | Text on success | 220 27% 6% |
--sb-warning | Warning states | 43 74% 66% |
Odds Buttons
| Variable | What it controls | Default dark theme |
|---|---|---|
--sb-outcome | Unselected odds button background | 225 4% 32% |
--sb-outcome-foreground | Unselected odds text | 0 0% 100% |
--sb-selection | Selected odds button background | 251 70% 56% |
--sb-selection-foreground | Selected odds text | 0 0% 100% |
Betslip Panel
| Variable | What it controls | Default dark theme |
|---|---|---|
--sb-betslip-body-background | Betslip background | 228 29% 97% |
--sb-betslip-body-foreground | Betslip text | 0 0% 10% |
--sb-betslip-body-muted | Muted areas | 220 13% 91% |
--sb-betslip-body-muted-foreground | Muted text | 220 9% 46% |
--sb-betslip-body-card | Cards inside betslip | 0 0% 100% |
--sb-betslip-body-border | Betslip borders | 217 12% 84% |
--sb-betslip-body-input | Input backgrounds | 0 0% 100% |
--sb-betslip-body-input-foreground | Input text | 0 0% 10% |
--sb-betslip-body-success | Success in betslip | 136 76% 30% |
--sb-betslip-body-warning | Warning in betslip | 43 75% 66% |
--sb-betslip-body-error | Error in betslip | 4 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.
type | Payload | When |
|---|---|---|
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.
| Event | How to get it | Suggested message |
|---|---|---|
| Login required | onRequireLogin | { type: 'sportsbook:requireLogin' } |
| Session expired | onSessionExpiredReload | { type: 'sportsbook:sessionExpired' } |
| App loaded | onLoad | { type: 'sportsbook:loaded' } |
Inbound Messages
Parent-to-sportsbook postMessage is not supported. You cannot post a message to change language, route, or sport selection.
| Goal | Supported approach |
|---|---|
| Change language | Change the iframe URL language query parameter and reload. |
| Deep link to a page or sport | Set sb-path on the iframe URL. |
| Update auth after login | Remount with a new authToken, or use a custom iframe page with token lookup logic. |
Authentication
The host system owns player authentication and token issuance.
- Your backend authenticates the player and issues a sportsbook auth token.
- The iframe page calls
Sportsbook.mount({ tenantRef, authToken, currency, language }). - The sportsbook calls
GET /api/v1/launch/{tenantRef}?authToken={token}. - The response establishes the player session used for bets and My Bets.
| Field | Type | Description |
|---|---|---|
sessionRef | string | Player session for bets and My Bets. |
displayName | string | Player display name. |
balance | number | Wallet balance. |
currency | string | Wallet currency. |
oddsFormat | enum | Player 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¤cy=USD&themeId=dark&tenantRef=YOUR_TENANT&authToken=TOKEN&sb-path=live/soccerQuery 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 route | sb-path value | Description |
|---|---|---|
/ | Omit the param or use an empty value. | Home / featured. |
/search | search | Search. |
/live | live | Live 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-bets | my-bets | Bet history. |
/match/{matchId} | match/{matchId} | Match detail, for example match/123456. |
/match/{matchId}-{teams} | match/{matchId}-home-vs-away | Match detail with optional SEO slug. |
/sweepnow | sweepnow | Sweepstakes 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/482453When 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 key | Type | Valid values | Effect |
|---|---|---|---|
language | string | en, en-GB, en-US, ja | UI language and API culture. |
currency | string | For example USD or GCOIN. | Wallet currency. |
tenantRef | string | Your tenant ref. | Required for launch. |
authToken | string | Session token. | Authenticated session. Avoid logging this value. |
themeId | enum | dark, light, system | Color preset. |
isUsLayout | boolean | true | Enables 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 key | Values | Effect |
|---|---|---|
content-only | Presence only. | My Bets renders without outer chrome for embedded panel mode. |
Example:
?sb-path=my-bets&content-onlyLanguages
| Code | Notes |
|---|---|
en | English, generic. |
en-GB | English, UK. |
en-US | English, US. |
ja | Japanese. 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.