airport-one-widgets
v0.2.38
Published
**Integration guide (v2 embed, domains, telemetry, troubleshooting):** [`docs/widget-embed-integration.md`](../../docs/widget-embed-integration.md) (repository root). **Plan your trip rollout/canary checklist:** [`docs/find-your-flight-rollout-checklist.m
Keywords
Readme
Airport One Widgets
Integration guide (v2 embed, domains, telemetry, troubleshooting): docs/widget-embed-integration.md (repository root).
Plan your trip rollout/canary checklist: docs/find-your-flight-rollout-checklist.md.
Fly My Airport FAB local demos: with the widgets dev server running, open /demo/fly-my-airport-fab.html (see root index.html for the full demo menu).
Airfare Search (v2)
The v2 airfare-search widget is an explicit opt-in contract and does not alias from
the v1 flight-search-form tag.
Installation
<script src="https://widgets.flymyairport.com"></script>Usage
<fma-airfare-search
data-widget-instance-id="YOUR_INSTANCE_UUID"
></fma-airfare-search>Required for managed instances:
data-widget-instance-id
Airfare Content
Core Purpose:
- Displays a grid of featured flight deals from a specified origin airport
- Renders within a Shadow DOM for style isolation and encapsulation
- Serves as a reusable widget that can be embedded in different contexts
Installation
To include the airfare-content custom element in your project, add the following script tag to your HTML file:
<script src="https://widgets.flymyairport.com"></script>Usage
To use the fma-airfare-content custom element, simply add the following HTML tag to your markup:
<fma-airfare-content></fma-airfare-content>Portal-managed instance (v2)
For embeds copied from the Airport One portal, bind the host element to a saved widget instance. At build time, set VITE_WIDGET_PUBLIC_CONFIG_API_BASE_URL to the public widget config API origin (no trailing slash), e.g. the Cloud Run widget-api service that serves GET /v1/widget-instances/{id}/config. The runtime then loads portal-managed defaults from that endpoint.
Instance id on the element (in order):
data-widget-instance-id— preferred; matches portal snippets.- HTML
id— if the data attribute is missing or whitespace-only, the trimmedidproperty is used (ensure it is unique on the page).
Changing either value triggers a new fetch and re-render. Explicit attributes on the element always override values from the public config API and from window.__A1_WIDGET_CONFIG__.
Example:
<fma-airfare-content
data-widget-instance-id="YOUR_INSTANCE_UUID"
></fma-airfare-content>The embedding origin must be allowlisted for that instance (see widget-api CORS / embed allowlists). If the API base env var is unset, the script skips the fetch and behaves like a legacy attribute-only embed.
You can customize the behavior and appearance of the element by setting its attributes. The available attributes are listed in the table below:
| Attribute | Type | Default | Description |
| ----------------------- | ------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| origin | string | null | The origin airport code |
| primary-color | string | #0B89FF | The primary color of the form |
| secondary-color | string | #0B89FF | The secondary color of the form |
| primary-hover-color | string | — | Primary color on hover (hex). When unset, falls back to primary. |
| secondary-hover-color | string | — | Secondary color on hover, e.g. price text (hex). When unset, falls back to secondary. |
| destinations | string | null | A comma-separated list of destination codes |
| theme | string | light | The theme of the widget - "light" or "dark" |
| consent-advertising | string | true | Dynamically turn off/on consent for Advertising - pass "true" or "false" |
| consent-analytics | string | true | Dynamically turn off/on consent for Analytics - pass "true" or "false" |
| consent-functional | string | true | Dynamically turn off/on consent for Functional - pass "true" or "false" |
| data-widget-instance-id | string | — | Portal instance UUID; loads public config when VITE_WIDGET_PUBLIC_CONFIG_API_BASE_URL is set (preferred over id for this purpose). |
| id | string | — | Fallback instance id when data-widget-instance-id is absent/empty; must be unique in the document. |
Examples
For example, to set the origin and destination airports, you can use the following markup:
<fma-airfare-content
origin="ECP"
destinations="aus,ind"
primary-color="#0D67BD"
secondary-color="#e47b26"
></fma-airfare-content>Consent Management
How to dynamically manage user consent preferences and pass them into the widget
There are two consent categories that can optionally be turned off/on via DOM manipulation and modifying attributes on the widget.
<fma-airfare-content
origin="ECP"
primary-color="#0D67BD"
secondary-color="#e47b26"
></fma-airfare-content>
...
// Call a similar function via your CMP integration to pass in the consent values for Analytics or Advertising
function changeConsent(consentAdvertising, consentAnalytics) {
// Select the flightWidget element
var flightWidget = document.getElementsByTagName('fma-airfare-content');
// Set user's advertising consent from CMP
flightWidget.setAttribute('consentAdvertising', consentAdvertising); // consentAdvertising param should be a string of "true" or "false"
// Set user's analytics consent from CMP
flightWidget.setAttribute('consentAnalytics', 'true') // consentAnalytics param should be a string of "true" or "false"
}Styling
CSS Parts
The widget uses Shadow DOM for style isolation and provides CSS parts for customization. You can style the widget using the ::part() pseudo-element selector.
Available Parts
| Part Name | Description |
| --------------------------------- | -------------------------------------------------------------------------------- |
| airfare-content-container | The main container that holds all flight items |
| airfare-content-item | Individual flight destination items |
| airfare-content-item-disclaimer | The real-time pricing / “Powered by KAYAK” disclaimer below the destination grid |
Styling Examples
/* Style the main container */
fma-airfare-content::part(airfare-content-container) {
background-color: #f8f9fa;
border-radius: 8px;
padding: 16px;
}
/* Style individual flight items */
fma-airfare-content::part(airfare-content-item) {
text-align: center;
}
fma-airfare-content::part(airfare-content-item):hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
transform: translateY(-2px);
}
/* Style the pricing disclaimer */
fma-airfare-content::part(airfare-content-item-disclaimer) {
font-size: 0.75rem;
margin-top: 1rem;
}Carfare Search
Core Purpose:
- Renders a responsive car rental search form (pick-up/drop-off, dates, time)
- Supports same-location and different-location drop-off
- Redirects to FlyMyAirport Cars with the correct query string
- Encapsulated via Shadow DOM; theme colors configurable
Installation
Use the same script loader as other widgets:
<script src="https://widgets.flymyairport.com"></script>Usage
Add the fma-carfare-search custom element to your page. If you don't pass an origin, it will default to window.__A1_WIDGET_CONFIG__.iata when present, or to the instance iata from the public config API when data-widget-instance-id / id is set and VITE_WIDGET_PUBLIC_CONFIG_API_BASE_URL is configured (same contract as airfare).
<!-- Minimal -->
<fma-carfare-search></fma-carfare-search>
<!-- With explicit origin and theme -->
<fma-carfare-search origin="FAT" theme="light"></fma-carfare-search>Available attributes:
| Attribute | Type | Default | Description |
| ----------------------- | ------- | ---------------- | ------------------------------------------------------------------------------ |
| origin | string | from global | Origin IATA (3 letters). Falls back to window.__A1_WIDGET_CONFIG__.iata. |
| primary-color | string | #0B89FF or cfg | Primary theme color (CSS color). |
| secondary-color | string | #0B89FF or cfg | Secondary theme color (CSS color). |
| theme | string | light | light or dark. |
| consent-advertising | boolean | true | Enable/disable Advertising consent within the widget. |
| consent-analytics | boolean | true | Enable/disable Analytics consent within the widget. |
| consent-functional | boolean | true | Enable/disable Functional consent within the widget. |
| data-widget-instance-id | string | — | Portal instance UUID; loads public config when the widget-api base env is set. |
| id | string | — | Fallback instance id when the data attribute is absent/empty. |
Examples
<!-- Set colors and origin -->
<fma-carfare-search
origin="ATW"
primary-color="#0D67BD"
secondary-color="#E47B26"
theme="dark"
></fma-carfare-search>
<!-- Toggle drop-off to a different location in the UI, pick dates & search -->When the user clicks Search, the widget redirects to:
https://flymyairport.com/from/{fromAirport}/cars?fromAirport={FROM}&toAirport={TO}&tripOption={same-location|different-location}&fromDateTime=YYYY-MM-DDTHH:mm&toDateTime=YYYY-MM-DDTHH:mmExample redirect from FAT, same-location, 2025-10-01 12:00 → 2025-10-02 12:00:
https://flymyairport.com/from/FAT/cars?fromAirport=FAT&toAirport=FAT&tripOption=same-location&fromDateTime=2025-10-01T12%3A00&toDateTime=2025-10-02T12%3A00Date/time format and encoding
- Times are interpreted as local to the pick-up location unless your integration adds its own timezone handling. Pass values without an offset, e.g.,
2025-10-01T12:00. - Always URL‑encode parameter values. Prefer constructing the query with
URLSearchParamsto avoid encoding mistakes.
const fromAirport = 'FAT';
const toAirport = 'FAT';
const params = new URLSearchParams({
fromAirport,
toAirport,
tripOption: 'same-location',
fromDateTime: '2025-10-01T12:00',
toDateTime: '2025-10-02T12:00',
});
const url = `https://flymyairport.com/from/${encodeURIComponent(fromAirport)}/cars?${params.toString()}`;Note: The /from/{fromAirport} path segment and the fromAirport query parameter must match. Always keep them in sync.
Consent Management
You can dynamically set consent attributes (kebab-case) on the element at runtime from your CMP integration.
<fma-carfare-search id="carfare-widget" origin="FAT"></fma-carfare-search>
<script>
function applyConsent({ advertising, analytics, functional }) {
const el = document.querySelector('#carfare-widget');
if (!el) return;
el.setAttribute('consent-advertising', String(!!advertising));
el.setAttribute('consent-analytics', String(!!analytics));
el.setAttribute('consent-functional', String(!!functional));
}
// Example usage
applyConsent({ advertising: true, analytics: true, functional: true });
</script>Consent attributes accept the strings "true" or "false". The widget parses these string values; do not rely on attribute presence/absence semantics for these flags.
Styling
This widget exposes a CSS part for outer layout and two CSS variables for colors. Colors are also applied internally via Tailwind classes.
Available CSS parts:
| Part Name | Description |
| -------------------------- | ----------------------------------------- |
| carfare-search-container | Wraps the entire car search form and CTA. |
CSS variables (set on the host):
--color-primary--color-secondary
Examples:
/* Customize surface/background */
fma-carfare-search::part(carfare-search-container) {
background: #f8f9fa;
border-radius: 8px;
padding: 16px;
}
/* Override theme colors via CSS variables */
fma-carfare-search {
--color-primary: #0d67bd;
--color-secondary: #e47b26;
}Global Config (optional)
If present, the widget will read defaults from window.__A1_WIDGET_CONFIG__:
<script>
window.__A1_WIDGET_CONFIG__ = {
iata: 'FAT',
primaryColor: '#0B89FF',
secondaryColor: '#0B89FF',
defaultDestinations: [],
};
// origin/primary/secondary from this object are used only when
// not explicitly set as attributes on the element.
</script>