Web SDKEvents

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.

EventPayloadWhen
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

EventFired byDetailMeaning
dc:searchsearch, mode="form" onlythe form valuesCancelable. preventDefault() to route client-side yourself; otherwise the element navigates to results-url.
continueToCheckoutcart{ cart }The user pressed continue.
booking.createdcheckout{ reference }A draft booking now exists. Not yet paid.
bookingReadycheckout{ bookingReference }Partner-MoR only. Your turn to charge. See Payments.
booking.payment.authorizedcheckout{ reference }Payment authorized; the booking is confirmed. This is the one to build a confirmation page on.
payment.completedpayment{ reference, kind }A payment-link payment finished.
dc:analyticsall{ name, props }The raw analytics channel, if you prefer it to on('analytics').
tokenRefreshNeededsearch, cart, checkoutThe 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:

  1. dc:analyticswidget_search_submitted
  2. booking.created — draft exists
  3. dc:analyticswidget_checkout_payment_authorized
  4. booking.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));
}