Booking Experts data layer events
Full reference of GA4 and custom events, parameters, and sample payloads.
Pre-release notice: These docs reflect the schema that becomes active on 18 Mar 2026. Events marked Active are part of that upcoming schema. Events marked Deprecated are legacy payloads still emitted today and will stop after 18 Mar 2026.
Looking for setup guidance? See Booking Experts data layer overview.
Deprecated events: See Deprecated data layer events for legacy payloads and removals.
GA4 events
add_to_cart
A user adds items to the cart.
Triggered when a user adds one or more items to the cart on a booking site or adds extras/upgrades in the checkout portal.
If the add-to-cart action comes from availability search, a search snapshot is included (same shape as search_results_loaded.search).
Top-level objects
ecommerce
Ecommerce payload wrapper for GA4 events.
Fields below apply only when ecommerce is present in the payload. Presence values are scoped to this group.
ecommerce.items[]
Items array for the ecommerce payload.
Fields below apply only when ecommerce.items[] is present in the payload. Presence values are scoped to this group.
search
Availability search snapshot for the add_to_cart action. Source: Website availability search state (dates, guests, amenities) when adding to cart.
Fields below apply only when search is present in the payload. Presence values are scoped to this group.
search.guest_group
Guest counts by group (see guest_group fields). Source: Guest group from search form.
Fields below apply only when search.guest_group is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"add_to_cart","ecommerce":{"currency":"EUR","value":350.0,"items":[{"item_id":"123123","item_name":"4-Person Luxury Villa","item_brand":"Administration Name","item_category":"Accommodation","item_category2":"house","item_variant":"single_night","item_list_id":"cart","item_list_name":"Cart","item_country":"Netherlands","item_region":"Twente","item_city":"Enschede","administration_id":"321321","administration_name":"Administration Name","coupon":"SUMMER10","discount":25.0,"price":350.0,"quantity":1,"index":1,"start_date":"2026-02-20","end_date":"2026-02-22","google_business_vertical":"hotel_rental"}]},"search":{"start_date":"2026-02-20","end_date":"2026-02-22","nights":2,"rentable_type":"house","guest_group":{"seniors":0,"adults":2,"adolescents":0,"children":1,"babies":0,"pets":0,"total":3},"price_range_min":100,"price_range_max":500,"sorting_id":"price_asc","amenities":{"facility":["pool"]},"amenities_count":2,"has_results":true,"results_count":42,"special_period_id":123,"special_period_name":"Summer Holiday"}});Clear ecommerce before every ecommerce event to avoid reusing items: dataLayer.push({ ecommerce: null });
remove_from_cart
A user removes items from the cart.
Triggered when a user removes one or more items from the cart on a booking site or removes extras/upgrades in the checkout portal.
Top-level objects
ecommerce
Ecommerce payload wrapper for GA4 events.
Fields below apply only when ecommerce is present in the payload. Presence values are scoped to this group.
ecommerce.items[]
Items array for the ecommerce payload.
Fields below apply only when ecommerce.items[] is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"remove_from_cart","ecommerce":{"currency":"EUR","value":350.0,"items":[{"item_id":"123123","item_name":"4-Person Luxury Villa","item_brand":"Administration Name","item_category":"Accommodation","item_category2":"house","item_variant":"single_night","item_list_id":"cart","item_list_name":"Cart","item_country":"Netherlands","item_region":"Twente","item_city":"Enschede","administration_id":"321321","administration_name":"Administration Name","coupon":"SUMMER10","discount":25.0,"price":350.0,"quantity":1,"index":1,"start_date":"2026-02-20","end_date":"2026-02-22","google_business_vertical":"hotel_rental"}]}});Clear ecommerce before every ecommerce event to avoid reusing items: dataLayer.push({ ecommerce: null });
view_cart
A user views their cart.
Triggered when a user views their cart on a booking site or reaches the upgrades step in the checkout portal.
Top-level objects
ecommerce
Ecommerce payload wrapper for GA4 events.
Fields below apply only when ecommerce is present in the payload. Presence values are scoped to this group.
ecommerce.items[]
Items array for the ecommerce payload.
Fields below apply only when ecommerce.items[] is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"view_cart","ecommerce":{"currency":"EUR","value":350.0,"items":[{"item_id":"123123","item_name":"4-Person Luxury Villa","item_brand":"Administration Name","item_category":"Accommodation","item_category2":"house","item_variant":"single_night","item_list_id":"cart","item_list_name":"Cart","coupon":"SUMMER10","discount":25.0,"price":350.0,"quantity":1,"index":1,"item_country":"Netherlands","item_region":"Twente","item_city":"Enschede","administration_id":"321321","administration_name":"Administration Name","start_date":"2026-02-20","end_date":"2026-02-22","google_business_vertical":"hotel_rental"}]}});Clear ecommerce before every ecommerce event to avoid reusing items: dataLayer.push({ ecommerce: null });
begin_checkout
A user begins checkout.
Triggered when a user begins checkout.
Source: checkout portal flow (PMS). This is emitted when the Stay step is shown.
If a CMS search snapshot cookie is present, a top-level search object is included.
Checkout portal emits a booking snapshot with totals and guest group counts (status = concept).
Top-level objects
ecommerce
Ecommerce payload wrapper for GA4 events.
Fields below apply only when ecommerce is present in the payload. Presence values are scoped to this group.
ecommerce.items[]
Items array for the ecommerce payload.
Fields below apply only when ecommerce.items[] is present in the payload. Presence values are scoped to this group.
search
Availability search snapshot for the checkout action. Source: Availability search snapshot when checkout starts (shared from CMS via cookie).
Fields below apply only when search is present in the payload. Presence values are scoped to this group.
search.guest_group
Guest counts by group (see guest_group fields). Source: Guest group from search form.
Fields below apply only when search.guest_group is present in the payload. Presence values are scoped to this group.
booking
Booking snapshot with status concept and checkout totals. Source: Checkout portal booking summary.
Fields below apply only when booking is present in the payload. Presence values are scoped to this group.
booking.guest_group
Guest counts by group (see guest_group fields). Source: Aggregated guest group from reservations.
Fields below apply only when booking.guest_group is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"begin_checkout","ecommerce":{"currency":"EUR","value":350.0,"coupon":"SUMMER10","items":[{"item_id":"123123","item_name":"4-Person Luxury Villa","item_brand":"Administration Name","item_category":"Accommodation","item_category2":"house","item_variant":"single_night","item_list_id":"checkout","item_list_name":"Checkout","coupon":"SUMMER10","discount":25.0,"price":350.0,"quantity":1,"index":1,"item_country":"Netherlands","item_region":"Twente","item_city":"Enschede","administration_id":"321321","administration_name":"Administration Name","start_date":"2026-02-20","end_date":"2026-02-22","google_business_vertical":"hotel_rental"}]},"search":{"start_date":"2026-02-20","end_date":"2026-02-22","nights":2,"rentable_type":"house","guest_group":{"seniors":0,"adults":2,"adolescents":0,"children":1,"babies":0,"pets":0,"total":3},"price_range_min":100,"price_range_max":500,"sorting_id":"price_asc","amenities":{"facility":["pool"]},"amenities_count":2,"has_results":true,"results_count":42,"special_period_id":123,"special_period_name":"Summer Holiday"},"booking":{"status":"concept","final":false,"guest_group":{"seniors":0,"adults":2,"adolescents":0,"children":1,"babies":0,"pets":0,"total":3},"currency":"EUR","total":350,"base_rent_total":350,"upgrade_total":0,"preference_total":0,"deposit_total":0,"deferred_deposit_total":0,"security_deposit_total":0,"tourist_taxes_total":0,"vat_total":50}});Clear ecommerce before every ecommerce event to avoid reusing items: dataLayer.push({ ecommerce: null });
We do not auto-clear booking. If you map booking outside booking events, clear it manually with dataLayer.push({ booking: null }).
add_shipping_info
A user submits guest details during checkout.
Triggered after a user successfully submits the details step during checkout.
Emitted when the confirmation step is loaded directly after the details form submit.
Top-level objects
ecommerce
Ecommerce payload wrapper for GA4 events.
Fields below apply only when ecommerce is present in the payload. Presence values are scoped to this group.
ecommerce.items[]
Items array for the ecommerce payload.
Fields below apply only when ecommerce.items[] is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"add_shipping_info","ecommerce":{"currency":"EUR","value":350.0,"coupon":"SUMMER10","shipping_tier":"Standard","items":[{"item_id":"123123","item_name":"4-Person Luxury Villa","item_brand":"Administration Name","item_category":"Accommodation","item_category2":"house","item_variant":"single_night","item_list_id":"checkout","item_list_name":"Checkout","coupon":"SUMMER10","discount":25.0,"price":350.0,"quantity":1,"index":1,"item_country":"Netherlands","item_region":"Twente","item_city":"Enschede","administration_id":"321321","administration_name":"Administration Name","start_date":"2026-02-20","end_date":"2026-02-22","google_business_vertical":"hotel_rental"}]}});Clear ecommerce before every ecommerce event to avoid reusing items: dataLayer.push({ ecommerce: null });
add_payment_info
A user selects a payment method during checkout.
Triggered when a user selects a payment method during checkout.
Emitted when the user selects a payment method in the payment portal.
Top-level objects
ecommerce
Ecommerce payload wrapper for GA4 events.
Fields below apply only when ecommerce is present in the payload. Presence values are scoped to this group.
ecommerce.items[]
Items array for the ecommerce payload.
Fields below apply only when ecommerce.items[] is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"add_payment_info","ecommerce":{"currency":"EUR","value":350.0,"coupon":"SUMMER10","payment_type":"ideal","items":[{"item_id":"123123","item_name":"4-Person Luxury Villa","item_brand":"Administration Name","item_category":"Accommodation","item_category2":"house","item_variant":"single_night","item_list_id":"checkout","item_list_name":"Checkout","coupon":"SUMMER10","discount":25.0,"price":350.0,"quantity":1,"index":1,"item_country":"Netherlands","item_region":"Twente","item_city":"Enschede","administration_id":"321321","administration_name":"Administration Name","start_date":"2026-02-20","end_date":"2026-02-22","google_business_vertical":"hotel_rental"}]}});Clear ecommerce before every ecommerce event to avoid reusing items: dataLayer.push({ ecommerce: null });
purchase
A user completes a purchase.
Triggered when a user completes a purchase.
Emitted on the checkout portal after returning from the payment portal with a success status.
transaction_iduses the booking number in PMS (non-PII).customer_typeis derived from prior bookings in the last 540 days when a contact is known.
Additional booking metadata can be included at the top level under booking (booking.status reflects the booking state).
Checkout portal includes portal_settings to analyze required fields impact on conversion.
Affiliate payouts should generally use booking.base_rent_total to exclude upgrades and deposits.
If marketing consent is granted, include user_data with hashed identifiers.
No address fields are sent.
If a CMS search snapshot cookie is present, a top-level search object is included.
Top-level objects
ecommerce
Ecommerce payload wrapper for GA4 events.
Fields below apply only when ecommerce is present in the payload. Presence values are scoped to this group.
ecommerce.items[]
Items array for the ecommerce payload.
Fields below apply only when ecommerce.items[] is present in the payload. Presence values are scoped to this group.
search
Availability search snapshot for the purchase. Source: Availability search snapshot shared from CMS via cookie.
Fields below apply only when search is present in the payload. Presence values are scoped to this group.
search.guest_group
Guest counts by group (see guest_group fields). Source: Guest group from search form.
Fields below apply only when search.guest_group is present in the payload. Presence values are scoped to this group.
booking
Booking object. Source: Booking object. booking.status/final/guest_group plus booking totals fields are populated for checkout portal purchase/lead events.
Fields below apply only when booking is present in the payload. Presence values are scoped to this group.
booking.guest_group
Guest counts by group (see guest_group fields). Source: Aggregated guest group from reservations.
Fields below apply only when booking.guest_group is present in the payload. Presence values are scoped to this group.
portal_settings
Checkout portal settings snapshot (enabled/required fields and contact toggles). Source: Organization checkout portal settings.
Fields below apply only when portal_settings is present in the payload. Presence values are scoped to this group.
user_data
Hashed user-provided data for Google tags. Source: Hashed email/phone from booking contact, sent only with marketing consent.
Fields below apply only when user_data is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"purchase","ecommerce":{"transaction_id":"ORDER-123","affiliation":"Administration Name","currency":"EUR","value":350.0,"customer_type":"new","payment_type":"ideal","tax":20.0,"shipping":0.0,"coupon":"SUMMER10","items":[{"item_id":"123123","item_name":"4-Person Luxury Villa","item_brand":"Administration Name","item_category":"Accommodation","item_category2":"house","item_variant":"single_night","item_list_id":"checkout","item_list_name":"Checkout","item_country":"Netherlands","item_region":"Twente","item_city":"Enschede","administration_id":"321321","administration_name":"Administration Name","price":350.0,"quantity":1,"discount":25.0,"coupon":"SUMMER10","index":1,"start_date":"2026-02-20","end_date":"2026-02-22","google_business_vertical":"hotel_rental"}]},"search":{"start_date":"2026-02-20","end_date":"2026-02-22","nights":2,"rentable_type":"house","guest_group":{"seniors":0,"adults":2,"adolescents":0,"children":1,"babies":0,"pets":0,"total":3},"price_range_min":100,"price_range_max":500,"sorting_id":"price_asc","amenities":{"facility":["pool"]},"amenities_count":2,"has_results":true,"results_count":42,"special_period_id":123,"special_period_name":"Summer Holiday"},"booking":{"status":"booked","final":true,"guest_group":{"seniors":0,"adults":2,"adolescents":0,"children":1,"babies":0,"pets":0,"total":3},"currency":"EUR","total":350,"base_rent_total":350,"upgrade_total":0,"preference_total":0,"deposit_total":0,"deferred_deposit_total":0,"security_deposit_total":0,"tourist_taxes_total":0,"vat_total":50},"portal_settings":{"fields":["first_name","last_name","email","phone","note"],"required_fields":["first_name","last_name","email"],"optional_fields":["phone","note"],"fields_count":5,"required_fields_count":3,"optional_fields_count":2,"override_default_fields":true,"license_plates_enabled":true,"phone_enabled":true,"email_enabled":true,"whatsapp_enabled":false},"user_data":{"sha256_email_address":"...","sha256_phone_number":"..."}});Clear ecommerce before every ecommerce event to avoid reusing items: dataLayer.push({ ecommerce: null });
We do not auto-clear booking. If you map booking outside booking events, clear it manually with dataLayer.push({ booking: null }).
generate_lead
A lead is generated.
Triggered when a lead is generated (for example, a booking option or a sales form with a priced property).
Checkout portal booking options emit this after the option is created.
Additional booking metadata can be included under booking (booking.status = option).
CMS sales forms: we only emit generate_lead when a property price and site currency are available, so value and currency are always present.
If marketing consent is granted, include user_data with hashed identifiers.
No address fields are sent.
Top-level parameters
booking
Booking object. Source: Booking object. booking.status/final/guest_group plus booking totals fields are populated for checkout portal purchase/lead events.
Fields below apply only when booking is present in the payload. Presence values are scoped to this group.
booking.guest_group
Guest counts by group (see guest_group fields). Source: Aggregated guest group from reservations.
Fields below apply only when booking.guest_group is present in the payload. Presence values are scoped to this group.
user_data
Hashed user-provided data for Google tags. Source: Hashed email/phone from booking contact, sent only with marketing consent.
Fields below apply only when user_data is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"generate_lead","currency":"EUR","value":350.0,"lead_source":"Website","lead_id":"lead-123","booking":{"status":"option","final":false,"guest_group":{"seniors":0,"adults":2,"adolescents":0,"children":1,"babies":0,"pets":0,"total":3},"currency":"EUR","total":350,"base_rent_total":350,"upgrade_total":0,"preference_total":0,"deposit_total":0,"deferred_deposit_total":0,"security_deposit_total":0,"tourist_taxes_total":0,"vat_total":50},"user_data":{"sha256_email_address":"...","sha256_phone_number":"..."}});We do not auto-clear booking. If you map booking outside booking events, clear it manually with dataLayer.push({ booking: null }).
close_convert_lead
A lead is converted and closed.
Triggered when a lead is converted and closed (for example, an option confirmation).
Checkout portal option confirmations emit this after the option is finalized.
Additional booking metadata can be included under booking (booking.status reflects the booking state).
If marketing consent is granted, include user_data with hashed identifiers.
No address fields are sent.
Top-level parameters
booking
Booking object. Source: Booking object. booking.status/final/guest_group plus booking totals fields are populated for checkout portal purchase/lead events.
Fields below apply only when booking is present in the payload. Presence values are scoped to this group.
booking.guest_group
Guest counts by group (see guest_group fields). Source: Aggregated guest group from reservations.
Fields below apply only when booking.guest_group is present in the payload. Presence values are scoped to this group.
user_data
Hashed user-provided data for Google tags. Source: Hashed email/phone from booking contact, sent only with marketing consent.
Fields below apply only when user_data is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"close_convert_lead","currency":"EUR","value":350.0,"lead_id":"lead-123","booking":{"status":"booked","final":true,"guest_group":{"seniors":0,"adults":2,"adolescents":0,"children":1,"babies":0,"pets":0,"total":3},"currency":"EUR","total":350,"base_rent_total":350,"upgrade_total":0,"preference_total":0,"deposit_total":0,"deferred_deposit_total":0,"security_deposit_total":0,"tourist_taxes_total":0,"vat_total":50},"user_data":{"sha256_email_address":"...","sha256_phone_number":"..."}});We do not auto-clear booking. If you map booking outside booking events, clear it manually with dataLayer.push({ booking: null }).
view_item_list
A user is presented with a list of items.
We measure rentable types (items) being presented to the user for certain dates and a certain price (availability) by sending a view_item_list event with the relevant rentable types in an items array. This event is triggered when a website visitor searches for availabilities by entering information like arrival date, departure date guest group, required amenities, etc.
The same event can be used for sales module listings (properties) by supplying the property items as the list items.
Top-level objects
ecommerce
Ecommerce payload wrapper for GA4 events.
Fields below apply only when ecommerce is present in the payload. Presence values are scoped to this group.
ecommerce.items[]
Items array for the ecommerce payload.
Fields below apply only when ecommerce.items[] is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"view_item_list","ecommerce":{"item_list_id":"availability_search","item_list_name":"Availability Search","currency":"EUR","items":[{"item_id":"123123","item_name":"4-Person Luxury Villa","item_brand":"Administration Name","item_category":"Accommodation","item_category2":"house","item_variant":"single_night","item_country":"Netherlands","item_region":"Twente","item_city":"Enschede","administration_id":"321321","administration_name":"Administration Name","coupon":"SUMMER10","discount":25.0,"price":350.0,"quantity":1,"start_date":"2026-02-20","end_date":"2026-02-22","google_business_vertical":"hotel_rental","index":1}]}});Clear ecommerce before every ecommerce event to avoid reusing items: dataLayer.push({ ecommerce: null });
select_item
A user selects an item from a list.
Triggered when a user selects an item from a list (for example, clicking an accommodation card on the listing page).
This is the list click; the detail page view is tracked with view_item.
Top-level objects
ecommerce
Ecommerce payload wrapper for GA4 events.
Fields below apply only when ecommerce is present in the payload. Presence values are scoped to this group.
ecommerce.items[]
Items array for the ecommerce payload.
Fields below apply only when ecommerce.items[] is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"select_item","ecommerce":{"item_list_id":"availability_search","item_list_name":"Availability Search","items":[{"item_id":"123123","item_name":"4-Person Luxury Villa","item_brand":"Administration Name","item_category":"Accommodation","item_category2":"house","item_variant":"single_night","item_country":"Netherlands","item_region":"Twente","item_city":"Enschede","administration_id":"321321","administration_name":"Administration Name","coupon":"SUMMER10","discount":25.0,"price":350.0,"quantity":1,"start_date":"2026-02-20","end_date":"2026-02-22","google_business_vertical":"hotel_rental","index":1,"item_list_id":"availability_search","item_list_name":"Availability Search"}]}});Clear ecommerce before every ecommerce event to avoid reusing items: dataLayer.push({ ecommerce: null });
view_item
A user views an item detail.
Triggered when a user views an item detail page.
Used for rentable detail pages and sales module property detail pages.
Top-level objects
ecommerce
Ecommerce payload wrapper for GA4 events.
Fields below apply only when ecommerce is present in the payload. Presence values are scoped to this group.
ecommerce.items[]
Items array for the ecommerce payload.
Fields below apply only when ecommerce.items[] is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"view_item","ecommerce":{"currency":"EUR","value":350.0,"items":[{"item_id":"123123","item_name":"4-Person Luxury Villa","item_brand":"Administration Name","item_category":"Accommodation","item_category2":"house","item_variant":"single_night","item_country":"Netherlands","item_region":"Twente","item_city":"Enschede","administration_id":"321321","administration_name":"Administration Name","coupon":"SUMMER10","discount":25.0,"price":350.0,"quantity":1,"index":1,"start_date":"2026-02-20","end_date":"2026-02-22","google_business_vertical":"hotel_rental","item_list_id":"availability_search","item_list_name":"Availability Search"}]}});Clear ecommerce before every ecommerce event to avoid reusing items: dataLayer.push({ ecommerce: null });
view_promotion
A user views a promotion.
Triggered when a promotion is viewed or impressed.
Emitted in the checkout portal for discount card impressions.
Top-level objects
ecommerce
Ecommerce payload wrapper for GA4 events.
Fields below apply only when ecommerce is present in the payload. Presence values are scoped to this group.
ecommerce.items[]
Items array for the ecommerce payload.
Fields below apply only when ecommerce.items[] is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"view_promotion","ecommerce":{"promotion_id":"promo_123","promotion_name":"Summer Sale","creative_name":"Hero Banner","creative_slot":"homepage_hero","items":[{"item_id":"123123","item_name":"4-Person Luxury Villa","google_business_vertical":"hotel_rental"}]}});Clear ecommerce before every ecommerce event to avoid reusing items: dataLayer.push({ ecommerce: null });
select_promotion
A user selects a promotion.
Triggered when a promotion is selected (clicked).
Emitted for availability-search promotions and checkout portal discounts.
Top-level objects
ecommerce
Ecommerce payload wrapper for GA4 events.
Fields below apply only when ecommerce is present in the payload. Presence values are scoped to this group.
ecommerce.items[]
Items array for the ecommerce payload.
Fields below apply only when ecommerce.items[] is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"select_promotion","ecommerce":{"promotion_id":"promo_123","promotion_name":"Summer Sale","creative_name":"Hero Banner","creative_slot":"homepage_hero","items":[{"item_id":"123123","item_name":"4-Person Luxury Villa","google_business_vertical":"hotel_rental"}]}});Clear ecommerce before every ecommerce event to avoid reusing items: dataLayer.push({ ecommerce: null });
view_search_results
A user views search results.
Triggered when a user views search results.
Emitted by the CMS site search page after a query is submitted.
Top-level parameters
Sample data layer snippet
dataLayer.push({"event":"view_search_results","search_term":"summer holiday"});search
A user performs a search.
Triggered when a user performs a search.
Emitted by the CMS site search page when a query is present.
Current search event payload
window.dataLayer = window.dataLayer || [];window.dataLayer.push({ "event": "search", "search_term": "summer holiday"});Legacy search payload (deprecated)
window.dataLayer = window.dataLayer || [];window.dataLayer.push({ "event": "search", "search_term": "summer holiday", "result_count": 42});Top-level parameters
Custom events
search_results_loaded
Availability search results are rendered.
Custom event for the availability Search + Booking flow.
Emitted by CMS availability search results on booking sites.
Emitted when results are rendered or an availability API response is accepted for the current search.
All events include a full search snapshot including the results summary (has_results/results_count). Unknown values are null.
Dates are YYYY-MM-DD; currency is ISO 4217; numeric values are numbers.
This is the primary availability search tracking event; it captures both the search inputs and whether results were found.
We emit it on initial availability search loads and on subsequent amenity updates (search intent tracking).
Use it together with cart/checkout events in GA4 to understand which searches led to bookings (session/user attribution).
Only fire when results match the current search (use a request id if multiple calls are in-flight).
Payload: event + search.
Top-level objects
search
Full search snapshot including results summary. Source: Availability search snapshot (dates, guests, amenities, sorting, price range, results).
Fields below apply only when search is present in the payload. Presence values are scoped to this group.
search.guest_group
Guest counts by group (see guest_group fields). Source: Guest group from search form.
Fields below apply only when search.guest_group is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"search_results_loaded","search":{"start_date":"2026-02-20","end_date":"2026-02-22","nights":2,"rentable_type":"house","guest_group":{"seniors":0,"adults":2,"adolescents":0,"children":1,"babies":0,"pets":0,"total":3},"price_range_min":100,"price_range_max":500,"sorting_id":"price_asc","amenities":{"facility":["pool"]},"amenities_count":2,"has_results":true,"results_count":42,"special_period_id":123,"special_period_name":"Summer Holiday"}});checkout_progress
Checkout portal progress update.
Custom checkout portal event emitted on each checkout step and when guests update checkout details.
Emitted when the guest group or license plate details change, and when a step is loaded.
Payload: event + step + step_number + guest_group + license plate summary + portal_settings.
Top-level parameters
guest_group
Guest counts by group (see guest_group fields). Source: Checkout portal reservation guest group.
Fields below apply only when guest_group is present in the payload. Presence values are scoped to this group.
portal_settings
Checkout portal settings snapshot (fields and contact toggles). Source: Organization checkout portal settings.
Fields below apply only when portal_settings is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"checkout_progress","step":"stay","step_number":1,"license_plates_count":1,"available_parking_spots":2,"guest_group":{"seniors":0,"adults":2,"adolescents":0,"children":1,"babies":0,"pets":0,"total":3},"portal_settings":{"fields":["first_name","last_name","email","phone","note"],"required_fields":["first_name","last_name","email"],"optional_fields":["phone","note"],"fields_count":5,"required_fields_count":3,"optional_fields_count":2,"override_default_fields":true,"license_plates_enabled":true,"phone_enabled":true,"email_enabled":true,"whatsapp_enabled":false}});form_start
A user starts interacting with a form.
Triggered the first time a user interacts with a form in a session.
Emitted by CMS forms on the website (sales or booking sites).
GA4 docs: https://support.google.com/analytics/answer/9216061
Note: To use form parameters in GA4 reports, configure custom dimensions.
Top-level parameters
Sample data layer snippet
dataLayer.push({"event":"form_start","form_id":"42","form_name":"Contact Form","form_destination":"/forms/responses"});form_submit
A user submits a form.
Triggered when a user submits a form.
Emitted by CMS forms on the website (sales or booking sites).
GA4 docs: https://support.google.com/analytics/answer/9216061
Note: To use form parameters in GA4 reports, configure custom dimensions.
If marketing consent is granted and the form includes email or phone fields, include user_data with hashed identifiers.
GA4 Tag Manager user-provided data guidance: https://support.google.com/analytics/answer/14171268
CMS sales forms with a selected property price also emit generate_lead (with value and currency).
No address fields are sent.
Top-level parameters
user_data
Hashed user-provided data for Google tags. Source: Hashed email/phone from form response, sent only with marketing consent.
Fields below apply only when user_data is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"form_submit","form_id":"42","form_name":"Contact Form","form_destination":"/forms/responses","form_submit_text":"Send message","form_response_id":"12345","user_data":{"sha256_email_address":"...","sha256_phone_number":"..."}});failed_payment
A payment attempt fails during checkout.
Triggered when a payment attempt fails.
Emitted on the checkout portal after returning from the payment portal with a failure status.
If marketing consent is granted, include user_data with hashed identifiers.
No address fields are sent.
Top-level parameters
user_data
Hashed user-provided data for Google tags. Source: Hashed email/phone from booking contact, sent only with marketing consent.
Fields below apply only when user_data is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"failed_payment","transaction_id":"ORDER-123","currency":"EUR","value":350.0,"reason_failed":"failure","user_data":{"sha256_email_address":"...","sha256_phone_number":"..."}});user_identity_update
Associates a pseudonymous user id with the current session.
Triggered when a pseudonymous user id becomes available for analytics.
Emitted in the checkout portal when a booking contact is known and consent allows analytics.
No PII should be included in this event.
Top-level objects
user
Pseudonymous user identifier and optional returning customer flag. Source: Pseudonymous user id and returning_customer flag derived from booking contact.
Fields below apply only when user is present in the payload. Presence values are scoped to this group.
Sample data layer snippet
dataLayer.push({"event":"user_identity_update","user":{"user_id":"u_hmac_...","returning_customer":true}});