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
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.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.
<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
<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
// 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
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.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
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.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
yarn add @duffel/components
import {onDuffelAncillariesPayloadReady,renderDuffelAncillariesCustomElement,} from '@duffel/components'
<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.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.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.<!--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>
<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.window.onload = function () {document.querySelector('duffel-ancillaries').render({debug: true,offer_id: 'fixture_off_1',services: ['bags', 'seats', 'cancel_for_any_reason'],passengers: [ ... ],})}
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
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:{// 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:{// 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"
.
styles: {accentColor: "34,139,34",buttonCornerRadius: "8px",fontFamily: "Menlo, Courier, Monospace",}
note