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 |
Deep links
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.