Tracking inside embeds
MarketingIT / TechnicalWhen you embed the Preb booking widget on your own website, the widget runs
inside a frame — so your page's own Google Analytics, Tag Manager, or pixel can't
see what happens inside it directly. Instead, Preb sends events up to your
page, and you listen for them with a small window.Preb.on(...) snippet.
This is for the embedded widget on your site
If you use Preb's own hosted booking pages (not an embed), you don't need this — configure Meta, Google Ads, GA4, or GTM and Preb handles tracking on those pages for you.
The no-code way: automatic forwarding
The snippet from your event type's Embed tab ships with
data-preb-analytics="auto" switched on: Preb pushes every event straight into
the tags your page already has — Google Tag Manager (dataLayer), GA4 (gtag)
and Meta Pixel (fbq). Nothing is loaded or created; a page without these tags
is unaffected. Untick the option in the Embed tab if you want nothing forwarded.
<div
data-preb-link="acme/intro-call"
data-preb-analytics="auto"
></div>
<script src="https://app.preb.co/embed.js" async></script>
Events arrive under their Preb names (preb_booking_completed,
preb_form_started, …) with the payloads listed below. In Tag Manager, trigger
on a Custom Event named preb_booking_completed; in GA4 the events appear as
custom events; in Meta as custom events you can build audiences on.
Consent is respected the same way as everywhere else: funnel events only leave
the widget for consented visitors, and preb_booking_completed reaches GA4 and
Meta only when consent was granted (it always reaches the dataLayer, where
Tag Manager applies your own consent rules). The Embed tab has a checkbox that
adds the attribute for you.
Listen for events (custom code)
Place this before your embed snippet. The little stub queues your subscriptions until the embed script loads, so nothing is missed:
<!-- Place this before your embed snippet -->
<script>
window.Preb = window.Preb || {
_q: [],
on: function (a, b) { this._q.push([a, b]); }
};
// A completed booking — the conversion.
window.Preb.on('bookingSuccessful', function (data) {
// data: { uid, title, startTime, endTime, location,
// eventTypeId, eventTypeSlug, eventName }
});
// The same conversion in the exact shape Preb pushes to GA4 / GTM on hosted
// pages — forward it to your page's own tag so hosted and embedded bookings
// land in one report:
window.Preb.on('preb_booking_completed', function (data) {
if (window.gtag) window.gtag('event', 'preb_booking_completed', data);
if (window.dataLayer) window.dataLayer.push({ event: 'preb_booking_completed', ...data });
});
// Optional: funnel step events for drop-off analysis.
window.Preb.on('preb_event_type_viewed', function () { /* … */ });
window.Preb.on('preb_form_started', function () { /* … */ });
window.Preb.on('preb_day_selected', function () { /* … */ });
window.Preb.on('preb_time_selected', function () { /* … */ });
</script>
You can copy a ready-made version of this from your event type's Embed tab.
The events you can listen for
| Event | Fires when | Payload |
|---|---|---|
bookingSuccessful | A booking is confirmed | { uid, title, startTime, endTime, location, eventTypeId, eventTypeSlug, eventName } |
preb_booking_completed | Same moment — the conversion, in the shape Preb pushes to GA4/GTM | { preb_booking_uid, preb_contact_email, event_type_id, event_type_slug, event_name, marketing_consent } |
preb_event_type_viewed | The widget loads | event type |
preb_form_started | The visitor starts the form | event type |
preb_day_selected | A day is picked | event type + date |
preb_time_selected | A time is picked | event type + time |
Every event identifies the event type being booked, so a page that embeds more than one booking link can tell them apart:
window.Preb.on('preb_form_started', function (data) {
// data.event_type_slug → 'discovery-call'
// data.event_name → 'Discovery Call'
// data.event_type_id → Preb's internal ID
});
Wire these into gtag, dataLayer.push, fbq, or any analytics you run on
your page.
Funnel events respect consent
The preb_* funnel events are only sent up to your page for visitors who
accepted marketing cookies — see Consent inside embeds
for how the widget learns that. bookingSuccessful and preb_booking_completed always fire
so your booking confirmation logic runs regardless; preb_booking_completed
carries marketing_consent so you can decide what to attach. Don't attach ad
tracking that your own consent tooling hasn't cleared.
Consent inside embeds
Embedded on your site, the widget never shows a cookie banner of its own — your page owns consent, and a second banner inside a booking form would be wrong for your visitors. Instead, you hand the decision to the widget:
<!-- From your cookie banner's "accept" handler: -->
<script>
window.Preb.consent('granted'); // or 'denied' when a visitor withdraws
</script>
Preb.consent() applies to every Preb widget on the page, including ones that
open later (a popup), and updates a widget that is already open. It works
before embed.js has loaded as long as you include the small stub at the top
of this page.
If your site has no cookie banner at all — for example a landing page that sets no non-essential cookies — you can declare consent on the element instead:
<div data-preb-link="acme/intro-call" data-preb-consent="granted"></div>
Until the widget receives a granted decision it runs with consent denied:
no Meta Pixel, GTM or GA4 script is loaded inside the widget, no preb_* funnel
events are sent, and the booking is reported to Meta and Google server-side as
unconsented — exactly as for a hosted-page visitor who declined.
Your consent decision, your responsibility
Calling Preb.consent('granted') tells Preb that this visitor agreed to
marketing cookies on your site. Only call it after a real opt-in from your own
consent tooling. The event-type setting Hide cookie banner does not affect
embeds — inside an embed the banner is never shown, regardless of that setting.
Verify your setup
Open your page with the embed, book a test appointment, and watch your browser's
developer Console — a quick console.log inside each handler confirms the
events arrive. Then check they land in your analytics (GA4 Realtime, GTM
Preview, or Meta Pixel Helper).
Attribution in embeds
The inline and popup embeds automatically forward ad click IDs and UTM tags
(gclid, fbclid, utm_*) from your page's URL into the widget, so campaign
attribution keeps working. They also pass along your page's address so
Meta receives your landing page — not the widget's own address — as the source
of the conversion. If instead you link out to a hosted booking page from
a button, add the forwarding snippet from the Embed tab to your landing page.
See Attribution & UTM tracking.