> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://support.booqi.me/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# GA4 Datalayer requirements

# DataLayer Requirements - Booqi.me Booking Platform

Below you will find our datalayer documentation. 

### .JSON Container
We have a generic .json file that you can import directly in your Google Tagmanager, to add all events and triggers.
You can use the following container: 

${frame}[](https://drive.google.com/file/d/1ec14zwiUF0nqAqyMtDDlbhBehilJVFZz/preview)


Please make sure to fill in the empty placeholders were needed. Also always double check and test if everything is working for your specific case.

## Datalayer Information
## 1. General Page View Events

### 1.1 Homepage View
```javascript
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
```javascript
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/`).

```javascript
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:**
```javascript
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).

```javascript
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.

```javascript
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).

```javascript
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).

```javascript
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.

```javascript
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).

```javascript
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.

```javascript
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.

```javascript
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.

```javascript
{
  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.

```javascript
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.

```javascript
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.

```javascript
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.

```javascript
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:
```javascript
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.


