Embed the booking widget
The widget shows your booking page on your site in a frame from
book.tuppence.ai, as a pop-up button or inline steps. Clients stay on your site; bookings are
marked source: widget.
Get the code
Section titled “Get the code”Share → Your website generates the tag: choose A button where you put the code, A button in
the corner of every page or The booking steps in the page itself, and optionally a starting
service. It includes your accent colour and data-ch="website" for attribution.
<script async src="https://book.tuppence.ai/embed.js" data-slug="bellas-barks" data-mode="button" data-ch="website"></script>On a website builder
Section titled “On a website builder”| Builder | Where the tag goes |
|---|---|
| WordPress | A Custom HTML block; the footer for every page. |
| Wix | Every page: Settings → Custom code → Add Custom Code, All pages, Body – end (needs Premium and a connected domain). On one page, Wix boxes pasted code and traps pop-ups, so use Add → Embed code → HTML iframe with data-mode="inline" and a tall box. |
| Squarespace | A Code block (Core plan and above); every page: Code Injection → Footer. |
| Shopify | Online Store → Themes → Customize → Add section → Custom Liquid; the footer for every page. |
| Linktree, Instagram, other profiles | Use your link, not the tag (see the share panel’s cards). |
Choose how it shows
Section titled “Choose how it shows”| Attribute | |
|---|---|
data-slug | Required. Your address after book.tuppence.ai/. |
data-mode | button (default: a button where the tag is), popup (a floating corner button) or inline (the flow in the page, full height, never scrolling itself). |
data-service, data-variant, data-staff, data-location, data-date | Preselect service (svc_…), option (svar_…), person (stf_…), place (loc_…) or day (YYYY-MM-DD). |
data-ch | The channel: website or a channel you’ve set up; unknown codes count as other. |
data-label, data-color | Button text (default Book now) and colour (#RRGGBB); text is white, or near-black for contrast. |
data-title | Screen-reader name for the pop-up and frame (default Book online). |
data-test | Test mode: no money moves. |
As an element, after one embed.js tag without data-slug:
<script async src="https://book.tuppence.ai/embed.js"></script><tuppence-booking slug="bellas-barks" mode="inline"></tuppence-booking>From your own button: TuppenceBook.open({ slug: "bellas-barks", service: "svc_…" }) and
TuppenceBook.close().
What the client sees
Section titled “What the client sees”| Pop-up | A dialog holding focus until closed (Close, Escape or click outside), then returning it to the button. Full-screen below 560 px. |
| Inline | Sized to the current step; your page scrolls, not the frame. |
| Paying | Deposits and saved cards stay in the frame. Its allow="payment *" enables Apple Pay and Google Pay. |
Hear when a client books
Section titled “Hear when a client books”Your site never sees client input, and the frame needs no cookies. Two events bubble to window:
| Event | detail |
|---|---|
tuppence:booking.completed | booking: id, status, starts_at, ends_at, next_step (no client details) |
tuppence:booking.cancelled | reason: "closed" (pop-up closed without booking) |
window.addEventListener("tuppence:booking.completed", (event) => { console.log("booked", event.detail.booking.id);});Browser events are lost if the page closes; rely on webhooks
(booking.created, booking.confirmed).
Pin the loader with Subresource Integrity
Section titled “Pin the loader with Subresource Integrity”embed.js is the current loader, cached five minutes. For
Subresource Integrity,
https://book.tuppence.ai/embed.json gives the current loader’s path (/embed.<version>.js:
immutable, cached a year, served permanently) and integrity.
<script async src="https://book.tuppence.ai/embed.8bc7b2f42d.js" integrity="sha384-xMs122Ue090L+BYAO2VZz1vS2VGFNmZ22EhrwRlXwWVtN8QdNRD2LV9bs3ji2Ix1" crossorigin="anonymous" data-slug="bellas-barks" data-mode="button"></script>Pinned loaders keep working but get no fixes; check embed.json periodically.
A site with a Content-Security-Policy
Section titled “A site with a Content-Security-Policy”Allow https://book.tuppence.ai in script-src and frame-src; no inline script or style is
needed.
Without scripts, put https://book.tuppence.ai/embed/<slug> in an <iframe> with a title,
allow="payment *" and a fixed height. Only embed.js can resize it and pass on booking events.
- Where your bookings come from:
data-chand channels. - Webhooks: booking events on your server.