Bookmaker Odds Comparison

Bookmaker Odds Comparison

The bookmakerOddsComparison widget renders a per-event 1x2 odds-comparison table across multiple bookmaker brands, served from the per-event snapshot pre-aggregated by the odds-pipeline-worker. Each row is a clickable affiliate link (/go/<cloakedLink>) wrapping logo + brand name + the 1 / X / 2 price cells.

Key features:

  • Cross-provider odds: one row per configured brand, side-by-side prices for the 1, X, and 2 outcomes. Inactive brands are hidden entirely (no greyed-out rows).
  • Two config approaches: point the widget at a Sanity-managed config with configid (recommended), or pass the config inline as a configuration JSON. configid takes precedence — see below.
  • Localized names + logos: team / competition names render translated (and with logos) for the visitor’s locale when the matching Sanity team / league doc is linked to its odds entity; otherwise the canonical name shows and no logo is used.
  • Event / competition subtitles: optional eventsubtitle / competitionsubtitle attributes, surfaced as meta.eventSubtitle / meta.competitionSubtitle.
  • Affiliate-funnel CTA: each row is a single semantic <a> to the brand’s cloaked tracking link. Optional widget-level CTA button via ctakey / ctatext.
  • Tracking-link strategy (tlTarget): switch between the default Vulcan cloaked links and the RBO legacy-id links without changing anything else.
  • Two markets (market): 1x2 (1 / X / 2 columns) or a tournament outright (one column per outcome – e.g. World Cup Winner) set via the market field in the config. See the Outright section at the bottom of this page.

Whichever config approach you use, the display / behaviour attributes — CTA (ctakey / ctatext), ctacolors / ctahovercolors, tlTarget, rel, target, anchorid, eventsubtitle, competitionsubtitle, country, language — always live as top-level attributes on the tag, never inside the configuration JSON. (rel and target control the affiliate anchors. rel accepts only nofollow or follow — any other value, or omitted, becomes nofollow. target accepts a standard anchor target such as _blank or _self — any other value, or omitted, becomes _blank.)


Configuring the widget: configid vs configuration

There are two ways to give the widget its event + brands, and configid takes precedence over configuration — if both are present, configid wins and configuration is ignored:

Approach Where the config lives Use when
configid (recommended) A Sanity Bookmaker Odds config document, referenced by its slug. internalEventId, market, brands, title, subtitle are loaded from Sanity at render time. Editorial-managed placements — editors curate the event + brands in Sanity; the page only carries the slug.
configuration (inline / legacy) A JSON object on the tag: internalEventId, market, brands, and optional title / subtitle. Ad-hoc / hard-coded placements, or where no Sanity config document exists.

⚠️ Precedence, and no silent fallback. When configid is present the widget resolves it from Sanity and does not fall back to configuration. A configid that doesn’t resolve renders a clear error (so a wrong slug is obvious) rather than quietly using an inline config. Use one approach per widget.

Localized names + logos are automatic — no attribute needed. When the event’s teams / competition are linked to their odds entity in Sanity (with translations / images), names render localized for the language / country locale and logos become available to the layout; otherwise the widget falls back to the canonical name with no logo.

The recommended setup, shown first: the event + brands + title / subtitle live in the referenced Sanity Bookmaker Odds document; the tag carries the configid slug plus every top-level display attribute. This is a live widget (the referenced config exists in this environment).

Expand me...

All widget attributes — inline configuration

The same widget with the inline configuration JSON instead of a configid, so every config field is visible on the tag. If both configid and configuration are present, configid wins and this JSON is ignored.

Expand me...

The tlTarget top-level attribute controls how every affiliate link in the widget (brand logo, each odds cell, and the BET NOW button) is built:

tlTarget Link form Notes
vulcan (default) /go/<cloakedLink>?country=…&language=…&wid=… Standard Vulcan cloaked-link strategy. Used when tlTarget is omitted.
rbo /go/<legacyId>.html RBO legacy strategy. Uses each brand’s legacyId; no query params are appended.
  • The value is case-insensitive (RBO, Rbo, rbo all work) and any unrecognized value falls back to vulcan.
  • For rbo, each brand’s legacyId is read from the brands[] entry in the configuration JSON (it falls back to the brand’s Sanity reference legacyId when omitted). If no legacyId can be resolved for a brand, that link safely falls back to the Vulcan form.
  • legacyId is ignored when tlTarget is vulcan, so it is harmless to always include it.

Full attributes (all options)

Expand me...

Minimal attributes (defaults applied)

Expand me...

With CTA translation key (resolved server-side via i18n)

Expand me...

With CTA literal text (no translation lookup)

Expand me...

Set tlTarget="rbo" and provide a legacyId for each brand. Every affiliate link in the widget (brand logo, odds cells, and the BET NOW button) is then built as /go/<legacyId>.html instead of the Vulcan /go/<cloakedLink> form.

Expand me...


Outright market (market: "outright")

The same bookmakerOddsComparison widget renders a tournament outright (e.g. World Cup Winner) when market is set to "outright" in the configuration JSON. Instead of fixed 1 / X / 2 columns, each brand row shows that bookmaker’s price for every outcome (one cell per selection – the competing teams or nations), served from the outright snapshot pre-aggregated by the odds-pipeline-worker.

Everything else is identical to the 1x2 market: brands, title / subtitle, ctakey / ctatext, tlTarget, and per-brand legacyId all behave exactly the same. Only two fields differ from the examples above – market is "outright" and internalEventId points at an outright event.

Note: Delasport does not offer outright markets, so these examples use Altenar- and Bahigo-backed brands. A configured brand with no outright price for the event is simply hidden, the same inactive-row behaviour as the 1x2 market.

Outright – full attributes (all options)

Expand me...

Outright – minimal attributes (defaults applied)

Expand me...

Set tlTarget="rbo" and provide a legacyId for each brand. Every affiliate link in the outright table – the brand-logo column headers, every odds cell, and the footer BET NOW buttons – is then built as /go/<legacyId>.html instead of the Vulcan /go/<cloakedLink> form.

Expand me...