Visos online booking

Embed the booking widget

One script tag puts the business's booking flow on any website: inline in the page or as a pop-up. The business's tenant key (vb_…) and the allowed website origins are set in Visos under Settings › Online booking. The widget only loads on an allowed origin.

Snippet

Inline: the widget appears where the element is, and grows with its content.

<div data-visos-booking data-mode="inline"></div>
<script src="https://book.visos.app/embed/v1.js" async
        data-visos-booking data-tenant="vb_xxxxxxxxxxxx"
        data-locale="nl"></script>

Pop-up: any element with data-mode="popup" opens the widget full screen on phones and as a centred sheet on larger screens. Escape or a click on the backdrop closes it.

<button data-visos-booking data-mode="popup" data-service="svc_eye_exam">Book an eye exam</button>
<script src="https://book.visos.app/embed/v1.js" async data-visos-booking data-tenant="vb_xxxxxxxxxxxx"></script>

A script tag without any other [data-visos-booking] element mounts an inline widget right after itself.

Attributes

Set on the script tag they are the defaults for the page; set on an element they apply to that element.

AttributeMeaning
data-tenantThe business's tenant key, vb_ followed by 12 characters. Required.
data-modeinline (default) or popup.
data-storeA store id: skips the store step when the business offers that store.
data-serviceA service id: skips the service step when the business offers that service.
data-localenl, en, … — used when the business supports it, else its default language.
data-labelPopup on an empty element: the text of the button the loader creates.
data-titleThe accessible title of the iframe and the pop-up.

JavaScript API

// Mount elements added after the page loaded.
VisosBooking.init();

// Open the pop-up from your own code; prefill is shown to the customer, who can change it.
const booking = VisosBooking.open({
  store: "…", service: "…",
  prefill: { name: "Jane Doe", email: "[email protected]", phone: "+31612345678" },
});
booking.close();

// Listen; the returned function stops listening.
const stop = VisosBooking.on("booked", ({ bookingId, startsAt, endsAt, storeId, serviceId }) => { … });

Events

EventWhenPayload
readyThe widget loaded its configuration.{ mode }
stepThe customer moved to another step.{ step }: store, service, time, identify, verify, details, confirm, done
bookedThe appointment was booked.{ bookingId, startsAt, endsAt, storeId, serviceId }
closedThe pop-up was closed.{}

The loader also dispatches a DOM event that bubbles from the widget's element (or the document for a pop-up):

document.addEventListener("visos:booking-completed", (event) => {
  const { bookingId, startsAt, storeId } = event.detail;
});

The widget and the page talk through postMessage with the envelope { source: "visos-booking", type, … }; the loader accepts messages only from the widget origin and the frames it created.

Headless

To build your own booking screens instead, use the headless API with the business's publishable key (pk_…, Settings › Online booking) through the @optics/booking-sdk package: configuration, availability, holds, bookings and customer sign-in. The publishable key works only from the allowed origins.