Skip to content

Integration

The betting frame allows seamless integration into partner websites, providing a complete betting experience with customization options for theming, localization, and event handling. The integration can be done either as a Single Page Application (SPA) or with Server-Side Rendering (SSR), depending on your needs.

Configuration options

AppInitOptions

AppInitOptions is the top-level configuration object, which has the following structure:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
interface AppInitOptions {
  token: string;
  locale: string;
  currency: string;
  rootElement: string;
  isAuthorized: boolean;
  url: BettingUrl;
  features: Record<FeatureKeys, boolean>;
  theme: Theme;
  defaultSettings: DefaultSettings;
}
Property Description Type Required
token Token of the current player Token string yes
locale Selected language Locale code yes
currency Currency code in the ISO:4217 format string yes
rootElement Identifier of the DOM element in which betting will be embedded string yes
isAuthorized Player's authorization status boolean yes
url All endpoints for betting BettingUrl yes
features A set of Features that are responsible for connecting various SPA functionality. Record<FeatureKeys, boolean> no
defaultSettings Default settings for the SPA. DefaultSettings yes

BettingURL contains all the necessary endpoints for the SPA:

1
2
3
4
5
interface BettingUrl {
  gqlEndpoint: string;
  staticEndpoint: string;
  basename: string;
}
Property Description Type Required
gqlEndpoint Path to the GraphQL server string yes
staticEndpoint Path to the server where all the statistics are stored (js/css/assets) string yes
basename The basename field is used to specify the base URL for all relative links within the embedded betting. This is particularly useful when the application is deployed within a subdirectory of a domain. string yes

Features

The SPA provides an option for enabling or disabling various new, or experimental features:

  • IS_MEMORY_ROUTER uses MemoryRouter instead of BrowserRouter, allowing internal navigation within the SPA without changing the site's URL

Default settings

DefaultSetting options are used to set the initial configuration of the application.
They define default values for various settings, such as display odds, which can later be changed by gambler.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
interface DefaultSettings {
  oddFormat: OddFormat;
  oddAcceptStrategy: OddAcceptStrategy;
}

type OddFormat =
  | "Decimal"
  | "Fractional"
  | "US"
  | "HongKong"
  | "Indo"
  | "Malay";

type OddAcceptStrategy = "acceptAll" | "acceptHigher" | "alwaysAsk";
Property Description Type Default value Required
oddFormat Default odd format for the SPA. OddFormat Decimal false
oddAcceptStrategy Default odd accept strategy for the SPA. OddAcceptStrategy acceptAll false

SPA Integration

To integrate the betting SPA into your product, follow these steps:

1. Add DOM containers

You must include the following elements in your HTML layout:

  • Main container — this is where the entire betting application will be rendered:
    1
    <div id="betting__container"></div>
    
  • Betslip containers — separate element for betslip views:
1
<div id="betting-betslip"></div>

Note

These elements must exist in the DOM before initializing the SPA

2. Add the bootstrap script

Include the script for the appropriate environment. Use the staging version during development and testing, and production for live deployment.

  • Production:
    1
    2
    3
    4
    5
    <script
      type="module"
      defer
      src="https://spa.databet.cloud/v2/<project-name>/bootstrap.js"
    ></script>
    
  • Staging: `html

` !!! note

1
  This links will be provided by data.bet

Note

type="module" is required attribute

3. Initialize the application

Once the script has loaded, a global object bettingLoader becomes available on the window. Use its load method to start the SPA:

1
2
3
4
5
6
interface BettingLoader {
  load: (
    options: AppInitOptions,
    onLoad: (bettingAPI: BettingAPI) => void
  ) => void;
}

Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<div id="betting__container"></div>
<div id="betting-betslip"></div>

<script
  type="module"
  async
  src="https://spa.databet.cloud/v2/<project-name>/bootstrap.js"
  onload="loadBetting()"
></script>
<script>
  function loadBetting() {
    bettingLoader.load(
      {
        url: {
          staticEndpoint: `<link to static>`, // will be provided by data.bet
          gqlEndpoint: "<link to api endpoint>", // will be provided by data.bet
          basename: "/",
        },
        token: `<token>`,
        locale: "uk",
        currency: "usd",
        rootElement: "betting__container",
        isAuthorized: true,
        theme: {
          palette: {
            colorsPrimary1: "#000000",
            colorsPrimary2: "#ffffff",
            colorsSecondary1: "#f3f3f3",
            colorsSecondary2: "#e3e3e3",
            colorsSecondary3: "#9999a1",
            colorsAccent1: "#ff6b00",
            colorsAccent2: "#ffb700",
            colorsAccent3: "#a900d9",
            textButton: "#ffffff",
            textPrimary: "#000000",
            textSecondary: "#656565",
            notificationBlocked: "#b5b5b5",
            notificationError: "#ff3e33",
            notificationInfo: "#0852ff",
            notificationSuccess: "#05BC0B",
            notificationWarning: "#ff9000",
          },
        },
        defaultSettings: {
          oddFormat: "Decimal",
        },
      },
      (bettingAPI) => {
        // use bettingAPI to interact with spa on runtime
      }
    );
  }
</script>

Important

Changes to the token, locale, or currency require a page reload to take effect. This limitation is expected to be resolved in future updates.

4.Style the betslip containers

!!! Migration from integration two dedicated containers

The SPA renders betslip view into dedicated container, depending on screen size:

React Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<script>

  type IStypeBetslip = Pick<ToggleWidgetBetslipPayload, "breakpoint" | "isOpen">;

  const BetslipStyleGetter: Record<
    "static" | "island",
    (data: IStypeBetslip) => string
  > = {
    static: ({ isOpen, breakpoint }: IStypeBetslip): string => {
      if (breakpoint === "mobile") {
        if (isOpen) {
          document.body.classList.add("overflow-hidden");
          return "fixed bottom-0 left-0 top-0 z-40 lg:hidden w-full h-full";
        } else {
          document.body.classList.remove("overflow-hidden");

          return "fixed bottom-0 left-0 -z-40 w-full";
        }
      }

      if (breakpoint === "tablet") {
        return "fixed top-0 left-auto right-0 z-40 h-[100vh]";
      }

      return "";
    },
    island: ({ isOpen, breakpoint }): string => {
      if (breakpoint === "mobile") {
        if (isOpen) {
          document.body.classList.add("overflow-hidden");
          return "fixed bottom-0 left-0 top-0 z-40 lg:hidden w-full h-full max-h-full";
        } else {
          document.body.classList.remove("overflow-hidden");

          return "fixed bottom-0 left-0 z-40 w-full";
        }
      }
      if (breakpoint === "tablet") {
        return "fixed inset-x-1/2 bottom-0 z-[999999] w-full max-w-[320px] max-h-[100vh] -translate-x-1/2";
      }
      return "fixed inset-x-1/2 bottom-0 z-[999999] w-full max-w-[320px] max-h-[80vh] -translate-x-1/2";
    },
  };

  const BetslipContainer: FC = () => {
    const [state, setState] = useState<ToggleWidgetBetslipPayload | undefined>();

    const initBetting = useCallback(() => {
      if (!window.bettingAPI) return;

      window.bettingAPI.subscribe("toggle-widget-betslip", setState);
    }, []);

    useEffect(() => {
      document.addEventListener("betting-init", initBetting);

      return () => document.removeEventListener("betting-init", initBetting);
    }, [initBetting]);

    const getter = state
      ? BetslipStyleGetter[state.widgetType] || BetslipStyleGetter["static"]
      : undefined;

    const className = state && getter
      ? getter({ isOpen: state.isOpen, breakpoint: state.breakpoint })
      : "";

    return <div id="betting-betslip" className={className}></div>;
  };
</script>

Again, feel free to adapt this styling for your layout — e.g., adjusting height or position to avoid overlapping your app’s header or sidebar.

SSR Integration

Note

Support for server-side rendering (SSR) is currently under development. Stay tuned for updates in future releases.