Alongside the car-rental Smartblock
The data and basket payload contracts are still evolving while Koala completes its integration with CarTrawler. Expect small changes before the final guide is published.
The
car-rental Smartblock
already set up window.CTStore and window.CTStore.dataSource on your page. Koala reads the same dataSource, so you
often add very little.
Never modify or remove existing dataSource fields. They belong to the car-rental Smartblock, and changing them
would break it. To give Koala more, only add Koala-native fields. When both an existing field and its Koala-native
counterpart are present, Koala uses the richer Koala-native one.
Set up the widget
Add the koala namespace
Your window.CTStore already has dataSource and the shared events bus. Add the koala namespace, with your Koala
handlers on koala.events. It must exist before the Koala loader runs.
// Add alongside your existing CTStore setup. Do not change dataSource.
window.CTStore.koala = {
events: {
onReady: [(status) => {}],
onAvail: [(status, data) => {}],
onBundle: [(status, data) => {}],
onBasket: [(status, data) => updateOrderSummary(data.selectedBundles)],
onError: [(status, data) => console.error(data.message)],
},
};
Place the custom HTML element
Put the following custom HTML element where the Koala offer should appear:
<koala-smartblock-sb4 data-config-name="your-slug"></koala-smartblock-sb4>
Set up the Koala loader script
Include the Koala loader script once, after the custom HTML element is present in the DOM and window.CTStore.koala is
defined. It is asynchronous and loads in addition to the car-rental loader you already have. The loader script URL
determines which Koala environment the widget talks to: build against the staging URL and switch to production at the
last step (see Testing and going live).
<script async src="[koala-loader-staging-url]"></script>
What Koala reads from your existing data
Koala derives the journey, trip price, travellers, and currency from fields the car-rental Smartblock already populates, so you may not need to add anything. Click a property to see an example value and, for object properties, the shape Koala expects to find:
Existing car-rental fields on window.CTStore.dataSource that Koala reads. Do not change them.
- Example
'EUR' - Example
'en-GB' - Example
'IE' - custom
- Example
'confirm'
- Flight
The journey as the car-rental Smartblock carries it.
- Leg
One flight leg of the journey.
- Example
'outbound' - FlightStop
One end of a leg.
- Example
'DUB' - Example
'2026-07-11T06:25:00' - Example
'Europe/Dublin'
- FlightStop
One end of a leg.
- Example
'DUB' - Example
'2026-07-11T06:25:00' - Example
'Europe/Dublin'
- Example
'FR22'
- Example
320.5 - Example
1 - classstringCabin class.
- bookingRefstringYour booking number.
- Passengers
Traveler counts as the car-rental Smartblock carries them.
- Example
2 - teensnumberMapped to ADULT.
- childrennumberMapped to CHILD.
- infantsnumberMapped to INFANT.
A quote is only possible when this context is complete and well-formed. Some fields that are optional for car-rental become effectively required for Koala:
flight.legs[].flightNomust be present and well-formed (carrier code plus number, for exampleFR22). Koala splits it into the airline (first 2 characters) and the flight number (the rest, up to 4 digits). Without it, or if the code is not 2 characters or the number is longer than 4 digits, flights cannot be quoted.passengersmust be populated with at least one count. Koala derives the travellers from it. Without it, there is no one to quote for.flight.farePricemust be set; it is the trip price.
Validate the trip context before the widget loads.
Adding richer data
To go beyond what car-rental carries, add Koala-native fields. They never replace the existing ones; Koala uses them when present.
Baggage cover needs per-traveller checked-bag counts, which car-rental does not carry. Add a travelers array
(Koala uses it instead of passengers when present), and leave passengers in place:
Add a travelers array to enable baggage cover. Koala uses it instead of passengers when present; leave passengers in place.
- Example
'ADULT' - Example
1
Trains, buses, ferries, or accommodation can be added with segments or stays; their shapes are documented in the
reference page Trip context.
// On a page that already runs the car-rental Smartblock.
// Keep everything that is already there; only add Koala-native fields.
window.CTStore.koala = {
events: {
/* ... */
},
};
// Optional: enable baggage cover by adding per-traveller bag counts.
window.CTStore.dataSource.travelers = [{ ageRange: 'ADULT', numberOfCheckedBags: 1 }];
Reacting to events
You have two event surfaces. Register on koala.events for everything Koala-specific; the basket also reaches your
existing handler.
- The basket: because the shared
events.onBasketalso carries car-rental's basket, Koala adds its part under akoalakey so the two coexist. Your current handler already receives Koala's selection atdata.koala:The recommended way iswindow.CTStore.events.onBasket = [(status, data) => {updateOrderSummary(data.koala.selectedBundles); // Koala's part},];window.CTStore.koala.events.onBasket. That event carries no car-rental data, so the basket is the top-leveldata(data.selectedBundles), notdata.koala. - Everything else: register
onReady,onAvail,onBundle, andonErroronkoala.events. The car-rental Smartblock's ownonReady/onAvail/onProduct/onErrorare separate events about the car-rental widget.
The full event reference is documented in the reference page Events; how the two surfaces coexist in Events and basket state.
Updating the trip after page load
If the trip changes after page load, update window.CTStore.dataSource (without removing car-rental fields) and call
window.CTStore.koala.restart() to re-quote Koala.
Create the subscription after booking
One last call completes the integration. After a booking ends with a sale on your side, your backend makes one HTTP POST to Koala, whether or not the traveller selected protection:
- protection selected: the call creates the subscription, the traveller's policy;
- nothing selected: the call deletes the quote, so Koala measures conversion against all bookings.
You never build this request yourself: the widget prepares it and keeps it up to date as the basket changes. The
prepared request is the book object on window.CTStore.koala.basketPayload (also delivered with every Koala
onBasket event as data.book). It carries msgRaw, the request body with [TOKEN] placeholders for the few values
only your system knows (the booking number, the policyholder's details, each traveller's name), and fullUrl, the URL
to POST it to.
When the traveller submits the booking, pass the prepared book to your backend along with the booking. Once the
booking is confirmed and paid, your backend replaces every [TOKEN] placeholder in msgRaw with the real values and
POSTs it to fullUrl as JSON. No token appears twice, so the substitution is a plain replace over the serialized body.
If the booking is never completed, send nothing.
The two steps in code are documented in Creating the subscription; the payload shape and the full placeholder list in the reference page Request template.