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:

  1. ?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.
  2. Default preset (fallback) - if no ?preset= param is provided, the widget loads a default preset configured for your deployment.
  3. 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=darkbrand_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

FieldTypeDefaultDescription
colorModestring"dark""dark" or "light" (overridable per embed via ?colorMode=)
layoutModestring"carousel""carousel" or "feed" (overridable per embed via ?layoutMode=)
widgetModestring"operator""operator", "affiliate", or "clean". When set in the preset, it takes precedence over the ?widgetMode= iframe param. See Widget Modes.
productModestring"sportsbook""sportsbook", "dfs", or "prediction_market". See Product Modes.
factFlowDisplayTypestring"base""base", "expanded"
oddsTypestring"american""american", "decimal", "fractional", "multiplier", or "probability"
currencystring"USD"Currency code (USD, EUR, GBP, etc.)

Sizing

FieldTypeDefaultDescription
carouselFlowARnumber0.9Aspect ratio for carousel flow cards (up to 3 for short, wide cards)
carouselParlayARnumber0.9Aspect ratio for carousel parlay cards (up to 3)
carouselGapPctnumber3.33Gap between carousel cards (%)
feedFlowARnumber0.9Aspect ratio for feed flow cards (up to 3)
feedParlayARnumber0.9Aspect ratio for feed parlay cards (up to 3)
feedGapPctnumber3.33Gap between feed cards (%)
carouselBorderThicknessPctnumber0.625Card border thickness in carousel (%)
feedBorderThicknessPctnumber0.625Card 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:

FieldTypeDefaultDescription
boldParlayBetNamebooleanfalseBold (700) vs. light (300) parlay-leg bet names
boldDisplayNamebooleantrueWhen 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

FieldTypeDefaultDescription
betslipModestring"static""static" (fixed) or "payout" (adjustable)
betslipBetWordstring"Bet"Label for the bet button
betslipWinWordstring"Win"Label for the win display
betslipConnectorWordstring"to"Connector word between the bet and win amounts
betslipAmountnumber10Default wager amount

Feature Toggles

FieldTypeDefaultDescription
showParlaySubtitlebooleantrueShow parlay subtitle text
showFiltersbooleantrueShow filter chips above the feed
showPaginationbooleantrueShow pagination dots (carousel)
allowOverrideIframeFiltersbooleantrueAllow users to change iframe-set filters
showCountdownbooleantrueShow the countdown-to-game-time clock on cards
showLiveScoresbooleanfalseShow the LIVE pill with period, clock, and score on in-play events. Can be overridden per embed with the showLiveScores iframe param.
showLiveDetailbooleanfalseShow the secondary live-detail strip (sport-specific game state) on in-play events

Container & Page

FieldTypeDefaultDescription
pageBgHexstring"0a0a1a"Page background color (hex without #)
containerBgHexstring"FFFFFF"Container background color
containerBgOpacitynumber2Container background opacity (0–100)
containerBorderHexstring"FFFFFF"Container border color
containerBorderOpacitynumber8Container 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:

FieldDescription
flow_background_hex_1Card background color
subject_name_hexSubject/player name color
matchup_info_hexMatchup info text color
narrative_hexNarrative text color
bet_name_hexBet name text color
tagline_hexTagline text color
odds_value_hexOdds display color
expand_close_hexExpand/close button color
subject_photo_outline_hexPlayer photo border color
bet_placement_button_hex_1CTA button gradient start
bet_placement_button_hex_2CTA button gradient end
bet_placement_cta_text_hexCTA button text color
emoji_outline_hexEmoji container outline (Fun Flow)
emoji_background_hexEmoji container background (Fun Flow)
emoji_glow_hexEmoji glow effect (Fun Flow)
count_down_clock_hexCountdown timer color
flow_border_hex_1Card border color
flow_border_radius_pctCard border radius (%)
custom_brand_fontFont family name
flow_button_radius_pctButton border radius (%)
graph_bar_red_hexRed bar color (Fact Flow)
graph_bar_green_hexGreen bar color (Fact Flow)
graph_bar_neutral_hexNeutral bar color (Fact Flow)
graph_trend_line_hexTrend line color (Fact Flow)
parlay_header_bg_hex_1Parlay header gradient start
parlay_header_bg_hex_2Parlay header gradient end

Each color field has a corresponding _opacity field (0–100). For example, flow_background_hex_1_opacity: 100.

📘

Info

The syncMap object 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 # - use FFFFFF, 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 iframe src
  • 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


Did this page help you?