19 — Booking Engine Integration
PRD Document · Savoy Signature Hotels — Multi-Site Headless Platform
Version: 1.0 · Date: 2026-03-04
Related docs:07_Modules_and_Templates.md(M03 — Booking Bar),03_MultiSite_and_Domains.md
1. Purpose
Section titled “1. Purpose”This document defines the integration between the Savoy Signature headless platform and the external booking systems — Navarino (Bookpoint calendar widget) and Synxis (SHR’s central reservation system). It covers the frontend widget embedding, configuration per hotel, URL redirect logic, and analytics tracking.
2. Booking Flow Overview
Section titled “2. Booking Flow Overview”[!IMPORTANT] The actual booking transaction (payment, reservation confirmation) happens entirely on the Synxis external domain. The Savoy website is responsible only for collecting dates, guest count, and optional promo code, then redirecting.
3. Navarino Bookpoint Widget
Section titled “3. Navarino Bookpoint Widget”3.1 What It Is
Section titled “3.1 What It Is”Navarino provides a JavaScript widget (Bookpoint) that renders a date-picker calendar. It is embedded into the Booking Bar module (M03) as a Client Component.
3.2 Widget Loading
Section titled “3.2 Widget Loading”'use client';
import Script from 'next/script';import { useEffect, useRef } from 'react';
interface BookingBarProps { navarinoHotelCode: string; synxisHotelId: string; synxisBaseUrl: string; locale: string; variant: 'inline' | 'overlay' | 'sticky';}
export function BookingBarClient({ navarinoHotelCode, synxisHotelId, synxisBaseUrl, locale, variant}: BookingBarProps) { const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => { // Initialize Navarino widget after script loads if (window.Bookpoint && containerRef.current) { window.Bookpoint.init({ container: containerRef.current, hotelCode: navarinoHotelCode, language: locale === 'pt' ? 'pt-PT' : 'en-GB', onSubmit: (data) => { // Redirect to Synxis with selected params const params = new URLSearchParams({ hotel: synxisHotelId, arrive: data.checkIn, // YYYY-MM-DD depart: data.checkOut, // YYYY-MM-DD adult: String(data.adults), child: String(data.children || 0), ...(data.promoCode && { promo: data.promoCode }), locale: locale, });
// Track event before redirect window.dataLayer?.push({ event: 'booking_bar_submit', siteKey: 'savoy-palace', hotelCode: navarinoHotelCode, locale, checkIn: data.checkIn, checkOut: data.checkOut, guests: data.adults, });
window.location.href = `${synxisBaseUrl}?${params.toString()}`; }, }); } }, [navarinoHotelCode, synxisHotelId, synxisBaseUrl, locale]);
return ( <section className={`booking-bar booking-bar--${variant}`} data-module="bookingBar" data-module-id={moduleId}> <Script src="https://widget.navarino.co/bookpoint.js" strategy="lazyOnload" onReady={() => { // Widget initialization handled by useEffect }} /> <div ref={containerRef} className="booking-bar__widget" /> </section> );}3.3 Widget Performance
Section titled “3.3 Widget Performance”- Loading: The Navarino script is loaded with
strategy="lazyOnload"to avoid blocking the main thread and LCP. - Bundle impact: The external script is not counted in the site’s JS budget but is monitored via Lighthouse.
- Fallback: If the widget fails to load, a simple HTML form with date inputs and a direct link to Synxis is displayed.
4. Per-Hotel Configuration
Section titled “4. Per-Hotel Configuration”Each hotel has its own Navarino code and Synxis ID, configured in the siteRoot Document Type in Umbraco.
4.1 Umbraco Properties on siteRoot
Section titled “4.1 Umbraco Properties on siteRoot”| Property | Type | Example |
|---|---|---|
navarinoHotelCode | Textstring | SVP |
synxisHotelId | Textstring | 12345 |
synxisBaseUrl | URL | https://be.synxis.com/ |
bookingBarEnabled | Toggle | true |
bookingBarVariant | Dropdown (inline / overlay / sticky) | sticky |
4.2 Configuration Matrix
Section titled “4.2 Configuration Matrix”| Hotel | Navarino Code | Synxis ID | Default Variant |
|---|---|---|---|
| Savoy Palace | SVP | TBD | sticky |
| Royal Savoy | RSV | TBD | sticky |
| Savoy Gardens | TBD | TBD | inline |
| Saccharum | TBD | TBD | sticky |
| Next | TBD | TBD | inline |
| Calheta Beach | TBD | TBD | inline |
| Galosol | TBD | TBD | inline |
| Savoy Signature (Group) | N/A | N/A | N/A (no booking on group site) |
[!NOTE] Navarino and Synxis IDs to be confirmed by the Savoy Signature operations team during the STAGE integration phase.
5. Synxis Redirect URL Structure
Section titled “5. Synxis Redirect URL Structure”The Synxis booking engine expects query parameters in a specific format:
https://be.synxis.com/?hotel={synxisHotelId}&arrive={YYYY-MM-DD}&depart={YYYY-MM-DD}&adult={N}&child={N}&promo={PROMO_CODE}&locale={LOCALE}5.1 Parameter Mapping
Section titled “5.1 Parameter Mapping”| Parameter | Source | Required |
|---|---|---|
hotel | siteRoot.synxisHotelId | ✅ Yes |
arrive | Navarino calendar selection | ✅ Yes |
depart | Navarino calendar selection | ✅ Yes |
adult | Guest counter (default: 2) | ✅ Yes |
child | Guest counter (default: 0) | ❌ Optional |
promo | Promo code input field | ❌ Optional |
locale | Current page locale (pt / en) | ✅ Yes |
6. Booking Bar Variants
Section titled “6. Booking Bar Variants”The Booking Bar module (M03) supports three presentation modes:
| Variant | Behavior | Typical Placement |
|---|---|---|
inline | Rendered within the page content flow | Homepage (below hero), Room listing pages |
overlay | Floats over the hero image, semi-transparent background | Homepage (over hero slider) |
sticky | Fixed to the bottom of the viewport, slides up on scroll | All inner pages (contextual prompt to book) |
7. Special Offers and Promo Codes
Section titled “7. Special Offers and Promo Codes”7.1 CMS-Driven Promotions
Section titled “7.1 CMS-Driven Promotions”Umbraco can define special offer pages with a pre-filled promo code:
// On specialOfferDetailPageconst promoCode = page.properties.promoCode; // e.g., 'SUMMER2026'
// The Booking Bar on this page auto-fills the promo code<BookingBarClient navarinoHotelCode={site.navarinoHotelCode} synxisHotelId={site.synxisHotelId} synxisBaseUrl={site.synxisBaseUrl} locale={locale} variant="inline" defaultPromoCode={promoCode} // Pre-filled/>7.2 URL-Based Promo Codes
Section titled “7.2 URL-Based Promo Codes”Marketing campaigns can pass promo codes via URL query string:
https://savoysignature.com/savoy-palace/pt?promo=SUMMER2026The proxy.ts or page component extracts the promo param and passes it to the Booking Bar.
8. Acceptance Criteria
Section titled “8. Acceptance Criteria”- Navarino Bookpoint widget loads and initializes correctly on all 7 hotel sites (not group site).
- Widget respects the page locale (
pt-PToren-GB). - Date selection redirects to Synxis with all required query parameters.
-
booking_bar_submitdataLayer event fires before redirect. - Promo code field pre-fills from CMS or URL query string.
-
stickyvariant is visible on scroll and does not overlap content or navigation. - Fallback HTML form is shown if Navarino script fails to load.
- Booking Bar is not rendered on the Savoy Signature group site.
Next document: 20_Roadmap_and_Phases.md