Skip to content

Commit 9f8f9e2

Browse files
committed
fix GTM docs
1 parent 228fff2 commit 9f8f9e2

2 files changed

Lines changed: 63 additions & 108 deletions

File tree

src/docs-app/data/google-tag-manager/08-advanced-iframe-purchase-tracking-via-postmessage.md

Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Advanced & Preferred: iFrame Purchase Tracking via postMessage
22

3-
43
Tracking conversions and user activity accurately within an iFrame (like the Showpass embedded purchase widget) is a significant challenge due to browser privacy measures that increasingly block third-party cookies and tracking mechanisms.
54

65
To overcome this, Showpass advocates for a more robust method: **iFrame tracking using the postMessage API**. This technique allows secure communication between the Showpass iFrame (child) and your website (parent page), enabling the iFrame to send event data directly to your GTM container on the parent page.
@@ -25,6 +24,7 @@ For more context on iFrame tracking challenges and solutions:
2524
This setup involves two Google Tag Manager containers:
2625

2726
1. **Child GTM Container (for the Showpass iFrame):**
27+
2828
- Create a new **empty GTM Container ID**
2929
- This container is specifically for the Showpass widget environment
3030
- Its role is to capture ecommerce events within the iFrame and `postMessage` them to the parent window (your website)
@@ -77,17 +77,17 @@ This tag will send data from the iFrame's Data Layer to your parent website.
7777
</script>
7878
```
7979

80-
- **Crucial:**
81-
- Ensure you have enabled the **Support document.write** checkbox (under Advanced Settings) if required
82-
- **Replace `GTM_CHILD_ID`** in the script with your actual Child GTM Container ID (e.g., `GTM-XXXXXXX`)
83-
- The script above assumes your child GTM Data Layer is named `dataLayer_GTM-XXXXXXX` (where `GTM-XXXXXXX` is your Child Container ID). GTM creates this namespace automatically to avoid conflicts
80+
- **Crucial:**
81+
- Ensure you have enabled the **Support document.write** checkbox (under Advanced Settings) if required
82+
- **Replace `GTM_CHILD_ID`** in the script with your actual Child GTM Container ID (e.g., `GTM-XXXXXXX`)
83+
- The script above assumes your child GTM Data Layer is named `dataLayer_GTM-XXXXXXX` (where `GTM-XXXXXXX` is your Child Container ID). GTM creates this namespace automatically to avoid conflicts
8484

8585
4. **Triggering:**
8686
- Click **Choose a trigger to make this tag fire...**
8787
- Select a trigger like **Custom Event**
8888
- **Event name:** Use regex matching to fire on all Showpass ecommerce events:
8989
```text
90-
view_item|add_to_cart|remove_from_cart|begin_checkout|purchase
90+
view_item|add_to_cart|remove_from_cart|begin_checkout|purchase|ecommerce_clear
9191
```
9292
- Check **Use regex matching**
9393
5. Click **Save**
@@ -128,45 +128,58 @@ This tag listens for messages from the Showpass iFrame and processes them.
128128
- Paste the following script:
129129
130130
```html
131-
<script>
131+
<script nonce="{{nonce}}">
132+
// Assuming you've set up a 'nonce' variable as per Section 5
132133
(function () {
133-
// Prevent adding multiple listeners
134-
if (window.showpassPostMessageListenerAdded) {
135-
return;
136-
}
137-
window.showpassPostMessageListenerAdded = true;
138-
139-
window.addEventListener(
140-
"message",
141-
function (event) {
134+
try {
135+
var receiveMessage = function (event) {
142136
try {
143-
// IMPORTANT: For production, verify origin for security
144-
// Example: if (event.origin !== 'https://showpass.com') return;
145-
146-
var data = event.data;
147-
148-
// Ensure the received message is an array (child GTM dataLayer)
149-
if (Array.isArray(data) && data.length > 0) {
150-
// Process each item in the received dataLayer array
151-
data.forEach(function (item) {
152-
if (item && typeof item === "object" && item.event) {
153-
// Push the ecommerce event to the parent's dataLayer
154-
window.dataLayer = window.dataLayer || [];
155-
window.dataLayer.push(item);
137+
// Optional: Add origin check for security if Showpass iFrame origin is fixed and known
138+
// if (event.origin !== "https://widgets.showpass.com") return;
139+
140+
if (
141+
event &&
142+
typeof event.data != "undefined" &&
143+
Array.isArray(event.data)
144+
) {
145+
for (var i = 0; i < event.data.length; i++) {
146+
if (event.data[i] && typeof event.data[i].event != "undefined") {
147+
// Push specific, expected ecommerce events to the parent dataLayer
148+
// You can expand this list based on what you want to track from the iFrame
149+
if (
150+
event.data[i].event == "view_item" ||
151+
event.data[i].event == "add_to_cart" ||
152+
event.data[i].event == "remove_from_cart" ||
153+
event.data[i].event == "begin_checkout" ||
154+
event.data[i].event == "purchase" ||
155+
event.data[i].event == "ecommerce_clear"
156+
) {
157+
// Create a new object to avoid potential reference issues
158+
var eventToPush = JSON.parse(JSON.stringify(event.data[i]));
159+
dataLayer.push(eventToPush);
160+
}
156161
}
157-
});
162+
}
158163
}
159164
} catch (err) {
160-
console.error("Showpass postMessage Listener Error:", err);
165+
// console.error("Parent GTM postMessage Listener Error (inner): ", err);
161166
}
162-
},
163-
false
164-
);
167+
};
168+
169+
if (typeof window.addEventListener !== "undefined") {
170+
window.addEventListener("message", receiveMessage, false);
171+
} else if (typeof window.attachEvent !== "undefined") {
172+
// For older IE
173+
window.attachEvent("onmessage", receiveMessage);
174+
}
175+
} catch (err) {
176+
// console.error("Parent GTM postMessage Listener Error (outer): ", err);
177+
}
165178
})();
166179
</script>
167180
```
168181

169-
> **Security Note:** In production, you should verify `event.origin` to ensure messages are only accepted from trusted sources (e.g., `https://showpass.com` or your own domain).
182+
> **Security Note:** In production, you should verify `event.origin` to ensure messages are only accepted from trusted sources (e.g., `https://showpass.com` or your own domain).
170183
171184
4. **Triggering:**
172185
- Click **Choose a trigger to make this tag fire...**

src/docs-app/data/google-tag-manager/09-advanced-tracking-widget-and-direct-purchases.md

Lines changed: 15 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Advanced: Differentiating Widget (iFrame) vs. Direct Showpass.com Event Tracking
22

3-
43
In some advanced scenarios, you might want to differentiate GTM tag firing behavior based on whether an event originates from within the embedded Showpass widget (iFrame on your site) or from a direct interaction on `showpass.com` (if your GTM container is also deployed there, or if Showpass sends server-side events that populate your website's GTM).
54

65
This allows for more granular control, such as:
@@ -47,90 +46,33 @@ function() {
4746

4847
Now, use the `{{Custom JS - Is iFrame}}` variable as a condition in your relevant GTM triggers.
4948

50-
### Scenario A: Triggers for postMessage Data (from Showpass Widget)
51-
52-
These triggers should **only** fire when the event data originates from the iFrame via `postMessage`.
53-
54-
- **If your postMessage listener tag** (from Section 8B) pushes distinct events: You might not need to modify the triggers for your actual ecommerce tags (like GA4 ecommerce) if those tags are already listening for the specific events pushed by your listener (e.g., `iframe_add_to_cart`)
55-
- **If your postMessage listener tag pushes standard event names** (e.g., `add_to_cart`) that could also occur directly on your site or `showpass.com`:
56-
You need to ensure the triggers for tags that should **only** process iFrame `postMessage` data have an added condition
49+
Rename your existing Custom ecommerce trigger for processing direct purchases **Showpass - Ecommerce events - direct purchase**
5750

58-
1. Edit the relevant trigger (e.g., the one that fires your GA4 ecommerce tag for events received via `postMessage`)
59-
2. Under "This trigger fires on," add a condition:
60-
- `{{Custom JS - Is iFrame}}` **equals** `false`
51+
**Event name**
6152

62-
> **Note:** This assumes your listener for postMessage events is on the parent page, and the data is pushed to the parent's dataLayer. The 'Is iFrame' variable on the parent page will be `false`. The logic here depends on where the final decision to fire a tag is made based on the source of the data.
63-
64-
### Scenario B: Triggers for Direct Showpass.com Events
53+
```
54+
view_item|add_to_cart|remove_from_cart|begin_checkout|purchase|ecommerce_clear
55+
```
6556

66-
If you want tags to fire **only** when events occur directly on `showpass.com` (not from the widget via `postMessage`):
57+
Check off use regex matching
6758

68-
1. Edit the relevant trigger
69-
2. Under "This trigger fires on," add a condition:
70-
- `{{Page Hostname}}` **equals** `showpass.com` (or contains `showpass.com`)
71-
- **OR** add a custom Data Layer variable that indicates the source
59+
**This trigger fires on** select **Some custom events**
7260

73-
Alternatively, you can add a custom flag to the Data Layer when pushing events from different sources to make differentiation easier.
61+
Fire this trigger when an Event occurs and all of these conditions are true
7462

75-
---
63+
`{{Custom JS - Is iFrame}}` equals **false**
7664

77-
## Step 3: Alternative Approach - Add Source Identifier to Data Layer
78-
79-
A more explicit approach is to modify how events are pushed to the Data Layer to include a **source** identifier.
80-
81-
### In the Parent postMessage Listener Script
82-
83-
Modify the postMessage listener tag (from Section 8B1) to add a source flag:
84-
85-
```html
86-
<script>
87-
(function () {
88-
if (window.showpassPostMessageListenerAdded) {
89-
return;
90-
}
91-
window.showpassPostMessageListenerAdded = true;
92-
93-
window.addEventListener(
94-
"message",
95-
function (event) {
96-
try {
97-
var data = event.data;
98-
99-
if (Array.isArray(data) && data.length > 0) {
100-
data.forEach(function (item) {
101-
if (item && typeof item === "object" && item.event) {
102-
// Add a source identifier
103-
item.event_source = "iframe_widget";
104-
105-
window.dataLayer = window.dataLayer || [];
106-
window.dataLayer.push(item);
107-
}
108-
});
109-
}
110-
} catch (err) {
111-
console.error("Showpass postMessage Listener Error:", err);
112-
}
113-
},
114-
false
115-
);
116-
})();
117-
</script>
118-
```
65+
Attach this trigger to your GA4 ecommerce tag in the Child GTM Container
11966

120-
### Create a GTM Variable for Event Source
67+
Create a new trigger for widget purchases named **Showpass - Ecommerce events - widget purchase** with the same ecommerce events
12168

122-
1. In GTM, go to **Variables** and click **New**
123-
2. **Name:** `DLV - event_source`
124-
3. **Variable Type:** **Data Layer Variable**
125-
4. **Data Layer Variable Name:** `event_source`
126-
5. Click **Save**
69+
**This trigger fires on** select **Some custom events**
12770

128-
### Use in Triggers
71+
Fire this trigger when an Event occurs and all of these conditions are true
12972

130-
Now you can add conditions to your triggers:
73+
`{{Custom JS - Is iFrame}}` equals **true**
13174

132-
- **For widget events only:** `{{DLV - event_source}}` **equals** `iframe_widget`
133-
- **For direct events only:** `{{DLV - event_source}}` **does not equal** `iframe_widget` (or is undefined)
75+
Attach this trigger to the **`Custom HTML - Post Message Ecommerce Data to Parent`** tag
13476

13577
---
13678

0 commit comments

Comments
 (0)