White-label ticketing · launch a branded box office in minutes

For venues

Embed the booking flow on your site

The whole TicketWave booking experience runs inside a single embed. Works on WordPress, Squarespace, Webflow, Wix, or a plain HTML file.

Preview · what loads inside the iframe

Your salon

Haircut

45 min · EUR 60.00

  1. 1Who
  2. ·
  3. 2When
  4. ·
  5. 3You

Alex Chen

Senior stylist

EUR 60 · 45 min

Sam Park

Stylist

EUR 50 · 45 min

Branded with your accent colour at runtime.

Minimal install

Two lines anywhere on your page. Replace your-tenant-slug with your TicketWave URL slug — visible in the address bar of your dashboard, or under Settings → Brand.

<script src="https://www.ticketwavehq.com/booking-widget.js" defer></script>
<div data-tw-booking="your-tenant-slug"></div>

Deep-link to a specific service

Skip the service-picker step and open straight at one service:

<div
  data-tw-booking="your-tenant-slug"
  data-tw-service="hair-cut"
></div>

Override the height

The widget auto-resizes via a postMessage handshake; this override only matters if your CMS strips it. Sets the iframe min-height in pixels.

<div
  data-tw-booking="your-tenant-slug"
  data-tw-height="1400"
></div>

What loads inside

  • · Your tenant brand strip (logo + accent colour)
  • · Service picker → resource picker → slot picker → contact form
  • · Stripe Checkout for deposits / full charge
  • · Confirmation page + magic-link manage URL emailed to the customer

Troubleshooting

The widget isn't appearing
Check the browser console. The loader logs a warning ifdata-tw-bookingis missing, or if your slug returns 404. The most common cause is a typo in the slug — open ticketwavehq.com/book/your-slugin a fresh tab and check the page renders.
Content Security Policy blocking the iframe
If your site sends a strict CSP, you need to allow:
script-src https://www.ticketwavehq.com;
frame-src  https://www.ticketwavehq.com;
connect-src https://www.ticketwavehq.com;
WordPress installs with the “Really Simple SSL” or “WP Hide” plugins frequently lock this down by default.
The iframe height never grows past 900px
That happens when the parent page strips the postMessage from the iframe — sandboxed iframes, certain CDNs, or aggressive ad-blocker rules can interfere. Force a static height with data-tw-height(see “Override the height” above) and the widget stops trying to auto-resize.
React / Vue / SPA frameworks
The loader uses MutationObserver so it picks up containers that mount after page load. No framework-specific install needed — just render the <div data-tw-booking> in your component tree. Make sure the script tag is loaded once (e.g. in layout.tsx for Next.js, orindex.html for Vite), not on every component render.
Mobile Safari clipping checkout
Stripe Checkout opens in the parent window (not the iframe), so the iframe height isn't the issue — but iOS Safari with -webkit-overflow-scrolling: touch on an ancestor sometimes clips the iframe. Remove that style from the container, or set overflow: visible on the parent.

When to skip the embed

If your customers prefer a clean booking page over an embed, link them straight to https://www.ticketwavehq.com/book/your-tenant-slug. The hosted page wears your brand and handles everything the widget does — no install required.

Not on TicketWave yet?

Start free →