Embedding widgets

Put the booking flow, the agenda or a "Book now" button on any website with two lines of HTML, and react to bookings in the page.

The fastest way to take bookings on a website is not the API but a widget: the same booking flow as the organisation's booking site, in an iframe that resizes itself, themed to fit. It works on WordPress, Wix, Squarespace, Webflow and hand-written pages.

The snippet

Staff build a widget under Settings > Website & widgets in the admin app and copy two lines:

<script src="https://demo.plekbooking.com/embed/v1/plek.js" defer></script>
<div data-plek-widget="wgt_7fK2qLpa"></div>
  • The script comes from the organisation's booking site ({slug}.plekbooking.com, or its own domain).
  • wgt_… is a saved widget preset: the flow (booking, catalogue, activity, agenda, button, gift-cards, request) and its settings (which activities or locations, layout, look, texts). Edits to the preset go live without pasting the snippet again.
  • Several widgets on one page are fine; give each its own data-plek-key.

Narrowing a widget

Attributes narrow what a preset shows, never widen it:

Attribute Example Does
data-plek-activity an activity id Only this activity
data-plek-location a location id Only this location
data-plek-series a series id Only this series
data-plek-session a session id Open this session's booking form
data-plek-theme light, dark Force a colour scheme
data-plek-label Book a trial class The button text of a button widget
data-plek-scroll-offset 80 Height of a fixed header on the host page, in px
data-plek-debug (present) Log what the widget does in the browser console

The widget mirrors its step in the host page's URL fragment, so the back button works and a step can be shared: https://www.example-studio.be/classes#plek=/activity/1b9e…. With several widgets on one page, each uses #plek-{key}=…. Links like ?plek=/activity/… work too, and ?plek-code=EARLY (or ?code=EARLY on the booking site) fills in a discount code.

Payment and allowed websites

The checkout runs inside the widget only on a website the organisation allowed (Settings > Website & widgets > Your websites). There, payment opens at the top of the window and the customer comes back to your page at #plek=/confirmation/{id}. On other websites, or when the preset says so, payment opens in a new tab and the widget follows the result. Allowed websites are also the only ones that may frame the widgets (frame-ancestors).

Events in the page

The widget dispatches DOM events on its element (they bubble), without personal data, for analytics or your own follow-up:

Event When detail
plek:checkout-started The customer starts paying ids of what is being booked
plek:booked A booking is confirmed (once per booking) booking id
plek:purchased A gift card or pass is bought order id
plek:waitlist-joined Someone joined a waiting list session or series id
plek:hire-requested A venue hire request was sent hireId
document.addEventListener('plek:booked', (event) => {
  window.dataLayer?.push({ event: 'plek_booked', ...event.detail });
});

Versions

/embed/v1/plek.js only ever takes compatible changes. Anything breaking will be a new /embed/v2/plek.js next to it, and v1 keeps working. The old web components (<plek-booking-flow> from /elements/main.js) still work through a compatibility layer until October 2027; replace them with a widget.

When to use the API instead

Use the public booking API when you want your own look end to end, a native app, or bookings from a system rather than a person. Everything the widgets do goes through it; see The booking flow.