Skip to content
English
  • There are no suggestions because the search field is empty.

Google tag manager & Google analytics

Want to track how people use your booking widget? Just add your Google Analytics ID in the Now Book It admin app

Basic setup

go to Venue > Diary > Integrations.

You've got two options:

  • A Google Analytics tracking ID (looks like UA-XXXXX-Y)
  • A Google Tag Manager ID (looks like GTM-XXXXXXX) — we'll add the right scripts for you automatically

That's it for most venues.

Keep reading only if you need the tracking data sent to your own website instead. For example, to feed it into a third-party tracking tool.

Also tracking Meta (Facebook) conversions? That's a separate setup, see our Meta Pixel tracking article.

What the widget sends

Every event the widget fires uses the same name, category and payload every time. If you're setting up Tag Manager triggers or GA4 conversions, build them around these exact values, don't change them.

Where the data goes

By default, the widget sends events straight to Google itself, using whichever Analytics or Tag Manager ID you've set up. If you turn on analytics=bubble instead, the widget stops sending anything to Google directly — instead, it hands each event to your website, and it's up to your own tracking setup to forward it on.

Every event includes the same core details: event, event_category, event_action, event_label, and cookie_flags. If the widget's launch link includes a #referrer= value, you'll also get a referrer field.

The extra details in the tables below appear differently depending on your setup: on GA4 (G-) containers and in bubble mode, they sit alongside venue_name at the top level of the event. On Universal Analytics or Tag Manager, you'll find the same details nested inside event_data and event_value.

Conversion events

Event Category What's in it When it fires
Booking Confirmed Booking service_name, service_id, covers, section_id, section_name, service_price, service_type (+ any opted-in customer fields) A booking was saved on a sitting that doesn't need payment. This is your standard "booking made" conversion.
Booking Paid Payment Same as above A booking was saved and its payment or card guarantee went through.
Private Function Paid Payment service_name, service_id, covers, section_id, section_name, service_price, service_type A private-function payment link was paid.
Booking Confirmed Online Manage Booking service_name, service_id, covers, section_id, section_name, service_type (+ any opted-in customer fields) A guest confirmed an existing booking from their email link.
Booking Edited Online Manage Booking A guest changed an existing booking from their email link.
Booking Cancelled Online Manage Booking A guest cancelled a booking, either from the link or the confirmation screen.

For events marked "opted-in customer fields": if the venue has switched these on in the admin app, you'll also get whichever of email, phone, first_name, last_name, subscribed, and booking_date they've opted into. If none are switched on, none of these fields are sent.

What happens as guests move through the widget

These events show you the shape of the booking funnel i.e. where guests land, what they change, and where they drop off.

Event Category What's in it When it fires
Covers updated User input covers_count Guest changed the party size.
Date selected User input date Guest picked a different date. (The date the widget opens on isn't reported.)
Time selected User input time, service_name, service_id, service_type Guest picked a time — includes which sitting that time belongs to.
Booking option selected User input booking_options Guest changed their booking options or menu selections.
Event URL service_name, service_id Guest arrived via a manage-booking link, for that booking's sitting.
Private Function URL service_name, service_id Guest arrived via a private-function payment link.
Error saving User input The booking failed to save for some reason other than the time slot being taken.
Time expired User input The time the guest chose got taken by someone else while they were filling in their details.
Payment Timeout Timeout The guest ran out of time on the payment hold without paying.

Screen views

Every screen in the widget sends its own event, named after that screen:

Error, Select Venue, Booking Details (landing), Booking Details (takeaway), Customer Details, Payment Details, Thank You, Manage Booking, Standby List, Payment Details (private function), Payment Confirmation.

Each screen view is sent as an event named after the page, with event_category set to "Page View", plus page_title, page_url, and page.

The widget also pushes something called nbi_widget_step onto its own internal dataLayer every time the guest moves to a new step. This one doesn't leave the widget, so it's only useful if your tracking container is running inside the widget itself. If your container's on your own page, use the screen view events above instead.

Got a Meta Pixel connected too? It gets these same page names as its own events — see the Meta Pixel tracking article.

Adding a custom referrer in Tag Manager

Want a custom "referrer" URL value to show up inside Google Tag Manager? Here's how:

  1. In Tag Manager, go to Workspace → Variables and create a new user-defined variable. Call it something like "Custom Fragment Referrer".
  2. Set the variable type to URL.
  3. Set the component type to Fragment.
  4. Save and publish the variable.
  5. Add #referrer=MY_REFERRER_URL to the end of the iframe's URL, swapping in your own value for MY_REFERRER_URL.

From then on, every event fired in Tag Manager will also carry your "Custom Fragment Referrer" value.

If you'd rather not use the URL fragment, the same referrer value is also available as a property called referrer inside the dataLayer's eventModel object — you can use that as your variable's source instead.

When the referrer value changes dynamically

Sometimes you won't know the referrer value in advance, so you can't hardcode it.

If you can't set #referrer=MY_REFERRER_URL when the page loads using a back-end language like PHP, C#, or Java — which is often the case on website builders like Wix or Squarespace — you can set it with JavaScript instead. Just add this after the iframe's HTML:

<script> var frame = document.querySelector('[data-id="nbi-widget"]'); frame.src += '#referrer=' + window.location.href; </script> 

On Squarespace and similar builders: the code box you're typing into is often already inside its own iframe, so you need to reach one level further up. Use window.parent instead:

<script> var frame = document.querySelector('[data-id="nbi-widget"]'); frame.src += '#referrer=' + window.parent.location.href; </script> 

Want to use a tracking ID instead of a referrer URL? First, read it out of your page's URL (swap mytrackingid for whatever your parameter is actually called):

<script> var url = new URL(window.location.href); var trackingId = url.searchParams.get('mytrackingid'); </script> 

Then pass it into the widget's iframe:

<script> var frame = document.querySelector('[data-id="nbi-widget"]'); frame.src += '#referrer=' + trackingId; </script> 

Sending events to your own page instead

Want to handle the tracking data yourself — say, to feed it into a third-party tracking tool — rather than letting the widget send it straight to Google? You can.

Add &analytics=bubble to the widget's iframe URL. This stops the widget sending anything to Google itself, and instead sends each event to your page. Then add the matching code below to your page to catch that data and pass it wherever you need it.

Sending events to Google Tag Manager's dataLayer:

<script> window.addEventListener('message', function (e) {   if (e.origin !== 'https://bookings.dev.nowbookit.com') return;   if (!e.data || typeof e.data !== 'string') return;   if (e.data.indexOf('NBIWidget2GoogleAnalytics') === -1) return;    var payload;   try {     payload = JSON.parse(e.data);   } catch (error) {     // add your own logging here     return;   }    if (payload.type !== 'NBIWidget2GoogleAnalytics' || !payload.event) return;   var event = payload.event;    var dataLayer = window.dataLayer || (parent.window && parent.window.dataLayer);   if (dataLayer) dataLayer.push(event); }); </script> 

Sending events to Google Analytics 3 (Universal Analytics), using ga():

<script> window.addEventListener('message', function (e) {   if (e.origin !== 'https://bookings.dev.nowbookit.com') return;   if (!e.data || typeof e.data !== 'string') return;   if (e.data.indexOf('NBIWidget2GoogleAnalytics') === -1) return;    var payload;   try {     payload = JSON.parse(e.data);   } catch (error) {     // add your own logging here     return;   }    if (payload.type !== 'NBIWidget2GoogleAnalytics' || !payload.event) return;   var event = payload.event;    var ga = window.ga || (parent.window && parent.window.ga);   if (!ga) return;    if (event.page_title) {     ga('send', { hitType: 'pageview', title: event.page_title, page: event.page_url });   } else {     ga('send', {       hitType: 'event',       eventCategory: event.event_category,       eventAction: event.event_action,       eventLabel: event.event_label,     });   } }); </script> 

Sending events to Google Analytics 4, using gtag():

<script> window.addEventListener('message', function (e) {   if (e.origin !== 'https://bookings.dev.nowbookit.com') return;   if (!e.data || typeof e.data !== 'string') return;   if (e.data.indexOf('NBIWidget2GoogleAnalytics') === -1) return;    var payload;   try {     payload = JSON.parse(e.data);   } catch (error) {     // add your own logging here     return;   }    if (payload.type !== 'NBIWidget2GoogleAnalytics' || !payload.event) return;   var event = payload.event;    if (typeof gtag !== 'function') return;    if (event.page_title) {     gtag('event', 'page_view', Object.assign({       page_title: event.page_title,       page_location: event.page_url,     }, event));   } else {     gtag('event', event.event, Object.assign({       event_category: event.event_category,       event_action: event.event_action,       event_label: event.event_label,     }, event));   } }); </script> 

Sending events to your own third-party tracking tool: every tool's setup is different, but you'll always read the data the same way, through payload.event:

<script> window.addEventListener('message', function (e) {   if (e.origin !== 'https://bookings.dev.nowbookit.com') return;   if (!e.data || typeof e.data !== 'string') return;   if (e.data.indexOf('NBIWidget2GoogleAnalytics') === -1) return;    var payload;   try {     payload = JSON.parse(e.data);   } catch (error) {     // add your own logging here     return;   }    if (payload.type !== 'NBIWidget2GoogleAnalytics' || !payload.event) return;   var event = payload.event;    // event.event / event_category / event_action / event_label / value ...   // send it wherever you need:   // myTracker.track(event.event, event);   console.log('nbi widget event', event); }); </script> 

Want to test it out before you go live? Open the booking widget's embed builder and reload the reference page with &my-analytics-test=true added to the URL. That flags the page in Google Analytics so it's easy to spot. Paste in your own GTM-XXXXXXX or UA-XXXXX-Y code, and every widget on the page will use it and send tracking data straight to your account.