Analytics and ad tracking
This page is for whoever sets up tracking on a venue’s website: an in-house marketer, a web developer, or an agency. It covers the events the Paloma widget sends to the page it sits on, how to turn them into GA4, Google Ads and Meta conversions with Google Tag Manager, and what campaign data we keep on each inquiry.
You’ll need to know your way around GA4 and GTM. You don’t need to know anything about Paloma.
How widget tracking works
The Paloma widget opens in an iframe on top of the venue’s page. GA4, GTM and ad pixels on that page can’t see inside the iframe, so clicks and submissions in the widget are invisible to them by default.
To close that gap, the widget reports each step of the guest’s inquiry to the host page as an event your tags can trigger on. The event names all start with paloma_.
Two common situations bring people here:
- Setting up tracking for the first time on a site that has the widget, or is about to.
- Replacing an existing form with Paloma. Point the triggers you built on the old form at the matching Paloma events below.
How events reach your page
For every event, the widget does two things on the host page:
window.dataLayer.push({
event: "paloma_form_submit",
paloma: {/* properties */},
});
window.dispatchEvent(
new CustomEvent("paloma_form_submit", { detail: {/* properties */} }),
);
dataLayeris where GTM picks events up. If the page has nodataLayer, the widget creates an empty one first. A GTM container that loads after the widget still sees the events already pushed, so load order doesn’t matter.- The
CustomEventis for sites without GTM. You can listen for it directly:
window.addEventListener("paloma_form_submit", (e) => console.log(e.detail));
Properties sit under a paloma object in the dataLayer, so in GTM you read them with a Data Layer Variable named paloma.<property>, for example paloma.inquiry_id. On the CustomEvent they sit directly on detail.
Event reference
| Event | Fires when | Event-specific properties |
|---|---|---|
paloma_widget_open |
The widget becomes visible | none |
paloma_form_start |
The guest’s first click in the widget, once per widget session | entry_point |
paloma_form_step |
The guest answers an inquiry question and moves on | step_index, step_type |
paloma_explore |
The guest opens spaces, sample menus, pricing, availability or chat (once per section per session) | section |
paloma_form_submit |
We confirmed the inquiry was saved. A failed submission never fires it, and editing and resubmitting doesn’t count twice. | inquiry_id, guest_count, booking_intent, search_stage |
paloma_widget_close |
The guest closes the widget | submitted, last_step_index, last_step_type |
We won’t rename these events, so triggers you build on them keep working.
Property reference
The properties below may change as the widget evolves. We may add properties or new values, and the ones listed here can change too. If you want to drive a campaign or workflow off a specific property, email us first so we can let you know before it changes.
Every event carries these four properties:
| Property | What it holds |
|---|---|
venue_id |
The venue’s Paloma id. Useful when one site embeds more than one venue. |
venue_name |
The venue’s business name |
surface |
Where the event came from. Always embed today. |
locale |
The widget’s language: en, fr or es |
The event-specific properties:
| Property | Event | Values |
|---|---|---|
entry_point |
paloma_form_start |
The button the guest pressed first. The welcome screen buttons are event_inquiry, ask_question and see_spaces. The full list is event_inquiry, event_planner, ask_question, see_spaces, sample_menus, view_pricing, check_availability, inquiry_from_chat, inquiry_from_spaces, inquiry_from_menus, inquiry_from_availability. |
step_index |
paloma_form_step |
The screen’s position in the order the guest saw it, starting at 1. Skipped questions aren’t counted, so step 4 is always the fourth screen the guest saw. |
step_type |
paloma_form_step |
date, event_times, guests, spaces, details, contact or choice. Never the venue’s own question wording, so a venue editing its questions never breaks a trigger. |
section |
paloma_explore |
spaces, menus, pricing, availability or chat |
inquiry_id |
paloma_form_submit |
Our id for the inquiry. Use it to deduplicate conversions. |
guest_count |
paloma_form_submit |
The party size as a number. A range reports its lower end (“40 - 50” sends 40). Left out when the guest’s answer has no number in it, such as “not sure”. |
booking_intent |
paloma_form_submit |
How ready the guest said they were to commit: exploring or ready_to_book. Comes from the “Reserve if available?” question. |
search_stage |
paloma_form_submit |
How far along the guest said they were in choosing a venue: just_started, actively_comparing or finalizing. Comes from the “How far along are you in your search?” question. |
submitted |
paloma_widget_close |
true if the guest sent an inquiry in this widget session, otherwise false. A session lasts until the page is reloaded, so a guest who closes and reopens the widget picks up where they left off, and paloma_widget_close fires on each close. |
last_step_index, last_step_type |
paloma_widget_close |
The last step the guest answered. A guest who closes without answering anything sends last_step_index: 0 and no last_step_type. |
A venue asks whichever of those two questions it wants, so an inquiry can carry booking_intent, search_stage, both or neither, and a guest who skips the question sends nothing rather than a guess. Both values follow the option the guest picked, not its wording, so editing those labels, or a guest answering in French or Spanish, doesn’t change what your tags see.
Setting up GTM
GTM’s menus move around from time to time. If a label below doesn’t match what you see, look for the closest equivalent.
1. Create the variables
For each property you want to use, create a variable of type Data Layer Variable and set Data Layer Variable Name to paloma. plus the property. The examples below use three:
| Variable name (yours to choose) | Data Layer Variable Name |
|---|---|
Paloma inquiry_id |
paloma.inquiry_id |
Paloma guest_count |
paloma.guest_count |
Paloma booking_intent |
paloma.booking_intent |
2. Create the triggers
Create one trigger per event you want to use, of type Custom Event. Set Event name to the event exactly as written in the table above, for example paloma_form_submit, and leave Use regex matching off.
Most setups need paloma_form_submit at minimum. Add the others for funnel reporting:
| Funnel step | Trigger on |
|---|---|
| Opened the widget | paloma_widget_open |
| Started an inquiry | paloma_form_start |
| Progress through the questions | paloma_form_step |
| Browsed spaces, menus, pricing, availability or chat | paloma_explore |
| Sent an inquiry (the conversion) | paloma_form_submit |
| Left the widget | paloma_widget_close |
3. Add the tags
GA4. Add a Google Analytics: GA4 Event tag on the paloma_form_submit trigger. Set the event name to generate_lead, or to whatever your naming convention uses. Add event parameters inquiry_id set to {{Paloma inquiry_id}} and guest_count set to {{Paloma guest_count}}. Then in GA4, mark generate_lead as a key event.
Google Ads (optional). Add a Google Ads Conversion Tracking tag on the paloma_form_submit trigger with your conversion ID and label. Set Transaction ID to {{Paloma inquiry_id}} so a conversion is never counted twice. If you bid on value, {{Paloma guest_count}} can stand in as the conversion value.
Meta pixel (optional). On the paloma_form_submit trigger, add a Custom HTML tag (or use the Meta pixel template if you already have one):
<script>
fbq("track", "Lead", {}, { eventID: "{{Paloma inquiry_id}}" });
</script>
Setting eventID to the inquiry id lets Meta deduplicate the browser event against a Conversions API event for the same inquiry. If you also want the start of an inquiry in Meta, fire a custom event such as fbq('trackCustom', 'PalomaInquiryStart') on the paloma_form_start trigger.
Splitting conversions by buying intent
booking_intent tells you whether the guest said they were ready to reserve or were still exploring. To count the two separately, add the condition {{Paloma booking_intent}} equals ready_to_book to a second paloma_form_submit trigger, and point your highest-value conversion tag at that one. search_stage works the same way when you want guests who are finalizing on their own. Both properties are left out when the venue doesn’t ask the question, so a filtered trigger fires only when the guest actually answered.
Guests who left without sending
To build a remarketing audience of guests who started but didn’t finish, create a trigger on paloma_widget_close with an extra condition: a Data Layer Variable for paloma.submitted equals false. To see where they stopped, add paloma.last_step_index as a parameter. It tells you how many screens the guest got through, which is usually more useful than paloma.last_step_type, since many screens share the type choice.
Sites without GTM
If the site loads gtag.js directly, listen for the paloma_* events and pass them on yourself:
<script>
window.addEventListener("paloma_form_submit", function (e) {
gtag("event", "generate_lead", {
inquiry_id: e.detail.inquiry_id,
guest_count: e.detail.guest_count,
});
});
</script>
Checking it in GTM Preview
- Open the venue’s site in Tag Assistant (GTM’s Preview button).
- Open the widget and walk through an inquiry.
- Watch the events arrive in this order:
paloma_widget_open,paloma_form_start, onepaloma_form_stepper screen, anypaloma_exploreevents along the way,paloma_form_submitonce the confirmation screen shows, andpaloma_widget_closewhen you close it. - Click an event and open the Data Layer tab to see its
palomaobject.
A test inquiry is a real inquiry and lands in the venue’s Paloma dashboard. If you’d rather test somewhere else, ask us and we’ll set up a test environment for you.
Campaign data on inquiries
When a guest reaches the widget from a link carrying campaign parameters, we store those parameters on the inquiry, so each inquiry can be tied back to the campaign that produced it.
We keep these parameters and nothing else from the address:
| Parameter | Source |
|---|---|
utm_source, utm_medium, utm_campaign, utm_term, utm_content |
Standard campaign tags |
gclid |
Google Ads click |
gad_source |
Google Ads |
fbclid |
Meta click |
msclkid |
Microsoft Ads click |
Alongside them we store:
- The landing page: the address and path of the page the guest arrived on, without its query string.
- The referring site: its domain only.
- The time of the click. Meta’s Conversions API needs it to build an
fbcvalue (fb.1.<click time in ms>.<fbclid>), and it can’t be worked out later.
This works for the widget embedded on the venue’s site and for the venue’s standalone widget link (/events/...). Nothing on the venue’s side needs setting up.
A few things to know:
- Last touch is the visit that produced the inquiry. First touch is the earliest campaign visit we remember for that guest. First touch is best effort. If a guest comes back through a different website, or their browser doesn’t keep site data, we only have the last touch.
- A visit with no campaign parameters stores nothing.
- Inquiries from before we started capturing this carry no campaign data, and it can’t be added afterwards.
Campaign data is stored on the inquiry. It isn’t shown in the Paloma dashboard or included in exports.
Privacy
The events contain no personal information about guests. The only text they carry is our ids, the venue’s business name, and fixed values we define (like guests or contact). We never send a guest’s name, email, phone number, company, written answers, messages, dietary notes or the exact event date. guest_count is a number we work out from the party size answer, not the answer itself.
What the venue’s tags do with these events, such as forwarding them to Google, Meta or Microsoft, falls under the venue’s own consent and privacy setup. Gate these tags behind consent mode or the cookie banner the same way you gate the site’s other marketing tags.
Limits
- Funnel events come from the embedded widget only. The standalone widget link (
/events/...) sends no funnel events, though it does capture campaign data on inquiries. - Self-hosted widget scripts need updating. If the venue’s site loads its own copy of the widget script instead of ours, it gets neither the events nor campaign capture until it’s updated to the current script. Sites using the snippet from the Paloma dashboard get both automatically.
- Ad blockers still apply. The events are sent inside the guest’s browser, so an ad blocker or a blocked GTM container on the host page can stop your tags from passing them on.
Common questions
My form_submit trigger stopped firing when the widget went live.
The old trigger listened to the site’s contact form, and the widget doesn’t use it. Change the trigger’s event name to paloma_form_submit (and form_start to paloma_form_start).
I see paloma_form_step events but no paloma_form_submit.
paloma_form_submit fires only after we’ve saved the inquiry, once the guest sees the confirmation screen. A guest who leaves before that point never sends one. Check paloma_widget_close for submitted: false, and its last_step_index, to see where they stopped.
Can I trigger on a specific question?
Trigger on step_type rather than step_index if you care about a kind of question, like contact. The question order can differ between venues and change over time; step_type stays the same.
For anything else, reach us at support@palomaparties.com.