purchase

A user completes a purchase.

Status: Active

Triggered when a user confirms a booking.

GA4 docs: https://developers.google.com/analytics/devguides/collection/ga4/reference/events?client_type=gtag#purchase

  • transaction_id uses the booking number in PMS (non-PII).

  • customer_type is 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).

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.

Fields marked as Deprecated are kept for compatibility with the existing legacy payment event. They will be removed in a future incremental cleanup.

Sample data layer snippet

dataLayer.push({ ecommerce: null });  // Clear the previous ecommerce object.  dataLayer.push({  "event": "purchase",  "ecommerce": {    "transaction_id": "ORDER-123",    "currency": "EUR",    "value": 350.0,    "customer_type": "new",    "coupon": "SUMMER10",    "rent_amount": 350.0,    "rent_amount_ex_vat": 35.0,    "booking_window": 7,    "first_start_date": "2026-02-20",    "last_end_date": "2026-02-22",    "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"      }    ]  },  "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 }).

Top-level objects

Parameter

Sample

Presence

Description

ecommerce

{...} (see below)

always

Ecommerce payload wrapper for GA4 events.

booking

{...} (see below)

always

Booking object. Source: Booking object. booking.status/final/guest_group plus booking totals fields are populated for checkout portal purchase/lead events.

user_data

{...} (see below)

if available

Hashed user-provided data for Google tags. Source: Hashed email/phone from booking contact, sent only with marketing consent.

ecommerce

Ecommerce payload wrapper for GA4 events.

Field

Sample

Presence

Description

transaction_id

ORDER-123

always

Unique transaction ID. Source: Booking reference/number.

currency

EUR

always

Currency of the items associated with the event, in 3-letter ISO 4217 format. Source: Currency used for totals/items (booking/order/reservation currency; availability/property search uses the active site currency).

value

350.0

always

Total value of the purchase. Source: Total order/booking value or sum of item prices.

customer_type

new

if available

Whether the customer is new or returning ("new" or "returning"). PMS uses a 540-day lookback window. Source: New vs returning based on booking history within 540 days.

coupon

SUMMER10

if available

Coupon code applied to the purchase. Source: Applied coupon codes for the booking/reservation, comma-separated when multiple.

rent_amount

350.0

if available

Deprecated: legacy compatibility field; removal will be handled in a future incremental cleanup.

rent_amount_ex_vat

35.0

if available

Deprecated: legacy compatibility field; removal will be handled in a future incremental cleanup.

booking_window

7

if available

Deprecated: legacy compatibility field; removal will be handled in a future incremental cleanup.

first_start_date

2026-02-20

if available

Deprecated: legacy compatibility field; removal will be handled in a future incremental cleanup.

last_end_date

2026-02-22

if available

Deprecated: legacy compatibility field; removal will be handled in a future incremental cleanup.

items[]

[...] (see below)

always

Items array for the ecommerce payload.

ecommerce.items[]

Items array for the ecommerce payload.

Field

Sample

Presence

Description

item_id

123123

always

ID of the item. Combine with item_category and item_category2. Source: rentable type id (Accommodation), cost id (Upgrade, Preference), bundle id (Package), or amenity id (Preference with Amenity item_category2). Availability/property search: category or property id.

Notes: Legacy checkout portal used prefixed ids (A/C/P).

item_name

4-Person Luxury Villa

always

The name of the item. Source: rentable type id (Accommodation), cost id (Upgrade, Preference), bundle id (Package), or amenity id (Preference with Amenity item_category2). Availability/property search: localized category/property name.

item_brand

Administration Name

if available

The localized name of the site. Source: Checkout portal: administration name. Availability/property search: site/brand name shown on the website (can differ from the administration name).

item_category

Accommodation

always

Top-level item type.

  • Accommodation

  • Upgrade

  • Preference

  • Package

Source: Checkout portal: Accommodation for rentable types, Upgrade for extras, Preference for amenities/preferences, Package for bundles. Availability/property search: Accommodation.

item_category2

house

if available

Semantic segment for accommodations or sub-bucket for extras.

Accommodation: house pitch room berth apartment other

Extras: Amenity Upgrade Package

Source: Checkout portal: accommodation semantic segment or extras bucket. Availability/property search: accommodation semantic segment.

item_category3

if available

PMS extra type for extras only.

  • tourist_taxes

  • cleaning

  • parking

Source: Checkout portal extras only: cost extra_type. Not set for accommodations, packages, or availability/property search.

item_variant

single_night

if available

Stay duration category for the accommodation.

  • single_night - 1 night

  • weekend - 2-3 nights incl weekend

  • midweek - 2-4 nights without weekend

  • week - 6-8 nights or 5 nights incl weekend

  • extended_stay - 9-13 nights

  • long_stay - 14+ nights

Source: Checkout portal accommodations and CMS availability items; derived from arrival/departure.

item_list_id

checkout

if available

ID of the list where the item is shown. Source: Availability/property search list id (availability_search/property_search). Cart/checkout events may supply list id like Cart or Checkout.

item_list_name

Checkout

if available

Name of the list where the item is shown. Source: Availability/property search list name (Availability search/Property search). Cart/checkout events may supply list name like Cart or Checkout.

item_country

Netherlands

if available

The country where the administration is located. Source: Administration country from BEX (shared across checkout portal and availability/property search).

item_region

Twente

if available

The region where the administration is located. Source: Administration region from BEX (shared across checkout portal and availability/property search).

item_city

Enschede

if available

The city where the administration is located. Source: Administration city from BEX (shared across checkout portal and availability/property search).

administration_id

321321

if available

The ID of the administration in BEX PMS. Source: Checkout portal: BEX administration id. Availability/property search: the same BEX administration id (Booking Experts administration mapping).

Notes: Renamed from park_id in legacy checkout payloads.

administration_name

Administration Name

if available

The name of the administration in BEX PMS. Source: Checkout portal: BEX administration name. Availability/property search: the same BEX administration name (Booking Experts administration mapping).

Notes: Renamed from park_name in legacy checkout payloads.

price

350.0

if available

Price for the item line (stay total for accommodation).

Source: Availability/property search: price for the stay. Checkout portal: order item unit price; accommodation uses stay total derived from booking total minus upgrades.

quantity

1

if available

Quantity of the item. Source: Order item quantity; otherwise 1.

discount

25.0

if available

Discount applied to the item. Source: Discount amount for the order item.

coupon

SUMMER10

if available

Coupon applied to the item. Source: Coupon code applied to the reservation or order item (first code, if any).

index

1

if available

Position of the item in the list. Source: Position in the result list (availability/property search only).

start_date

2026-02-20

if available

The date when the booking starts. Source: Stay arrival date or availability start date.

end_date

2026-02-22

if available

The date when the booking ends. Source: Stay departure date or availability end date.

google_business_vertical

hotel_rental

if available

Google Ads business vertical for dynamic remarketing (examples: "hotel_rental", "retail"). Source: Remarketing business vertical configured globally; not from booking data.

booking

Booking object. Source: Booking object. booking.status/final/guest_group plus booking totals fields are populated for checkout portal purchase/lead events.

Field

Sample

Presence

Description

status

booked

if available

Booking lifecycle status (concept/option/booked/cancelled). Source: Checkout portal status override or booking state from PMS.

final

true

if available

True when the booking is confirmed or imported. Source: Confirmed/imported flag from PMS.

currency

EUR

if available

Booking currency (ISO 4217). Source: Booking currency.

total

350

if available

Sum of all guest order items. Source: Total of guest debtor items.

base_rent_total

350

if available

Base rent (accommodation rent) order items. Source: Base rent total.

upgrade_total

0

if available

Upgrade order items (bundles/extras), excluding deposits. Source: Upgrade extras total.

preference_total

0

if available

Preference order items (amenities/preferences). Source: Preference items total.

deposit_total

0

if available

Reservation deposit order items (non-deferred). Source: Deposit total.

deferred_deposit_total

0

if available

Reservation deposit order items marked deferred. Source: Deferred deposit total.

security_deposit_total

0

if available

Security deposits (borg), from security deposit policies. Source: Security deposit total.

tourist_taxes_total

0

if available

Tourist tax order items. Source: Tourist taxes total.

vat_total

50

if available

VAT total for guest debtor items. Source: VAT total.

guest_group

{...} (see below)

if available

Guest counts by group (see guest_group fields). Source: Aggregated guest group from reservations.

booking.guest_group

Guest counts by group (see guest_group fields). Source: Aggregated guest group from reservations.

Field

Sample

Presence

Description

seniors

0

always

Number of seniors. Source: Guest group seniors count.

adults

2

always

Number of adults. Source: Guest group adults count.

adolescents

0

always

Number of adolescents. Source: Guest group adolescents count.

children

1

always

Number of children. Source: Guest group children count.

babies

0

always

Number of babies. Source: Guest group babies count.

pets

0

always

Number of pets. Source: Guest group pets count.

total

3

always

Total guests (sum of guest group counts). Source: Guest group total.

user_data

Hashed user-provided data for Google tags. Source: Hashed email/phone from booking contact, sent only with marketing consent.

Field

Sample

Presence

Description

sha256_email_address

...

if available

Hex-encoded SHA-256 after normalization. Source: Hashed email (marketing consent required).

sha256_phone_number

...

if available

Hex-encoded SHA-256 after normalization. Source: Hashed phone number (marketing consent required).