Ancillaries Component
About
See it on GitHub →
You can find the source code and release notes for this component on GitHub.

See it on npm →
This component is available to be installed with npm.
Why sell ancillaries?
Live demo
Step-by-step guide
1. Install the component
Shell (using yarn)
yarn add @duffel/components
⒉ Add the component to your page
fixture_off_1
", which will tell the component to load a pre-made example offer. We'll also add debug={true}
which enables debug mode, which will show you more information about what's happening in the component in your browser's console.React
import { DuffelAncillaries } from '@duffel/components'const MyComponent = () => (<DuffelAncillariesdebug={true}offer_id="fixture_off_1"services={['bags', 'seats', 'cancel_for_any_reason']}passengers={[{id: 'pas_0000AUde3KY1SptM6ABSfU',given_name: 'Mae',family_name: 'Jemison',gender: 'F',title: 'dr',born_on: '1956-10-17',email: 'm.jemison@nasa.gov',phone_number: '+16177562626',},{id: 'pas_0000AUde3KY1SptM6ABSfT',given_name: 'Dorothy',family_name: 'Green',gender: 'F',title: 'dr',born_on: '1942-10-17',},]}onPayloadReady={console.log}/>)
3. Handling selection
onPayloadReady
event, which is an object containing two properties:data
: A JSON object matching the Duffel API's order creation payload schema that you can then use to create the order from your server.metadata
: An object with helpful information about the selected ancillaries, which can be used to enrich your price breakdown or order summary with the description and price of the selected ancillaries.
React
<DuffelAncillariesdebug={true}offer_id="fixture_off_1"services={["bags", "seats", "cancel_for_any_reason"]}passengers={[ ... ]}onPayloadReady={(data: CreateOrderPayload, metadata: OnPayloadReadyMetadata) => {/*** In a real environment, instead of logging the data, you'd post the payload* to your server so it can be used to* create an order with the Duffel API.** For more information on creating orders, see* https://duffel.com/docs/guides/quick-start#creating-a-booking-using-the-selected-offer*/console.log('Ancillaries selected. Order payload:', data)console.log('Ancillaries selected. Ancillary services chosen:', metadata)}}/>
Using real data
Option A: Using an offer ID and client key
React
<DuffelAncillariesdebug={true}offer_id='offer_id_here'client_key='client_key_here'services={["bags", "seats", "cancel_for_any_reason"]}passengers={[ ... ]}onPayloadReady={console.log}/>
Option B: Using a full offer
React
// Using a client key so that the component retrieves the seat map itself.<DuffelAncillariesdebug={true}services={['bags', 'seats', 'cancel_for_any_reason']}offer={ ... }client_key='client_key_here'passengers={[ ... ]}/>// You may include the seat map, so the component won't retrieve it.<DuffelAncillariesdebug={true}services={['bags', 'seats', 'cancel_for_any_reason']}offer={ ... }seat_maps={ ... }passengers={[ ... ]}/>
Adding a markup
note
metadata
object returned by the onPayloadReady
event will include the ancillaries with the markup applied, so you can use this to calculate the price that you should charge your users.Option A: Simple markup
markup
object as a property when initialising the component, with a key for each ancillary you want to mark up. Each ancillary has an amount
and a rate
property. The amount
property is a fixed amount to add to the price of each ancillary, and the rate
property is a percentage to add to the price of each ancillary.JavaScript
markup: {bags: {amount: 1, // Add 1.00 to the price of each bagrate: 0.01, // Also add 1% to the price of each bag},seats: {amount: 2, // Add 2.00 to the price of each seatrate: 0, // Don't add any percentage markup},cancel_for_any_reason: {amount: 0, // Don't add any amount markuprate: 0.25, // Add 25% to Cancel For Any Reason.},}
rate
is applied first, followed by amount
. For example, if a bag costs 10.00
, and you have a markup of amount: 1
and rate: 0.1
, the final price will be 12.00
(10 increased by 10% is 11, plus 1 to make 12).Option B: Advanced markup
JavaScript
priceFormatters: {bags: (amount, currency, service) => {// If the bag costs less than $20, add a 20% markup.// Otherwise, add a 10% markup.const percentageMarkup = amount < 20 ? 0.2 : 0.1return { amount: amount * (1 + percentageMarkup) }}}
currency
property in the object you return from the price formatter.JavaScript
priceFormatters: {bags: (amount, currency, service) => {const moneyToPointsExchangeRate = 100 // $1.00 = 100 pointsreturn {amount: amount * moneyToPointsExchangeRate,currency: 'Duffel Points',}}}
Using the component in non-React environments
Option A: Using npm or yarn
Shell (using yarn)
yarn add @duffel/components
JavaScript
import {onDuffelAncillariesPayloadReady,renderDuffelAncillariesCustomElement,} from '@duffel/components'
HTML
<duffel-ancillaries></duffel-ancillaries>
renderDuffelAncillariesCustomElement
to render it. The function accepts an object with the same properties as the React component, so see the React guide for more details.JavaScript
window.onload = function () {renderDuffelAncillariesCustomElement({debug: true,offer_id: 'fixture_off_1',services: ['bags', 'seats', 'cancel_for_any_reason'],passengers: [ ... ]}
onDuffelAncillariesPayloadReady
to receive the payload when the user selects ancillaries. This function executes every time a user completes each separate ancillaries flow. For example, if the user selects additional baggage, then selects seats, the event will be sent twice.JavaScript
onDuffelAncillariesPayloadReady((data, metadata) => {/*** In a real environment, instead of logging the data, you'd post the payload* to your server so it can be used to* create an order with the Duffel API.** For more information on creating orders, see* https://duffel.com/docs/guides/quick-start#creating-a-booking-using-the-selected-offer*/console.log('Ancillaries selected. Order payload:', data)console.log('Ancillaries selected. Ancillary services chose:', metadata)})
Option B: Using the Duffel CDN
<head>
element.HTML
<!--Replace <VERSION> with the version you want to use. Seehttps://github.com/duffelhq/duffel-components/releasesfor a list of versions.--><scripttype="text/javascript"src="https://assets.duffel.com/components/ancillaries/<VERSION>/index.js"></script>
HTML
<duffel-ancillaries></duffel-ancillaries>
render
to render it. The function accepts an object with the same properties as the React component, so see the React guide for more details.JavaScript
window.onload = function () {document.querySelector('duffel-ancillaries').render({debug: true,offer_id: 'fixture_off_1',services: ['bags', 'seats', 'cancel_for_any_reason'],passengers: [ ... ],})}
JavaScript
document.querySelector('duffel-ancillaries').addEventListener('onPayloadReady', (event) => {/*** In a real environment, instead of logging the data, you'd post the payload* to your server so it can be used to* create an order with the Duffel API.** For more information on creating orders, see* https://duffel.com/docs/guides/quick-start#creating-a-booking-using-the-selected-offer*/console.log('Ancillaries selected. Order payload:', event.detail.data)console.log('Ancillaries selected. Ancillary services chose:',event.detail.metadata)})
Render options
debug
false
.true
when you're first setting up the component, but to set it to false
in production.services
bags
, seats
and cancel_for_any_reason
, and you must include at least one ancillary.client_key
client_key
with a create offer request to the Duffel API. This field is required if offer
or seat_maps
are not part of the configuration options.offer
offer_id
, but not both.offer_id
offer
, but not both. If you include offer_id
, client_key
is required.seat_maps
client_key
so that the component can retrieve the seat maps from the Duffel API itself.passengers
JavaScript
passengers: [{id: 'pas_001',given_name: 'Mae',family_name: 'Jemison',gender: 'F',title: 'dr',born_on: '1956-10-17',email: 'm.jemison@nasa.gov',phone_number: '+16177562626',},{id: 'pas_002',given_name: 'Amelia',family_name: 'Earhart',gender: 'F',title: 'mrs',born_on: '1987-07-24',email: 'amelia@duffel.com',phone_number: '+442080160509',},]
markup
markup
is an object with the following structure:JavaScript
{// The service you want to add a markup to.// Possible values are 'bags', 'seats' and 'cancel_for_any_reason'.[service]: {// A fixed amount to add to the price of each ancillary, e.g. 1amount: number,// A percentage to add to the price of each ancillary, e.g. 0.1 for 10%rate: number,},}
markup
and priceFormatters
at the same time for the same service.priceFormatters
priceFormatters
is an object with the following structure:JavaScript
{// The service you want to add a markup to.// Possible values are 'bags', 'seats' and 'cancel_for_any_reason'.[service]: (amount, currency, service) => {// A function that takes the amount, currency and service as arguments// and returns an object with the following structure:return {// The new amount to display.amount: number,// The currency to display, e.g. "GBP", or "Points".// Currency is optional, and if not supplied the original currency will be used.// If currency is a valid ISO 4217 currency code, the amount will be formatted automatically.// For example, if currency is "GBP" and amount is 1.23, the amount will be formatted as "£1.23".currency: string,}},}
priceFormatters
and markup
at the same time for the same service.styles
accentColor
: A comma-separated string of RGB values to customise the component's UI, for example"34,139,34"
.buttonCornerRadius
: A string with the corner radius to apply to buttons, for example"8px"
.fontFamily
: A string with the name of the font family to use, for example"Menlo"
.
JavaScript
styles: {accentColor: "34,139,34",buttonCornerRadius: "8px",fontFamily: "Menlo, Courier, Monospace",}
note
Our mission is to make selling travel effortless. If this component doesn't meet your needs, tell us what's missing at help@duffel.com so we can improve it.