> ## 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.

# Bidding & Optimization for Agencies

> How to use Restoo widget events to measure the booking funnel and choose the right optimization conversions for Google Ads, Meta, TikTok, and ChatGPT Ads.

This guide is for agencies and marketing teams running paid campaigns for a business that uses the Restoo widget. It explains which widget events to **measure** and which ones to hand to the bidding algorithms as **conversions**, so campaigns optimize toward real reservations instead of intermediate steps.

It builds on [Restoo Connect](/widget/connect), which forwards widget events to your analytics and advertising platforms without any custom code. Before you go on, enable the destinations you use in your account:

<CardGroup cols={2}>
  <Card title="Set Up Your Integrations" icon="sliders" href="/widget/integrations">
    Enable GA4, Google Ads, Meta, TikTok, ChatGPT Ads, or GTM in your Restoo account.
  </Card>

  <Card title="Event Mappings" icon="table" href="/widget/connect-mappings">
    How each Restoo event maps to each platform.
  </Card>
</CardGroup>

Advanced integrations that prefer to handle the events themselves can build a custom integration from the [Restoo Widget Events](/widget/events) reference instead of using Restoo Connect. Most campaigns do not need this.

<Note>
  The recommendations below are general defaults, not absolute rules. Where a
  guideline depends on account volume or campaign goals, it is marked as such.
  Always validate against the account's own data.
</Note>

## Diagnostic events vs. optimization conversions

Not every event should become a conversion. Split them into two groups.

**Diagnostic events** tell you *where* people drop off. Use them for reporting, funnels, and audiences — but do **not** let a bidding strategy optimize toward them. Optimizing toward an early step teaches the algorithm to find people who complete that step, not people who book.

**Optimization conversions** are the small set of events you deliberately feed to Smart Bidding, Meta's optimization, TikTok's optimization goal, or the conversion event of a ChatGPT Ads campaign. Restoo models a reservation as a *lead*, not an ecommerce purchase (see [Acquisition model](/widget/connect-mappings#acquisition-model)), so these events carry **no `value` or `currency`** — optimize for conversion *volume*, not value/ROAS.

The table maps each funnel stage to the event Restoo Connect sends to each platform. A dash means it does not send that stage to that platform.

| Funnel stage (Restoo event)                                                                | Role          | GA4                                     | Google Ads           | Meta                                | TikTok                              | ChatGPT Ads                             |
| ------------------------------------------------------------------------------------------ | ------------- | --------------------------------------- | -------------------- | ----------------------------------- | ----------------------------------- | --------------------------------------- |
| Booking start viewed (`booking_start_viewed`)                                              | Diagnostic    | `restoo_booking_start_viewed`           | —                    | `RestooBookingStartViewed`          | `RestooBookingStartViewed`          | `restoo_booking_start_viewed`           |
| Availability search (`booking_start_submitted`)                                            | Diagnostic    | `search`                                | —                    | `Search`                            | `Search`                            | `restoo_booking_start_submitted`        |
| No availability (`booking_no_availability_viewed`)                                         | Diagnostic    | `restoo_booking_no_availability_viewed` | —                    | `RestooBookingNoAvailabilityViewed` | `RestooBookingNoAvailabilityViewed` | `restoo_booking_no_availability_viewed` |
| List viewed (`booking_item_list_viewed`)                                                   | Diagnostic    | `view_item_list`                        | —                    | `RestooBookingItemListViewed`       | `RestooBookingItemListViewed`       | `contents_viewed`                       |
| Item detail viewed (`booking_item_detail_viewed`)                                          | Diagnostic    | `view_item`                             | —                    | `ViewContent`                       | `ViewContent`                       | `contents_viewed`                       |
| Item selected (`booking_item_selected`)                                                    | Diagnostic    | `select_item`                           | —                    | `RestooBookingItemSelected`         | `RestooBookingItemSelected`         | `items_added`                           |
| Details form viewed (`booking_details_form_viewed`)                                        | Diagnostic    | `restoo_booking_details_form_viewed`    | —                    | `ViewContent`                       | `ViewContent`                       | `restoo_booking_details_form_viewed`    |
| Details form started (`booking_details_form_started`)                                      | Diagnostic    | `form_start`                            | —                    | `RestooBookingDetailsFormStarted`   | `RestooBookingDetailsFormStarted`   | `restoo_booking_details_form_started`   |
| Details form submitted (`booking_details_form_submitted`)                                  | Diagnostic    | `form_submit`                           | —                    | `RestooBookingDetailsFormSubmitted` | `RestooBookingDetailsFormSubmitted` | `restoo_booking_details_form_submitted` |
| Conditions viewed (`booking_conditions_viewed`)                                            | Diagnostic    | `restoo_booking_conditions_viewed`      | —                    | `RestooBookingConditionsViewed`     | `RestooBookingConditionsViewed`     | `restoo_booking_conditions_viewed`      |
| Conditions accepted (`booking_conditions_accepted`)                                        | Diagnostic    | `restoo_booking_conditions_accepted`    | —                    | `RestooBookingConditionsAccepted`   | `RestooBookingConditionsAccepted`   | `restoo_booking_conditions_accepted`    |
| Cancellation policy shown (`booking_cp_viewed`)                                            | Diagnostic    | `restoo_booking_cp_viewed`              | —                    | `RestooBookingCpViewed`             | `RestooBookingCpViewed`             | `restoo_booking_cp_viewed`              |
| Cancellation policy acknowledged (`booking_cp_acknowledged`)                               | Diagnostic    | `restoo_booking_cp_acknowledged`        | —                    | `RestooBookingCpAcknowledged`       | `RestooBookingCpAcknowledged`       | `restoo_booking_cp_acknowledged`        |
| Cancellation policy signed (`booking_cp_accepted`)                                         | Diagnostic    | `restoo_booking_cp_accepted`            | —                    | `RestooBookingCpAccepted`           | `RestooBookingCpAccepted`           | `restoo_booking_cp_accepted`            |
| **Booking confirmed (`booking_created`, status `CONFIRMED`)**                              | **Booking**   | `qualify_lead`                          | `booking_confirmed`  | `Schedule`                          | `Schedule`                          | `appointment_scheduled`                 |
| **Booking pending (`booking_created`, status `REQUESTED` or `PENDING_WAIT_LIST_BOOKING`)** | **Lead**      | `generate_lead`                         | `booking_lead`       | `Lead`                              | `SubmitForm`                        | `lead_created`                          |
| Booking modified (`booking_updated`)                                                       | Diagnostic    | `restoo_booking_updated`                | —                    | —                                   | —                                   | —                                       |
| **Contact (`action_taken`, concrete channel)**                                             | **Contact**   | `select_content`                        | `contact`            | `Contact`                           | `Contact`                           | `contact` (custom)                      |
| Customer identified (`customer_identified`)                                                | Matching data | `login`                                 | Enhanced Conversions | Advanced Matching                   | `identify`                          | `init` with `user`                      |

<Info>
  The Google Ads destination sends only three conversion actions —
  `booking_lead`, `booking_confirmed`, and `contact` — which are exactly [the
  three optimization conversions](#the-three-optimization-conversions). It never sends diagnostic events to
  Google Ads. GA4, Meta, and TikTok receive the wider set for measurement and
  audiences; ChatGPT Ads, for measurement.
</Info>

## The three optimization conversions

Everything you optimize toward comes from just three events:

<CardGroup cols={3}>
  <Card title="Booking" icon="calendar-check">
    `booking_created` with status `CONFIRMED`. The real outcome. Maps to
    `booking_confirmed` / `Schedule` / `qualify_lead` / `appointment_scheduled`.
  </Card>

  <Card title="Lead" icon="user-pen">
    `booking_created` pending confirmation or on a waiting list. Maps to
    `booking_lead` / `Lead` / `SubmitForm` / `generate_lead` / `lead_created`.
  </Card>

  <Card title="Contact" icon="phone">
    `action_taken` with a concrete channel (phone, email, WhatsApp…). Maps to
    `contact` / `Contact` / `select_content`.
  </Card>
</CardGroup>

## Recommendation: the booking as the primary conversion

**As a general default, make the booking your primary optimization conversion and the metric campaigns bid toward.** It is the closest signal to revenue, and it is the one outcome the business actually cares about.

Which of the two booking conversions plays that role depends on how the venue works:

| How the venue works                          | Primary conversion           |
| -------------------------------------------- | ---------------------------- |
| Confirms instantly                           | Confirmed booking            |
| Uses request-to-book or wait-list flows      | Lead                         |
| Both, depending on the time slot or capacity | Both, both marked as primary |

In the third case, marking both counts nothing twice: they are mutually exclusive, and added together they are exactly the bookings created. Track confirmations separately as a reporting metric if you care about the ratio between the two.

<Note>
  When a visitor edits an existing booking, Restoo Connect suppresses funnel and
  conversion events, so edits never inflate your booking or lead counts.
</Note>

## Recommendation: contact as a secondary conversion

Use **Contact** as a **secondary** conversion: it is reported and informs bidding without becoming the goal. It captures demand that never enters the online funnel — guests who call or message instead of booking — and that matters for venues that take many reservations by phone.

Keeping it secondary means the algorithm still learns from it, but it does not chase phone taps at the expense of bookings.

Keep as secondary the booking conversion your venue barely produces too — the **Lead** if you confirm instantly, or the **confirmed booking** if you work by request — so it is measured without distorting bidding along with a handful of cases.

## Low-volume accounts

Automated bidding needs a steady flow of the event it optimizes toward. As a rule of thumb — not a hard rule:

* **Google Ads** Smart Bidding works best with roughly **15–30 conversions in the last 30 days** on the optimization action. Target CPA/ROAS strategies need more than Maximize Conversions.
* **Meta** ad sets exit the *learning phase* near **\~50 optimization events per week** per ad set.
* **TikTok** similarly stabilizes around **\~50 conversions in 7 days** for the chosen optimization event.

Below those levels the booking is too rare for the algorithm to learn from, and it makes sense to **temporarily** move the optimization target one step earlier in the funnel.

**That earlier step is not the Lead.** Both booking conversions sit at the same funnel depth — both require the booking to exist — so switching from one to the other buys no volume, it just measures something else. The steps that really come earlier are the diagnostic ones, and what you can pick as a goal depends on the platform:

| Platform    | Usable earlier signal                                                |
| ----------- | -------------------------------------------------------------------- |
| Meta        | `ViewContent` (experience detail or details form viewed) or `Search` |
| TikTok      | `ViewContent` or `Search`                                            |
| ChatGPT Ads | `contents_viewed` (list or item detail) or `items_added`             |
| GA4 and GTM | `form_submit`, `form_start`, or `search`, imported as key events     |
| Google Ads  | None: the widget sends it only the three conversion actions          |

Restoo custom events are no use here: neither Meta, TikTok nor ChatGPT Ads accepts them as an optimization goal, however late their stage sits in the funnel. And on Google Ads, if booking volume does not clear the threshold, the only room left is in what goes with the switch:

1. **Consolidate** campaigns and ad sets so conversions are not split across many small groups.
2. **Broaden** targeting and use broad match / Advantage+ audiences to give the algorithm room.
3. **Enable Enhanced Conversions, Advanced Matching, `identify`, and the OpenAI Pixel's `user`** (via `customer_identified`) so every conversion is matched to more clicks — this recovers signal that would otherwise be lost.

Treat it as a temporary step, not the final goal: as soon as booking volume clears the thresholds, move the optimization target back to the confirmed booking.

<Warning>
  **Do not leave the algorithm optimizing toward diagnostic events or
  contacts.** If you optimize toward `ViewContent` or `Contact` permanently, you
  teach the algorithm to find people who *browse pages* or *tap call buttons* —
  not people who *book*. You will see cheap "conversions" and flat reservations.
  Any earlier-funnel target is a temporary step toward the booking conversion.
</Warning>

## Google Ads: primary and secondary conversions

Google Ads lets you mark each conversion action as **Primary** (used for bidding) or **Secondary** (observed only).

<Steps>
  <Step title="Create the three conversion actions">
    Create `booking_lead`, `booking_confirmed`, and `contact` in Google Ads and
    paste the conversion ID of the account, plus the label of each action, [into
    your Restoo account](/widget/integrations#google-ads). The step by step is in
    [set up conversion
    destinations](/widget/connect-mappings#set-up-conversion-destinations).
  </Step>

  <Step title="Mark your venue's booking conversion as Primary">
    Set `booking_confirmed` as the **Primary** action if the venue confirms
    instantly, `booking_lead` if it works by request or with a waiting list, or
    both if it does both. They are mutually exclusive, so marking both counts no
    booking twice.
  </Step>

  <Step title="Mark contact as Secondary">
    Set `contact` as **Secondary** so it is reported and can inform bidding
    without becoming the goal. Keep the booking conversion your venue barely
    produces as Secondary too.
  </Step>

  <Step title="Use conversion goals">
    Group the primary action into the campaign's conversion goal. Keep account
    default goals aligned so campaigns do not silently bid on the wrong action.
  </Step>
</Steps>

<Info>
  Because Restoo conversions carry no `value`, use **Maximize Conversions**
  (optionally with a Target CPA) rather than value-based Maximize Conversion
  Value / Target ROAS.
</Info>

## Meta, TikTok, and ChatGPT Ads: an equivalent strategy

Meta, TikTok, and ChatGPT Ads do not have a Primary/Secondary label, but you get the same effect by choosing the **optimization event / optimization goal** per campaign, while the other events keep flowing for measurement.

<Tabs>
  <Tab title="Meta">
    * **Default optimization event:** `Schedule` (confirmed booking), or `Lead` if the venue works by request or with a waiting list. They are mutually exclusive: every booking fires one of the two.
    * **Ramp-up or low volume:** optimize for `ViewContent` or `Search`, then move back to `Schedule`. Switching from `Schedule` to `Lead` buys no volume, they are the same funnel step.
    * **Phone-heavy venues:** a dedicated campaign optimizing for `Contact`.
    * **Do not also send these events from your server.** Meta's deduplication relies on an event ID, and Restoo Connect sends none, so the same booking reported through the [Conversions API](https://www.facebook.com/business/help/AboutConversionsAPI) is counted a second time. Send each conversion from **one** source — see [Avoiding duplicate conversions](#avoiding-duplicate-conversions-across-ga4-google-ads-and-gtm).
    * **Advanced Matching is always on** — the pixel ID held in your Restoo account is required to enable Meta at all, so match rates and attribution come configured.
  </Tab>

  <Tab title="TikTok">
    * **Default optimization event:** `Schedule` (confirmed booking), or `SubmitForm` if the venue works by request or with a waiting list. They are mutually exclusive: every booking fires one of the two. TikTok shows `SubmitForm` as `Lead` in reporting and optimization.
    * **Ramp-up or low volume:** optimize for `ViewContent` or `Search`, then move back to `Schedule`. See TikTok's [deep-funnel optimization](https://ads.tiktok.com/help/article/tips-for-deep-funnel-optimization) and [full-funnel marketing](https://ads.tiktok.com/help/article/full-funnel-marketing-tiktok) guidance.
    * Use `Search` and `ViewContent` for upper-funnel campaigns and retargeting pools.
    * `ttq.identify` provides customer matching.
    * **Do not also send these events from your server.** As with Meta, Restoo Connect sends no event IDs, so the same booking reported through the Events API is counted a second time. Send each conversion from **one** source — see [Avoiding duplicate conversions](#avoiding-duplicate-conversions-across-ga4-google-ads-and-gtm).
  </Tab>

  <Tab title="ChatGPT Ads">
    * **First, the conversion event:** in the conversions tab of Ads Manager, create a conversion event on your pixel with the standard name you are going to use. Without it, events are received but do not count as conversions.
    * **Campaign conversion event:** `appointment_scheduled` (confirmed booking), or `lead_created` if the venue works by request or with a waiting list. They are mutually exclusive: every booking fires one of the two. Each campaign optimizes toward **a single standard event**, fixed when the campaign is created and not changeable afterwards; optimizing toward the other one takes another campaign.
    * **Conversion optimization is in beta**: if that objective does not show up when you create the campaign, the account does not have it enabled and you have to ask OpenAI for it. Until then the campaign bids on clicks or impressions and conversions keep being measured. See [conversion-optimized campaigns](https://developers.openai.com/ads/conversion-optimized-campaigns).
    * **Ramp-up or low volume:** optimize for `contents_viewed` or `items_added`, then move back to the booking conversion. Like Meta and TikTok, ChatGPT Ads does not accept custom events as a goal, so the `restoo_*` events stay for measurement.
    * **Contact:** `contact` is a custom event, so it is measured but cannot be a campaign's goal.
    * **Do not also send these events from your server.** As with Meta, Restoo Connect sends no event IDs, so the same booking reported through OpenAI's [Conversions API](https://developers.openai.com/ads/conversions-api) is counted a second time. Send each conversion from **one** source — see [Avoiding duplicate conversions](#avoiding-duplicate-conversions-across-ga4-google-ads-and-gtm).
    * **Matching data** comes from the `user` Restoo Connect sets when the guest identifies themselves, and from the pixel's own automatic advanced matching.
  </Tab>
</Tabs>

## Abandonment and remarketing audiences

Audiences are built from the **diagnostic** events, which mark the stage each visitor reached, and exclude people who already converted. Which event marks each stage on each platform, how to set the audience up in GA4 and Google Ads, in GTM, in Meta and in TikTok, and what is particular about the cancellation policy is in [Remarketing to guests who did not complete their booking](/widget/abandoned-booking-remarketing). Suppression of guests who already booked, lookalikes and remarketing by experience are there too. ChatGPT Ads does not build audiences from pixel events — its audiences are uploaded lists — so it does not apply there.

## Worked examples

<AccordionGroup>
  <Accordion title="Independent venue" icon="utensils">
    Steady but modest volume, some phone reservations.

    * **Primary:** `booking_confirmed` (confirmed booking).
    * **Secondary:** `contact`, since many guests still call, and `booking_lead`
      for the time slots that fill up and switch to a waiting list.
    * Single consolidated Search + Performance Max / Advantage+ setup to keep
      conversions together.
    * Remarketing to "started but did not book"; suppress confirmed bookers.
  </Accordion>

  <Accordion title="Venue group" icon="building">
    Multiple venues under one or several Restoo accounts.

    * Optimize each campaign toward its venue's `booking_confirmed`; use
      `source.account_id` / `booking_account_id` to keep venues separate in
      reports and audiences.
    * Pool low-volume venues into a shared campaign optimizing for `booking_confirmed`
      across the group until each clears the volume threshold, then split.
    * Use the `search_alternative_venues` fallback (`action_taken`) to route
      demand from a full venue to a sister venue.
  </Accordion>

  <Accordion title="Venue with experiences" icon="champagne-glasses">
    Tasting menus, events, add-ons.

    * **Primary:** `booking_confirmed`. Keep it experience-agnostic so bidding is not
      starved.
    * Use `view_item_list`, `view_item`, and `select_item` (with
      `item_category` = `experience` / `add_on`) to build per-experience
      audiences and report on which experiences convert. Items are identified by
      ID, not by name — `best_burger:experience:7` rather than "Tasting menu" —
      so keep a mapping if your reports need readable labels.
    * Restoo omits those names on purpose: a free-text experience name can reveal
      special-category data by inference, which the ad platforms' own terms
      prohibit receiving. See [What Restoo deliberately
      omits](/widget/connect-mappings#what-restoo-deliberately-omits) for more
      information.
    * Retarget guests who viewed a high-margin experience but did not select it.
    * Note: item and booking events carry `price`, but conversions still send no
      `value` — optimize for volume and analyze value in GA4.
  </Accordion>

  <Accordion title="Venue with a cancellation policy" icon="credit-card">
    Signing the cancellation policy, with a card guarantee or a prepayment, is
    required to confirm the booking.

    * **Primary:** `booking_confirmed`. It only fires once the card is validated,
      so it already excludes anyone who abandoned at payment.
    * The cancellation policy breaks down into three events, which together show exactly
      where guests abandon: `booking_cp_viewed` (they saw the terms)
      → `booking_cp_acknowledged` (they ticked "I have read and
      accept") → `booking_cp_accepted` (the card validated).
    * A large gap between *acknowledged* and *signed* points at the payment step
      itself, not at the terms — worth raising with the business before spending
      more on traffic.
    * Retarget guests who acknowledged but never confirmed. The step-by-step for
      each platform is in [Remarketing to guests who did not complete their
      booking](/widget/abandoned-booking-remarketing).
    * **There is no conversion here before the card.** The form submission does not
      convert, and the booking does not exist until the signature completes, so
      whoever abandons at payment counts as neither conversion. What they leave
      behind are the diagnostic events above.
  </Accordion>

  <Accordion title="Single-date campaign (e.g. Valentine's, NYE)" icon="calendar-day">
    Short push for one date or weekend.

    * Too little time to accumulate confirmed bookings, so **optimize toward
      `ViewContent` or `Search`** for most of the flight, watching
      `booking_confirmed` as the success metric. The `Lead` is no use here: it
      requires the booking to exist, just like the confirmed-booking conversion.
    * Build the audience from `booking_start_submitted` /
      `booking_no_availability_viewed` for that date (the `booking_date` /
      `search_term` = `pax_..._day_..._shift_...` identifies the target date).
    * Retarget no-availability visitors with the next available slot.
    * Switch the target back to `booking_confirmed` if volume allows before the date.
  </Accordion>
</AccordionGroup>

## Avoiding duplicate conversions across GA4, Google Ads, and GTM

Double-counting is the most common setup error. It inflates conversions and misleads bidding. Pick **one** path to each destination.

<Warning>
  Never send the same event to the same destination twice. If GTM already
  forwards Restoo events to a GA4 property, do **not** also enable the direct
  `ga4` destination for that property, and vice versa.
</Warning>

**Rules of thumb:**

1. **Choose one routing model.** Either enable the **direct destinations**
   (`ga4`, `googleAds`, `metaPixel`, `tiktokPixel`, `openaiPixel`) *or* route everything through
   **GTM** (the `gtm` destination) and build the tags there. Do not do both for the same
   destination.

2. **Google Ads: one source of truth.** Send the booking conversion to Google
   Ads through **exactly one** of these:

   * the direct `googleAds` destination, or
   * a Google Ads conversion tag in GTM, or
   * a GA4 key event **imported** into Google Ads.

   Enabling two of these for the same action double-counts every booking.

3. **Browser vs. server (CAPI, Events API, Conversions API).** Restoo Connect sends **no event IDs**,
   which is what Meta CAPI, TikTok Events API, and OpenAI Conversions API deduplication rely on. A booking
   reported from the browser and again from your server is counted twice, so send
   each conversion from **one** source only. The identifier that would link them
   is the booking's own reference, and that reference opens the guest's personal
   data, so it never leaves the widget.

4. **Enhanced Conversions ≠ a conversion.** `gtag("set", "user_data", …)`,
   `fbq("init", …)`, `ttq.identify(…)`, and the `user` of `oaiq("init", …)` only enrich matching. They never fire
   a conversion, so they cannot double-count.

## How consent affects your numbers

Restoo Connect forwards nothing until it knows the visitor's consent, and each destination requires its own signals — see [Consent](/widget/consent#what-each-destination-requires). Two consequences shape what you will see in the platforms.

**Your advertising destinations will not match GA4.** Google Ads, Meta Pixel, TikTok Pixel and OpenAI Pixel each require all three advertising signals — `ad_storage`, `ad_user_data` and `ad_personalization` — for every event. GA4 requires only `analytics_storage`. A visitor who accepts analytics but declines advertising is measured in GA4 and invisible to the other four.

That gap is **structural, not a setup error**, and it shows up as the advertising platforms consistently under-reporting against GA4.

The exception is a GA4 property that feeds advertising itself — Google signals, a Google Ads link, or audiences exported to Ads. Which one yours is, [your account declares](/widget/integrations#google-analytics-4), and declaring that it does makes GA4 require the advertising signals too. That closes the gap by lowering GA4 to the same volume rather than raising the others.

**Matching data needs its own permission.** Enhanced Conversions, Advanced Matching, `ttq.identify` and the OpenAI Pixel's `user` all depend on `customer_identified`, which the widget only emits once the visitor grants `ad_user_data`. On your advertising destinations this is the same requirement as any other event, so identity arrives whenever conversions do.

On GA4 it is a stricter requirement than the events themselves: a visitor can be measured there without ever being matched.

If the numbers do not add up and you want to go from symptom to cause, the table is in [Troubleshooting](/widget/diagnostics#symptoms-and-likely-causes).

<Note>
  Wiring consent is the business's job, not yours — but it sets the limit on
  what you can measure and optimize toward. Confirm it before concluding that a
  campaign is underperforming.
</Note>

## Production checklist

<Steps>
  <Step title="Consent">
    Consent actually reaches the widget: a
    [`cmp`](/widget/advanced-installation#param-cmp) is declared, or the site
    calls [`setConsent()`](/widget/advanced-installation#setconsent-signals)
    from its cookie notice. Without it nothing is forwarded to any destination —
    see [how consent affects your numbers](#how-consent-affects-your-numbers).
  </Step>

  <Step title="Load order">
    Platform libraries (`gtag.js`, `fbq`, `ttq`, `oaiq`, GTM) load **before** the Restoo
    widget, so no early events are skipped.
  </Step>

  <Step title="One routing model">
    Direct destinations *or* GTM per destination — not both. No destination
    receives the same event twice.
  </Step>

  <Step title="Google Ads actions">
    `booking_lead`, `booking_confirmed`, and `contact` created and mapped, with
    the booking conversion the venue produces marked **Primary** and `contact`
    **Secondary**.
  </Step>

  <Step title="ChatGPT Ads conversion event">
    `appointment_scheduled` or `lead_created` created as a conversion event on
    the account's pixel in Ads Manager, and chosen as the campaign's event if
    conversion optimization is enabled.
  </Step>

  <Step title="Primary conversion verified">
    Confirmed a real confirmed booking fires `booking_confirmed` / `Schedule` /
    `qualify_lead` / `appointment_scheduled` **once**, and does not also fire the
    lead conversion. For request/wait-list accounts, confirmed the same with
    `booking_lead` / `Lead` / `generate_lead` / `lead_created`.
  </Step>

  <Step title="Deduplication">
    Each conversion reaches each platform from exactly one source. Confirmed no
    server-side CAPI / Events API is reporting the same bookings as Restoo
    Connect, which cannot deduplicate against it. Google Ads has a single source
    of truth.
  </Step>

  <Step title="Matching data">
    Enhanced Conversions (Google), Advanced Matching (`pixelId` set for Meta),
    TikTok `identify`, and the OpenAI Pixel's `user` are on. GA4 user-provided data collection enabled if
    used.
  </Step>

  <Step title="Attribution transfer">
    [Restoo Attribution Transfer](/widget/attribution-transfer) installed as its guide describes, on
    every page.
  </Step>

  <Step title="Audiences">
    Abandonment and remarketing audiences built [as their guide
    describes](/widget/abandoned-booking-remarketing); confirmed bookers
    excluded from prospecting.
  </Step>

  <Step title="Bidding sanity check">
    Campaigns bid toward the confirmed booking (or the temporary intermediate event),
    not toward forms or contacts. Volume clears the learning thresholds.
  </Step>
</Steps>

## Official references

**Google Ads**

* [Primary and secondary conversion actions](https://support.google.com/google-ads/answer/11461796)
* [About conversion actions](https://support.google.com/google-ads/answer/3419678)
* [About Smart Bidding](https://support.google.com/google-ads/answer/6259715)
* [Enhanced Conversions](https://support.google.com/google-ads/answer/13258081)

**Meta**

* [About the Conversions API](https://www.facebook.com/business/help/AboutConversionsAPI)
* [Meta Pixel event reference](https://developers.facebook.com/docs/meta-pixel/reference)

**TikTok**

* [Tips for deep-funnel optimization](https://ads.tiktok.com/help/article/tips-for-deep-funnel-optimization)
* [Full-funnel marketing on TikTok](https://ads.tiktok.com/help/article/full-funnel-marketing-tiktok)

**ChatGPT Ads**

* [Conversion-optimized campaigns](https://developers.openai.com/ads/conversion-optimized-campaigns)
* [Supported events](https://developers.openai.com/ads/supported-events)
* [Measurement Pixel](https://developers.openai.com/ads/measurement-pixel)

**GA4**

* [Recommended events](https://developers.google.com/analytics/devguides/collection/ga4/reference/events)
* [User-provided data collection](https://support.google.com/analytics/answer/14077171)

## Next steps

<CardGroup cols={2}>
  <Card title="Restoo Connect" icon="sliders" href="/widget/connect">
    What it sends to each platform and what it needs to receive it.
  </Card>

  <Card title="Event Mappings" icon="table" href="/widget/connect-mappings">
    The exact payload sent to each platform.
  </Card>
</CardGroup>
