Skip to main content

How to integrate a bsport widget on Wix

Step-by-step guide to adding a bsport widget to a Wix site, why the Embed HTML element causes problems, and the recommended Custom Code method.

Wix offers two ways to add a bsport widget to your site. Both work, but they behave very differently — and the one Wix suggests first is the one behind most of the problems studios report. This article walks you through both methods, explains the Wix limitations behind those problems, and shows how to avoid them.

Would you rather we set it up for you? The recommended method (Method 2) involves adding custom code to your Wix site. If you would like us to implement it, contact bsport support and send us a collaborator invitation to your Wix site (in Wix: Settings → Roles & Permissions). We will take it from there.

Before you start

Generate your widget code in the bsport back office: Settings → Widgets, choose the widget type, configure your options, then scroll down and copy the code. Every time you change a setting a new code is generated, and you have to paste the new version onto your site for the change to take effect.

Method 1 — Embed HTML element (quick, with limits)

  1. In the Wix Editor, click Add Elements → Embed Code → Embed HTML

  2. Drag the element onto the page where you want the widget

  3. Click Enter Code and paste your widget code

  4. Resize both the element on desktop and mobile mode and Publish

What to know before choosing this method: the iframe

Wix automatically places anything added with the Embed HTML element inside an iframe — a fixed-size frame that does not grow with its content. This is how Wix is built, not something in the widget, and it causes four recurring problems:

  • The widget is confined to a fixed-size box. It cannot grow beyond the size you set for the element, and it cannot adapt to its surroundings, even though the widget itself is responsive.

  • Scrolling breaks on mobile and tablet. If the content is taller than the frame, visitors often cannot scroll to reach it — a touch swipe inside a fixed-height iframe is usually picked up by the page rather than the frame. This is the most frequently reported symptom.

  • Popups and dialogs are trapped. A session detail or checkout dialog can only cover the frame, not the page, so it may appear cut off.

  • Tracking does not reach your page. Events the widget sends stay inside the frame, so Google Tag Manager or other analytics on your Wix site will not see them.

If you encounter any of these problems, we advise to use Method 2.

Calendar on Wix: keep the Embed HTML element and fix it

If you are adding the calendar widget and want to keep the Embed HTML element — for example so you can still place it with drag-and-drop in the Wix Editor — you can fix its two main iframe problems with a few extra scripts:

  • the calendar being cut off when its height changes (for example when switching weeks)

  • booking and description pop-ups opening too far above or below the visitor's screen

This option requires a connected domain and a premium Wix plan. It does not make widget events visible to Google Tag Manager — for that, use Method 2.

Method 2 — Custom Code (recommended)

This places the widget in the page itself rather than in a frame. It then expands to its natural height, scrolls with the page, opens dialogs over the full page, and its events are visible to your tracking.

Important: widgets added this way are not moved with drag-and-drop. The widget does not appear as an element in the Wix Editor, so you cannot drag it into place or resize it there. Instead, its position is set in the code: you tell the code which section of the page to place the widget in (the targetSelector, explained below). To move the widget later, you change that value in the code.

Steps

  1. Go to your Wix dashboard → Settings → Custom Code

  2. Click Add Custom Code

  3. Paste the code below, after replacing the values described in Values to replace

  4. Under Add Code to Pages, choose the specific page rather than all pages

  5. Set Place Code in to Body - end

  6. Give it a name you will recognise later, then Apply and Publish

The code

<script>
(function() {
'use strict';

// ─── SHARED CDN LOADER ───
function loadCDN() {
if (!window._bsportCDNPromise) {
window._bsportCDNPromise = new Promise((resolve) => {
if (window.BsportWidget) return resolve();
if (!document.getElementById('bsport-widget-cdn')) {
const script = document.createElement('script');
script.id = 'bsport-widget-cdn';
script.src = 'https://cdn.bsport.io/scripts/widget.js';
script.onload = resolve;
document.head.appendChild(script);
} else {
const interval = setInterval(() => {
if (window.BsportWidget) { clearInterval(interval); resolve(); }
}, 100);
}
});
}
return window._bsportCDNPromise;
}

// ─── WAIT FOR ELEMENT WITH RETRY ───
function waitForElement(selector, timeout = 15000) {
return new Promise((resolve) => {
// 1. Check immediately
const found = document.querySelector(selector);
if (found) return resolve(found);

// 2. Otherwise observe DOM changes
const observer = new MutationObserver(() => {
const el = document.querySelector(selector);
if (el) {
observer.disconnect();
clearTimeout(timer);
resolve(el);
}
});

observer.observe(document.body, {
childList: true,
subtree: true
});

// 3. Fallback timeout
const timer = setTimeout(() => {
observer.disconnect();
resolve(null);
}, timeout);
});
}

// ─── REUSABLE WIDGET FACTORY ───
function createBsportWidget({ containerId, widgetType, targetSelector, config }) {
let mounted = false;
let mountAttempts = 0;
const maxMountAttempts = 5;

async function addContainer() {
const existing = document.getElementById(containerId);
if (existing) {
return true;
}

const parentContainer = await waitForElement(targetSelector, 15000);
if (!parentContainer) {
return false;
}

const container = document.createElement('div');
container.id = containerId;
parentContainer.appendChild(container);
return true;
}

function mountWidget() {
if (mounted) return;

mountAttempts++;
if (mountAttempts > maxMountAttempts) {
return;
}

loadCDN().then(() => {
const container = document.getElementById(containerId);
if (!container) {
setTimeout(mountWidget, 500);
return;
}

if (typeof window.BsportWidget?.mount !== 'function') {
setTimeout(mountWidget, 500);
return;
}

try {
window.BsportWidget.mount({
parentElement: containerId,
companyId: 1234, // REPLACE with your company ID
franchiseId: null,
dialogMode: 1,
widgetType,
showFab: false,
fullScreenPopup: false,
styles: undefined,
config
});
mounted = true;
} catch (e) {
mounted = false;
setTimeout(mountWidget, 500);
}
});
}

function init() {
async function start() {
const added = await addContainer();
if (added) mountWidget();
}

if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => setTimeout(start, 3000));
} else {
start();
}
}

init();
}

// ─── WIDGET INSTANCES ───
createBsportWidget({
containerId: 'bsport-widget-planning', // REPLACE with a name of your choice
targetSelector: 'main[id="PAGES_CONTAINER"] section > div:nth-child(2) > div', // REPLACE with the section where the widget should appear
widgetType: 'calendar', // REPLACE with your widget type
config: { // REPLACE with the config from your widget code
calendar: {
}
}
});

})();
</script>

Values to replace

  • companyId — replace 1234 with your bsport company ID. You will find it in the widget code generated in your back office.

  • containerId — any name you like for the widget's container, for example bsport-widget-planning. Use a different name for each widget on the same page.

  • widgetType — the type of widget you want to show, for example calendar. Copy it from the widgetType line of your back-office widget code.

  • targetSelector — where the widget appears on the page. This is a CSS selector pointing to the section the widget is added into. To find it, open your published page in Chrome, right-click the section where you want the widget, choose Inspect, then right-click the highlighted element and choose Copy → Copy selector. This is what replaces drag-and-drop: to move the widget, change this value.

  • config — the widget's options. Copy the config object from your back-office widget code so the widget keeps the filters and display options you chose.

To show more than one widget, add another createBsportWidget({ ... }) block under WIDGET INSTANCES, with its own containerId, targetSelector, widgetType and config.

If the widget does not appear where you want it, or you would rather not edit code, contact bsport support and we will set it up for you.

Comparing the two methods

Embed HTML element (drag-and-drop)

  • Easy to position visually in the Wix editor

  • Subject to all the iframe limitations above

  • Fine for a short, fixed-height widget on desktop

Custom Code (injected into the body)

  • No iframe — the widget stretches freely and scrolls with the page

  • Dialogs open over the full page

  • Tracking events reach your site

  • No drag-and-drop: placement is set in the code with targetSelector

Adding the login button to your header

The bsport login button widget cannot be added to a Wix header with drag-and-drop: Wix headers do not accept the Embed HTML element at all.

It can still be done with Method 2. Injecting the login button code into the page body through Settings → Custom Code places it in the header without the iframe wrapper. Because this means positioning the button in code, we usually set it up for you — see How we can help below.

Troubleshooting

Visitors cannot scroll through everything on mobile.
This is the iframe limitation described above. Switch to Method 2.

A popup opens but is cut off.
The widget is inside an iframe. Switch to Method 2 — or, for the calendar widget, see Calendar on Wix above.

Google Tag Manager does not see widget events.
Events cannot leave the iframe. Switch to Method 2.

The widget does not appear with Method 2.
Check that targetSelector points to a section that exists on that page, that the company ID is correct, and that the code is assigned to the right page in Add Code to Pages.

Changes made in the back office are not showing.
The configuration does not update automatically on your site. Copy the newly generated code and replace the old one entirely. With Method 2, update the widgetType and config values in your custom code instead.

The widget looks different from the back-office preview, or does not respond to clicks.
Enable Compatibility Mode in your widget settings, then copy and paste the new code.

Nothing appears at all.
Check the widget has not been added twice — through both an Embed element and Custom Code. Two copies on one page will conflict.

The layout is cramped.
The widget is responsive but needs room. Make sure the section holding it is wide enough, and check the mobile view separately in the Wix editor.

How we can help

Moving to the Custom Code method means making changes inside your Wix site: adding or editing code in Settings → Custom Code, and sometimes adjusting the layout or styling of the page. If you would rather we handle it, we are happy to:

  • Move an existing widget out of the iframe to fix scrolling and popup issues

  • Add the login button to your header via Custom Code

  • Adjust widget sizing, placement and overflow

  • Guide your web developer through the implementation

To do this we need a collaborator invitation to your Wix site (in Wix: Settings → Roles & Permissions). Contact our support team and we will take it from there.

Still stuck? Contact our support team with the page URL and a screenshot, and we'll take a look.

Did this answer your question?