Articles on: Frequently asked questions

GA4 Datalayer requirements

DataLayer Requirements - Booqi.me Booking Platform


Document Information

  • Platform: Booqi (multi-venue booking system)
  • Version: 1.0
  • Last Updated: November 2025
  • Purpose: Define the dataLayer structure for tracking user interactions and e-commerce events across Booqi-powered shops




1. General Page View Events


1.1 Homepage View

window.dataLayer = window.dataLayer || [];
dataLayer.push({
event: 'page_view',
page_type: 'homepage',
page_category: 'booking',
language: 'de', // or detected language
user_type: 'guest' // or 'returning_customer'
});


1.2 Product View

dataLayer.push({
event: 'page_view',
page_type: 'product',
page_category: 'booking',
language: 'de', // or detected language
user_type: 'guest' // or 'returning_customer'
});




2. Product Interaction Events


2.1 Product View (Product Detail)

Trigger: When a user visits a product detail page (URL contains /product/).


dataLayer.push({
event: 'view_item',
ecommerce: {
currency: 'EUR',
value: 72.0,
items: [{
item_id: '1234567',
item_name: 'All-inclusive Day Ticket',
item_category: 'Admission Tickets',
item_variant: 'standard', // or venue-specific variants
price: 72.0,
quantity: 1,
item_type: 'adult',
booking_type: 'individual' // or 'group', 'subscription'
}]
}
});


For Group Products:

dataLayer.push({
event: 'view_item',
ecommerce: {
currency: 'EUR',
value: 650.0,
items: [{
item_id: '1234567',
item_name: 'Group Guided Tour',
item_category: 'Group Tickets',
price: 25.0,
quantity: 26,
item_type: 'group',
booking_type: 'group'
}]
}
});


2.2 Product List View

Trigger: When viewing multiple products on a category page (e.g., shop homepage).


dataLayer.push({
event: 'view_item_list',
ecommerce: {
item_list_id: 'admission-tickets',
item_list_name: 'Admission Tickets',
items: [{
item_id: '1234567',
item_name: 'All-inclusive Day Ticket',
item_category: 'Admission Tickets',
price: 72.0,
index: 0
},
{
item_id: '7654321',
item_name: 'All-inclusive Afternoon Ticket',
item_category: 'Admission Tickets',
price: 0.0, // varies by date
index: 1
}]
}
});


2.3 Product Click

Trigger: When a user selects a product on the category page.


dataLayer.push({
event: 'select_item',
ecommerce: {
items: [{
item_id: '1234567',
item_name: 'All-inclusive Day Ticket',
item_category: 'Admission Tickets',
price: 72.0,
index: 0
}]
}
});




3. Booking Funnel Events


3.1 Date Selection

Trigger: When a user confirms a visit date and proceeds to the next step (if date selection is available).


dataLayer.push({
event: 'date_selected',
visit_date: '2025-11-07',
visit_day: 'Friday',
price_adult: 72.0,
price_child: 36.0,
product_id: 'all-inclusive-day-ticket',
product_name: 'All-inclusive Day Ticket',
total_tickets: 2,
total_value: 108.0
});


3.2 Time Slot Selection

Trigger: When a user confirms a time slot and proceeds (if time slot selection is available).


dataLayer.push({
event: 'timeslot_selected',
course_date: '2025-11-13',
time_slot: '11:00 - 13:00',
course_type: '2h Ski Group Beginner',
participant_type: 'adult', // or 'child'
participant_age: '13+',
price: 60.0
});




4. Cart Events


4.1 Add to Cart

Trigger: When a user proceeds to checkout after selecting items.


dataLayer.push({
event: 'add_to_cart',
ecommerce: {
currency: 'EUR',
value: 108.0,
items: [{
item_id: '1234567',
item_name: 'All-inclusive Day Ticket',
item_category: 'Admission Tickets',
price: 72.0,
quantity: 1,
item_type: 'adult'
},
{
item_id: '7654321',
item_name: 'All-inclusive Day Ticket',
item_category: 'Admission Tickets',
price: 36.0,
quantity: 1,
item_type: 'child'
}]
}
});




5. Checkout Events


5.1 Begin Checkout

Trigger: When a user enters the checkout flow (personal-details step).


dataLayer.push({
event: 'begin_checkout',
ecommerce: {
currency: 'EUR',
value: 108.0,
items: [{
item_id: '1234567',
item_name: 'All-inclusive Day Ticket',
item_category: 'Admission Tickets',
price: 72.0,
quantity: 1,
item_type: 'adult'
},
{
item_id: '7654321',
item_name: 'All-inclusive Day Ticket',
item_category: 'Admission Tickets',
price: 36.0,
quantity: 1,
item_type: 'child'
}]
}
});


5.2 Add Shipping Info (Personal Details)

Trigger: When personal details are completed and the user can continue to payment.


dataLayer.push({
event: 'add_shipping_info',
ecommerce: {
currency: 'EUR',
value: 108.0,
items: [{
item_id: '1234567',
item_name: 'All-inclusive Day Ticket',
item_category: 'Admission Tickets',
price: 72.0,
quantity: 1
}]
},
user_data: {
email_address: 'user@example.com',
phone_number: '+31612345678',
first_name: 'Alex',
last_name: 'Example'
}
});


5.3 Purchase

Trigger: When a booking completes successfully and the user lands on the thank-you page. Ensure the event fires only once per confirmed purchase.


dataLayer.push({
event: 'purchase',
ecommerce: {
transaction_id: 'T123456789',
affiliation: 'Venue Name',
value: 108.0,
tax: 0.0,
shipping: 0.0,
currency: 'EUR',
coupon: '',
items: [{
item_id: '1234567',
item_name: 'All-inclusive Day Ticket',
item_category: 'Admission Tickets',
item_variant: 'standard',
price: 72.0,
quantity: 1,
item_type: 'adult'
},
{
item_id: '7654321',
item_name: 'All-inclusive Day Ticket',
item_category: 'Admission Tickets',
item_variant: 'standard',
price: 36.0,
quantity: 1,
item_type: 'child'
}]
},
user_data: {
email_address: 'user@example.com',
phone_number: '+31612345678',
first_name: 'Alex',
last_name: 'Example'
}
});




6. Enhanced E-commerce Product Fields


Standard Product Object Structure

Include these fields when available.


{
item_id: 'unique-product-id',
item_name: 'Product Display Name',
affiliation: 'Venue Name',
coupon: '',
discount: 0.0,
index: 0,
item_brand: 'Venue Brand',
item_category: 'Admission Tickets',
item_category2: 'All-inclusive',
item_category3: '',
item_list_id: 'category-list-id',
item_list_name: 'Category Display Name',
item_variant: 'standard',
location_id: 'venue-location',
price: 72.0,
quantity: 1,
item_type: 'adult',
age_group: '13+',
visit_date: '2025-11-13',
time_slot: '11:00 - 13:00',
includes_equipment: true,
includes_food: true,
season: 'winter_2025',
booking_type: 'individual',
min_quantity: 25,
group_size: 26
}




7. Error Tracking


7.1 Booking Errors

Trigger: When a booking error occurs.


dataLayer.push({
event: 'booking_error',
error_type: 'availability', // or 'payment', 'validation', 'system'
error_code: 'NO_AVAILABILITY',
error_message: 'Selected date is fully booked',
product_id: 'all-inclusive-day-ticket',
step: 'date_selection' // or 'payment', etc.
});




8. Additional Tracking Recommendations


8.1 Session Information

Push once on initial page load.


dataLayer.push({
session_id: 'unique-session-id',
timestamp: '2025-11-03T14:30:00Z',
user_agent: navigator.userAgent,
viewport_size: '1920x1080',
device_type: 'desktop',
referrer: document.referrer
});


8.2 Price Monitoring

Track dynamic pricing changes.


dataLayer.push({
event: 'price_update',
product_id: 'all-inclusive-day-ticket',
previous_price: 108.0,
new_price: 123.0,
visit_date: '2025-11-08',
reason: 'weekend_pricing' // or 'peak_season', 'demand'
});




9. Implementation Notes


Best Practices

  1. Initialize window.dataLayer = window.dataLayer || []; before any pushes.
  2. Clear the ecommerce object with dataLayer.push({ ecommerce: null }); before each ecommerce push to prevent data pollution.
  3. Fire events only after the corresponding user action completes.
  4. Implement schema validation for all dataLayer events during development.
  5. Test in Google Tag Manager Preview mode and leverage the dataLayer debugger.


Data Quality Requirements

  • Prices use EUR with two decimal places.
  • Dates use ISO format (YYYY-MM-DD).
  • Item IDs remain consistent and unique per product.
  • Populate all required fields.
  • Do not send PII unless explicitly consented and contractually required.


Priority Events for Initial Implementation

  1. Phase 1 (Critical): page_view, view_item, add_to_cart, begin_checkout, purchase
  2. Phase 2 (Important): view_item_list, select_item, date_selected, form_error
  3. Phase 3 (Nice to have): upsells, price monitoring, session tracking




10. Multi-tenant / White-label Considerations


For venues using Booqi, append venue context to all relevant events.


dataLayer.push({
event: 'page_view',
page_type: 'homepage',
venue: {
venue_id: 'venue-slug',
venue_name: 'Venue Name',
venue_type: 'indoor_ski', // or 'museum', 'attraction', etc.
venue_location: 'City, Country'
}
});


Include in ecommerce items:

affiliation: 'Venue Name',
location_id: 'venue-location'




11. Document Version History

  • v1.0 (Nov 2025): Initial requirements derived from a reference booking flow, generalized for all Booqi shops.

Updated on: 11/11/2025

Was this article helpful?

Share your feedback

Cancel

Thank you!