Skip to main content

17 — Embeddable Booking Widget Specification

Surface: Drop-in JavaScript widget for tenant external sites (WordPress, Wix, custom) Phase: P2 / R2 Competitive reference: SiteMinder Booking Engine, Cloudbeds Booking Widget, Mews Distributor, Rezdy


1. Overview​

Many tenants keep their existing marketing website (WordPress, Wix, Squarespace) and want to embed Melmastoon's booking funnel as a widget — "powered by Melmastoon" — without redirecting to a separate URL.

Embedding model: A lightweight <script> snippet added to the tenant's site. The widget renders inside an <iframe> (shadow-DOM isolation is not used — iframe provides better CSP/CORS isolation).


2. Snippet format​

Tenants add to their website:

<div id="melmastoon-widget"></div>
<script src="https://widget.melmastoon.com/v1/embed.js"
data-tenant="hotel-kabul-palace"
data-lang="ps"
data-currency="AFN"
data-theme="light"
async>
</script>

That's it. The script handles everything else.


3. Widget modes​

ModeDescriptiondata-mode value
Search bar (default)Compact search bar (dates + guests + "Check availability") that expands to full funnelsearch-bar
Full funnelFull booking flow embedded in the host pagefull-funnel
Availability calendarMonthly calendar showing available dates and lowest rateavailability-calendar
Floating buttonFixed "Book now" button that opens a modal with the search barfloating-button

4. Iframe vs shadow-DOM decision​

Decision: iframe

ConsiderationIframeShadow DOM
CSS isolation✅ Complete✅
Host page style bleed✅ None⚠️ Can leak through custom properties
Communication with hostpostMessageDirect JS
CSP compliance✅ iframe src allowlisted⚠️ Shadow DOM is in same origin
Third-party cookie handlingManaged by widget domainSame-origin; easier
Tenant custom fontsLoaded inside iframeLoaded inside shadow root

Tradeoff: iframe's postMessage communication is slightly more complex but provides complete isolation, which is the correct choice for a third-party embed.


5. Theming inheritance​

The widget loads tenant theme tokens from theme-config-service using the data-tenant attribute. Theme tokens are applied inside the iframe — the host page's CSS does not affect the widget.

Host page background adaptation: The widget iframe's background color can be set to transparent (via allow-transparent attribute) so the widget blends with the host page's background. Font is always the tenant's configured font, not the host page font.


6. postMessage protocol​

The embed.js script communicates with the iframe via postMessage:

// Host page → iframe
{ type: 'WIDGET_CONFIG', payload: { lang, currency, theme } }
{ type: 'WIDGET_RESIZE', payload: { width, height } }

// Iframe → host page
{ type: 'BOOKING_STARTED', payload: { search: { checkin, checkout, guests } } }
{ type: 'BOOKING_COMPLETE', payload: { booking_reference, total } }
{ type: 'WIDGET_HEIGHT_CHANGE', payload: { height: number } } // for auto-resize
{ type: 'BOOKING_ABANDONED', payload: { step, reason } }

Auto-resize: The iframe posts WIDGET_HEIGHT_CHANGE whenever its content height changes. The embed.js script resizes the <iframe> element on the host page accordingly, eliminating double scrollbars.


7. Conversion telemetry​

All standard booking funnel telemetry events (from C1-telemetry-event-dictionary.md) fire inside the iframe. The embed.js script additionally fires host-page events via window.postMessage for host-page analytics (GA4, GTM):

window.dataLayer?.push({ event: 'melmastoon_booking_complete', booking_reference: '...' });

8. CSP requirements​

Tenants' sites need to allowlist:

Content-Security-Policy:
frame-src https://widget.melmastoon.com;
script-src https://widget.melmastoon.com;
connect-src https://api.melmastoon.com;

embed.js includes a helper comment explaining the CSP additions required.


9. Accessibility​

The widget iframe has title="Melmastoon hotel booking". All content inside the iframe meets WCAG 2.2 AA (same as 13-tenant-booking-web-specification.md). The widget does not trap keyboard focus outside the iframe when closed.


10. Performance budgets​

MetricTarget
embed.js size≤ 10 kB gzipped
Widget initial render (search bar)≤ 1.5 s
Widget full funnel load≤ 2.5 s

11. Distribution​

Widget CDN: https://widget.melmastoon.com/v1/embed.js — immutable versioned URL at v1. Breaking changes require v2.

Tenants access their snippet in the operator desktop app under Settings → Direct booking → Widget embed code.


References​