Switchfly Widgets Integration Guide (1.0.0)
Download OpenAPI specification:
Embeddable travel widgets for partner sites.
Search Widget: Full-featured travel search (air, hotel, car, activities, bundles)

Hotel Deals Widget: Showcase featured hotel deals with click-through to booking
The Switchfly Search Widget is a comprehensive travel search solution that adapts to your brand and customer needs. It provides a consistent, accessible user experience across all product types while offering extensive customization options for visual styling, language support, and product availability.
Supported Languages
The widget includes built-in translations for English, French, Spanish, and Japanese. All UI text, labels, error messages, and validation prompts are automatically localized based on the locale parameter.

Custom Product Tabs
Product tabs are fully configurable—control which travel products appear (bundles, air, hotel, car, activities) and in what order. You can also inject custom external tabs (e.g., "Cruises" or "Deals") at specific positions within the tab row.

Branding & Theming
Colors, accents, and interactive states can be customized using branding tokens. The widget supports hex, RGB, HSL, and CSS variable formats, allowing seamless integration with your existing design system.

Search Errors & Validation
The widget includes comprehensive client-side validation and displays server-side errors returned from the booking platform. Error messages are localized and presented in accessible modal dialogs with clear messaging and recovery options.

Datepicker & UX Patterns
All date selection uses a consistent, compact datepicker interface with range highlighting, constraint enforcement (minimum/maximum dates, product-specific rules), and keyboard navigation support. Time selection is enabled for product types that require it (e.g., car rentals).

⚠️ IMPORTANT: targetUrl is Required
All Switchfly widgets require an explicit targetUrl parameter. Widgets will not function and will display a configuration error if targetUrl is not provided.
targetUrlspecifies your booking platform domain (e.g.,https://your-booking-site.com)- Widgets use
targetUrlas the base URL for API calls and search result navigation - Widgets do not default to any Switchfly environment - this prevents accidental requests to internal/test systems
- Both script embed and iframe embed modes require
targetUrl
SSO-Gated Loyalty Clients: For booking platforms protected by SSO (Single Sign-On), widgets work seamlessly *when configured properly to do so within Switchfly). When a user submits a search, the platform preserves the originally requested search URL through the SSO authentication flow and automatically redirects the user back to their search results after successful login. NOTE This is currently only supported for Switchfly's Standard Loyalty SSO.
- **Minimum supported width: 300px (below that, layout may stack / truncate)
- **Recommended embed width: 360px+
Widget Host vs Target URL
When integrating Switchfly widgets, it's important to distinguish between two URLs:
Widget Host (
your-cdn.com): The domain where widget HTML pages and JavaScript assets (IIFE bundle) are served from. This is used in:- Script embed:
<script src="https://your-cdn.com/dist/switchfly-widgets.iife.js"> - Iframe embed:
<iframe src="https://your-cdn.com/widgets/search/...">
- Script embed:
Target URL (
targetUrl): The booking/search platform domain where the widget redirects users when they submit a search. This is configured as:- Script embed:
targetUrl: 'https://your-booking-site.com'(JavaScript config property) - Iframe embed:
targetUrl=https%3A%2F%2Fyour-booking-site.com(URL parameter, URL-encoded)
- Script embed:
In most deployments, the widget host and target URL are the same domain (e.g., both https://your-booking-site.com). However, they can be different if widgets are hosted on a separate CDN.
Direct Script Embed (Search Widget)
Load the widget bundle and call createSearchWidget():
<div id="search-widget"></div>
<script src="https://your-cdn.com/dist/switchfly-widgets.iife.js"></script>
<script>
SwitchflyWidgets.createSearchWidget({
containerId: 'search-widget',
targetUrl: 'https://your-booking-site.com',
locale: 'en',
cobrand: 'partner123',
searchParam: '|city:7321',
prefillDestinationLabel: 'San Diego',
searchDateFormat: 'dd/mm/yy',
customTab1Label: 'Cruises',
customTab1Url: 'https://example.com/cruises',
customTab1Position: 'last',
branding: {
tokens: {
accentColor: '#0a66c2'
}
}
});
</script>
Iframe Embed (Search Widget)
<iframe
src="https://your-cdn.com/widgets/search/?targetUrl=https%3A%2F%2Fyour-booking-site.com&locale=en&searchParam=%7Ccity:7321&prefillDestinationLabel=San%20Diego&cobrand=partner123&searchDateFormat=dd/mm/yy&customTab1Label=Cruises&customTab1Url=https://example.com/cruises&customTab1Position=last&accentColor=%230a66c2"
width="100%"
height="600"
frameborder="0">
</iframe>
Direct Script Embed (Hotel Deals Widget)
<div id="hotel-deals"></div>
<script src="https://your-cdn.com/dist/switchfly-widgets.iife.js"></script>
<script>
SwitchflyWidgets.createHotelDealsWidget({
containerId: 'hotel-deals',
targetUrl: 'https://your-booking-site.com',
locale: 'en',
maxItems: 6,
showPrices: true,
title: 'Featured Hotels',
branding: {
tokens: {
accentColor: '#dc2626'
}
}
});
</script>
Iframe Embed (Hotel Deals Widget)
<iframe
src="https://your-cdn.com/widgets/hotelDeals/?targetUrl=https%3A%2F%2Fyour-booking-site.com&locale=en&maxItems=6&accentColor=%23dc2626"
width="100%"
height="600"
frameborder="0">
</iframe>
postMessage API
Widgets communicate with parent windows via postMessage for various events:
Widget → Parent Messages:
SWF_WIDGET_HEIGHT- Height changed (for iframe auto-resize)swf.widgets.search.navigate- Navigation request (required for sandboxed iframes)swf.widgets.search.error.dismissed- User dismissed error dialog
Parent → Widget Messages:
swf.widgets.search.configure- Inject error display (see Error Handling section)
Complete Parent Page Snippet (Iframe Embed):
var iframe = document.getElementById('search-widget-iframe');
// Parse ERROR_MESSAGE from URL on page load
var urlParams = new URLSearchParams(window.location.search);
var errorCode = urlParams.get('ERROR_MESSAGE');
// Send error to widget on load if present
if (errorCode) {
iframe.addEventListener('load', function() {
iframe.contentWindow.postMessage({
type: 'swf.widgets.search.configure',
payload: {
error: {
code: errorCode,
clearOnDismiss: true
}
}
}, '*');
});
}
// Listen for widget messages
window.addEventListener('message', function(event) {
// Validate origin matches iframe src
try {
var iframeOrigin = new URL(iframe.src).origin;
if (event.origin !== iframeOrigin) return;
} catch (e) {
return;
}
var data = event.data;
// Auto-resize iframe
if (data && data.type === 'SWF_WIDGET_HEIGHT') {
var height = parseInt(data.height, 10);
if (height > 0) {
iframe.style.height = height + 'px';
}
}
// Handle navigation requests (required for sandboxed iframes)
if (data && data.type === 'swf.widgets.search.navigate') {
var targetUrl = data.payload && data.payload.url;
var openInNewTab = data.payload && data.payload.openInNewTab;
if (targetUrl) {
if (openInNewTab) {
window.open(targetUrl, '_blank');
} else {
window.location.assign(targetUrl);
}
}
}
// Clear error params when dismissed
if (data && data.type === 'swf.widgets.search.error.dismissed') {
var url = new URL(window.location);
url.searchParams.delete('ERROR_MESSAGE');
window.history.replaceState({}, '', url);
}
});
Sandboxed Iframe Navigation (HubSpot, etc.)
Problem: Some CMS platforms (like HubSpot) render iframes in sandboxed contexts without the allow-top-navigation permission. When the widget tries to navigate via window.top.location.href, the browser throws a security error.
Solution: The widget automatically detects iframe mode and sends navigation requests via postMessage instead of attempting direct navigation. The parent page listener performs the actual navigation.
How It Works:
- Widget detects it's running in an iframe (
window.self !== window.top) - On search submit, widget sends
swf.widgets.search.navigatemessage to parent - Parent listener validates origin and performs navigation via
window.location.assign()
Message Format:
{
type: 'swf.widgets.search.navigate',
payload: {
url: 'https://booking-site.com/shopping?...', // Full search URL
reason: 'submit', // Always 'submit' for now
openInNewTab: false // true if Cmd/Ctrl+Click
}
}
Configuration Options:
useParentNavigation(boolean, default: auto-detect) - Force postMessage navigation even for non-iframe embedspostMessageOrigin(string, default:'*') - Target origin for postMessage (more secure than wildcard)
Example with Custom Origin:
SwitchflyWidgets.createSearchWidget({
containerId: 'search-widget',
targetUrl: 'https://your-booking-site.com',
useParentNavigation: true,
postMessageOrigin: 'https://your-parent-site.com'
});
URL Parameter Notes
- Colors must be URL-encoded (
#0a66c2→%230a66c2) cobrandparameter becomesnav=<value>in the final booking search URL- Only include parameters you want to override (all are optional)
- Destination prefill with numeric city IDs:
- Use
searchParam=|city:7321(URL-encoded:%7Ccity:7321) for the canonical token - Also provide
prefillDestinationLabel=San%20Diegofor display - Typeahead API cannot resolve numeric city IDs, so the label is required
- Airport codes (e.g.,
|airport:LAS) don't need a label—they resolve via typeahead
- Use
- Custom tabs:
- Supports up to 2 custom tabs with external URLs
- Custom tab URL is required for tab to render; label defaults to "Link" if omitted
- Position options:
first,last, orafter:<product>(e.g.,after:air) - Custom tabs open in new tab with
noopener,noreferrer - Custom tabs never become the active product tab
- Search date format:
- Use
searchDateFormatto control how dates are formatted in the Core deep-link URL (date1/date2 params) - Options:
mm/dd/yy(default),dd/mm/yy,yy/mm/dd,yyyy/mm/dd - This ONLY affects the URL format sent to the booking platform
- Does NOT change datepicker UI, on-screen date display, or locale-based formatting
- Use
Switchfly widgets support two integration methods:
- Iframe embed (recommended): simplest integration and maximum isolation from host page styles/scripts.
- Direct script embed (IIFE): renders inline on the host page for tighter visual integration.
Both methods are supported out of the gate. Hosting of the widget IIFE and the API proxy approach will be documented once finalized.
When users submit a search, the widget generates a deep-link URL to the booking platform with search parameters.
Traveler Representation:
All search URLs use room_info as the canonical traveler data format:
room_infois a JSON payload containing rooms, adults, children, child ages, seniors, and infants- The JSON is URL-encoded before being added to the search URL
- Example structure:
{"rooms":[{"numAdults":2,"numSeniors":0,"numInfantsInSeats":0,"numInfantsInLaps":0,"childAges":[8,12]}]} - Legacy traveler parameters (
adults,children,child_ageN,infantN) are no longer used
Product Type Flags: Search URLs also include product type flags to indicate the search intent:
air1=true- Air searchroom1=true- Hotel searchcar1=true- Car searchactivity1=true- Activity search
Other Parameters:
See individual widget configuration parameters for marketing/tracking parameters (discount_code, utm_source, etc.)
When a search fails on the booking platform, the user may be redirected back to the host page with an error parameter (e.g., ?ERROR_MESSAGE=NO_ROOMS_FOUND). The widget provides a postMessage API for the host page to inject and display these errors.
Flow Overview
- Parent page detects error: Parse
ERROR_MESSAGEfrom the URL query string - Parent sends error to widget: Use postMessage to send a
swf.widgets.search.configuremessage with error payload - Widget displays error: Shows error message in a modal dialog using existing UI components
- User dismisses error: Widget sends
swf.widgets.search.error.dismissedmessage back to parent - Parent clears error: Remove
ERROR_MESSAGEfrom URL usinghistory.replaceState()
Message Types
swf.widgets.search.configure (Parent → Widget)
Inject configuration including optional error display.
window.frames[0].postMessage({
type: 'swf.widgets.search.configure',
payload: {
error: {
code: 'NO_ROOMS_FOUND', // Required: error code
searchUrl: 'https://...', // Optional: reconstructed search URL
clearOnDismiss: true // Optional: whether to notify parent (default: true)
}
}
}, '*');
swf.widgets.search.error.dismissed (Widget → Parent)
Notification that the user dismissed the error dialog.
window.addEventListener('message', function(event) {
if (event.data.type === 'swf.widgets.search.error.dismissed') {
const errorCode = event.data.payload.code;
// Clear ERROR_MESSAGE from URL
const url = new URL(window.location);
url.searchParams.delete('ERROR_MESSAGE');
window.history.replaceState({}, '', url);
}
});
Supported Error Codes
The widget maps error codes to localized user-facing messages. If an unknown code is provided, the DEFAULT message is shown.
| Error Code | English Message |
|---|---|
DATE_TOO_FAR_IN_ADVANCE |
"The date is too far in advance. Please try again." |
DEFAULT |
"An unexpected error has occurred. Please try your search again." |
INTERNAL_ERROR |
"An unexpected error has occurred. Please try your search again." |
SESSION_ERROR |
"Your session has encountered an error. Please try your search again." |
THIRD_PARTY_ERROR |
"We are having problems communicating with our suppliers. Please try your search again." |
NO_FLIGHTS_FOUND |
"No available flights were found. Please adjust your search and try again." |
NO_ROOMS_FOUND |
"There are no rooms available during the dates you have selected. Please try different dates or destination." |
NO_CARS_FOUND |
"There are no cars available during the dates you have selected. Please try different dates or destination." |
NO_ACTIVITIES_FOUND |
"There are no activities available during the dates you have selected. Please try different dates or destination." |
SEARCH_LOCATION_NOT_FOUND |
"The search location was not found." |
All error messages are translated for all widget-supported languages (en, fr, es, ja).
Parent Page Implementation Example
<iframe id="search-widget-iframe" src="https://your-cdn.com/widgets/search/" width="100%" height="600"></iframe>
<script>
// On page load, check for ERROR_MESSAGE parameter
const urlParams = new URLSearchParams(window.location.search);
const errorCode = urlParams.get('ERROR_MESSAGE');
if (errorCode) {
// Wait for iframe to load
const iframe = document.getElementById('search-widget-iframe');
iframe.addEventListener('load', function() {
// Send error to widget
iframe.contentWindow.postMessage({
type: 'swf.widgets.search.configure',
payload: {
error: {
code: errorCode,
clearOnDismiss: true
}
}
}, '*');
});
}
// Listen for error dismissal
window.addEventListener('message', function(event) {
if (event.data.type === 'swf.widgets.search.error.dismissed') {
// Clear ERROR_MESSAGE from URL
const url = new URL(window.location);
url.searchParams.delete('ERROR_MESSAGE');
window.history.replaceState({}, '', url);
}
});
</script>
Replace the default Location API autocomplete with fixed location lists from your own JSON data. Useful for airlines with restricted route networks or when you want to limit search options to specific airports/cities.
Display Modes
Static locations support two display modes:
dropdown(default): Custom dropdown showing all items with icons. Best for small lists (5-15 items). Users click to open and scroll to find their location.typeahead: Autocomplete-style input with client-side filtering. Best for larger lists (20+ items). Users type to filter locations instantly (no network calls).
Script Embed with JSON URL
<div id="search-widget"></div>
<script src="https://your-cdn.com/dist/switchfly-widgets.iife.js"></script>
<script>
SwitchflyWidgets.createSearchWidget({
containerId: 'search-widget',
targetUrl: 'https://your-booking-site.com',
staticLocationsUrl: 'https://cdn.example.com/locations.json',
staticLocationsDisplayMode: 'typeahead' // Optional: 'dropdown' (default) or 'typeahead'
});
</script>
Script Embed with Inline JSON
<div id="search-widget"></div>
<script src="https://your-cdn.com/dist/switchfly-widgets.iife.js"></script>
<script>
SwitchflyWidgets.createSearchWidget({
containerId: 'search-widget',
targetUrl: 'https://your-booking-site.com',
staticLocationsDisplayMode: 'dropdown', // Optional: 'dropdown' or 'typeahead'
staticLocations: {
origins: [
{ displayValue: "Tokyo (TYO)", search: "|airport:TYO", locationType: "AIRPORT" },
{ displayValue: "Osaka", search: "|city:27562", locationType: "CITY" }
],
destinations: [
{ displayValue: "Los Angeles (LAX)", search: "|airport:LAX", locationType: "AIRPORT" },
{ displayValue: "San Francisco (SFO)", search: "|airport:SFO", locationType: "AIRPORT" }
]
}
});
</script>
Iframe Embed with JSON URL
<iframe
src="https://your-cdn.com/widgets/search/?targetUrl=https%3A%2F%2Fyour-booking-site.com&staticLocationsUrl=https%3A%2F%2Fcdn.example.com%2Flocations.json&staticLocationsDisplayMode=typeahead"
width="100%"
height="600"
frameborder="0">
</iframe>
Note: staticLocationsDisplayMode is optional. Defaults to dropdown if omitted.
Iframe Embed with postMessage (Dynamic)
<iframe id="search-widget" src="https://your-cdn.com/widgets/search/?targetUrl=https%3A%2F%2Fyour-booking-site.com" width="100%" height="600" frameborder="0"></iframe>
<script>
window.addEventListener('load', () => {
document.getElementById('search-widget').contentWindow.postMessage({
type: 'swf.widgets.search.configure',
payload: {
staticLocationsDisplayMode: 'typeahead', // Optional: 'dropdown' or 'typeahead'
staticLocations: {
origins: [
{ displayValue: "Tokyo (TYO)", search: "|airport:TYO", locationType: "AIRPORT" }
],
destinations: [
{ displayValue: "Los Angeles (LAX)", search: "|airport:LAX", locationType: "AIRPORT" }
]
}
}
}, 'https://your-cdn.com');
});
</script>
JSON Format
{
"origins": [
{
"displayValue": "Tokyo Haneda (HND)",
"search": "|airport:HND",
"locationType": "AIRPORT"
},
{
"displayValue": "Osaka",
"search": "|city:27562",
"locationType": "CITY"
}
],
"destinations": [
{
"displayValue": "Los Angeles (LAX)",
"search": "|airport:LAX",
"locationType": "AIRPORT"
}
]
}
Field Descriptions:
origins: Array of origin locations (optional - if omitted, origin field uses autocomplete)destinations: Array of destination locations (optional - if omitted, destination field uses autocomplete)displayValue: Text shown to user (e.g., "Tokyo (TYO)" or "Osaka")search: Search token sent to Core Shopping (format: "|airport:CODE" or "|city:ID")locationType: Must be "AIRPORT" or "CITY" (determines icon shown)
Display Mode Behavior:
dropdown(default): Custom dropdown with SVG icons. Shows all items at once. Best for small lists (5-15 items).typeahead: Autocomplete-style input with client-side filtering. User types to filter. Best for larger lists (20+ items). No network calls - instant filtering.
Notes:
- You can provide only
origins, onlydestinations, or both - Fields not in staticLocations fall back to autocomplete
- For car rentals, both pickup and dropoff use
destinationsarray - Invalid location items are logged to console and skipped
- Display mode applies to all static location fields in the widget
- Static locations are NOT filtered by product type - The same location list is shown for all product types (air, hotel, car, activity, bundle). This differs from API autocomplete mode, which filters results based on product type. Ensure your static locations are appropriate for all product types you're offering, or consider using API autocomplete for product-specific filtering.
Feature a specific hotel on search results or redirect directly to hotel details page. Useful for marketing campaigns, email newsletters, or partner sites promoting individual properties.
Feature Hotel on Search Results
Pass hotel_id to highlight/feature a specific hotel in search results:
Script Embed:
<div id="search-widget"></div>
<script src="https://your-cdn.com/dist/switchfly-widgets.iife.js"></script>
<script>
SwitchflyWidgets.createSearchWidget({
containerId: 'search-widget',
targetUrl: 'https://your-booking-site.com',
hotel_id: '12345'
});
</script>
Iframe Embed:
<iframe
src="https://your-cdn.com/widgets/search/?targetUrl=https%3A%2F%2Fyour-booking-site.com&hotel_id=12345"
width="100%"
height="600"
frameborder="0">
</iframe>
Redirect to Hotel Details Page
Combine hotel_id with redirect_to_hotel_details to bypass search results and go directly to the hotel details page:
Script Embed:
<div id="search-widget"></div>
<script src="https://your-cdn.com/dist/switchfly-widgets.iife.js"></script>
<script>
SwitchflyWidgets.createSearchWidget({
containerId: 'search-widget',
targetUrl: 'https://your-booking-site.com',
hotel_id: '12345',
redirect_to_hotel_details: true
});
</script>
Iframe Embed:
<iframe
src="https://your-cdn.com/widgets/search/?targetUrl=https%3A%2F%2Fyour-booking-site.com&hotel_id=12345&redirect_to_hotel_details=true"
width="100%"
height="600"
frameborder="0">
</iframe>
Notes:
hotel_idis passed through to the booking URL ashotel_idparameterredirect_to_hotel_detailsonly works whenhotel_idis also provided- These parameters work for all search types (not just hotel searches)
- The hotel ID format should match your booking platform's hotel identifier format
Feature a specific activity on search results or redirect directly to activity details page. Activities require both an activity ID and a CRS (provider/system identifier) such as "viator", "expedia", "getyourguide", etc.
Feature Activity on Search Results
Pass activity_id and activity_crs to highlight/feature a specific activity in search results:
Script Embed:
<div id="search-widget"></div>
<script src="https://your-cdn.com/dist/switchfly-widgets.iife.js"></script>
<script>
SwitchflyWidgets.createSearchWidget({
containerId: 'search-widget',
targetUrl: 'https://your-booking-site.com',
activity_id: '12345',
activity_crs: 'viator'
});
</script>
Iframe Embed:
<iframe
src="https://your-cdn.com/widgets/search/?targetUrl=https%3A%2F%2Fyour-booking-site.com&activity_id=12345%3Aviator"
width="100%"
height="600"
frameborder="0">
</iframe>
Redirect to Activity Details Page
Combine activity_id, activity_crs, and redirect_to_activity_details to bypass search results and go directly to the activity details page:
Script Embed:
<div id="search-widget"></div>
<script src="https://your-cdn.com/dist/switchfly-widgets.iife.js"></script>
<script>
SwitchflyWidgets.createSearchWidget({
containerId: 'search-widget',
targetUrl: 'https://your-booking-site.com',
activity_id: '12345',
activity_crs: 'viator',
redirect_to_activity_details: true
});
</script>
Iframe Embed:
<iframe
src="https://your-cdn.com/widgets/search/?targetUrl=https%3A%2F%2Fyour-booking-site.com&activity_id=12345%3Aviator&redirect_to_activity_details=true"
width="100%"
height="600"
frameborder="0">
</iframe>
Notes:
- CRS is required: Unlike hotels, activities always require a CRS (provider identifier)
- In iframe mode, combine ID and CRS using colon format:
activity_id=12345:viator - In script embed mode, provide
activity_idandactivity_crsas separate properties activity_idis passed through to the booking URL asactivity_idparameter inid:crsformatredirect_to_activity_detailsonly works whenactivity_idis also provided- These parameters work for all search types (not just activity searches)
- Common CRS values: "viator", "expedia", "getyourguide", etc.
The notes below call out CMS-specific considerations. Unless stated otherwise, iframe embed is the recommended approach.
HubSpot
- Recommended: Iframe embed in a Custom HTML module
- Supported: Direct script embed (subject to HubSpot script/CSP restrictions)
- Allowlist the widget host domain (for example,
your-cdn.com) in Content Security Policy (CSP) if needed - Listen for
SWF_WIDGET_HEIGHTto resize iframe dynamically - URL-encode all color parameters (
#→%23)
Wix
- Recommended: Iframe embed via HTML Embed or Custom Element
- Supported: Direct script embed
- For iframe: Set an explicit height (for example, 600px) or use an auto-height script
- Ensure the iframe
srcdomain (or script source domain) is allowlisted - URL-encode all color parameters (
#→%23)
Webflow
- Recommended: Iframe embed via Custom Code component
- Supported: Direct script embed
- For iframe: Set an explicit height or add a resize listener via postMessage
- URL-encode all color parameters (
#→%23)
Squarespace
- Recommended: Iframe embed using a Code Block
- Supported: Direct script embed
- For iframe: Set an explicit height (Squarespace does not support dynamic iframe resizing)
- Ensure the iframe
srcdomain (or script source domain) is allowlisted - URL-encode all color parameters (
#→%23)
WordPress
- Recommended: Iframe embed using Custom HTML block
- Supported: Direct script embed
- For script embeds, some themes or security plugins may block inline scripts
- For iframe: Set an explicit height or handle resizing via postMessage
- URL-encode all color parameters (
#→%23)
Shopify
- Recommended: Iframe embed using Custom HTML section or Liquid template
- Supported: Direct script embed
- Script embeds may require adding the widget domain to Shopify’s allowed script sources
- For iframe: Set an explicit height or implement postMessage-based resizing
- URL-encode all color parameters (
#→%23)
Search Widget HTML (iframe entrypoint)
Serves the search widget HTML page for iframe embedding.
All parameters are optional and override widget defaults.
Example with branding:
/widgets/search/?locale=fr&cobrand=partner123&accentColor=%230a66c2&bgColorWidget=%23ffffff
Example with destination prefill (numeric city ID):
/widgets/search/?searchParam=%7Ccity:7321&prefillDestinationLabel=San%20Diego
Example with custom tabs:
/widgets/search/?customTab1Label=Cruises&customTab1Url=https://example.com/cruises&customTab1Position=last
query Parameters
| locale | string Example: locale=en Widget locale (e.g., en, es, fr, ja) |
| searchParam | string Example: searchParam=%7Cairport:LAS Pre-fill destination search token (format: "|airport:CODE" or "|city:ID"). Examples:
For numeric city IDs, also provide |
| prefillDestinationLabel | string Example: prefillDestinationLabel=San Diego Optional display label for pre-filled destination. Required when using numeric city ID tokens (e.g., "|city:7321") because the Locations typeahead API cannot resolve numeric IDs. The widget will display this label in the destination input while sending the canonical token to Core Shopping on submit. Not needed for airport codes (e.g., "|airport:LAS") as those resolve via typeahead API. |
| cobrand | string Example: cobrand=partner123 Cobrand identifier (becomes nav= in booking URL) |
| searchDateFormat | string Default: "mm/dd/yy" Enum: "mm/dd/yy" "dd/mm/yy" "yy/mm/dd" "yyyy/mm/dd" Example: searchDateFormat=dd/mm/yy Date format for Core deep-link URL (date1/date2 query params). This only affects the format of dates sent to the booking platform—it does NOT change the datepicker UI or any on-screen date display. Options: mm/dd/yy, dd/mm/yy, yy/mm/dd, yyyy/mm/dd |
| availableProducts | string Example: availableProducts=bundle,air,hotel Comma-separated list of available product types for the search widget tab set. Valid values: bundle, air, hotel, car, activity Order matters—tabs will render in the order specified. Invalid values are ignored. If all values are invalid or parameter is empty, falls back to default: bundle,air,hotel,car,activity Bundle Tab Behavior: When the bundle tab is active, this parameter also controls which bundle package pills are displayed. For example, if availableProducts excludes "car", then bundle pills like "Flight+Hotel+Car" and "Hotel+Car" will be hidden. Only bundle combinations using available products will be shown. |
| defaultProductType | string Enum: "bundle" "air" "hotel" "car" "activity" Example: defaultProductType=bundle Default product type to display on widget load. Must be one of the values in availableProducts. If invalid or not in availableProducts list, defaults to first item in availableProducts. |
| customTab1Label | string Example: customTab1Label=Cruises Label for first custom tab (e.g., "Cruises") |
| customTab1Url | string Example: customTab1Url=https://example.com/cruises URL for first custom tab. Required for tab to render. Opens in new tab when clicked with noopener and noreferrer. |
| customTab1Position | string Default: "last" Enum: "first" "last" "after:bundle" "after:air" "after:hotel" "after:car" "after:activity" Example: customTab1Position=last Position for first custom tab in tab row. Options: "first", "last", "after:bundle", "after:air", "after:hotel", "after:car", "after:activity" |
| customTab2Label | string Example: customTab2Label=Deals Label for second custom tab |
| customTab2Url | string Example: customTab2Url=https://example.com/deals URL for second custom tab. Required for tab to render. Opens in new tab when clicked with noopener and noreferrer. |
| customTab2Position | string Default: "last" Enum: "first" "last" "after:bundle" "after:air" "after:hotel" "after:car" "after:activity" Example: customTab2Position=after:air Position for second custom tab in tab row. Options: "first", "last", "after:bundle", "after:air", "after:hotel", "after:car", "after:activity" |
| discountCode | string Example: discountCode=SUMMER2026 Discount code for promotional pricing.
Passed through to booking URL as |
| currency | string^[A-Z]{3}$ Example: currency=USD Currency code for price display (3-letter ISO 4217 code, e.g., USD, EUR, GBP).
Passed through to booking URL as |
| languageId | integer Example: languageId=3 Numeric language identifier for booking platform.
Passed through to booking URL as |
| utmSource | string Example: utmSource=newsletter UTM source parameter for campaign tracking.
Passed through to booking URL as |
| utmMedium | string Example: utmMedium=email UTM medium parameter for campaign tracking.
Passed through to booking URL as |
| utmCampaign | string Example: utmCampaign=summer_sale_2026 UTM campaign parameter for campaign tracking.
Passed through to booking URL as |
| utmContent | string Example: utmContent=hero_banner UTM content parameter for A/B testing and content differentiation.
Passed through to booking URL as |
| trackId | integer Example: trackId=1234 The agent ID of the referring agent.
Passed through to booking URL as |
| bgColorWidget | string Example: bgColorWidget=%23ffffff Background color (URL-encoded) |
| highlightColor | string Example: highlightColor=%23eef2ff Highlight color for focus/hover states (URL-encoded) |
| accentColor | string Example: accentColor=%230a66c2 Primary accent color (URL-encoded) |
| accentColorHover | string Example: accentColorHover=%23004182 Accent hover color (URL-encoded) |
| accentColorActive | string Example: accentColorActive=%23003366 Accent active/pressed color (URL-encoded) |
Responses
Widget CDN (placeholder - replace with your actual CDN)
QA environment (example)
Hotel Deals Widget HTML (iframe entrypoint)
Serves the hotel deals widget HTML page for iframe embedding.
All parameters are optional and override widget defaults.
Example with branding:
/widgets/hotelDeals/?locale=en&maxItems=6&accentColor=%23dc2626
query Parameters
| locale | string Example: locale=en Widget locale (e.g., en, es, fr, ja) |
| maxItems | integer [ 1 .. 12 ] Example: maxItems=6 Maximum number of hotels to display (1-12) |
| showPrices | boolean Example: showPrices=true Display hotel prices in tiles |
| currency | string^[A-Z]{3}$ Example: currency=USD Currency code for price display (3-letter ISO 4217 code, e.g., USD, EUR, GBP).
Passed through to booking URL as |
| title | string Example: title=Featured Hotels Widget title heading |
| cobrand | string Example: cobrand=partner123 Cobrand identifier (becomes nav= in booking URL) |
| searchParam | string Example: searchParam=%7Cairport:LAS Pre-fill destination search token (format: "|airport:CODE" or "|city:ID"). Examples:
For numeric city IDs, also provide |
| bgColorWidget | string Example: bgColorWidget=%23ffffff Background color (URL-encoded) |
| highlightColor | string Example: highlightColor=%23eef2ff Highlight color for focus/hover states (URL-encoded) |
| accentColor | string Example: accentColor=%230a66c2 Primary accent color (URL-encoded) |
| accentColorHover | string Example: accentColorHover=%23004182 Accent hover color (URL-encoded) |
| accentColorActive | string Example: accentColorActive=%23003366 Accent active/pressed color (URL-encoded) |
Responses
Widget CDN (placeholder - replace with your actual CDN)
QA environment (example)
