Comparison · Embedding

BookingsXP vs iframe wrappers and Graph plugins for Bookings

Last updated 9 min readPart of Microsoft Bookings on your website: every embed option9 sources

Use the plain Bookings iframe if you just need a booking page on your site and don't need to measure completed bookings. Use a Graph-based native form if you have an IT admin willing to register an app, grant tenant-wide Bookings permissions and own the business-rule logic. Use BookingsXP if you want a branded widget and conversion tracking without admin consent, and can live with its limits (listed below). In every case, Microsoft Bookings remains where appointments are created, and Outlook and Teams keep working as before.

This page describes the approaches by how they work rather than product by product: where the booking is actually completed, what permissions it needs, and what it can measure.

The approaches at a glance#

Where the booking is finishedMicrosoft admin consentLook and feelCompleted-booking trackingBookings with me
(a) Plain Bookings iframeThe page Microsoft hosts, inside your pageNot neededBookings colours and logo onlyNot visible to your page; RefID report onlyNo embed code offered
(b) Availability widget with hand-offThe page Microsoft hosts, usually in a new tabUsually not neededStyled date and time previewClicks yes, completions noVaries
(c) Graph-based native formA form on your site that calls Microsoft GraphYes: app registration plus admin consentFull controlYes, the form is yoursNot possible: Graph covers shared bookings only
(d) Tracking layer around the iframe or linkUnchangedVariesUnchangedDepends on the signal usedVaries
(e) BookingsXPBookingsXP widget on your site; appointment created in Microsoft BookingsNot neededTemplates, colours, fontsYes: dataLayer events and attribution in the bookingBest-effort only

What people mean by a "Microsoft Bookings widget"#

Microsoft ships only the booking page and its iframe code. As of October 2026 there is no official widget, popup or booking button. Anything sold as a "Microsoft Bookings widget" is a third-party layer of type (b) to (e) on this page, built on the booking page from (a) or on the Graph API. Three questions sort them:

  • Where is the booking finished: on your page, or on the page Microsoft hosts?
  • What Microsoft permissions does it need: none, or an app registration with admin consent?
  • Can it report a completed booking to your analytics, or only a click?

(a) The plain Bookings iframe#

The Bookings FAQ: "We provide a way for you to embed your Bookings calendar in your site via an iFrame. Link embedding code is located in the Bookings page tab." It's the only embed method Microsoft documents, and it's free with your plan. Where to find the embed code has the click path.

The trade-offs come from the page being hosted by Microsoft on its own domain. Your site's CSS and tags can't reach inside a cross-origin frame, and Microsoft documents no postMessage events. Your analytics therefore can't see a completed booking, and there's no native redirect to a thank-you page. The frame has a fixed height, which is behind most "cut off on mobile" complaints (iframe height fixes). If "Require a Microsoft 365 account from my organization to book" is on, the frame tries to load the Microsoft sign-in page, which refuses to be framed. Personal "Bookings with me" pages have no embed option (embedding Bookings with me).

(b) Availability widgets that hand off to the Bookings page#

These tools show a calendar of open days or times on your site. When the visitor clicks a time or a "Book" button, they're sent to the public Bookings page, often in a new tab, to finish. Because the booking is still made there, the Bookings rules, confirmation emails and Teams links apply unchanged.

The benefit is a nicer first impression than the raw iframe. The costs:

  • The visitor goes through two steps and usually leaves your site to finish.
  • Your tags can record the click but not the completed booking.
  • If the tool refreshes availability on a schedule rather than live, what visitors see can lag behind Bookings.

Some free widget services also cap monthly widget views on their free plan, and their own help says confirmed appointments should be checked in Microsoft Bookings. In other words, they don't report completed bookings back to you.

Ask the vendor how availability is fetched and how often.

(c) Plugins that build a native form on the Graph API#

These plugins render the whole booking form on your site and create the appointment through the Microsoft Graph Bookings API. You get full control of design and events, and some add their own extras, such as a card payment step, because they own the form. The price is set-up and permissions:

  • App registration and admin consent. You register an app in Microsoft Entra ID and a tenant admin grants consent. Checking staff availability (getStaffAvailability) supports application permissions only, and delegated permissions aren't supported, so a server-side app identity is required. Some plugins ask for a Global Administrator during set-up.
  • Tenant-wide access. Application permissions such as Bookings.Read.All and BookingsAppointment.ReadWrite.All apply to every booking calendar in the tenant. Microsoft doesn't document a way to limit them to one booking page, which some security teams won't accept.
  • Business rules are your job. Microsoft says apps that create appointments with application permissions must validate business rules themselves: business hours, time increments, lead time, buffers and staff selection. If the plugin's slot logic differs from Bookings, visitors may see times Bookings wouldn't offer, or miss valid ones.
  • Shared bookings only. "The Microsoft Bookings API in Microsoft Graph applies only to shared bookings." The overview also says the business should have a Microsoft 365 Business Premium subscription.
  • Throttling. Graph allows four concurrent Bookings requests per app ID and mailbox combination.
  • No change notifications. Bookings isn't a supported Graph subscription resource (Microsoft staff answers on Bookings webhooks), so a plugin can't be notified of bookings made elsewhere without polling.

Some services leave the Bookings iframe or link in place and add measurement around it: campaign data sent to Google Analytics, consent-tool integration, sometimes user IDs. They don't change the booking experience. Because the confirmation happens inside a cross-origin page, how each one detects a completed booking varies and isn't always documented. Before buying, ask what signal counts as a conversion: a click, an iframe view, or a confirmed appointment. Tracking the Bookings iframe with GTM explains what page tags can and can't see.

What we saw when testing (September 2026)#

To build our own widget we captured the public shared booking page and the calls it makes (13 live captures across several time zones) and made and cancelled a handful of test bookings. Four findings matter to anyone choosing, or building, a custom front end that doesn't use Graph:

  • No CORS. The public booking API returns no CORS headers, so scripts on your website can't call it, or read the embedded page, from the browser. Any custom front end needs a server in between. We also found nothing in the iframe for the parent page to listen to.
  • Booking is slow. Reads took roughly 0.3 to 1.3 seconds from our server, but creating a booking took about 5.5 seconds. A front end needs a clear "booking…" state so visitors don't click twice.
  • The service checks little on its own. Called directly, it accepted a booking inside the lead-time window and one over a busy Outlook block. It only rejected a clash with another Bookings appointment. The booking page enforces the rest in the browser, so a custom front end should check the slot is still free right before it creates the booking.
  • Email codes. Our shared test page, on default settings, never asked for a verification code, but pages that require one (common on "Bookings with me") reject the first submit and email the customer a 6-digit code. The booking exists only after the form is resubmitted with it, so the front end needs a code step.

(e) BookingsXP#

BookingsXP renders its own booking widget on your site from your public booking page link. You don't sign in to Microsoft, register an Entra app or grant admin consent. Our server sits between the widget and the public page, which is how it works around the missing CORS headers. Before every booking it re-checks live that the slot is still free, and when a page asks for an email code, the widget shows a code box and Microsoft emails the code to the customer (BookingsXP can't switch that check off). The appointment is created in Microsoft Bookings, so the usual confirmation email, the staff member's Outlook calendar and the Teams link all work as before. Availability, staff, services, business hours, buffers and lead times come from your Bookings settings.

What it adds:

  • Embed. A script tag and web component with inline mode (which resizes to its content), popup or floating button. The script embed works in any site or framework today. React, Vue, Svelte and Astro packages are built but their npm release is pending. A WordPress plugin is available as a zip download (WordPress.org listing pending). There's also a hosted booking page at bookingsxp.com/book/<your-name> if you have no site to embed in; it isn't a custom domain (embed).
  • Events. Each step (widget_viewed through booking_completed) is pushed to window.dataLayer. Google Ads, Meta Pixel and LinkedIn conversions fire if those tags are on your page (analytics).
  • Attribution. UTM parameters, click IDs, referrer and landing page are written into the booking notes. Our test booking through the widget showed that summary in the notes of the Outlook event.
  • Website builders. There are setup pages for WordPress, Elementor, Webflow, Squarespace, Wix, Framer, HubSpot, GoDaddy, Google Sites and Shopify. Each says where the builder's embed block runs code in its own iframe (Wix, GoDaddy and Google Sites do). There, the widget's events stay inside that frame and page-level tracking is lost, so each of those pages gives the tracked alternative.
  • Optional data layer. Off by default, and when it's off BookingsXP stores no booking details. If you turn it on, it keeps a copy of each widget booking for signed webhooks, CSV export and reports (webhooks).

Honest trade-offs#

ApproachGood atWatch out for
(a) Plain iframeFree, documented by Microsoft, no set-up beyond copying codeFixed height; no events; no thank-you redirect; logo and colours only; fails if org sign-in is required
(b) Hand-off widgetBetter-looking availability previewVisitor finishes on the Bookings page; completions not trackable; times may lag if synced on a schedule
(c) Graph native formFull design control; own events; can add extras like paymentsEntra app and admin consent; tenant-wide permissions; must reproduce the Bookings rules; shared bookings only; throttling
(d) Tracking layerAdds campaign data without changing the pageConversion signal varies; ask what it counts; no UX change
(e) BookingsXPNo admin consent; branded widget; completed-booking events; source written into the booking"Bookings with me" pages best-effort only; webhooks cover only widget bookings, not bookings on the Microsoft-hosted page, by staff in the calendar, or cancellations from Microsoft email links; no round robin, routing or payments because rules come from Bookings; framework packages not yet on npm; the no-JavaScript iframe fallback can't resize or push events

When to keep the plain iframe#

  • A booking page on your site is all you need, and nobody is asking which campaign produced each meeting.
  • You don't mind the fixed-height frame, or the page sits somewhere with plenty of space.
  • You'd rather not add any third party to the booking flow.

When to move beyond the iframe#

  • Marketing needs completed bookings in GA4, Google Ads or Meta, not just clicks.
  • The booking experience has to match your site's design.
  • Sales wants to see the lead source on each appointment.
  • Choose a Graph-based form if you also need things only a custom form can do, and your admins accept tenant-wide application permissions.

Keeping Bookings and filling the gaps with BookingsXP#

All five approaches keep Microsoft Bookings as the system of record. BookingsXP aims to cover the website and tracking gaps without the admin-consent step that Graph-based forms need. Shared booking pages are fully supported, and personal pages work on a best-effort basis. There's a free plan with no credit card, and paid plans add templates, remove the badge, and include webhooks and advanced analytics (pricing).

BookingsXP is independent and not affiliated with or endorsed by Microsoft. Microsoft, Microsoft 365, Microsoft Bookings, Outlook and Teams are trademarks of the Microsoft group of companies. Other product names are trademarks of their respective owners.

Questions people also ask

Sources

  1. Microsoft Learn: Bookings faq (opens in a new tab) · learn.microsoft.com
  2. Microsoft Learn: Customize booking page (opens in a new tab) · learn.microsoft.com
  3. Microsoft Learn: Booking api overview (opens in a new tab) · learn.microsoft.com
  4. Microsoft Learn: Bookingbusiness getstaffavailability (opens in a new tab) · learn.microsoft.com
  5. Microsoft Learn: Bookingbusiness post appointments (opens in a new tab) · learn.microsoft.com
  6. Microsoft Learn: Bookingsbusiness business rules (opens in a new tab) · learn.microsoft.com
  7. Microsoft Learn: Throttling limits (opens in a new tab) · learn.microsoft.com
  8. Microsoft Learn: Bookings webhooks (opens in a new tab) · learn.microsoft.com
  9. Microsoft Learn: Cant embed bookings page into website (opens in a new tab) · learn.microsoft.com