Widget Events
The embedded reservation widget emits events on your website as guests interact with it. Use them to track the booking funnel and conversions in your own analytics setup (Google Analytics / Tag Manager, Meta Pixel, etc.).
How It Works
The widget runs inside an iframe on your page. The embed script forwards interactions to your website and dispatches a DOM CustomEvent named molzait_event on window. The payload is in event.detail and always contains a name field plus event-specific data:
window.addEventListener('molzait_event', (event) => {
const { name, ...data } = event.detail;
console.log(name, data);
});
Notes:
- Events never contain personal data (no guest names, emails or phone numbers) — only IDs, amounts and enum values.
- Events only fire when the widget is embedded on your website. Visits via the direct booking link (
reserve.molzait.com) happen outside your domain and cannot be tracked this way. - All monetary amounts are in cents (e.g.
10000= €100).
Event Reference
reserve_opened
Fired once when the reservation flow is opened.
| Field | Type | Description |
|---|---|---|
restaurantId | string | null | null when a multi-location widget opens with the location picker |
trigger | string | How the flow was opened, see Triggers |
{ "name": "reserve_opened", "restaurantId": "rest-123", "trigger": "button" }
gift_card_shop_opened
Fired once when the gift card shop is opened. Same payload as reserve_opened.
{ "name": "gift_card_shop_opened", "restaurantId": "rest-123", "trigger": "api" }
reservation_step_viewed
Fired on every step change in the reservation flow. This is the funnel event — the sequence of these events per session shows exactly where guests drop off.
| Field | Type | Description |
|---|---|---|
restaurantId | string | The restaurant the guest is booking at |
step | string | The step now shown, see Steps |
stepOrder | string | The restaurant's configured step order, see Step Order |
{
"name": "reservation_step_viewed",
"restaurantId": "rest-123",
"step": "date_selection",
"stepOrder": "partysize_experience_date"
}
Steps
| Value | Screen |
|---|---|
partysize | Party size selection |
experience | Experience list |
experience_detail | Experience detail page |
date_selection | Date picker |
time_selection | Time slot picker |
products | Add-on product selection (only for experiences with products) |
checkout | Contact details & confirmation form |
result | Success / result screen |
alternatives | Alternative locations for a fully-booked slot |
Step Order
The order of the first three steps is configured per restaurant, so do not assume a fixed sequence — build funnel reports on the step names and use stepOrder to interpret the sequence. Possible values:
partysize_experience_datepartysize_date_experienceexperience_date_partysizedate_experience_partysize
Steps can also be skipped automatically, e.g. the experience steps when a restaurant offers only one experience.
experience_selected
Fired when a guest actively picks an experience (from the list or by confirming the detail page). Not fired when the widget auto-selects the only available experience.
| Field | Type | Description |
|---|---|---|
restaurantId | string | The restaurant the guest is booking at |
experienceId | string | ID of the selected experience |
experienceName | object | Localized name: { "de": "...", "en": "..." } |
{
"name": "experience_selected",
"restaurantId": "rest-123",
"experienceId": "exp-456",
"experienceName": { "de": "Weinverkostung", "en": "Wine Tasting" }
}
gift_card_added_to_cart
Fired when a voucher is added to the gift card shop cart.
| Field | Type | Description |
|---|---|---|
restaurantId | string | The restaurant the voucher belongs to |
templateId | string | Gift card template ID |
amount | number | Voucher value in cents |
quantity | number | Number of vouchers added |
{
"name": "gift_card_added_to_cart",
"restaurantId": "rest-123",
"templateId": "template-789",
"amount": 5000,
"quantity": 1
}
widget_closed
Fired when the guest leaves the reservation flow or gift card shop (close button, backdrop click or back navigation). The last reservation_step_viewed before this event is the abandonment point.
| Field | Type | Description |
|---|---|---|
view | string | reserve or gift_card_shop |
{ "name": "widget_closed", "view": "reserve" }
reservation_created
The reservation conversion event. Fired once when a reservation is successfully created (including after a payment redirect).
| Field | Type | Description |
|---|---|---|
reservationId | string | ID of the created reservation |
attendees | number | Party size |
startTime | Date | Reservation start (a JavaScript Date object) |
endTime | Date | null | Reservation end |
experience | object | { id, name: { de, en } } |
prepaymentValue | number | null | Prepaid amount in cents, null if no prepayment |
{
"name": "reservation_created",
"reservationId": "res-abc",
"attendees": 4,
"startTime": "2026-08-01T17:00:00.000Z",
"endTime": "2026-08-01T19:00:00.000Z",
"experience": { "id": "exp-456", "name": { "de": "Weinverkostung", "en": "Wine Tasting" } },
"prepaymentValue": 8000
}
gift_card_purchased
The gift card conversion event. Fired once per order after a successful payment, covering all vouchers in the order.
| Field | Type | Description |
|---|---|---|
orderId | string | ID of the gift card order |
amount | number | Total value of all issued vouchers in cents |
restaurantId | string | The restaurant the vouchers belong to |
{ "name": "gift_card_purchased", "orderId": "order-xyz", "amount": 10000, "restaurantId": "rest-123" }
Triggers
reserve_opened and gift_card_shop_opened carry a trigger field so you can separate real user clicks from programmatic opens:
| Value | Meaning |
|---|---|
button | The guest clicked a button inside the widget (floating button, restaurant page) |
api | Opened from your website: window.molzait API, data-molzait-open elements or #mol-reserve / #mol-open / #mol-giftshop links |
auto | Opened automatically on page load (payment return, deep links, always-visible display modes) |
For click metrics, filter on trigger === 'button' or trigger === 'api' — auto opens are not user interactions.
Integration Examples
Google Tag Manager
Push every event to the data layer and configure triggers in GTM:
window.addEventListener('molzait_event', (event) => {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ event: 'molzait_' + event.detail.name, ...event.detail });
});
Google Analytics 4 (gtag.js)
Map the events to GA4 ecommerce events:
window.addEventListener('molzait_event', (event) => {
const data = event.detail;
switch (data.name) {
case 'reserve_opened':
if (data.trigger !== 'auto') {
gtag('event', 'begin_checkout', { method: data.trigger });
}
break;
case 'experience_selected':
gtag('event', 'select_item', {
items: [{ item_id: data.experienceId, item_name: data.experienceName.en }],
});
break;
case 'gift_card_added_to_cart':
gtag('event', 'add_to_cart', {
currency: 'EUR',
value: (data.amount * data.quantity) / 100,
items: [{ item_id: data.templateId, quantity: data.quantity }],
});
break;
case 'reservation_created':
gtag('event', 'purchase', {
transaction_id: data.reservationId,
currency: 'EUR',
value: (data.prepaymentValue || 0) / 100,
});
break;
case 'gift_card_purchased':
gtag('event', 'purchase', {
transaction_id: data.orderId,
currency: 'EUR',
value: data.amount / 100,
});
break;
}
});
Meta Pixel
window.addEventListener('molzait_event', (event) => {
const data = event.detail;
if (data.name === 'reservation_created') {
fbq('track', 'Purchase', { value: (data.prepaymentValue || 0) / 100, currency: 'EUR' });
}
if (data.name === 'gift_card_purchased') {
fbq('track', 'Purchase', { value: data.amount / 100, currency: 'EUR' });
}
});
Legacy Events
The two conversion events are additionally dispatched as dedicated CustomEvents for backwards compatibility with existing integrations:
molzait_reservation_createdmolzait_gift_card_purchased
Their event.detail matches the payloads above (with a type instead of a name field). New integrations should use molzait_event only.