Events
There are two channels, and they carry different things. Subscribing to one does not get you the other.
SDK events reach you through DriveCars.on() or init({ onEvent }). There
are four, and they are about the session and the integration itself.
DOM events are CustomEvents the elements dispatch. They bubble, so you
listen on the element or on any container above it. They are about the customer’s
journey — a booking created, a payment authorized. They are not routed through
on(), with one exception noted below.
If you are wiring up a confirmation page or a conversion pixel, you want the DOM events.
SDK events
const off = DriveCars.on('tokenRefreshFailed', ({ error }) => {
console.error('session refresh failed', error);
});
// later
off();on() returns an unsubscribe function. init({ onEvent }) is a catch-all that
fires for every one of these in addition to any on() handlers.
| Event | Payload | When |
|---|---|---|
tokenRefreshed | { token } | A new session token has been applied to every mounted element. |
tokenRefreshFailed | { error } | Your onRefreshToken rejected. The elements keep the stale token — surface this to your user. |
analytics | { name, props? } | Relayed from every element’s analytics channel. |
mount:rejected | { tag, reason } | A mount() was refused because the component is not in your enabled_components. |
analytics is the exception to the two-channel rule: the SDK installs a single
document-level listener for the elements’ dc:analytics DOM event and re-emits
it here, so you can subscribe once instead of on every element.
The analytics names emitted today:
widget_opened, widget_search_submitted, car_clicked,
widget_cart_opened, widget_cart_item_removed,
widget_cart_continue_clicked, widget_checkout_opened,
widget_checkout_payment_authorized, widget_checkout_failed,
widget_payment_opened, widget_payment_completed, widget_payment_failed,
widget_payment_link_status.
Treat that list as additive. New names may appear; do not fail on an unrecognised one.
DOM events
All of these bubble. Listen on a container:
document.addEventListener('booking.payment.authorized', (e) => {
console.log('confirmed', e.detail.reference);
});Rentals and the shared flow
| Event | Fired by | Detail | Meaning |
|---|---|---|---|
dc:search | search, mode="form" only | the form values | Cancelable. preventDefault() to route client-side yourself; otherwise the element navigates to results-url. |
continueToCheckout | cart | { cart } | The user pressed continue. |
booking.created | checkout | { reference } | A draft booking now exists. Not yet paid. |
bookingReady | checkout | { bookingReference } | Partner-MoR only. Your turn to charge. See Payments. |
booking.payment.authorized | checkout | { reference } | Payment authorized; the booking is confirmed. This is the one to build a confirmation page on. |
payment.completed | payment | { reference, kind } | A payment-link payment finished. |
dc:analytics | all | { name, props } | The raw analytics channel, if you prefer it to on('analytics'). |
tokenRefreshNeeded | search, cart, checkout | — | The element saw a 401 on a call made with the session token. |
tokenRefreshNeeded is handled for you once init() has run — the SDK listens
at the document root and calls your onRefreshToken. You only need it if you
are using bare elements with no runtime. <drivecars-payment> never fires it,
because it authenticates with a payment-link token rather than the session.
Ordering
For a rental in the default drivecars MoR mode, a completed purchase looks
like this:
dc:analytics→widget_search_submittedbooking.created— draft existsdc:analytics→widget_checkout_payment_authorizedbooking.payment.authorized— confirmed
In partner_invoiced mode, bookingReady fires in place of the in-widget card
form, and booking.payment.authorized fires only after you call back with your
PSP’s reference.
Seeing what you actually receive
The quickest way to check your wiring is to log both channels at once against the sandbox, before you build anything on top of them:
DriveCars.init({
session,
onRefreshToken,
onEvent: (event, payload) => console.log('[sdk]', event, payload),
});
for (const name of [
'dc:search', 'dc:analytics', 'continueToCheckout',
'booking.created', 'bookingReady', 'booking.payment.authorized',
'payment.completed', 'tokenRefreshNeeded',
]) {
document.addEventListener(name, (e) => console.log('[dom]', name, e.detail));
}