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