Your booking page does not have to live only at 369.dev. Paste one snippet from Share & embed into your website and clients can book without leaving your site. The embed shows the same services, availability, and payment steps as the public page.
Choose an embed style
| Style | Best for |
|---|---|
| Inline | A dedicated booking page or section on your site; the booking flow renders in place and grows to fit its content |
| Popup button | Any page on the site; a floating button opens the booking flow in an overlay |
| Plain iframe | Site builders that block custom scripts; fixed height, no popup, no JavaScript API |
All three come ready to copy from Share & embed with your workspace and page already filled in. Every embed shows a "Powered by Workspace369" credit line.
Add an inline booking page
- Open the booking page's Share & embed action and copy the inline snippet.
- Paste it into your site's HTML where the booking flow should appear.
<script src="https://369.dev/booking.js" data-booking
data-workspace="WS_ID"
data-page="SLUG" async></script>
WS_ID is your workspace ID and SLUG is the page's link slug; the snippet from Share & embed already contains both, and the default page needs no data-page at all. The frame sizes itself to the booking flow as the client moves through it, so it needs no fixed height.
Add a popup button
- Open the booking page's Share & embed action and copy the popup snippet.
- Paste it just before the closing
</body>tag of every page where the button should appear, or into your site builder's site-wide footer or custom-code area so the button appears everywhere.
<script src="https://369.dev/booking.js" data-booking
data-workspace="WS_ID"
data-page="SLUG"
data-mode="popup" data-label="Book now" data-color="#111827" async></script>
data-label sets the button text and data-color its color. The booking flow opens in an overlay that scrolls inside itself; the client closes it with the close control or by pressing Escape.
To open the popup from your own button or link instead, add data-w369-booking to any element on the page:
<a href="#" data-w369-booking>Book a consultation</a>
Use a plain iframe
- Open the booking page's Share & embed action and copy the iframe snippet.
- Paste it into your site's HTML where the booking flow should appear.
<iframe src="https://369.dev/ws/WS_ID/book/SLUG?embed=1" title="Book an appointment" width="100%" height="900" style="border:0;display:block" loading="lazy"></iframe>
Use this when your site builder strips or blocks script tags. The iframe cannot resize itself, so adjust height to fit the longest step of the booking flow. The popup mode, the data- attributes, and the JavaScript API are not available with a plain iframe.
Attributes reference
| Attribute | Required | Purpose |
|---|---|---|
data-booking | Yes | Marks the script tag as a booking embed |
data-workspace | Yes | Your workspace ID |
data-page | No | The booking page slug; omit it for the default page |
data-mode="popup" | No | Shows a floating button instead of an inline frame |
data-label | No | The popup button text; defaults to "Book now" |
data-color | No | The popup button color as a hex value |
data-service | No | Starts the flow with a service already selected |
data-member | No | Starts the flow with a host already selected |
data-theme | No | Applies a specific theme to the embed |
data-prefill-name, data-prefill-email, data-prefill-phone | No | Prefill the client's details |
Advanced — data-service, data-member, and data-theme take internal identifiers and are meant for developer integrations; most sites should let the visitor choose.
Keep campaign attribution
utm_source, utm_medium, utm_campaign, utm_term, and utm_content on the URL of the page hosting the embed are forwarded to the booking page, so campaign links keep their attribution.
React to bookings from your page
The script installs a small JavaScript API on the page:
<button type="button" onclick="W369Booking.open({ prefill: { name: 'Ada Lovelace', email: 'ada@example.com' } })">Book an appointment</button>
<script>
window.addEventListener('w369:booked', (event) => {
const { bookingId, status, startMs } = event.detail;
// record a conversion, show a thank-you message, and so on
});
</script>
W369Booking.open({ page, service, member, theme, prefill })opens the booking flow in the popup overlay. Every option is optional and overrides the matching script attribute;prefilltakes{ name, email, phone }.W369Booking.close()closes the popup.w369:bookedfires onwindowwhen a client completes the flow.event.detailcarriesbookingId,status, andstartMs, the appointment's start time in milliseconds.
Payments inside an embed
When a service requires a deposit or full payment, the embed does not try to take the card inside the frame. The client sees a Continue to secure payment button that opens Stripe Checkout at the top level of the browser window. After paying, the client lands on a confirmation page on 369.dev with a Back to example.com button, where example.com is your site's domain, that returns them to your website.
The slot stays held for 30 minutes during payment, exactly as on the public page.
Troubleshooting
| Symptom | Check |
|---|---|
| Nothing renders | Your site builder may block custom scripts; confirm the script tag survived publishing, or switch to the plain iframe |
| "Booking is not available" | The page is paused, or the last active page was paused or deleted. Resume it in Booking Pages |
| The frame is cut off | Inline embeds size themselves; a plain iframe needs a larger height; popups scroll inside the overlay |
Continue to Manage booking requests.
Embeds always show "Powered by Workspace369". Deposits and full payments open Stripe Checkout in the top-level window and need a connected Stripe account.