Data Layer Push
How to use Data Layer Push to send service data to analytics platforms.
Booking Conversions via dataLayer.push()
Covers: Pay‑As‑You‑Go, Trial, and Monthly bookings
1) Purpose
This guide shows Franscape customers how to send reliable booking conversion data from their website/app to Google Tag Manager (GTM) and onwards to analytics/ads platforms using dataLayer.push(). It includes a reference payload, event naming, GTM setup, and testing steps.
2) Who this is for
-
FranScape Administrators
-
Agencies integrating Franscape with GA4, Google Ads, and Meta CAPI (via sGTM)
-
Developers adding/validating conversion tracking in production
3) Prerequisites
-
Live website with GTM Web container installed
-
(Optional but recommended) Server GTM (sGTM) container for GA4 → Ads/Meta routing
-
Access to GA4 property (DebugView helpful)
-
Chrome DevTools (Console) for validation
4) Canonical dataLayer.push payload
FranScape will automatically fire this push at the moment the booking is confirmed (after successful payment/commit)
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
bookingCost: 1750, // integer value in minor units (e.g. 1750 = £17.50)
bookingType: "pay_as_you_go", // "pay_as_you_go" | "trial" | "monthly"
classId: 174306, // your class identifier
courseType: "3 to 1", // depends on client configuration (e.g. group size/type)
discountCode: "", // optional code applied
event: "completePaygBooking", // EVENT NAME (varies by booking type, see §5)
franchiseeId: 2, // internal fran ID
franchiseeName: "024: Swimtime East Anglia", // the name entered by the client
"gtm.uniqueEventId": 58, // populated by GTM when present – safe to omit when pushing
numConsumers: 1, // number of swimmers/participants
transaction_id: "class_174306-customer_3969-2025-10-20T15:45:58.617Z" // unique order ID
});
</script>
5) Standard event names (per booking type)
These are the event names that will push via the payload:
-
Pay‑As‑You‑Go:
completePaygBooking -
Trial:
completeTasterBooking -
Monthly:
completeMonthlyBooking
Everything else in the payload remains the same across booking types.
6) GTM (Web) container setup
6.1) Data Layer Variables (DLVs)
Create these DLVs in your Web container (Variables → New → Data Layer Variable):
| DLV name (suggested) | Data Layer Variable Name |
|---|---|
dlv.bookingCost |
bookingCost |
dlv.bookingType |
bookingType |
dlv.classId |
classId |
dlv.courseType |
courseType |
dlv.discountCode |
discountCode |
dlv.franchiseeId |
franchiseeId |
dlv.franchiseeName |
franchiseeName |
dlv.numConsumers |
numConsumers |
dlv.transaction_id |
transaction_id |
(You don’t need a DLV for gtm.uniqueEventId.)
6.2) Triggers
Create one Custom Event trigger per booking type (or use a single trigger group if you prefer):
-
Trigger: Custom Event → Event name =
completePaygBooking -
Trigger: Custom Event → Event name =
completeTasterBooking -
Trigger: Custom Event → Event name =
completeMonthlyBooking
Option: create one trigger with RegEx
^complete(Payg|Taster|Monthly)Booking$if a single tag should fire for all types.
6.3) GA4 Event Tag (Web)
If you send GA4 directly from Web GTM:
-
Tag Type: GA4 Event
-
Configuration Tag: your GA4 config
-
Event Name:
(or one tag per event name) -
Event Parameters:
-
value=/ 100 -
currency=GBP(or dynamic if multi‑currency) -
transaction_id= -
Optional:
booking_type=,course_type=,franchisee_name=,num_consumers=
-
-
Trigger: choose the custom event trigger(s) from §6.2
If you are using sGTM, you can also forward GA4 from the web container (recommended) and let the server container route to Ads/Meta.
7) Server GTM (sGTM) routing (optional but recommended)
If you have an sGTM container:
-
Ensure the GA4 Client is present.
-
Set up tags that listen for the same GA4 event names and forward to destinations:
-
Google Ads Conversion: Value =
value, Currency =currency, Transaction ID =transaction_id. -
Meta CAPI: Include
event_name,event_id(if present),value,currency, andevent_source_url.
-
-
If your Web layer sends
bookingCostas minor units, convert to decimal before sending downstream (either in Web GA4 event mapping or in sGTM tag/transformations).
Keep the event names identical across Web and Server so preview/debug traces are easy to follow.
8) Testing & Validation
8.1) Chrome Console (no GTM access required)
Open DevTools → Console and run:
console.dir(window.dataLayer)
-
Expand entries where
eventiscompletePaygBooking,completeTasterlBooking, orcompleteMonthlyBooking. -
To see just booking events:
window.dataLayer.filter(e => e.event && /complete(Payg|Trial|Monthly)Booking/.test(e.event)) -
Watch real‑time pushes:
window.dataLayer.push = new Proxy(window.dataLayer.push, {
apply(t, thisArg, args) {
console.log("dataLayer.push fired:", args[0]);
return Reflect.apply(t, thisArg, args);
}
});
8.2) GTM Web Preview
-
Click Preview in your Web container, enter your site URL, and reproduce a booking.
-
In Tag Assistant, select the booking event and confirm your DLVs and tag fires.
8.3) sGTM Preview (if used)
-
Open Preview on the Server container and your site.
-
In the Server Tag Assistant, confirm the GA4 event arrives with
value,currency, andtransaction_id, and that Ads/Meta tags fire.
8.4) GA4 DebugView
-
Open Admin → DebugView and confirm the booking event appears with the mapped parameters.
9) Data dictionary
| Field | Type | Example | Required | Notes |
|---|---|---|---|---|
event |
string | completePaygBooking |
✅ | Use one of the three names in §5. |
bookingCost |
integer (minor units) | 1750 |
✅ | Convert to decimal when populating GA4/Ads value. |
bookingType |
string | pay_as_you_go |
✅ | One of pay_as_you_go, taster, monthly. |
classId |
number/string | 174306 |
✅ | Your internal class ID. |
courseType |
string | 3 to 1 |
✅ | Client‑configured label. |
discountCode |
string | `` | ◻︎ | Empty string if none. |
franchiseeId |
number/string | 2 |
✅ | Internal franchise identifier. |
franchiseeName |
string | 024: Swimtime East Anglia |
✅ | As entered by client. |
numConsumers |
number | 1 |
✅ | Count of participants. |
transaction_id |
string | class_174306-customer_3969-2025-10-20T15:45:58.617Z |
✅ | Must be unique per booking. |
10) Troubleshooting
-
Event not firing in GTM Preview → Check the
eventname matches trigger exactly; ensure the push runs afterpayment confirmation. -
No value in Ads/GA4 → Confirm conversion value is
bookingCost/100andcurrencyis set (GBP). -
Duplicates in Ads/Meta → Ensure
transaction_idis unique; enable dedup where supported. -
Nothing in GA4 DebugView → Add
?gtm_debug=xto the URL or enable GA4 debug mode; check network blockers.
11) Security & PII
-
Do not include direct personal data (names, emails) in the payload.
-
Use numeric IDs or hashed identifiers when needed for auditing.
12) Appendices
A) Minimal example per booking type
// Pay‑As‑You‑Go
window.dataLayer.push({
event: "completePaygBooking",
bookingType: "pay_as_you_go",
bookingCost: 1750,
transaction_id: "...",
classId: 174306,
courseType: "3 to 1",
numConsumers: 1,
franchiseeId: 2,
franchiseeName: "024: Swimtime East Anglia",
discountCode: ""
});
// Trial
window.dataLayer.push({
event: "completeTrialBooking",
bookingType: "trial",
bookingCost: 0, // or the trial fee in minor units
transaction_id: "...",
classId: 174306,
courseType: "3 to 1",
numConsumers: 1,
franchiseeId: 2,
franchiseeName: "024: Swimtime East Anglia",
discountCode: ""
});
// Monthly
window.dataLayer.push({
event: "completeMonthlyBooking",
bookingType: "monthly",
bookingCost: 1750, // first payment value (minor units) if applicable
transaction_id: "...",
classId: 174306,
courseType: "3 to 1",
numConsumers: 1,
franchiseeId: 2,
franchiseeName: "024: Swimtime East Anglia",
discountCode: ""
});
B) Example GA4 Event Parameter mapping (Web)
| GA4 Parameter | Value |
|---|---|
value |
/ 100 |
currency |
GBP |
transaction_id |
|
booking_type |
|
course_type |
|
franchisee_name |
|
num_consumers |
|