Tracking & analytics
Know which ads and pages book appointments
Microsoft Bookings has no analytics and no conversion tracking. BookingsXP reports every step of the booking to GA4, Tag Manager and your ad platforms, and writes the source of each booking into its notes in Microsoft Bookings.
Events and attribution are on the Free plan
- Widget views
- 4,812
- unique visits that saw a widget
- Bookings
- 187
- 3 failed attempts
- Conversion rate
- 3.9%
- bookings ÷ views
- Missed demand
- 96
- visits that found no open times
Booking funnel
Unique visits reaching each step.
- Saw the widget4,812
- Picked a day1,904, a drop of −60%
- Picked a time1,122, a drop of −41%
- Started details498, a drop of −56%
- Booked187, a drop of −62%
3.9% of visits that saw the widget booked. Largest drop: Started details to booked (−62%).
Channels
GA4-style default channel grouping.
| Channel | Views | Bookings | Conv. |
|---|---|---|---|
| Paid search | 1,642 | 78 | 4.8% |
| Organic search | 1,318 | 52 | 3.9% |
| Direct | 824 | 29 | 3.5% |
| Paid social | 486 | 9 | 1.9% |
| 212 | 11 | 5.2% | |
| Referral | 198 | 5 | 2.5% |
| Organic social | 132 | 3 | 2.3% |
Campaigns
From utm_campaign.
| Campaign | Views | Bookings | Conv. |
|---|---|---|---|
| spring-physio | 1,106 | 58 | 5.2% |
| brand | 536 | 20 | 3.7% |
| october-newsletter | 212 | 11 | 5.2% |
| retargeting-q3 | 486 | 9 | 1.9% |
Devices
| Device | Views | Bookings | Conv. |
|---|---|---|---|
| Mobile | 2,934 | 101 | 3.4% |
| Desktop | 1,702 | 80 | 4.7% |
| Tablet | 176 | 6 | 3.4% |
Pages
Where the widget was when people booked.
| Page | Views | Bookings | Conv. |
|---|---|---|---|
| /physio | 2,210 | 96 | 4.3% |
| /book | 1,380 | 58 | 4.2% |
| /massage | 804 | 22 | 2.7% |
| /contact | 418 | 11 | 2.6% |
When appointments land
Booked appointments by weekday and hour (America/New_York).
| 7:00 | 8:00 | 9:00 | 10:00 | 11:00 | 12:00 | 13:00 | 14:00 | 15:00 | 16:00 | 17:00 | 18:00 | 19:00 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Sun | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Mon | 0 | 2 | 4 | 5 | 4 | 3 | 3 | 4 | 3 | 3 | 4 | 3 | 0 |
| Tue | 0 | 3 | 5 | 6 | 4 | 3 | 3 | 4 | 4 | 3 | 5 | 4 | 0 |
| Wed | 0 | 2 | 4 | 5 | 4 | 2 | 3 | 3 | 3 | 3 | 4 | 3 | 0 |
| Thu | 0 | 2 | 4 | 4 | 3 | 2 | 3 | 3 | 3 | 2 | 4 | 3 | 0 |
| Fri | 0 | 2 | 3 | 4 | 3 | 2 | 2 | 2 | 2 | 1 | 0 | 0 | 0 |
| Sat | 0 | 0 | 3 | 4 | 4 | 3 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
- Widget views
- 4,812
- unique visits that saw a widget
- Bookings
- 187
- 3 failed attempts
- Conversion rate
- 3.9%
- bookings ÷ views
- Missed demand
- 96
- visits that found no open times
Booking funnel
Unique visits reaching each step.
- Saw the widget4,812
- Picked a day1,904, a drop of −60%
- Picked a time1,122, a drop of −41%
- Started details498, a drop of −56%
- Booked187, a drop of −62%
3.9% of visits that saw the widget booked. Largest drop: Started details to booked (−62%).
Channels
GA4-style default channel grouping.
| Channel | Views | Bookings | Conv. |
|---|---|---|---|
| Paid search | 1,642 | 78 | 4.8% |
| Organic search | 1,318 | 52 | 3.9% |
| Direct | 824 | 29 | 3.5% |
| Paid social | 486 | 9 | 1.9% |
| 212 | 11 | 5.2% | |
| Referral | 198 | 5 | 2.5% |
| Organic social | 132 | 3 | 2.3% |
Campaigns
From utm_campaign.
| Campaign | Views | Bookings | Conv. |
|---|---|---|---|
| spring-physio | 1,106 | 58 | 5.2% |
| brand | 536 | 20 | 3.7% |
| october-newsletter | 212 | 11 | 5.2% |
| retargeting-q3 | 486 | 9 | 1.9% |
The problem
The booking happens where your tags cannot see it
- 01
Your tags cannot run there
The Bookings page is on Microsoft's domain. You cannot add GA4, Tag Manager, the Google tag or a Meta pixel to it, so the visit you paid for ends at the link.
- 02
There is no conversion to count
Bookings sends no event when someone books, so Google Ads and Meta cannot learn which clicks turn into appointments, and automated bidding has no booking signal to work from.
- 03
The source is lost
The appointment in Outlook says who booked and when, not whether they came from an ad, a search or a newsletter. The RefId workaround is reported unreliable, and its value never appears in the calendar event.
Events
What the widget sends, and where
dataLayer as bookingsxp.<event> and dispatched as a bookingsxp:<event> DOM event. Four steps also go straight to GA4, and a confirmed booking fires your ad conversions.| dataLayer event | When | GA4 event | Ad platforms (Pro) |
|---|---|---|---|
| bookingsxp.widget_viewed | The widget came into view | bookingsxp_view | Meta ViewContent |
| bookingsxp.service_selected | A service was picked | Not sent | None |
| bookingsxp.staff_selected | A person was picked (if offered) | Not sent | None |
| bookingsxp.date_selected | A day was picked | Not sent | None |
| bookingsxp.slot_selected | A time was picked | bookingsxp_slot | None |
| bookingsxp.form_started | The visitor started typing their details | bookingsxp_form_start | None |
| bookingsxp.booking_submitted | The form was sent | Not sent | None |
| bookingsxp.booking_completed | Microsoft Bookings confirmed the booking | generate_lead + bookingsxp_booked | Google Ads conversion, Meta Schedule, LinkedIn conversion |
| bookingsxp.booking_failed | The booking could not be made | Not sent | None |
| bookingsxp.no_availability | The visitor found no open times | Not sent | None |
- GA4 events are sent directly when
gtag.jsis on the page and you add your measurement ID; otherwise use Tag Manager on the dataLayer events.valueandcurrencycome from the service price when Bookings has one. - Google Ads, Meta and LinkedIn fire only when that platform's tag is already on the page and its ID is set in the widget. Google Ads gets the booking ID as the transaction ID; Meta gets it as the event ID, so duplicates are dropped.
Attribution
The source, inside the booking
Initial assessment
Wed 14 Oct, 10:15–11:00Dr. Maya Chen
- Customer
- Alex Rivera
- alex.rivera@example.com
- Phone
- +1 555 0142
Notes
Left knee, running injury.
— Booked on your website · Ref BXP-7K3M9Q
Source: google / cpc · Campaign: spring-physio (Paid search)
Keyword: sports physio near me
First page: /physio?area=knee
Booked from: northwind.example/book
Referrer: google.com
Ad click: gclidWritten into the booking by BookingsXP. Microsoft Bookings keeps it with the appointment in Outlook, Teams and the Bookings app.
- What is captured
- utm_source, utm_medium, utm_campaign, utm_term and utm_content; the gclid, gbraid, wbraid, fbclid, msclkid, li_fat_id or ttclid click ID; the referrer; the first page; and the page the booking was made on.
- First touch that counts
- The loader remembers the last campaign visit for 90 days, so someone who clicks an ad on Monday and books from a bookmark on Friday is still credited to the ad. A plain return visit does not overwrite it.
- GA4-style channels
- Each booking is classified as Paid search, Paid social, Organic search, Organic social, Email, Referral, Direct or Other, the same grouping GA4 uses by default.
- In Bookings' own export
- Optionally, BookingsXP answers a custom question on your Bookings page, such as “How did you hear about us?”, with the source, and hides it from visitors. It then shows up in Microsoft's own reports and exports.
- A reference on both sides
- Each booking gets a reference like BXP-7K3M9Q, written into the notes and sent to Microsoft as the booking's tracking data, so you can match a booking in Outlook to its row in BookingsXP.
Dashboard
What the dashboard reports
- Views, bookings and conversion rateAll plans
- Unique visits that saw a widget, confirmed bookings, failed attempts and bookings ÷ views, with a daily chart of each.
- Missed demandAll plans
- Visits that opened the widget and found no open times. The number to show whoever sets staff hours.
- Booking funnelPro
- Saw the widget, picked a day, picked a time, started details, booked: where visitors drop off.
- Channels and source / mediumPro
- GA4-style channel grouping, plus the raw source and medium, with views, bookings and conversion rate for each.
- CampaignsPro
- Every utm_campaign that brought a visit, and how many of those visits booked.
- PagesPro
- Which pages the widget was on when people booked, for sites with the widget in several places.
- Services and devicesPro
- Which services people considered and booked, and how mobile, desktop and tablet visitors convert.
- When appointments landPro
- A weekday by hour heatmap of booked appointments, in your own time zone.
- CSV exportPro
- Every event in the period as a CSV file, for your own reporting.
Privacy
Enhanced conversions without shipping raw emails
- Hashed in the browser
- With enhanced conversions on, the widget computes a SHA-256 hash of the email on the visitor's device and sends Google Ads only the hash, as sha256_email_address. The raw address never goes to Google.
- Only on a confirmed booking
- The hash exists only on booking_completed, and only for widgets with enhanced conversions switched on. Update your privacy notice before you turn it on.
- Global Privacy Control honoured
- When the browser sends GPC, or your consent tool sets window.bxpConsent = false, the loader sends only the page path and the referrer's domain, and forgets any stored campaign touch.
- No cookies set
- The loader sets no cookies. It reads only the _ga, _fbp and _fbc cookies your own tags already set, so GA4 and Meta can join the booking to the visit.
Setup
Set it up in Tag Manager
bookingsxp.booking_completed. The step-by-step guide is in GTM and GA4 setup, with platform notes for Google Tag Manager and Google Ads.// What the loader pushes on your page when a booking is confirmed
window.dataLayer.push({
event: "bookingsxp.booking_completed",
bookingsxp: {
name: "booking_completed",
widgetId: "w_8fk2m1qz",
businessName: "Northwind Wellness",
service: { id: "8b3c2f4e-…", name: "Initial assessment", durationMinutes: 45 },
staff: { id: "f41e9a27-…", name: "Dr. Maya Chen" },
slot: {
start: "2026-10-14T14:15:00.000Z",
end: "2026-10-14T15:00:00.000Z",
timeZone: "America/New_York",
},
booking: { id: "AAMkADk2ZTJh…" },
},
});Trigger Custom Event
Event name: bookingsxp.booking_completed
Variables Data Layer Variable bookingsxp.service.name
Data Layer Variable bookingsxp.booking.id
Tag Google Analytics: GA4 Event
Event name: generate_lead
Parameters: service_name = {{bookingsxp.service.name}}
Trigger: the Custom Event above// Or listen in your own code, no Tag Manager needed
window.addEventListener("bookingsxp:booking_completed", (e) => {
const { service, slot, booking } = e.detail;
console.log("Booked", service.name, slot.start, booking.id);
});Thank-you page
Send people to your own confirmation page
Redirect URL
https://northwind.example/thank-you?id={booking_id}&service={service}&start={start}Where the visitor lands
https://northwind.example/thank-you?id=AAMkADk2ZTJh…&service=Initial%20assessment&start=2026-10-14T14%3A15%3A00.000Z{booking_id} is Microsoft's booking ID, {service} the service name and {start} the start time in ISO format, all URL-encoded. Relative URLs work, and a redirect-url attribute on the element overrides the saved setting for one page.
Plans
What each plan tracks
| Feature | Free | Pro | Business |
|---|---|---|---|
| dataLayer events for Google Tag Manager | Included | Included | Included |
| GA4 events | Included | Included | Included |
| Source and campaign in every booking's notes | Included | Included | Included |
| Thank-you page redirect | Included | Included | Included |
| Views, bookings, conversion rate, missed demand | 30 days | 12 months | 24 months |
| Funnel, channel, campaign, page and device reports | Not included | Included | Included |
| Google Ads, Meta and LinkedIn conversions | Not included | Included | Included |
| Enhanced conversions (hashed email) | Not included | Included | Included |
| CSV export | Not included | Included | Included |
Want the booking data itself in your CRM? Webhooks and data
FAQ
Questions about tracking
Count every booking
Events, GA4 and attribution in every booking are on the Free plan. Add Google Ads, Meta and reports when you need them.