For the complete documentation index, see llms.txt. Any page on this site can be fetched as Markdown by appending .md to its URL.

Callback scheduling

Sharing and embedding

Share a calendar's booking link, or put its booking page on your own website with an embed snippet.

This page is being rolled out. If Scheduling isn't in your sidebar, it isn't enabled for your organization yet — contact support.

Every calendar has a public booking page at its booking link. Copy it from the Calendars list or from the Share section of the calendar's Booking Page tab, and send it anywhere: an email, a text message, a button on your website. Nobody needs an account to book.

The Share section always shows the saved link. If you change Booking link on Basic Info, save before copying, and expect the old link to stop working.

Embedding the booking page

The Share section has two snippets with your calendar's link filled in. Copy them from there rather than from this page. For a calendar whose booking link is https://book.example.com/sales they look like this.

Inline embed shows the booking page inside your page, where you paste it:

<script src="https://book.example.com/embed.js" async></script>
<div data-tandem-booking="sales"></div>

Button embed adds a Schedule a callback button that opens the booking page in a panel on the right side of the screen:

<script src="https://book.example.com/embed.js" async></script>
<button type="button" data-tandem-booking-open="sales">Schedule a callback</button>

Any website can embed a booking page; there is no list of allowed sites to configure.

A few things about how the snippets behave:

  • The script must load from its src. Pasting the contents of embed.js into an inline <script> does nothing, and the browser console shows tandem-booking: load embed.js with <script src>.
  • One script tag per page is enough. It serves every inline embed and every button on the page, for any of your calendars, and loading it twice does no harm.
  • An inline embed sizes itself to the booking page's height as the customer moves through it, growing and shrinking between steps. It starts at 560 pixels until the page reports its height. The Continue and Schedule callback buttons sit in the page after the step's content, not pinned to the bottom of the screen. Put the <div> in the page's HTML: the script fills in the inline embeds that exist when the page finishes loading.
  • The button can be any element with a data-tandem-booking-open attribute, styled however you like, including one added to the page later.
  • The panel keeps its full height. It does not resize to the content, and the booking page's buttons stay at the bottom of it.
  • The page scrolls back up between steps. When the customer moves to the next step and the top of an inline embed is above the visible part of your page, the script scrolls it into view. This uses a tandem-booking:step message from the booking page. It is not a window event, and your page does not receive it.
  • The panel closes with its close button (×) in the top corner, or with Escape while focus is on your page. Escape pressed inside the booking page doesn't close it.

Tracking bookings on your site

When a customer books through an embed, the script fires a tandem-booking:booked event on your page's window. Its detail has:

  • bookingId — the booking's id.
  • kind — scheduled for a picked time, or asap for As soon as possible.
  • start — when the callback starts, as a UTC timestamp such as 2026-10-08T14:30:00Z.
<script>
    window.addEventListener('tandem-booking:booked', (event) => {
        const { bookingId, kind, start } = event.detail;
        // Send it to your analytics, show a thank-you message, and so on.
        console.log('Callback booked', bookingId, kind, start);
    });
</script>

The event fires only for an embedded booking page. A customer who books on the booking link directly is on our page, not yours, so your page gets nothing. The event carries no name, phone number, or other details the customer entered.

Next steps

On this page