Set up server-side Google Tag Manager
Server-side Google Tag Manager routes Rex's conversion data through a tagging container you host, instead of straight to Google. If you already run an sGTM container, this sends Rex's confirmed bookings into it — carrying the ad-click IDs that make paid-campaign attribution work.
This is for venues already running a server-side GTM container. If you don't have one, use the Google Analytics integration instead — it sends the same booking to GA4 directly, with nothing to host.
How this differs from the other Google integrations
| Field | Description |
|---|---|
| Google Tag Manager | Browser-side. Fires data layer events across the whole booking funnel. Blockable by the guest's browser. |
| Google Analytics | Server-side, straight to GA4. Sends the confirmed booking. Nothing to host. |
| Server-side GTM (this article) | Server-side, into your own container. Sends the confirmed booking plus ad-click attribution, and you control what happens next. |
The event Rex sends here arrives flat. Unlike the browser Google Tag Manager event, there is no ecommerce object — the fields sit at the top level. Tags in your container that expect an ecommerce object will read empty values.
Before you start
You need three things from your own setup:
- A running server-side GTM container with a public HTTPS URL.
- Your GA4 Measurement ID.
- A Measurement Protocol API secret from that container.
Server-side GTM is also a plan feature. If there is no Server-side GTM card in your integration settings, your plan does not include it.
Set it up
Open the Server-side GTM card
Open Integrations from the Marketplace group in the sidebar and find the Server-side GTM card. These settings are account-wide and apply to every venue.
Fill in the connection fields
Enter your container URL, Measurement ID and API secret. Leave Server Preview Header empty unless you are actively debugging.
| Field | Description |
|---|---|
| sGTM Endpoint URL | Full URL of your server-side GTM container (must start with https://) |
| GA4 Measurement ID | Your GA4 Measurement ID (e.g. G-XXXXXXXXXX) |
| API Secret | Measurement Protocol API secret from your sGTM container |
| Server Preview Header | Optional x-gtm-server-preview header value. Set only when sGTM preview mode is active. |
You can give the container URL with or without a collection path — Rex appends the Measurement Protocol path itself if you leave it off. The URL must be publicly reachable over HTTPS: private and internal addresses are rejected, so a container that is only reachable inside your network will not work.
GA4 Measurement ID is shared with the Google Analytics card. Changing it in one place changes it in both.
Turn on the Reservation Confirmed event
Under Tracking Events, tick Reservation Confirmed. Nothing is sent until this is ticked, even with every other field filled in.
The Reservation Confirmed option shows the exact payload Rex will send. Open it and build your container tags against those field names.
Test it with preview mode
Turn on preview mode in your sGTM container, paste its x-gtm-server-preview value into Server Preview Header, and take a test booking through your reservation page in a normal browser. The event should appear in your container's preview stream. Clear the header afterwards.
Test by booking through the reservation page in a browser, not from the Host App. Bookings taken by staff are skipped — see below.
What Rex sends
One purchase event per confirmed booking. Alongside the order value, currency, reservation number, package name, guest count and discount codes, Rex forwards the advertising and session identifiers it captured when the guest booked — the GA4 session, Google click IDs, and the Meta and TikTok click identifiers where present.
Those identifiers are the reason to use this integration. They are what let your container attribute a booking back to the campaign that produced it, server-side, after the browser is gone.
Which bookings are skipped
Rex only sends bookings it can attribute. A booking with no browser session behind it would land in GA4 as Unassigned traffic and distort your reports, so those are dropped rather than sent.
- Bookings taken in the Host App or by an admin. There is no browser GA4 session behind them.
- Bookings where the guest's GA4 session cookie is missing or unreadable.
- Reservations that are not confirmed.
- Bookings whose net value works out below zero.
This means your container will see fewer purchases than your Rex reservation reports. That gap is your non-web bookings, and it is expected.
Troubleshooting
No events reaching the container
Check Reservation Confirmed is ticked under Tracking Events — that is the most common cause, because every other field can look complete without it. Then confirm the endpoint is a public HTTPS URL and the API secret came from this container rather than from GA4 directly.
Events arrive but tags read empty values
Your tags are almost certainly looking for an ecommerce object. This event is flat: value, currency, transaction_id and the rest sit at the top level. Repoint your variables at the top-level names shown in the Reservation Confirmed payload.
Traffic shows as Unassigned in GA4
Check whether the bookings involved came through the Host App. Those are skipped precisely to avoid this, so Unassigned rows usually point at a tag in your container overwriting the session or client identifiers Rex sent.
Only some web bookings come through
Guests who block cookies have no readable GA4 session, so those bookings are skipped. Consistent gaps beyond that are worth checking against a consent banner that blocks Google cookies until the guest accepts.
Nothing appears in preview mode
The Server Preview Header value is only valid while that preview session is open. Restart preview in your container, copy the fresh value in, and try again — then clear the field, because a stale header can affect live events.
Updated Aug 25, 2026
Was this helpful?