Presets
Presets are JSON files that capture all theme and layout settings for the widget. Partners design presets in the playground and deploy them for production use.
How Preset Loading Works
In production, the widget loads your theme from a remote URL at startup. The Odditt team configures the preset hosting for your deployment.
Loading Priority
The widget resolves its theme in this order:
?preset=query param (highest priority) - when present in the iframe URL, the widget fetches the corresponding preset JSON file. This lets you control the theme per embed.- Default preset (fallback) - if no
?preset=param is provided, the widget loads a default preset configured for your deployment. - Built-in defaults - if no preset is configured, the widget renders with built-in default colors.
Mode-Specific Preset Files
When the iframe URL includes both ?colorMode= and ?layoutMode= alongside ?preset=, the widget first looks for a mode-specific file named {preset}_{layoutMode}_{colorMode}.json (e.g. ?preset=brand&layoutMode=feed&colorMode=dark → brand_feed_dark.json) and falls back to the bare {preset}.json if it doesn't exist. This lets you ship one preset name with per-mode variants. The ?colorMode= and ?layoutMode= params always override the mode values stored inside the loaded preset.
Production Deployment
Step 1: Design in the Playground
Use the playground to design and save your theme. Saved presets follow your playground login across browsers and devices.
Step 2: Deploy from the Playground
Click 🚀 Deploy on a saved preset. The playground publishes it to your instance's Odditt-managed preset hosting and shows you a ready-to-open test URL (https://your-instance.odditt.com?preset=your-preset-name) so you can preview it live immediately. No hosting setup on your side.
Prefer to self-host? You can also download the preset JSON and serve it from your own servers - tell the Odditt team and we'll point your instance at your hosting location instead.
Step 3: Promote to Default (optional)
Once a preset is approved, ask the Odditt team to promote it to your instance's default - after that, embeds with no ?preset= param load it automatically.
Step 4: Embed with Preset
<iframe
src="https://widget.example.com/?preset=brand_dark_v2"
width="100%"
height="480"
frameborder="0"
style="border: none;"
></iframe>The widget fetches the corresponding preset file based on the ?preset= value. For example, ?preset=brand_dark_v2 loads brand_dark_v2.json from your configured preset hosting location.
Multiple Presets
A single production instance can serve different themes by changing the ?preset= query param:
<!-- Dark theme -->
<iframe src="https://widget.example.com/?preset=brand_dark_v2" ...></iframe>
<!-- Light theme -->
<iframe src="https://widget.example.com/?preset=brand_light_v1" ...></iframe>
<!-- Sport-specific -->
<iframe src="https://widget.example.com/?preset=nba_special" ...></iframe>Preset JSON Structure
The downloaded .json file contains all theme and configuration settings. All fields are optional - only provided values override defaults.
{
"funFlowDark": { "flow_background_hex_1": "062b53", "..." : "..." },
"funFlowLight": {},
"factFlowDark": {},
"factFlowLight": {},
"plainFlowDark": {},
"plainFlowLight": {},
"syncMap": {},
"colorMode": "dark",
"layoutMode": "carousel",
"factFlowDisplayType": "base",
"carouselFlowAR": 0.9,
"carouselParlayAR": 0.9,
"carouselGapPct": 3.33,
"feedFlowAR": 0.9,
"feedParlayAR": 0.9,
"feedGapPct": 3.33,
"carouselBorderThicknessPct": 0.625,
"feedBorderThicknessPct": 0.625,
"oddsType": "american | decimal | fractional | multiplier | probability",
"currency": "USD",
"betslipMode": "static",
"betslipBetWord": "Bet",
"betslipWinWord": "Win",
"betslipAmount": 10,
"showParlaySubtitle": true,
"showFilters": true,
"showPagination": true,
"allowOverrideIframeFilters": true,
"containerBgHex": "FFFFFF",
"containerBgOpacity": 2,
"containerBorderHex": "FFFFFF",
"containerBorderOpacity": 8,
"pageBgHex": "0a0a1a"
}Top-Level Settings
| Field | Type | Default | Description |
|---|---|---|---|
colorMode | string | "dark" | "dark" or "light" (overridable per embed via ?colorMode=) |
layoutMode | string | "carousel" | "carousel" or "feed" (overridable per embed via ?layoutMode=) |
widgetMode | string | "operator" | "operator", "affiliate", or "clean". When set in the preset, it takes precedence over the ?widgetMode= iframe param. See Widget Modes. |
productMode | string | "sportsbook" | "sportsbook", "dfs", or "prediction_market". See Product Modes. |
factFlowDisplayType | string | "base" | "base", "expanded" |
oddsType | string | "american" | "american", "decimal", "fractional", "multiplier", or "probability" |
currency | string | "USD" | Currency code (USD, EUR, GBP, etc.) |
Sizing
| Field | Type | Default | Description |
|---|---|---|---|
carouselFlowAR | number | 0.9 | Aspect ratio for carousel flow cards (up to 3 for short, wide cards) |
carouselParlayAR | number | 0.9 | Aspect ratio for carousel parlay cards (up to 3) |
carouselGapPct | number | 3.33 | Gap between carousel cards (%) |
feedFlowAR | number | 0.9 | Aspect ratio for feed flow cards (up to 3) |
feedParlayAR | number | 0.9 | Aspect ratio for feed parlay cards (up to 3) |
feedGapPct | number | 3.33 | Gap between feed cards (%) |
carouselBorderThicknessPct | number | 0.625 | Card border thickness in carousel (%) |
feedBorderThicknessPct | number | 0.625 | Card border thickness in feed (%) |
Scale & Typography Keys
Seventeen optional *Scale multipliers (number, default 1) fine-tune individual element sizes on top of the card's base unit - useful when a wider aspect ratio (shorter card) shouldn't shrink every element in lockstep. Spacing: spaceSectionScale, spaceLegScale, spaceListScale. Fonts: fontNarrativeScale, fontNameScale, fontBetScale, fontOddsScale, fontParlayHeaderScale, fontMatchupScale, fontCountdownScale, fontLegNumberScale, fontTaglineScale, fontSplitScale, fontExpandScale, fontGraphLabelScale, fontUserCountScale, sgpFontScale. A value of 1 renders identically to a preset that omits the key.
Two weight toggles accompany them:
| Field | Type | Default | Description |
|---|---|---|---|
boldParlayBetName | boolean | false | Bold (700) vs. light (300) parlay-leg bet names |
boldDisplayName | boolean | true | When false, flattens all subject/player name weights to 400. Omitting the key keeps each card's built-in weight - only an explicit false changes rendering. |
All of these are set visually in the playground's per-element size controls and land in the downloaded preset JSON automatically.
Betslip
| Field | Type | Default | Description |
|---|---|---|---|
betslipMode | string | "static" | "static" (fixed) or "payout" (adjustable) |
betslipBetWord | string | "Bet" | Label for the bet button |
betslipWinWord | string | "Win" | Label for the win display |
betslipConnectorWord | string | "to" | Connector word between the bet and win amounts |
betslipAmount | number | 10 | Default wager amount |
Feature Toggles
| Field | Type | Default | Description |
|---|---|---|---|
showParlaySubtitle | boolean | true | Show parlay subtitle text |
showFilters | boolean | true | Show filter chips above the feed |
showPagination | boolean | true | Show pagination dots (carousel) |
allowOverrideIframeFilters | boolean | true | Allow users to change iframe-set filters |
showCountdown | boolean | true | Show the countdown-to-game-time clock on cards |
showLiveScores | boolean | false | Show the LIVE pill with period, clock, and score on in-play events. Can be overridden per embed with the showLiveScores iframe param. |
showLiveDetail | boolean | false | Show the secondary live-detail strip (sport-specific game state) on in-play events |
Container & Page
| Field | Type | Default | Description |
|---|---|---|---|
pageBgHex | string | "0a0a1a" | Page background color (hex without #) |
containerBgHex | string | "FFFFFF" | Container background color |
containerBgOpacity | number | 2 | Container background opacity (0–100) |
containerBorderHex | string | "FFFFFF" | Container border color |
containerBorderOpacity | number | 8 | Container border opacity (0–100) |
Per-Flow Color Themes
The six flow theme objects (funFlowDark, funFlowLight, factFlowDark, factFlowLight, plainFlowDark, plainFlowLight) share the same structure. Key color fields:
| Field | Description |
|---|---|
flow_background_hex_1 | Card background color |
subject_name_hex | Subject/player name color |
matchup_info_hex | Matchup info text color |
narrative_hex | Narrative text color |
bet_name_hex | Bet name text color |
tagline_hex | Tagline text color |
odds_value_hex | Odds display color |
expand_close_hex | Expand/close button color |
subject_photo_outline_hex | Player photo border color |
bet_placement_button_hex_1 | CTA button gradient start |
bet_placement_button_hex_2 | CTA button gradient end |
bet_placement_cta_text_hex | CTA button text color |
emoji_outline_hex | Emoji container outline (Fun Flow) |
emoji_background_hex | Emoji container background (Fun Flow) |
emoji_glow_hex | Emoji glow effect (Fun Flow) |
count_down_clock_hex | Countdown timer color |
flow_border_hex_1 | Card border color |
flow_border_radius_pct | Card border radius (%) |
custom_brand_font | Font family name |
flow_button_radius_pct | Button border radius (%) |
graph_bar_red_hex | Red bar color (Fact Flow) |
graph_bar_green_hex | Green bar color (Fact Flow) |
graph_bar_neutral_hex | Neutral bar color (Fact Flow) |
graph_trend_line_hex | Trend line color (Fact Flow) |
parlay_header_bg_hex_1 | Parlay header gradient start |
parlay_header_bg_hex_2 | Parlay header gradient end |
Each color field has a corresponding _opacity field (0–100). For example, flow_background_hex_1_opacity: 100.
InfoThe
syncMapobject controls which color fields are synced across flow types when the sync feature is used in the playground.
Troubleshooting
Preset Not Loading
- Check that the
?preset=value matches the filename without.json - Ensure the JSON file is publicly accessible (try opening the URL in a browser)
- Check the browser console / network tab for fetch errors
- Confirm the JSON is valid
- Contact the Odditt team to verify your preset hosting is correctly configured
Colors Not Applying
- Hex values must not include
#- useFFFFFF, not#FFFFFF - Opacity values must be between 0 and 100
- Verify you customized the correct flow type tab (Fun/Fact/Plain) and color mode (dark/light)
Widget Shows Defaults
- The
?preset=query parameter is missing from the iframesrc - The preset hosting may not be configured yet - contact the Odditt team
- The preset file returns a non-200 response (404, CORS error, etc.)
Next Steps
- Playground - design and export your theme
- Iframe Parameters - combine presets with filters and entity scoping
Updated about 15 hours ago

