# Google Analytics 4

This document describes what events the Escape Navigator booking and gift-certificate widgets send to your **Google Analytics 4** property, and how to read them in standard GA4 reports.

The implementation follows the **GA4 Enhanced Ecommerce** specification, so the entire customer journey shows up in `Reports → Monetization → Purchases` and in `Explore → Funnel exploration` **out of the box**, with no custom funnel setup required.

***

### 1. Setup

1. In **Google Analytics 4**, create a property and a data stream and copy the **Measurement ID** (it looks like `G-XXXXXXXX`).
2. In Escape Navigator, enable the Google Analytics integration and paste the Measurement ID in your **organization profile** and/or in the **widget-specific** settings (Analytics & Conversions section).
3. Save the settings. While the integration is disabled or the Measurement ID is empty, **no events are sent**.

Optional: if you run **Google Ads** campaigns, you can also enter your Conversion ID (`AW-…`) and Conversion Label in the same widget settings. When both fields are filled, an extra `conversion` event is sent on every successful payment (see §6).

***

### 2. Currency and amounts

* All amounts are sent in **major currency units** (e.g. EUR 12.50, USD 7.00), **not** in cents or other minor units.
* The `currency` field is taken from your organization profile, except for fully created orders and certificate sales — in those cases the currency stored on the order is used, falling back to the profile currency.

***

### 3. Page views (virtual screens)

The widget is embedded into your website, so visitors do not navigate between URLs while booking. Instead, each step of the funnel sends a `page_view` event with a **virtual path** so you can still build funnels in GA4.

The path format is `/escapenavigator/<WIDGET_UUID>/<STEP_NAME>`. The widget UUID lets you tell apart different "Book now" buttons embedded on the same site.

#### Booking funnel page views

| Step name (path)        | What the visitor sees                     |
| ----------------------- | ----------------------------------------- |
| `slots_list`            | Schedule with date / time selection       |
| `select-players`        | Players count, language, tariff selection |
| `filling-client-data`   | Contact form (name, email, phone)         |
| `select-payment-method` | Payment method selection screen           |

#### Gift-certificate shop page views

| Step name (path)           | What the visitor sees                          |
| -------------------------- | ---------------------------------------------- |
| `certificate_shop_catalog` | Delivery type, design, and value picker        |
| `certificate_shop_client`  | Contact and shipping form                      |
| `certificate_shop_payment` | Payment method selection                       |
| `certificate_shop_success` | Success screen (sent together with `purchase`) |

***

### 4. The booking Enhanced Ecommerce funnel (games)

The widget emits the **full standard GA4 ecommerce sequence**. Each event includes a `currency`, a `value` (when applicable), and a standard `items[]` array.

| GA4 event          | When it is sent in the widget                                                                                                                                                                           |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `view_item_list`   | The schedule is rendered and at least one slot is visible. Sent **once per slice** (date + view + selected room) — switching the date or the quest re-emits the event for the new list.                 |
| `select_item`      | The visitor clicks a slot **and** the temporary hold succeeds. Misclicks on busy slots do not emit it.                                                                                                  |
| `view_item`        | The "select players" screen opens for the chosen quest.                                                                                                                                                 |
| `add_to_cart`      | The preorder is successfully created on the server (after the contact form is submitted). For multi-bookings (several slots in one session) a single event with all items is emitted, not one per slot. |
| `begin_checkout`   | The payment method screen opens (the visitor sees the cart total and is about to pay).                                                                                                                  |
| `add_payment_info` | The visitor clicks the actual payment button: Stripe / PayPal / Square / "pay at the venue" / "send request". One event per click.                                                                      |
| `purchase`         | The payment succeeds (online or "pay at venue" confirmation).                                                                                                                                           |

#### Item payload for games

Each item in `items[]` for the booking funnel carries:

* `item_id` — internal quest ID (numeric, as string).
* `item_name` — quest title.
* `item_category` — quest type as defined in your Escape Navigator settings.
* `item_variant` — for `view_item_list` / `select_item`: the date and time of the slot. For `add_to_cart` / `begin_checkout` / `add_payment_info` / `purchase`: the number of players (e.g. `"4 players"`).
* `price` — slot price (in `view_item_list` / `select_item` it's the base price; later it is the actual order total).
* `quantity` — always `1` (one slot = one item).
* `location_id` — venue address (only when the backend response includes it).
* `index` — position of the item in the list (`view_item_list` only).

#### Additional parameters

* `view_item_list` and `select_item` also include `item_list_id` (= `widget:<UUID>`) and `item_list_name` (= `widget_schedule` or `widget_schedule_modal`).
* `add_payment_info` includes `payment_type` (`stripe` | `paypal` | `square` | `at-place`) and `payment_plan` (`full` | `half`).
* `begin_checkout` and `purchase` include `coupon` if the visitor applied a promo code.
* `purchase` additionally has `transaction_id` (Escape Navigator order code) and `affiliation` (your organization title).

#### List deduplication

Schedules often contain many time slots for the same quest. In `view_item_list` we deduplicate items by `item_id` (= quest ID), so each unique quest appears **once** per list. This avoids inflating impressions in GA4 reports and keeps the event well below GA4's 500-events-per-session quota.

***

### 5. The gift-certificate funnel

Certificates use the **same GA4 event names** (`view_item`, `begin_checkout`, `purchase`) but with a different payload, so you can filter them in GA4 reports.

| GA4 event        | When it is sent                                                                                                                                    |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `view_item`      | The visitor clicks "Continue" after picking delivery type, design, and amount.                                                                     |
| `begin_checkout` | The payment screen loads with the actual order data from the server (once per session of this screen — applying a promo code does not re-emit it). |
| `purchase`       | The success screen with the real certificate code is shown.                                                                                        |

#### Item payload for certificates

* `item_category` — always `gift_certificate`. **Use this as your primary filter** to separate certificates from games in GA4 reports.
* `item_id` — composite ID like `cert:<designId>:<nominalId>:<value>`.
* `item_name` — design title.
* `item_variant` — either `nominal_id:<id>` (catalog nominal) or `face_value_cents:<cents>` (custom amount).
* `price` — preview price in `view_item`; actual order total in `begin_checkout` and `purchase`.

#### Extra parameters on certificate events

`delivery_type`, `design_id`, `nominal_id`, `custom_nominal_cents` are passed as **event-level** parameters. To see them in GA4 reports, register them as **Custom dimensions** in `GA4 → Admin → Custom definitions → Create custom dimension`, scope = `Event`.

***

### 6. Google Ads conversion event

If you have entered **both** the Google Ads Conversion ID (`AW-…`) and the Conversion Label in the widget settings, every successful payment additionally emits a `conversion` event with `value`, `currency`, and `send_to: '<conversion-id>/<conversion-label>'`. This is the format Google Ads expects for conversion tracking.

If only one of the two fields is filled, the event would be malformed and **is not sent**.

***

### 7. Enhanced Conversions (PII)

Just before `purchase`, the widget calls `gtag('set', 'user_data', { email, phone_number })` using the email and phone the visitor entered. This is the data Google needs for **Enhanced Conversions** in Google Ads and for **User-Provided Data Collection** in GA4.

The actual matching is enabled by you in the GA4 / Google Ads admin — the widget only provides the raw values when the visitor has entered them.

***

### 8. Facebook Pixel mirror

If you have also enabled the **Facebook (Meta) Pixel** integration and entered a Pixel ID, the widget emits these Facebook events in parallel with the GA4 ones:

| Widget event                    | GA4 event          | Facebook Pixel event |
| ------------------------------- | ------------------ | -------------------- |
| Visitor saw slot list           | `view_item_list`   | — (not sent)         |
| Visitor clicked a slot          | `select_item`      | — (not sent)         |
| Visitor opened "select players" | `view_item`        | `ViewContent`        |
| Preorder created                | `add_to_cart`      | `AddToCart`          |
| Payment screen opened           | `begin_checkout`   | `InitiateCheckout`   |
| Visitor clicked "Pay"           | `add_payment_info` | `AddPaymentInfo`     |
| Payment succeeded               | `purchase`         | `Purchase`           |

GA4 and Facebook Pixel are independent: you can enable one without the other.

***

### 9. Reading the funnel in GA4

Because the widget uses standard ecommerce events, you get the funnel **for free**:

1. `Reports → Life cycle → Monetization → Purchases` — shows `view_item`, `add_to_cart`, `begin_checkout`, `purchase` counts and conversion rates between them.
2. `Reports → Life cycle → Monetization → Ecommerce purchases` — top-selling items (= top-booked quests) by `item_id` and `item_name`.
3. `Explore → Funnel exploration` — drag the events `view_item_list → select_item → view_item → add_to_cart → begin_checkout → add_payment_info → purchase` into the funnel steps and you'll see drop-off rates between each step.
4. `Explore → Path exploration` — see what visitors do after `view_item_list` (which slots get the most attention).

For Google Ads campaign attribution, mark `purchase` as a **Key event** in `Admin → Events`, then import it as a conversion in Google Ads.

***

### 10. Migration note for existing customers

**Breaking change in event timing.** Before this update, the widget emitted `begin_checkout` at the moment the preorder was created (right after the contact form). Per GA4 specification, that moment is actually `add_to_cart`, and `begin_checkout` should fire when the visitor reaches the payment screen.

We have realigned the events with the spec:

| Step                                    | Old event        | New event          |
| --------------------------------------- | ---------------- | ------------------ |
| Preorder created (after contact form)   | `begin_checkout` | `add_to_cart`      |
| Payment screen opened                   | *(no event)*     | `begin_checkout`   |
| Visitor clicked the actual "Pay" button | *(no event)*     | `add_payment_info` |

If your team had custom funnel explorations or Google Ads conversions wired to the **old** `begin_checkout` event, you should:

1. Update Funnel Exploration steps to use the new events.
2. If `begin_checkout` was used as a Google Ads conversion, decide whether to keep it (now firing later in the funnel, closer to intent-to-pay) or switch to `add_to_cart` (firing at the same moment as before).

***

### 11. How to verify everything works

1. In Google Analytics open **DebugView** (`Admin → DebugView`) and follow the official Google guide to put your browser into debug mode.
2. Open your site in the same browser and make a test booking or certificate purchase.
3. Verify the events arrive in DebugView in this exact order: `page_view → view_item_list → select_item → view_item → page_view → add_to_cart → page_view → begin_checkout → add_payment_info → purchase`.
4. Compare the `transaction_id` in `purchase` with the order code in your Escape Navigator dashboard.

***

### 12. Summary

| Event                     | Booking                | Certificate shop      | Notes                                           |
| ------------------------- | ---------------------- | --------------------- | ----------------------------------------------- |
| `page_view`               | Yes (every step)       | Yes (every step)      | Virtual paths under `/escapenavigator/<UUID>/…` |
| `view_item_list`          | Yes (schedule)         | —                     | Deduplicated by quest ID                        |
| `select_item`             | Yes (slot click)       | —                     | After successful hold                           |
| `view_item`               | Yes (quest details)    | Yes (selected design) |                                                 |
| `add_to_cart`             | Yes (preorder created) | —                     | One event for multi-bookings                    |
| `begin_checkout`          | Yes (payment screen)   | Yes (payment screen)  | Single event per session of the screen          |
| `add_payment_info`        | Yes (Pay clicked)      | — (planned)           | `payment_type` + `payment_plan` parameters      |
| `purchase`                | Yes                    | Yes                   | With `transaction_id` and `coupon`              |
| `conversion` (Google Ads) | If configured          | If configured         | Requires both Conversion ID and Label           |

If the integration is disabled or the Measurement ID is missing, **none** of the above events are sent.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.escapenavigator.com/google-analytics-4.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
