> ## Documentation Index
> Fetch the complete documentation index at: https://restoo.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Event Mappings

> Events and data sent by Restoo Connect to each supported analytics and advertising platform.

This reference documents how [Restoo Connect](/widget/connect) maps native [Restoo Widget Events](/widget/events) to each supported analytics and advertising platform.

For each platform, the tables show the native Restoo event, the platform event or API call it produces, and a link to an example of the data sent. Standard platform events are documented separately from Restoo custom events and customer-data updates.

You do not need to read all of it: go straight to your platform.

<CardGroup cols={3}>
  <Card title="Google Analytics 4" icon="chart-line" href="#google-analytics-4">
    `ga4`
  </Card>

  <Card title="Google Tag Manager" icon="tags" href="#google-tag-manager">
    `gtm`
  </Card>

  <Card title="Google Ads" icon="bullseye" href="#google-ads">
    `googleAds`
  </Card>

  <Card title="Meta Pixel" icon="meta" href="#meta-pixel">
    `metaPixel`
  </Card>

  <Card title="TikTok Pixel" icon="tiktok" href="#tiktok-pixel">
    `tiktokPixel`
  </Card>

  <Card title="OpenAI Pixel" icon="openai" href="#openai-pixel">
    `openaiPixel`
  </Card>
</CardGroup>

<Note>
  When a visitor edits an existing booking, Restoo Connect suppresses funnel and
  conversion events. It continues to forward `action_taken`,
  `customer_identified`, and `customer_signed_out` to every platform, and
  `booking_updated` to GA4 and Google Tag Manager only. An edit is not a new
  conversion, so it never reaches Google Ads, Meta, TikTok, or ChatGPT Ads.
</Note>

## Acquisition model

Restoo measures bookings as **lead acquisition**, not as ecommerce. A booking is not treated as a purchase, but as capturing and qualifying a potential customer.

Every booking that gets created fires **exactly one conversion**, chosen by the status it is created with:

| Conversion            | Fires when                                                        | What it marks         |
| --------------------- | ----------------------------------------------------------------- | --------------------- |
| **Lead**              | The booking is created pending confirmation or on a waiting list. | Interest captured     |
| **Confirmed booking** | The booking is created already confirmed.                         | The lead is qualified |

The two are mutually exclusive. A confirmed booking fires the confirmed-booking conversion and not the lead one; a pending booking fires the lead conversion and not the confirmed-booking one. Added together they equal the total bookings created, so no booking is ever counted twice.

<Note>
  With a cancellation policy, the booking does not exist until the guest signs the
  policy, so the conversion is emitted then and not when the form is submitted. If
  they abandon the signature page, no conversion is counted. The status the booking
  is created with still decides which of the two fires: a booking with a
  cancellation policy can also end up pending confirmation or on a waiting list.
</Note>

Along the way, Restoo also emits behavioral events — which options a guest sees, which ones they select, and where they drop off — without any of that affecting conversion measurement. The details form submission is one of them: while the booking does not exist, there is nothing to convert.

This approach has three advantages:

* **It doesn't pollute your revenue.** Bookings are never counted as sales, so they don't distort revenue reports or get mixed up with actual product sales such as gift cards.
* **It reflects the real business.** A booking is an intention to visit, not a closed transaction, and the lead model represents that faithfully.
* **Campaigns optimize correctly.** Each platform optimizes for booking acquisition, with no bias toward the bookings that happen to carry a prepayment.

Every platform receives these conversions translated into its own event model, so "a booking is a lead" stays consistent across all of them:

| Conversion        | GA4             | Google Ads          | Meta Pixel | TikTok Pixel | OpenAI Pixel            |
| ----------------- | --------------- | ------------------- | ---------- | ------------ | ----------------------- |
| Lead              | `generate_lead` | `booking_lead`      | `Lead`     | `SubmitForm` | `lead_created`          |
| Confirmed booking | `qualify_lead`  | `booking_confirmed` | `Schedule` | `Schedule`   | `appointment_scheduled` |

The rest of this page documents every event each platform receives, including the behavioral ones, and the exact data sent with each.

## What Restoo deliberately omits

Some fields you might expect are absent from every payload documented here. That is by design, so it is worth knowing before you go looking for them.

**Catalogue names.** Experiences, add-ons and list items are identified by ID — `best_burger:experience:7` — never by name.

An experience name is free text written by the business, and special-category data can be inferred from it: a gluten-free menu suggests health, a halal dinner suggests religious belief, a themed experience can suggest sexual orientation. Under the GDPR that requires explicit, separate consent that this flow does not collect, and Meta's and Google's terms prohibit receiving it — sending it would put the ad account at risk.

If your reports need readable labels, keep your own ID-to-name mapping.

**Customer fields no destination reads.** The identity payload carries only a hashed email and phone, because those are the only two fields any destination consumes. A name, postal code and country used to travel with it and were removed: hashing is pseudonymization, not anonymization, so a field nobody reads is personal data exposed for no purpose.

**Money on conversions.** Conversions carry no `value` or `currency` — see [Acquisition model](#acquisition-model).

<Note>
  These fields are removed at the source, not per destination. Every widget event
  is broadcast to the page that embeds the widget, so any third-party script
  running there can read it. Filtering inside a destination would protect Meta and
  TikTok while leaving that channel wide open.
</Note>

## Google Analytics 4

With `ga4` enabled, Restoo Connect calls `gtag("event", eventName, data)`. Standard GA4 event names are used when there is a suitable equivalent. Restoo-specific events use the `restoo_` prefix.

Every call carries `send_to` with the measurement ID of the property [configured in your account](/widget/integrations#google-analytics-4), so events reach that property and no other destination configured on the page. The examples below leave it out, since it is the same in all of them.

### Standard events

These events use names defined by GA4. The table links to the exact payload sent for each mapping, including any additional Restoo parameters.

| Restoo event                                                      | Standard GA4 event sent                                                                                                | Data sent                                                                   |
| ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| [`booking_start_submitted`](/widget/events#booking-funnel)        | `search`                                                                                                               | [Booking start data](#ga4-booking-start-data)                               |
| [`booking_item_list_viewed`](/widget/events#item-list-events)     | `view_item_list`                                                                                                       | [Item-list data](#ga4-item-list-data)                                       |
| [`booking_item_selected`](/widget/events#item-list-events)        | `select_item`                                                                                                          | [Item-list data](#ga4-item-list-data)                                       |
| [`booking_item_detail_viewed`](/widget/events#item-list-events)   | `view_item`                                                                                                            | [Item-detail data](#ga4-item-detail-data)                                   |
| [`booking_details_form_started`](/widget/events#booking-funnel)   | `form_start`                                                                                                           | [Details form and booking data](#ga4-booking-details-form-and-booking-data) |
| [`booking_details_form_submitted`](/widget/events#booking-funnel) | `form_submit`                                                                                                          | [Details form and booking data](#ga4-booking-details-form-and-booking-data) |
| [`booking_created`](/widget/events#booking-funnel)                | `qualify_lead` if `booking.status` is `CONFIRMED`; `generate_lead` if it is `REQUESTED` or `PENDING_WAIT_LIST_BOOKING` | [Booking data](#ga4-booking-details-form-and-booking-data)                  |
| [`action_taken`](/widget/events#actions)                          | `select_content` when the action qualifies                                                                             | [Action data](#ga4-action-data)                                             |
| [`customer_identified`](/widget/events#customer)                  | `login`                                                                                                                | [Customer data](#ga4-customer-data)                                         |

For the meaning of these event and item parameters, see Google's [recommended events reference](https://developers.google.com/analytics/devguides/collection/ga4/reference/events) and [ecommerce documentation](https://developers.google.com/analytics/devguides/collection/ga4/ecommerce).

### Restoo custom events

These events have no direct GA4 equivalent. Their names use the `restoo_` prefix so they can be identified as custom events.

| Restoo event                                                      | Custom GA4 event sent                                                | Data sent                                                                           |
| ----------------------------------------------------------------- | -------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| [`booking_start_viewed`](/widget/events#booking-funnel)           | `restoo_booking_start_viewed`                                        | [Booking start data](#ga4-booking-start-data)                                       |
| [`booking_details_form_viewed`](/widget/events#booking-funnel)    | `restoo_booking_details_form_viewed`                                 | [Booking details form and booking data](#ga4-booking-details-form-and-booking-data) |
| [`booking_conditions_viewed`](/widget/events#booking-funnel)      | `restoo_booking_conditions_viewed`                                   | [Booking data](#ga4-booking-details-form-and-booking-data)                          |
| [`booking_conditions_accepted`](/widget/events#booking-funnel)    | `restoo_booking_conditions_accepted`                                 | [Booking data](#ga4-booking-details-form-and-booking-data)                          |
| [`booking_cp_viewed`](/widget/events#booking-funnel)              | `restoo_booking_cp_viewed`                                           | [Booking data](#ga4-booking-details-form-and-booking-data)                          |
| [`booking_cp_acknowledged`](/widget/events#booking-funnel)        | `restoo_booking_cp_acknowledged`                                     | [Booking data](#ga4-booking-details-form-and-booking-data)                          |
| [`booking_cp_accepted`](/widget/events#booking-funnel)            | `restoo_booking_cp_accepted`                                         | [Booking data](#ga4-booking-details-form-and-booking-data)                          |
| [`booking_updated`](/widget/events#booking-funnel)                | `restoo_booking_updated`                                             | [Booking data](#ga4-booking-details-form-and-booking-data)                          |
| [`booking_no_availability_viewed`](/widget/events#booking-funnel) | `restoo_booking_no_availability_viewed`                              | [Booking and availability data](#ga4-no-availability-data)                          |
| [`action_taken`](/widget/events#actions)                          | `restoo_action_taken`                                                | [Action data](#ga4-action-data)                                                     |
| [`customer_identified`](/widget/events#customer)                  | `restoo_customer_identified` when hashed email or phone is available | [Customer data](#ga4-customer-data)                                                 |
| [`customer_signed_out`](/widget/events#customer)                  | `restoo_customer_signed_out`                                         | [Customer data](#ga4-customer-data)                                                 |

The `booking_*`, `action_*`, and `availability_outcome` fields are also custom parameters. See [GA4 custom event parameters](https://developers.google.com/analytics/devguides/collection/ga4/event-parameters) for how to expose them in reports.

`generate_lead` and `qualify_lead` do not include `value` or `currency`: a reservation is modeled as a lead, not an ecommerce purchase.

### GA4 booking start data

When the booking start page is shown, Restoo Connect sends the custom event without parameters:

```js theme={null}
gtag("event", "restoo_booking_start_viewed", {});
```

Submitting valid party size and date criteria sends a `search`, with a synthetic search term:

```js theme={null}
gtag("event", "search", {
  search_term: "pax_4_day_friday_shift_dinner",
});
```

The search term describes the total party size, weekday, and shift without including an exact date or personal data. Its format is `pax_{guests}_day_{weekday}_shift_{shift}`; children are included in the guest count.

### GA4 item-list data

```js theme={null}
gtag("event", "view_item_list", {
  item_list_id: "best_burger:booking_experiences",
  item_list_name: "best_burger:booking_experiences",
  items: [
    {
      item_id: "best_burger:experience:7",
      item_list_id: "best_burger:booking_experiences",
      item_list_name: "best_burger:booking_experiences",
      item_category: "experience",
      price: 65,
    },
  ],
});
```

`select_item` sends the same structure **plus** the amount the guest chose: `quantity` carries the number of experience tickets, or the add-on units. A list being shown has no quantity yet, so `view_item_list` never includes it. List IDs are scoped to the account and list type.

| List type             | Fields included on each item                                                      |
| --------------------- | --------------------------------------------------------------------------------- |
| `booking_experiences` | `item_category: "experience"`, `price`, and `quantity` on `select_item`           |
| `booking_time_slots`  | `item_category: "time_slot"`, `item_date`, `item_time`, `item_floor_plan_area_id` |
| `booking_add_ons`     | `item_category: "add_on"`, `price`, and `quantity` on `select_item`               |

Prices are converted from the currency's smallest unit to decimal units.

### GA4 item-detail data

```js theme={null}
gtag("event", "view_item", {
  item_list_id: "best_burger:booking_experiences",
  item_list_name: "best_burger:booking_experiences",
  items: [
    {
      item_id: "best_burger:experience:7",
      item_category: "experience",
      item_list_id: "best_burger:booking_experiences",
    },
  ],
});
```

For an area, `item_category` is `floor_plan_area`.

### GA4 booking details form and booking data

The three guest-details form events — `restoo_booking_details_form_viewed` when it is shown, `form_start` when the guest begins filling it in, and `form_submit` when they submit it — include the same fixed form identifiers and the current booking context:

```js theme={null}
gtag("event", "form_submit", {
  form_id: "booking_details_form",
  form_name: "Booking details form",
  booking_account_id: "best-burger",
  booking_business_name: "Best Burger",
  booking_status: "CONFIRMED",
  booking_shift_type_id: "DINNER",
  booking_shift_type_name: "Dinner",
  booking_date: "2026-07-25",
  booking_weekday: "saturday",
  booking_time: "20:30:00",
  booking_pax: 2,
  booking_pax_children: 0,
  booking_is_time_limited: false,
  booking_floor_plan_area_name: "Terrace",
  booking_cancellation_policy_type: "PREPAYMENT",
});
```

`generate_lead`, `qualify_lead`, and the other Restoo-specific booking events receive the same booking fields without `form_id` and `form_name`. Fields whose source value is `null` or `undefined` are omitted.

See [BookingFunnel](/widget/events#bookingfunnel) for the source booking fields and [BookingStatus](/getting-started/enums#bookingstatus), [ShiftType](/getting-started/enums#shifttype), and [CancellationPolicyType](/getting-started/enums#cancellationpolicytype) for enum definitions.

### GA4 no-availability data

```js theme={null}
gtag("event", "restoo_booking_no_availability_viewed", {
  booking_account_id: "best-burger",
  booking_business_name: "Best Burger",
  booking_status: "CONFIRMED",
  booking_date: "2026-07-25",
  booking_weekday: "saturday",
  booking_pax: 4,
  booking_pax_children: 0,
  booking_is_time_limited: false,
  availability_outcome: "SHIFT_FULL",
});
```

See [AvailabilityOutcome](/getting-started/enums#availabilityoutcome) for the possible values and their meanings.

### GA4 action data

`action_taken` always emits the Restoo-specific event:

```js theme={null}
gtag("event", "restoo_action_taken", {
  action_category: "contact",
  action_option: "whatsapp",
});
```

It additionally emits `select_content` for a concrete contact channel:

```js theme={null}
gtag("event", "select_content", {
  content_type: "contact_method",
  content_id: "contact_whatsapp",
});
```

For a no-availability fallback, `content_type` is `availability_fallback` and `content_id` is the selected option. Opening the contact menu (`option: "open"`) or using a generic one-step action (`option: "click"`) does not emit the contact `select_content` event.

### GA4 customer data

Before the identification events are sent, Restoo Connect sets the available hashed email and phone as global `user_data`:

```js theme={null}
gtag("set", "user_data", {
  sha256_email_address: "ff8d9819fc0e12bf...",
  sha256_phone_number: "7f4597251b6a9f2c...",
});

gtag("event", "restoo_customer_identified", {});
gtag("event", "login", { method: "form" });
```

`restoo_customer_identified` is only sent when a hashed email or phone is available; `login` is always sent. When the identified customer has neither, `user_data` is set to `{}` so no earlier visitor's identity is left behind. On sign-out, Restoo Connect always clears `user_data` — that removal needs no consent — and, when this property's own consent requirement is met, also sends `restoo_customer_signed_out`:

```js theme={null}
gtag("set", "user_data", {});
gtag("event", "restoo_customer_signed_out", {});
```

Global `user_data` is not event data. GA4 only ingests it when [user-provided data collection](https://support.google.com/analytics/answer/14077171) is enabled for the property.

## Google Tag Manager

With `gtm` enabled, Restoo Connect pushes objects to `window.dataLayer`. Event names mirror the direct GA4 destination, but booking data is nested under `restoo` and item data is nested under `ecommerce`.

### Standard events

These `dataLayer` events mirror the standard GA4 mapping. They can be used as Custom Event triggers for GA4 or other tags in GTM.

| Restoo event                                                      | Standard `dataLayer` event sent                                                                                        | Data sent                                                                       |
| ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| [`booking_start_submitted`](/widget/events#booking-funnel)        | `search`                                                                                                               | [Booking start push](#gtm-booking-start-pushes)                                 |
| [`booking_item_list_viewed`](/widget/events#item-list-events)     | `view_item_list`                                                                                                       | [Item-list push](#gtm-item-pushes)                                              |
| [`booking_item_selected`](/widget/events#item-list-events)        | `select_item`                                                                                                          | [Item-list push](#gtm-item-pushes)                                              |
| [`booking_item_detail_viewed`](/widget/events#item-list-events)   | `view_item`                                                                                                            | [Item-detail push](#gtm-item-pushes)                                            |
| [`booking_details_form_started`](/widget/events#booking-funnel)   | `form_start`                                                                                                           | [Details form push](#gtm-booking-details-form-and-booking-pushes)               |
| [`booking_details_form_submitted`](/widget/events#booking-funnel) | `form_submit`                                                                                                          | [Details form and booking pushes](#gtm-booking-details-form-and-booking-pushes) |
| [`booking_created`](/widget/events#booking-funnel)                | `qualify_lead` if `booking.status` is `CONFIRMED`; `generate_lead` if it is `REQUESTED` or `PENDING_WAIT_LIST_BOOKING` | [Booking push](#gtm-booking-details-form-and-booking-pushes)                    |
| [`action_taken`](/widget/events#actions)                          | `select_content` when the action qualifies                                                                             | [Action pushes](#gtm-action-pushes)                                             |
| [`customer_identified`](/widget/events#customer)                  | `login`                                                                                                                | [Customer pushes](#gtm-customer-pushes)                                         |

### Restoo custom events

These events have no direct standard equivalent. Their names use the `restoo_` prefix. Events with additional data store it under the `restoo` key.

| Restoo event                                                      | Custom `dataLayer` event sent                                | Data sent                                                                 |
| ----------------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------- |
| [`booking_start_viewed`](/widget/events#booking-funnel)           | `restoo_booking_start_viewed`                                | [Booking start push](#gtm-booking-start-pushes)                           |
| [`booking_details_form_viewed`](/widget/events#booking-funnel)    | `restoo_booking_details_form_viewed`                         | [Booking details form push](#gtm-booking-details-form-and-booking-pushes) |
| [`booking_conditions_viewed`](/widget/events#booking-funnel)      | `restoo_booking_conditions_viewed`                           | [Full booking push](#gtm-restoo-specific-booking-pushes)                  |
| [`booking_conditions_accepted`](/widget/events#booking-funnel)    | `restoo_booking_conditions_accepted`                         | [Full booking push](#gtm-restoo-specific-booking-pushes)                  |
| [`booking_cp_viewed`](/widget/events#booking-funnel)              | `restoo_booking_cp_viewed`                                   | [Full booking push](#gtm-restoo-specific-booking-pushes)                  |
| [`booking_cp_acknowledged`](/widget/events#booking-funnel)        | `restoo_booking_cp_acknowledged`                             | [Full booking push](#gtm-restoo-specific-booking-pushes)                  |
| [`booking_cp_accepted`](/widget/events#booking-funnel)            | `restoo_booking_cp_accepted`                                 | [Full booking push](#gtm-restoo-specific-booking-pushes)                  |
| [`booking_updated`](/widget/events#booking-funnel)                | `restoo_booking_updated`                                     | [Full booking push](#gtm-restoo-specific-booking-pushes)                  |
| [`booking_no_availability_viewed`](/widget/events#booking-funnel) | `restoo_booking_no_availability_viewed`                      | [Full booking and availability push](#gtm-restoo-specific-booking-pushes) |
| [`action_taken`](/widget/events#actions)                          | `restoo_action_taken`                                        | [Action pushes](#gtm-action-pushes)                                       |
| [`customer_identified`](/widget/events#customer)                  | `restoo_customer_identified` when matching data is available | [Customer pushes](#gtm-customer-pushes)                                   |
| [`customer_signed_out`](/widget/events#customer)                  | `restoo_customer_signed_out`                                 | [Customer pushes](#gtm-customer-pushes)                                   |

See Google's [data layer documentation](https://developers.google.com/tag-platform/tag-manager/datalayer) for how GTM processes the `event` field and other variables in each push. The nested `restoo` objects are Restoo-specific variables that you can expose with Data Layer Variable definitions in GTM.

### GTM booking start pushes

```js theme={null}
window.dataLayer.push({
  event: "restoo_booking_start_viewed",
});

window.dataLayer.push({
  event: "search",
  search_term: "pax_4_day_friday_shift_dinner",
});
```

The search term uses the same synthetic value documented in [GA4 booking start data](#ga4-booking-start-data).

### GTM item pushes

```js theme={null}
window.dataLayer.push({
  event: "view_item_list",
  ecommerce: {
    item_list_id: "best_burger:booking_experiences",
    item_list_name: "best_burger:booking_experiences",
    items: [
      {
        item_id: "best_burger:experience:7",
        item_list_id: "best_burger:booking_experiences",
        item_list_name: "best_burger:booking_experiences",
        item_category: "experience",
        price: 65,
      },
    ],
  },
});
```

`select_item` uses the same `ecommerce` object. `view_item` uses the [GA4 item-detail data](#ga4-item-detail-data) under `ecommerce`.

### GTM booking details form and booking pushes

```js theme={null}
window.dataLayer.push({
  event: "form_submit",
  form_id: "booking_details_form",
  form_name: "Booking details form",
  restoo: {
    booking_account_id: "best-burger",
    booking_business_name: "Best Burger",
    booking_status: "CONFIRMED",
    booking_date: "2026-07-25",
    booking_weekday: "saturday",
    booking_time: "20:30:00",
    booking_pax: 2,
    booking_pax_children: 0,
    booking_is_time_limited: false,
  },
});

window.dataLayer.push({
  event: "generate_lead",
  restoo: {
    booking_account_id: "best-burger",
    booking_business_name: "Best Burger",
    booking_status: "REQUESTED",
    booking_date: "2026-07-25",
    booking_weekday: "saturday",
    booking_time: "20:30:00",
    booking_pax: 2,
    booking_pax_children: 0,
    booking_is_time_limited: false,
  },
});
```

`restoo_booking_details_form_viewed` and `form_start` use the first structure, changing only the `event`. `qualify_lead` uses the second with `event: "qualify_lead"` and `booking_status: "CONFIRMED"`. The complete set of booking fields is shown in [GA4 booking details form and booking data](#ga4-booking-details-form-and-booking-data).

### GTM Restoo-specific booking pushes

Restoo-specific events include a fuller booking context. The event name changes according to the mapping table; the `restoo` structure remains the same.

```js theme={null}
window.dataLayer.push({
  event: "restoo_booking_conditions_viewed",
  restoo: {
    booking_account_id: "best-burger",
    booking_business_name: "Best Burger",
    booking_status: "CONFIRMED",
    booking_shift_type_id: "DINNER",
    booking_shift_type_name: "Dinner",
    booking_date: "2026-07-25",
    booking_weekday: "saturday",
    booking_time: "20:30:00",
    booking_floor_plan_area_id: "best_burger:floor_plan_area:3",
    booking_floor_plan_area_name: "Terrace",
    booking_pax: 2,
    booking_pax_children: 0,
    booking_experience_id: "best_burger:experience:7",
    booking_experience_price_per_ticket: 65,
    booking_experience_currency: "EUR",
    booking_experience_tickets: 2,
    booking_add_ons: [
      {
        id: "best_burger:add_on:12",
        quantity: 2,
        unit_price: 25,
        currency: "EUR",
      },
    ],
    booking_is_time_limited: false,
    booking_cancellation_policy_type: "PREPAYMENT",
    booking_cancellation_policy_amount: 30,
    booking_cancellation_policy_amount_type: "PER_PAX",
    booking_cancellation_policy_fee_amount: 60,
    booking_cancellation_policy_charged_amount: 60,
    booking_cancellation_policy_notice_hours: 24,
    booking_cancellation_policy_currency: "EUR",
    booking_amount: 180,
    booking_currency: "EUR",
  },
});
```

Fields that do not apply are present as `null`, except `booking_add_ons`, which is an empty array when nothing was added. Monetary fields use decimal currency units. See [CancellationPolicyAmountType](/getting-started/enums#cancellationpolicyamounttype) for the possible amount types.

`restoo_booking_no_availability_viewed` adds `availability_outcome` to the same `restoo` object.

### GTM action pushes

```js theme={null}
window.dataLayer.push({
  event: "restoo_action_taken",
  restoo: {
    action_category: "contact",
    action_option: "whatsapp",
  },
});

window.dataLayer.push({
  event: "select_content",
  content_type: "contact_method",
  content_id: "contact_whatsapp",
});
```

The second push is conditional and follows the same rules as [GA4 action data](#ga4-action-data).

### GTM customer pushes

```js theme={null}
window.dataLayer.push({
  event: "restoo_customer_identified",
  user_data: {
    sha256_email_address: "ff8d9819fc0e12bf...",
    sha256_phone_number: "7f4597251b6a9f2c...",
  },
});

window.dataLayer.push({
  event: "login",
  method: "form",
});
```

If no hashed email or phone is available, the first event is replaced by `window.dataLayer.push({ user_data: {} })`; `login` is still emitted.

Sign-out is **two separate pushes**, not one carrying both keys. The `user_data` reset goes without an `event` and always happens, because removing data needs no permission; the event goes on its own, and only when GTM's own consent requirement is met:

```js theme={null}
window.dataLayer.push({ user_data: {} });

window.dataLayer.push({ event: "restoo_customer_signed_out" });
```

This matters for your tags: a data layer variable reading `user_data` on the sign-out event will not find the key in that push, because it arrived in the previous one.

<Note>
  Before every event push, Restoo Connect first clears the transient `restoo`,
  `ecommerce`, form, search, content, and `method` fields so values from a previous event
  are not reused. `user_data` persists until it is replaced or cleared.
</Note>

## Google Ads

With `googleAds` enabled, Restoo Connect sends conversions through `gtag("event", "conversion", data)` and manages hashed customer data through `gtag("set", "user_data", data)`.

### Standard conversions

All conversion events use Google Ads' standard `conversion` event name. `booking_lead`, `booking_confirmed`, and `contact` identify the configured conversion action, not custom event names sent to Google Ads.

| Restoo event                                       | Standard Google Ads call                                                                                                                                               | Data sent                                              |
| -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| [`booking_created`](/widget/events#booking-funnel) | `gtag("event", "conversion", …)` for `booking_confirmed` if `booking.status` is `CONFIRMED`, or for `booking_lead` if it is `REQUESTED` or `PENDING_WAIT_LIST_BOOKING` | [Booking conversion data](#google-ads-conversion-data) |
| [`action_taken`](/widget/events#actions)           | `gtag("event", "conversion", …)` for `contact` when a concrete channel is selected                                                                                     | [Contact conversion data](#google-ads-conversion-data) |

### Customer data updates

These calls update global matching data; they are not events or conversions.

| Restoo event                                     | Google Ads call                | Data sent                                  |
| ------------------------------------------------ | ------------------------------ | ------------------------------------------ |
| [`customer_identified`](/widget/events#customer) | `gtag("set", "user_data", …)`  | [Customer data](#google-ads-customer-data) |
| [`customer_signed_out`](/widget/events#customer) | `gtag("set", "user_data", {})` | [Customer data](#google-ads-customer-data) |

See Google's [conversion setup guide](https://support.google.com/google-ads/answer/12718882) for how Google Ads interprets conversion actions and [Enhanced Conversions documentation](https://support.google.com/google-ads/answer/13258081) for customer matching data.

Restoo Connect does not send Restoo custom events to Google Ads.

### Google Ads conversion data

Every conversion sends only its configured destination:

```js theme={null}
gtag("event", "conversion", {
  send_to: "AW-123456789/abc123DEF456",
});
```

Conversions carry no `value`, no `currency`, and no `transaction_id`. The booking's own reference would be the natural transaction ID, but that reference is also the key to the guest's personal data, so it never leaves the widget.

### Google Ads customer data

```js theme={null}
gtag("set", "user_data", {
  sha256_email_address: "ff8d9819fc0e12bf...",
  sha256_phone_number: "7f4597251b6a9f2c...",
});
```

On sign-out, or when the identified customer has no hashed email or phone, Restoo Connect sends `gtag("set", "user_data", {})`. Customer data enriches a conversion when available but is not required for it to fire.

### Set up conversion destinations

<Steps>
  <Step title="Create the conversion actions">
    In Google Ads, go to **Goals → Conversions → New conversion action →
    Website**. Create the `booking_lead`, `booking_confirmed`, and `contact` actions you want to
    track and choose manual setup with the Google tag. Use these as the
    conversion action description:

    | Action              | Fires when                                                                                                                                                                      |
    | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `booking_lead`      | A booking is created pending confirmation or on a waiting list — status `REQUESTED` or `PENDING_WAIT_LIST_BOOKING` (see [BookingStatus](/getting-started/enums#bookingstatus)). |
    | `booking_confirmed` | A booking is created with status `CONFIRMED`.                                                                                                                                   |
    | `contact`           | The guest taps a contact action — phone, email, or WhatsApp.                                                                                                                    |

    Each booking fires only one of the first two. Configure both even if your venue
    confirms instantly: a time slot that fills up switches to request or waiting
    list, and without `booking_lead` those bookings would go unmeasured.
  </Step>

  <Step title="Copy the conversion ID and each label">
    Open **Tag setup** for the conversion action and copy its conversion ID and
    its label. See [how to find the ID and
    label](https://support.google.com/google-ads/answer/7548399). The conversion
    ID belongs to the account and is the same for all three actions; the label is
    different in each one.
  </Step>

  <Step title="Map them in your Restoo account">
    Paste the conversion ID once, and each label into the action it belongs to, in
    your [Google Ads integration settings](/widget/integrations#google-ads).

    Only actions with a label configured are emitted, and a page cannot point
    them somewhere else: `connect` accepts only `false`, to [turn a whole
    destination off](/widget/connect#turn-a-destination-off-for-one-installation).
  </Step>
</Steps>

## Meta Pixel

With `metaPixel` enabled, Restoo Connect sends events through `fbq("trackSingle", pixelId, eventName, data)` — and `fbq("trackSingleCustom", …)` for custom ones — and manages Advanced Matching by reinitializing your pixel through `fbq("init", pixelId, userData)`. The pixel ID is [held in your Restoo account](/widget/integrations#meta-pixel) and is required to enable this destination at all.

### Standard events

All tracking events sent to Meta use standard Meta Pixel event names.

| Restoo event                                                    | Standard Meta event sent                                                                                  | Data sent                                        |
| --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| [`booking_start_submitted`](/widget/events#booking-funnel)      | `Search`                                                                                                  | [Search data](#meta-search-and-content-data)     |
| [`booking_item_detail_viewed`](/widget/events#item-list-events) | `ViewContent`                                                                                             | [Item content](#meta-search-and-content-data)    |
| [`booking_details_form_viewed`](/widget/events#booking-funnel)  | `ViewContent`                                                                                             | [Booking content](#meta-search-and-content-data) |
| [`booking_created`](/widget/events#booking-funnel)              | `Schedule` if `booking.status` is `CONFIRMED`; `Lead` if it is `REQUESTED` or `PENDING_WAIT_LIST_BOOKING` | [Booking content](#meta-lead-and-schedule-data)  |
| [`action_taken`](/widget/events#actions)                        | `Contact` when a concrete channel is selected                                                             | [Contact data](#meta-contact-and-customer-data)  |

### Restoo custom events

Funnel stages are sent as custom events rather than standard ones: Meta's standard events are optimizable, and none of these stages is a conversion. Meta does not count them as conversions unless you build a custom conversion on top of them (see [standard and custom website events](https://www.facebook.com/business/help/964258670337005)).

They are all sent with `fbq("trackSingleCustom", pixelId, …)`.

| Restoo event                                                      | Custom Meta event sent              | Data sent                                                |
| ----------------------------------------------------------------- | ----------------------------------- | -------------------------------------------------------- |
| [`booking_start_viewed`](/widget/events#booking-funnel)           | `RestooBookingStartViewed`          | [No parameters](#meta-search-and-content-data)           |
| [`booking_no_availability_viewed`](/widget/events#booking-funnel) | `RestooBookingNoAvailabilityViewed` | [Booking content and reason](#meta-no-availability-data) |
| [`booking_item_list_viewed`](/widget/events#item-list-events)     | `RestooBookingItemListViewed`       | [List content](#meta-item-list-data)                     |
| [`booking_item_selected`](/widget/events#item-list-events)        | `RestooBookingItemSelected`         | [List content](#meta-item-list-data)                     |
| [`booking_details_form_started`](/widget/events#booking-funnel)   | `RestooBookingDetailsFormStarted`   | [Booking content](#meta-lead-and-schedule-data)          |
| [`booking_details_form_submitted`](/widget/events#booking-funnel) | `RestooBookingDetailsFormSubmitted` | [Booking content](#meta-lead-and-schedule-data)          |
| [`booking_conditions_viewed`](/widget/events#booking-funnel)      | `RestooBookingConditionsViewed`     | [Booking content](#meta-lead-and-schedule-data)          |
| [`booking_conditions_accepted`](/widget/events#booking-funnel)    | `RestooBookingConditionsAccepted`   | [Booking content](#meta-lead-and-schedule-data)          |
| [`booking_cp_viewed`](/widget/events#booking-funnel)              | `RestooBookingCpViewed`             | [Booking content](#meta-lead-and-schedule-data)          |
| [`booking_cp_acknowledged`](/widget/events#booking-funnel)        | `RestooBookingCpAcknowledged`       | [Booking content](#meta-lead-and-schedule-data)          |
| [`booking_cp_accepted`](/widget/events#booking-funnel)            | `RestooBookingCpAccepted`           | [Booking content](#meta-lead-and-schedule-data)          |

### Customer data updates

Both calls require the pixel ID [configured in your account](/widget/integrations#meta-pixel). They update Meta Advanced Matching data; they are not Pixel events.

| Restoo event                                     | Meta call                                                         | Data sent                                        |
| ------------------------------------------------ | ----------------------------------------------------------------- | ------------------------------------------------ |
| [`customer_identified`](/widget/events#customer) | `fbq("init", pixelId, …)` when hashed email or phone is available | [Customer data](#meta-contact-and-customer-data) |
| [`customer_signed_out`](/widget/events#customer) | `fbq("init", pixelId, {})`                                        | [Customer data](#meta-contact-and-customer-data) |

See Meta's [Pixel event reference](https://developers.facebook.com/docs/meta-pixel/reference) for the meaning and expected parameters of its standard events.

Of `action_taken`, only contact through a concrete channel travels here. Every other action — add to calendar, invite guests, get directions, recommend, share, modify, cancel — happens once the booking is already made, so it feeds no audience and counts as no conversion: those stay in GA4 and GTM.

### Meta search and content data

When the booking start page is shown, Restoo Connect sends the custom event without parameters:

```js theme={null}
fbq("trackSingleCustom", "123456789012345", "RestooBookingStartViewed", {});
```

Submitting valid party size and date criteria sends a `Search`, with a synthetic search term; an experience detail sends a `ViewContent`:

```js theme={null}
fbq("trackSingle", "123456789012345", "Search", {
  search_string: "pax_4_day_friday_shift_dinner",
});

fbq("trackSingle", "123456789012345", "ViewContent", {
  content_ids: ["best_burger:experience:7"],
  content_type: "product",
});
```

The guest-details form also sends `ViewContent`, with booking content:

```js theme={null}
fbq("trackSingle", "123456789012345", "ViewContent", {
  content_ids: [
    "best-burger",
    "best_burger:experience:7",
    "best_burger:add_on:12",
  ],
  content_type: "product",
  content_name: "Best Burger",
});
```

Booking `content_ids` contains the account ID followed by the selected experience and add-on IDs.

### Meta item-list data

```js theme={null}
fbq("trackSingleCustom", "123456789012345", "RestooBookingItemListViewed", {
  content_ids: ["best_burger:experience:7", "best_burger:experience:9"],
  content_type: "product",
});
```

`RestooBookingItemSelected` sends the same structure with the items the guest chose. Neither carries `content_name` nor quantities: the item IDs are all that attribution and audiences need.

### Meta no-availability data

```js theme={null}
fbq(
  "trackSingleCustom",
  "123456789012345",
  "RestooBookingNoAvailabilityViewed",
  {
    content_ids: ["best-burger"],
    content_type: "product",
    content_name: "Best Burger",
    availability_outcome: "SHIFT_FULL",
  },
);
```

It carries the booking content as it stands at the time of the search, so `content_ids` may contain only the account ID. See [AvailabilityOutcome](/getting-started/enums#availabilityoutcome) for the possible values and their meanings.

### Meta Lead and Schedule data

```js theme={null}
fbq("trackSingle", "123456789012345", "Lead", {
  content_ids: [
    "best-burger",
    "best_burger:experience:7",
    "best_burger:add_on:12",
  ],
  content_type: "product",
  content_name: "Best Burger",
});
```

`Schedule` and the custom events for the details form, the booking conditions, and the cancellation policy receive the same content.

Meta events carry no prices, `value`, `currency`, or event ID. Because there is no event ID, Meta cannot match these events against a server-side [Conversions API](https://www.facebook.com/business/help/AboutConversionsAPI) integration, so do not report the same bookings from both — see [Avoiding duplicate conversions](/widget/bidding-optimization#avoiding-duplicate-conversions-across-ga4-google-ads-and-gtm).

### Meta contact and customer data

```js theme={null}
fbq("trackSingle", "123456789012345", "Contact", {
  method: "whatsapp",
});

fbq("init", "123456789012345", {
  em: "ff8d9819fc0e12bf...",
  ph: "7f4597251b6a9f2c...",
});
```

`em` and `ph` contain normalized SHA-256 hashes. The identification call is only made when at least one hashed value is available. On sign-out, Restoo Connect sends `fbq("init", pixelId, {})`.

## TikTok Pixel

With `tiktokPixel` enabled, Restoo Connect sends events through `ttq.instance(pixelId).track(eventName, data)` and manages customer matching data through `ttq.instance(pixelId).identify(data)`. Both are scoped to the pixel [configured in your account](/widget/integrations#tiktok-pixel), so a page with more than one pixel installed only receives them on that one.

### Standard events

All tracking events sent to TikTok use standard TikTok Pixel event names.

| Restoo event                                                    | Standard TikTok event sent                                                                                      | Data sent                                               |
| --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| [`booking_start_submitted`](/widget/events#booking-funnel)      | `Search`                                                                                                        | [Search data](#tiktok-search-and-content-data)          |
| [`booking_item_detail_viewed`](/widget/events#item-list-events) | `ViewContent`                                                                                                   | [Item content](#tiktok-search-and-content-data)         |
| [`booking_details_form_viewed`](/widget/events#booking-funnel)  | `ViewContent`                                                                                                   | [Booking content](#tiktok-search-and-content-data)      |
| [`booking_created`](/widget/events#booking-funnel)              | `Schedule` if `booking.status` is `CONFIRMED`; `SubmitForm` if it is `REQUESTED` or `PENDING_WAIT_LIST_BOOKING` | [Booking content](#tiktok-submitform-and-schedule-data) |
| [`action_taken`](/widget/events#actions)                        | `Contact` when a concrete channel is selected                                                                   | [Contact data](#tiktok-contact-and-customer-data)       |

<Note>
  TikTok renamed `SubmitForm` to `Lead` and keeps the old name working, converting
  it on its backend. Restoo sends `SubmitForm`, which is the one still listed in
  the standard events reference, and you will see it as `Lead` in your reporting
  and optimization. See [TikTok's updated standard
  events](https://ads.tiktok.com/help/article/how-to-adopt-tiktoks-updated-standard-events).
</Note>

### Restoo custom events

Funnel stages are sent as custom events rather than standard ones: none of them is a conversion. TikTok uses custom events for reporting and audiences, but they cannot be chosen as a campaign optimization goal (see [custom events](https://ads.tiktok.com/help/article/custom-events)).

| Restoo event                                                      | Custom TikTok event sent            | Data sent                                                  |
| ----------------------------------------------------------------- | ----------------------------------- | ---------------------------------------------------------- |
| [`booking_start_viewed`](/widget/events#booking-funnel)           | `RestooBookingStartViewed`          | [No parameters](#tiktok-search-and-content-data)           |
| [`booking_no_availability_viewed`](/widget/events#booking-funnel) | `RestooBookingNoAvailabilityViewed` | [Booking content and reason](#tiktok-no-availability-data) |
| [`booking_item_list_viewed`](/widget/events#item-list-events)     | `RestooBookingItemListViewed`       | [List content](#tiktok-item-list-data)                     |
| [`booking_item_selected`](/widget/events#item-list-events)        | `RestooBookingItemSelected`         | [List content](#tiktok-item-list-data)                     |
| [`booking_details_form_started`](/widget/events#booking-funnel)   | `RestooBookingDetailsFormStarted`   | [Booking content](#tiktok-submitform-and-schedule-data)    |
| [`booking_details_form_submitted`](/widget/events#booking-funnel) | `RestooBookingDetailsFormSubmitted` | [Booking content](#tiktok-submitform-and-schedule-data)    |
| [`booking_conditions_viewed`](/widget/events#booking-funnel)      | `RestooBookingConditionsViewed`     | [Booking content](#tiktok-submitform-and-schedule-data)    |
| [`booking_conditions_accepted`](/widget/events#booking-funnel)    | `RestooBookingConditionsAccepted`   | [Booking content](#tiktok-submitform-and-schedule-data)    |
| [`booking_cp_viewed`](/widget/events#booking-funnel)              | `RestooBookingCpViewed`             | [Booking content](#tiktok-submitform-and-schedule-data)    |
| [`booking_cp_acknowledged`](/widget/events#booking-funnel)        | `RestooBookingCpAcknowledged`       | [Booking content](#tiktok-submitform-and-schedule-data)    |
| [`booking_cp_accepted`](/widget/events#booking-funnel)            | `RestooBookingCpAccepted`           | [Booking content](#tiktok-submitform-and-schedule-data)    |

### Customer data updates

These calls update TikTok matching data; they are not Pixel events.

| Restoo event                                     | TikTok call                                                                 | Data sent                                          |
| ------------------------------------------------ | --------------------------------------------------------------------------- | -------------------------------------------------- |
| [`customer_identified`](/widget/events#customer) | `ttq.instance(pixelId).identify(…)` when hashed email or phone is available | [Customer data](#tiktok-contact-and-customer-data) |
| [`customer_signed_out`](/widget/events#customer) | `ttq.instance(pixelId).identify({})`                                        | [Customer data](#tiktok-contact-and-customer-data) |

See TikTok's [standard events reference](https://ads.tiktok.com/help/article/standard-events-parameters) and [parameter reference](https://ads.tiktok.com/help/article/about-parameters) for the meaning and expected format of its standard fields.

Of `action_taken`, only contact through a concrete channel travels here. Every other action — add to calendar, invite guests, get directions, recommend, share, modify, cancel — happens once the booking is already made, so it feeds no audience and counts as no conversion: those stay in GA4 and GTM.

### TikTok search and content data

When the booking start page is shown, Restoo Connect sends the custom event without parameters:

```js theme={null}
ttq.instance("C1234567890ABCDEFGHI").track("RestooBookingStartViewed", {});
```

Submitting valid party size and date criteria sends a `Search`, with a synthetic search term; an experience detail sends a `ViewContent`:

```js theme={null}
ttq.instance("C1234567890ABCDEFGHI").track("Search", {
  search_string: "pax_4_day_friday_shift_dinner",
});

ttq.instance("C1234567890ABCDEFGHI").track("ViewContent", {
  content_ids: ["best_burger:experience:7"],
  content_type: "product",
});
```

The guest-details form also sends `ViewContent`, with booking content:

```js theme={null}
ttq.instance("C1234567890ABCDEFGHI").track("ViewContent", {
  content_ids: [
    "best-burger",
    "best_burger:experience:7",
    "best_burger:add_on:12",
  ],
  content_type: "product",
  content_name: "Best Burger",
});
```

### TikTok item-list data

```js theme={null}
ttq.instance("C1234567890ABCDEFGHI").track("RestooBookingItemListViewed", {
  content_ids: ["best_burger:experience:7", "best_burger:experience:9"],
  content_type: "product",
});
```

`RestooBookingItemSelected` sends the same structure with the items the guest chose. Neither carries `content_name` nor quantities: the item IDs are all that attribution and audiences need.

### TikTok no-availability data

```js theme={null}
ttq
  .instance("C1234567890ABCDEFGHI")
  .track("RestooBookingNoAvailabilityViewed", {
    content_ids: ["best-burger"],
    content_type: "product",
    content_name: "Best Burger",
    availability_outcome: "SHIFT_FULL",
  });
```

It carries the booking content as it stands at the time of the search, so `content_ids` may contain only the account ID. See [AvailabilityOutcome](/getting-started/enums#availabilityoutcome) for the possible values and their meanings.

### TikTok SubmitForm and Schedule data

```js theme={null}
ttq.instance("C1234567890ABCDEFGHI").track("SubmitForm", {
  content_ids: [
    "best-burger",
    "best_burger:experience:7",
    "best_burger:add_on:12",
  ],
  content_type: "product",
  content_name: "Best Burger",
});
```

`Schedule` and the custom events for the details form, the booking conditions, and the cancellation policy receive the same content.

TikTok events carry no prices, `value`, `currency`, or event ID. As with Meta, that means these events cannot be matched against a server-side Events API integration — see [Avoiding duplicate conversions](/widget/bidding-optimization#avoiding-duplicate-conversions-across-ga4-google-ads-and-gtm).

### TikTok contact and customer data

```js theme={null}
ttq.instance("C1234567890ABCDEFGHI").track("Contact", {
  method: "whatsapp",
});

ttq.instance("C1234567890ABCDEFGHI").identify({
  email: "ff8d9819fc0e12bf...",
  phone_number: "7f4597251b6a9f2c...",
});
```

`email` and `phone_number` contain normalized SHA-256 hashes. Identification is only sent when at least one value is available. On sign-out, Restoo Connect sends `ttq.instance(pixelId).identify({})`.

## OpenAI Pixel

With `openaiPixel` enabled, Restoo Connect sends events to the ChatGPT Ads pixel through `oaiq("measureSingle", pixelId, eventName, data, options)` and sets customer matching data through `oaiq("init", { pixelId, user })`. Both are scoped to the pixel [configured in your account](/widget/integrations#openai-pixel), so a page with more than one pixel initialized only receives them on that one: `measure`, the call that broadcasts to every pixel, is never used.

On this destination the event name and the shape of its data travel separately: every standard event requires a specific `data.type`, and the SDK **drops the whole event** if `data` carries a field it does not document for that type. The data in the tables below is exactly what fits.

### Standard events

| Restoo event                                                    | Standard OpenAI event sent                                                                                                     | Data sent                                        |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------ |
| [`booking_item_list_viewed`](/widget/events#item-list-events)   | `contents_viewed`                                                                                                              | [List contents](#openai-pixel-list-data)         |
| [`booking_item_detail_viewed`](/widget/events#item-list-events) | `contents_viewed`                                                                                                              | [Item contents](#openai-pixel-list-data)         |
| [`booking_item_selected`](/widget/events#item-list-events)      | `items_added`                                                                                                                  | [List contents](#openai-pixel-list-data)         |
| [`booking_created`](/widget/events#booking-funnel)              | `appointment_scheduled` if `booking.status` is `CONFIRMED`; `lead_created` if it is `REQUESTED` or `PENDING_WAIT_LIST_BOOKING` | [Conversion data](#openai-pixel-conversion-data) |

<Note>
  ChatGPT Ads has no standard search event and no standard form event, so the
  availability search and the details form — `Search` and `ViewContent` on Meta
  and TikTok — travel here as custom events.
</Note>

### Restoo custom events

Funnel stages are sent as custom events — the `custom` event, with the name in `custom_event_name` — rather than standard ones: none of them is a conversion. ChatGPT Ads accepts them for measurement, but [not as a campaign's optimization goal](https://developers.openai.com/ads/conversion-optimized-campaigns). Contact travels as a custom event too, because no standard event describes it. They carry the `restoo_` prefix because they share the pixel with whatever custom events your own site sends.

| Restoo event                                                      | `custom_event_name` sent                      | Data sent                                               |
| ----------------------------------------------------------------- | --------------------------------------------- | ------------------------------------------------------- |
| [`booking_start_viewed`](/widget/events#booking-funnel)           | `restoo_booking_start_viewed`                 | [No contents](#openai-pixel-booking-data)               |
| [`booking_start_submitted`](/widget/events#booking-funnel)        | `restoo_booking_start_submitted`              | [Booking contents](#openai-pixel-booking-data)          |
| [`booking_no_availability_viewed`](/widget/events#booking-funnel) | `restoo_booking_no_availability_viewed`       | [Booking contents](#openai-pixel-booking-data)          |
| [`booking_details_form_viewed`](/widget/events#booking-funnel)    | `restoo_booking_details_form_viewed`          | [Booking contents](#openai-pixel-booking-data)          |
| [`booking_details_form_started`](/widget/events#booking-funnel)   | `restoo_booking_details_form_started`         | [Booking contents](#openai-pixel-booking-data)          |
| [`booking_details_form_submitted`](/widget/events#booking-funnel) | `restoo_booking_details_form_submitted`       | [Booking contents](#openai-pixel-booking-data)          |
| [`booking_conditions_viewed`](/widget/events#booking-funnel)      | `restoo_booking_conditions_viewed`            | [Booking contents](#openai-pixel-booking-data)          |
| [`booking_conditions_accepted`](/widget/events#booking-funnel)    | `restoo_booking_conditions_accepted`          | [Booking contents](#openai-pixel-booking-data)          |
| [`booking_cp_viewed`](/widget/events#booking-funnel)              | `restoo_booking_cp_viewed`                    | [Booking contents](#openai-pixel-booking-data)          |
| [`booking_cp_acknowledged`](/widget/events#booking-funnel)        | `restoo_booking_cp_acknowledged`              | [Booking contents](#openai-pixel-booking-data)          |
| [`booking_cp_accepted`](/widget/events#booking-funnel)            | `restoo_booking_cp_accepted`                  | [Booking contents](#openai-pixel-booking-data)          |
| [`action_taken`](/widget/events#actions)                          | `contact` when a concrete channel is selected | [Contact data](#openai-pixel-contact-and-customer-data) |

### Customer data updates

These calls set the pixel's matching data; they are not events.

| Restoo event                                     | OpenAI call                                                               | Data sent                                                |
| ------------------------------------------------ | ------------------------------------------------------------------------- | -------------------------------------------------------- |
| [`customer_identified`](/widget/events#customer) | `oaiq("init", { pixelId, user })` when hashed email or phone is available | [Customer data](#openai-pixel-contact-and-customer-data) |
| [`customer_signed_out`](/widget/events#customer) | `oaiq("init", { pixelId, user: {} })`                                     | [Customer data](#openai-pixel-contact-and-customer-data) |

See OpenAI's [supported events](https://developers.openai.com/ads/supported-events) and [pixel reference](https://developers.openai.com/ads/measurement-pixel) for the meaning and expected format of its fields.

Of `action_taken`, only contact through a concrete channel travels here. Every other action — add to calendar, invite guests, get directions, recommend, share, modify, cancel — happens once the booking is already made, so it feeds no audience and counts as no conversion: those stay in GA4 and GTM.

### OpenAI Pixel booking data

When the booking start page is shown, Restoo Connect sends the custom event with no contents:

```js theme={null}
oaiq(
  "measureSingle",
  "AbC123dEf456GhI789JkL0",
  "custom",
  { type: "custom" },
  { custom_event_name: "restoo_booking_start_viewed" },
);
```

The other stages carry the booking contents as they stand at that moment: the business, with the party size as quantity, and, when present, the experience with its tickets and the add-ons with their units. When searching for availability or finding none, the booking has no experience or add-ons yet, so only the business travels.

```js theme={null}
oaiq(
  "measureSingle",
  "AbC123dEf456GhI789JkL0",
  "custom",
  {
    type: "custom",
    contents: [
      { id: "best-burger", name: "Best Burger", content_type: "product", quantity: 4 },
      { id: "best_burger:experience:7", content_type: "product", quantity: 4 },
      { id: "best_burger:add_on:12", content_type: "product", quantity: 2 },
    ],
  },
  { custom_event_name: "restoo_booking_details_form_viewed" },
);
```

Only the business carries `name`; the other items are identified by ID, for the reasons in [what Restoo deliberately omits](#what-restoo-deliberately-omits). No item carries `amount` or `currency`.

Two values that Meta and TikTok do receive never travel to this destination: the synthetic search term of `Search` and the `availability_outcome` of the no-availability stage. Neither is a field the SDK documents, and carrying them would drop the whole event.

### OpenAI Pixel list data

```js theme={null}
oaiq("measureSingle", "AbC123dEf456GhI789JkL0", "contents_viewed", {
  type: "contents",
  contents: [
    { id: "best_burger:experience:7", content_type: "product" },
    { id: "best_burger:experience:9", content_type: "product" },
  ],
});
```

`items_added` sends the same structure with the items the guest chose, and an item's detail sends `contents_viewed` with that single item. None carries `name` or quantities: the item IDs are all that attribution and audiences need.

### OpenAI Pixel conversion data

```js theme={null}
oaiq("measureSingle", "AbC123dEf456GhI789JkL0", "appointment_scheduled", {
  type: "customer_action",
});
```

`lead_created` sends exactly the same. The `customer_action` type, which is the one these two events require, does not accept `contents`, so the conversion carries no booking IDs: they travel in the funnel stages that precede it.

OpenAI Pixel events carry no prices, `amount`, `currency`, or event ID. As with Meta and TikTok, that means they cannot be matched against a server-side integration of OpenAI's Conversions API — see [Avoiding duplicate conversions](/widget/bidding-optimization#avoiding-duplicate-conversions-across-ga4-google-ads-and-gtm).

### OpenAI Pixel contact and customer data

```js theme={null}
oaiq(
  "measureSingle",
  "AbC123dEf456GhI789JkL0",
  "custom",
  { type: "custom" },
  { custom_event_name: "contact" },
);

oaiq("init", {
  pixelId: "AbC123dEf456GhI789JkL0",
  user: {
    email_sha256: "ff8d9819fc0e12bf...",
    phone_number_sha256: "7f4597251b6a9f2c...",
  },
});
```

Contact carries no channel: a `custom` event accepts no fields of its own on the pixel. `email_sha256` and `phone_number_sha256` contain normalized SHA-256 hashes; the phone one is the MSISDN format, the same one Meta receives (see [Customer identity](/widget/consent#customer-identity)). Identification is only sent when at least one value is available. On sign-out, Restoo Connect sends `oaiq("init", { pixelId, user: {} })`, which retracts the identity from the pixel.

## Next steps

<CardGroup cols={2}>
  <Card title="Bidding and optimization" icon="bullseye" href="/widget/bidding-optimization">
    Choose which events your campaigns optimize toward on each platform.
  </Card>

  <Card title="Consent" icon="shield-check" href="/widget/consent">
    What each destination needs to receive an event, signal by signal.
  </Card>
</CardGroup>
