CDN script tag
Install any Medos widget with a single script tag from the CDN: deferred, at the end of the body, or loaded on demand in a single-page app.
The CDN bundle is a self-contained IIFE. It ships React, MUI, and every other dependency inside the bundle, so you don't need a build step.
The script tag
<script src="https://widgets.medos.one/v2/unified.js"></script>This is the production endpoint. It's the same URL for every site — there's nothing to configure per environment.
The other bundles
unified.js is the booking widget, and the rest of this page is about it. The
other widgets are separate scripts with the same loading
rules — load only what a page uses, since each carries its own copy of React:
| Widget | Script | Global |
|---|---|---|
| Booking | https://widgets.medos.one/v2/unified.js | window.MedosBooking |
| Patient portal | https://widgets.medos.one/v2/portal.js | window.MedosPatientPortal |
| Enquiry form | https://widgets.medos.one/v2/enquiries.js | window.MedosEnquiry |
| Package purchase | https://widgets.medos.one/v2/packages.js | window.MedosPackagePurchase |
What's inside
The bundle includes React 19, MUI v7, TanStack Query, Zustand, and every other runtime dependency, so there's nothing else to install.
It's roughly 970 KB uncompressed, served gzipped from CloudFront with a
one-year immutable cache (max-age=31536000). Because the URL is versioned,
returning visitors get it straight from cache.
Where to put the tag
These patterns are the same for every widget — swap in the script and global from the table above.
<!-- At the end of <body>, before the code that calls init() -->
<script src="https://widgets.medos.one/v2/unified.js"></script><!-- In <head>; the global is ready by the time DOMContentLoaded fires -->
<script defer src="https://widgets.medos.one/v2/unified.js"></script>// For SPAs that only need a widget on some routes. Resolves with the global,
// and skips the request if the script has already loaded.
function loadMedos(src, globalName) {
return new Promise((resolve, reject) => {
if (window[globalName]) return resolve(window[globalName]);
const s = document.createElement("script");
s.src = src;
s.onload = () => resolve(window[globalName]);
s.onerror = reject;
document.head.appendChild(s);
});
}
const MedosBooking = await loadMedos(
"https://widgets.medos.one/v2/unified.js",
"MedosBooking",
);After it loads
The bundle exposes exactly one global:
interface Window {
MedosBooking: {
init: (config: MedosBookingConfig) => void;
open: (config?: Partial<MedosBookingConfig>) => void;
close: () => void;
};
}Every option and callback is documented in
Configure options. The other bundles each expose their own
global with the same init / open / close shape — except the package
widget, which has init only. See Widgets.
Checking the script actually loaded
If MedosBooking is undefined at runtime, the script failed to load. Add an
error handler to the tag:
<script
src="https://widgets.medos.one/v2/unified.js"
onerror="console.error('Medos Booking failed to load')"
></script>