@technoapple/ga4 1.0.4 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/node.js.yml +31 -31
- package/.prettierignore +1 -1
- package/LICENSE +21 -21
- package/README.md +386 -48
- package/REQUIREMENTS.md +548 -0
- package/babel.config.js +5 -5
- package/build/main/ga4/ga4.d.ts +13 -0
- package/build/main/ga4/ga4.js +24 -1
- package/build/main/helpers/debounce.d.ts +5 -0
- package/build/main/helpers/debounce.js +23 -0
- package/build/main/helpers/delegate.d.ts +8 -0
- package/build/main/helpers/delegate.js +37 -0
- package/build/main/helpers/dom-ready.d.ts +1 -0
- package/build/main/helpers/dom-ready.js +13 -0
- package/build/main/helpers/parse-url.d.ts +11 -0
- package/build/main/helpers/parse-url.js +32 -0
- package/build/main/helpers/session.d.ts +4 -0
- package/build/main/helpers/session.js +50 -0
- package/build/main/index.d.ts +9 -0
- package/build/main/index.js +19 -2
- package/build/main/plugins/clean-url-tracker.d.ts +17 -0
- package/build/main/plugins/clean-url-tracker.js +105 -0
- package/build/main/plugins/event-tracker.d.ts +27 -0
- package/build/main/plugins/event-tracker.js +76 -0
- package/build/main/plugins/impression-tracker.d.ts +32 -0
- package/build/main/plugins/impression-tracker.js +202 -0
- package/build/main/plugins/index.d.ts +8 -0
- package/build/main/plugins/index.js +20 -0
- package/build/main/plugins/media-query-tracker.d.ts +20 -0
- package/build/main/plugins/media-query-tracker.js +96 -0
- package/build/main/plugins/outbound-form-tracker.d.ts +17 -0
- package/build/main/plugins/outbound-form-tracker.js +55 -0
- package/build/main/plugins/outbound-link-tracker.d.ts +19 -0
- package/build/main/plugins/outbound-link-tracker.js +63 -0
- package/build/main/plugins/page-visibility-tracker.d.ts +24 -0
- package/build/main/plugins/page-visibility-tracker.js +93 -0
- package/build/main/plugins/url-change-tracker.d.ts +20 -0
- package/build/main/plugins/url-change-tracker.js +76 -0
- package/build/main/types/plugins.d.ts +78 -0
- package/build/main/types/plugins.js +3 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/docs/examples/react.md +95 -0
- package/docs/examples/vanilla.md +65 -0
- package/docs/examples/vue.md +87 -0
- package/jest.config.ts +195 -195
- package/package.json +56 -56
- package/src/dataLayer.ts +85 -85
- package/src/ga4/ga4.ts +69 -40
- package/src/ga4/ga4option.ts +4 -4
- package/src/ga4/index.ts +4 -4
- package/src/helpers/debounce.ts +28 -0
- package/src/helpers/delegate.ts +51 -0
- package/src/helpers/dom-ready.ts +7 -0
- package/src/helpers/parse-url.ts +37 -0
- package/src/helpers/session.ts +39 -0
- package/src/index.ts +34 -7
- package/src/plugins/clean-url-tracker.ts +112 -0
- package/src/plugins/event-tracker.ts +90 -0
- package/src/plugins/impression-tracker.ts +230 -0
- package/src/plugins/index.ts +8 -0
- package/src/plugins/media-query-tracker.ts +116 -0
- package/src/plugins/outbound-form-tracker.ts +65 -0
- package/src/plugins/outbound-link-tracker.ts +72 -0
- package/src/plugins/page-visibility-tracker.ts +104 -0
- package/src/plugins/url-change-tracker.ts +84 -0
- package/src/types/dataLayer.ts +9 -9
- package/src/types/global.ts +12 -12
- package/src/types/gtag.ts +259 -259
- package/src/types/plugins.ts +98 -0
- package/src/util.ts +18 -18
- package/test/dataLayer.spec.ts +55 -55
- package/test/ga4.spec.ts +36 -36
- package/tsconfig.json +28 -28
- package/tsconfig.module.json +11 -11
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ImpressionTracker = void 0;
|
|
4
|
+
const dom_ready_1 = require("../helpers/dom-ready");
|
|
5
|
+
/**
|
|
6
|
+
* Tracks when specific DOM elements become visible in the viewport
|
|
7
|
+
* using `IntersectionObserver`.
|
|
8
|
+
*
|
|
9
|
+
* Useful for tracking ad impressions, CTA visibility, or any
|
|
10
|
+
* element that enters the user's viewport.
|
|
11
|
+
*/
|
|
12
|
+
class ImpressionTracker {
|
|
13
|
+
send;
|
|
14
|
+
rootMargin;
|
|
15
|
+
attributePrefix;
|
|
16
|
+
eventName;
|
|
17
|
+
hitFilter;
|
|
18
|
+
items = [];
|
|
19
|
+
elementMap = {};
|
|
20
|
+
thresholdMap = {};
|
|
21
|
+
mutationObserver = null;
|
|
22
|
+
impressedIds = new Set();
|
|
23
|
+
supported;
|
|
24
|
+
constructor(send, options) {
|
|
25
|
+
this.supported =
|
|
26
|
+
typeof IntersectionObserver !== 'undefined' &&
|
|
27
|
+
typeof MutationObserver !== 'undefined';
|
|
28
|
+
this.send = send;
|
|
29
|
+
this.rootMargin = options?.rootMargin ?? '0px';
|
|
30
|
+
this.attributePrefix = options?.attributePrefix ?? 'data-ga4-';
|
|
31
|
+
this.eventName = options?.eventName ?? 'element_impression';
|
|
32
|
+
this.hitFilter = options?.hitFilter;
|
|
33
|
+
if (!this.supported)
|
|
34
|
+
return;
|
|
35
|
+
this.handleIntersectionChanges = this.handleIntersectionChanges.bind(this);
|
|
36
|
+
this.handleDomMutations = this.handleDomMutations.bind(this);
|
|
37
|
+
const elements = options?.elements;
|
|
38
|
+
(0, dom_ready_1.domReady)(() => {
|
|
39
|
+
if (elements && elements.length > 0) {
|
|
40
|
+
this.observeElements(elements);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
observeElements(elements) {
|
|
45
|
+
if (!this.supported)
|
|
46
|
+
return;
|
|
47
|
+
const newItems = this.normalizeElements(elements);
|
|
48
|
+
this.items = this.items.concat(newItems);
|
|
49
|
+
newItems.forEach((item) => {
|
|
50
|
+
const observer = this.getObserverForThreshold(item.threshold);
|
|
51
|
+
const element = document.getElementById(item.id);
|
|
52
|
+
this.elementMap[item.id] = element;
|
|
53
|
+
if (element) {
|
|
54
|
+
observer.observe(element);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
if (!this.mutationObserver && document.body) {
|
|
58
|
+
this.mutationObserver = new MutationObserver(this.handleDomMutations);
|
|
59
|
+
this.mutationObserver.observe(document.body, {
|
|
60
|
+
childList: true,
|
|
61
|
+
subtree: true,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
unobserveElements(elements) {
|
|
66
|
+
if (!this.supported)
|
|
67
|
+
return;
|
|
68
|
+
const idsToRemove = new Set(elements.map((el) => (typeof el === 'string' ? el : el.id)));
|
|
69
|
+
this.items = this.items.filter((item) => {
|
|
70
|
+
if (idsToRemove.has(item.id)) {
|
|
71
|
+
const element = this.elementMap[item.id];
|
|
72
|
+
if (element && this.thresholdMap[item.threshold]) {
|
|
73
|
+
this.thresholdMap[item.threshold].unobserve(element);
|
|
74
|
+
}
|
|
75
|
+
delete this.elementMap[item.id];
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
});
|
|
80
|
+
if (this.items.length === 0) {
|
|
81
|
+
this.disconnectAll();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
unobserveAllElements() {
|
|
85
|
+
this.disconnectAll();
|
|
86
|
+
this.items = [];
|
|
87
|
+
this.elementMap = {};
|
|
88
|
+
}
|
|
89
|
+
normalizeElements(elements) {
|
|
90
|
+
return elements.map((el) => {
|
|
91
|
+
if (typeof el === 'string') {
|
|
92
|
+
return { id: el, threshold: 0, trackFirstImpressionOnly: true };
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
id: el.id,
|
|
96
|
+
threshold: el.threshold ?? 0,
|
|
97
|
+
trackFirstImpressionOnly: el.trackFirstImpressionOnly ?? true,
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
getObserverForThreshold(threshold) {
|
|
102
|
+
if (!this.thresholdMap[threshold]) {
|
|
103
|
+
this.thresholdMap[threshold] = new IntersectionObserver(this.handleIntersectionChanges, {
|
|
104
|
+
rootMargin: this.rootMargin,
|
|
105
|
+
threshold: [threshold],
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return this.thresholdMap[threshold];
|
|
109
|
+
}
|
|
110
|
+
handleIntersectionChanges(entries) {
|
|
111
|
+
entries.forEach((entry) => {
|
|
112
|
+
if (!entry.isIntersecting)
|
|
113
|
+
return;
|
|
114
|
+
const id = entry.target.id;
|
|
115
|
+
if (!id)
|
|
116
|
+
return;
|
|
117
|
+
const item = this.items.find((i) => i.id === id);
|
|
118
|
+
if (!item)
|
|
119
|
+
return;
|
|
120
|
+
if (item.trackFirstImpressionOnly && this.impressedIds.has(id))
|
|
121
|
+
return;
|
|
122
|
+
this.impressedIds.add(id);
|
|
123
|
+
const prefix = this.attributePrefix;
|
|
124
|
+
const attrParams = {};
|
|
125
|
+
for (let i = 0; i < entry.target.attributes.length; i++) {
|
|
126
|
+
const attr = entry.target.attributes[i];
|
|
127
|
+
if (attr.name.startsWith(prefix)) {
|
|
128
|
+
const key = attr.name.slice(prefix.length).replace(/-/g, '_');
|
|
129
|
+
attrParams[key] = attr.value;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
let params = {
|
|
133
|
+
element_id: id,
|
|
134
|
+
...attrParams,
|
|
135
|
+
};
|
|
136
|
+
if (this.hitFilter) {
|
|
137
|
+
const filtered = this.hitFilter(params, entry.target);
|
|
138
|
+
if (filtered === null)
|
|
139
|
+
return;
|
|
140
|
+
params = filtered;
|
|
141
|
+
}
|
|
142
|
+
this.send(this.eventName, params);
|
|
143
|
+
if (item.trackFirstImpressionOnly && this.thresholdMap[item.threshold]) {
|
|
144
|
+
this.thresholdMap[item.threshold].unobserve(entry.target);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
handleDomMutations(mutations) {
|
|
149
|
+
mutations.forEach((mutation) => {
|
|
150
|
+
mutation.addedNodes.forEach((node) => {
|
|
151
|
+
if (node.nodeType !== Node.ELEMENT_NODE)
|
|
152
|
+
return;
|
|
153
|
+
this.walkNodeTree(node, (id) => {
|
|
154
|
+
const element = document.getElementById(id);
|
|
155
|
+
if (element) {
|
|
156
|
+
this.elementMap[id] = element;
|
|
157
|
+
const item = this.items.find((i) => i.id === id);
|
|
158
|
+
if (item && this.thresholdMap[item.threshold]) {
|
|
159
|
+
this.thresholdMap[item.threshold].observe(element);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
mutation.removedNodes.forEach((node) => {
|
|
165
|
+
if (node.nodeType !== Node.ELEMENT_NODE)
|
|
166
|
+
return;
|
|
167
|
+
this.walkNodeTree(node, (id) => {
|
|
168
|
+
const element = this.elementMap[id];
|
|
169
|
+
if (element) {
|
|
170
|
+
const item = this.items.find((i) => i.id === id);
|
|
171
|
+
if (item && this.thresholdMap[item.threshold]) {
|
|
172
|
+
this.thresholdMap[item.threshold].unobserve(element);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
this.elementMap[id] = null;
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
walkNodeTree(node, callback) {
|
|
181
|
+
if (node.id && node.id in this.elementMap) {
|
|
182
|
+
callback(node.id);
|
|
183
|
+
}
|
|
184
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
185
|
+
this.walkNodeTree(node.children[i], callback);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
disconnectAll() {
|
|
189
|
+
Object.values(this.thresholdMap).forEach((observer) => observer.disconnect());
|
|
190
|
+
this.thresholdMap = {};
|
|
191
|
+
if (this.mutationObserver) {
|
|
192
|
+
this.mutationObserver.disconnect();
|
|
193
|
+
this.mutationObserver = null;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
remove() {
|
|
197
|
+
this.unobserveAllElements();
|
|
198
|
+
this.impressedIds.clear();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
exports.ImpressionTracker = ImpressionTracker;
|
|
202
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1wcmVzc2lvbi10cmFja2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3BsdWdpbnMvaW1wcmVzc2lvbi10cmFja2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLG9EQUFnRDtBQVFoRDs7Ozs7O0dBTUc7QUFDSCxNQUFhLGlCQUFpQjtJQUNsQixJQUFJLENBQWU7SUFDbkIsVUFBVSxDQUFTO0lBQ25CLGVBQWUsQ0FBUztJQUN4QixTQUFTLENBQVM7SUFDbEIsU0FBUyxDQUF5QztJQUNsRCxLQUFLLEdBQXFCLEVBQUUsQ0FBQztJQUM3QixVQUFVLEdBQW1DLEVBQUUsQ0FBQztJQUNoRCxZQUFZLEdBQXlDLEVBQUUsQ0FBQztJQUN4RCxnQkFBZ0IsR0FBNEIsSUFBSSxDQUFDO0lBQ2pELFlBQVksR0FBZ0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUN0QyxTQUFTLENBQVU7SUFFM0IsWUFBWSxJQUFrQixFQUFFLE9BQWtDO1FBQzlELElBQUksQ0FBQyxTQUFTO1lBQ1YsT0FBTyxvQkFBb0IsS0FBSyxXQUFXO2dCQUMzQyxPQUFPLGdCQUFnQixLQUFLLFdBQVcsQ0FBQztRQUU1QyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sRUFBRSxVQUFVLElBQUksS0FBSyxDQUFDO1FBQy9DLElBQUksQ0FBQyxlQUFlLEdBQUcsT0FBTyxFQUFFLGVBQWUsSUFBSSxXQUFXLENBQUM7UUFDL0QsSUFBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLEVBQUUsU0FBUyxJQUFJLG9CQUFvQixDQUFDO1FBQzVELElBQUksQ0FBQyxTQUFTLEdBQUcsT0FBTyxFQUFFLFNBQVMsQ0FBQztRQUVwQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVM7WUFBRSxPQUFPO1FBRTVCLElBQUksQ0FBQyx5QkFBeUIsR0FBRyxJQUFJLENBQUMseUJBQXlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzNFLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTdELE1BQU0sUUFBUSxHQUFHLE9BQU8sRUFBRSxRQUFRLENBQUM7UUFDbkMsSUFBQSxvQkFBUSxFQUFDLEdBQUcsRUFBRTtZQUNWLElBQUksUUFBUSxJQUFJLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO2dCQUNqQyxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQ2xDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsZUFBZSxDQUFDLFFBQWlEO1FBQzdELElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUztZQUFFLE9BQU87UUFFNUIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2xELElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFekMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ3RCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDOUQsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDakQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDO1lBQ25DLElBQUksT0FBTyxFQUFFO2dCQUNULFFBQVEsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7YUFDN0I7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLElBQUksUUFBUSxDQUFDLElBQUksRUFBRTtZQUN6QyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUN0RSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUU7Z0JBQ3pDLFNBQVMsRUFBRSxJQUFJO2dCQUNmLE9BQU8sRUFBRSxJQUFJO2FBQ2hCLENBQUMsQ0FBQztTQUNOO0lBQ0wsQ0FBQztJQUVELGlCQUFpQixDQUFDLFFBQWlEO1FBQy9ELElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUztZQUFFLE9BQU87UUFFNUIsTUFBTSxXQUFXLEdBQUcsSUFBSSxHQUFHLENBQ3ZCLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUM5RCxDQUFDO1FBRUYsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ3BDLElBQUksV0FBVyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUU7Z0JBQzFCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUN6QyxJQUFJLE9BQU8sSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRTtvQkFDOUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDO2lCQUN4RDtnQkFDRCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNoQyxPQUFPLEtBQUssQ0FBQzthQUNoQjtZQUNELE9BQU8sSUFBSSxDQUFDO1FBQ2hCLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDekIsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1NBQ3hCO0lBQ0wsQ0FBQztJQUVELG9CQUFvQjtRQUNoQixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDaEIsSUFBSSxDQUFDLFVBQVUsR0FBRyxFQUFFLENBQUM7SUFDekIsQ0FBQztJQUVPLGlCQUFpQixDQUFDLFFBQWlEO1FBQ3ZFLE9BQU8sUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFO1lBQ3ZCLElBQUksT0FBTyxFQUFFLEtBQUssUUFBUSxFQUFFO2dCQUN4QixPQUFPLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLHdCQUF3QixFQUFFLElBQUksRUFBRSxDQUFDO2FBQ25FO1lBQ0QsT0FBTztnQkFDSCxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUU7Z0JBQ1QsU0FBUyxFQUFFLEVBQUUsQ0FBQyxTQUFTLElBQUksQ0FBQztnQkFDNUIsd0JBQXdCLEVBQUUsRUFBRSxDQUFDLHdCQUF3QixJQUFJLElBQUk7YUFDaEUsQ0FBQztRQUNOLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVPLHVCQUF1QixDQUFDLFNBQWlCO1FBQzdDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxFQUFFO1lBQy9CLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLEdBQUcsSUFBSSxvQkFBb0IsQ0FDbkQsSUFBSSxDQUFDLHlCQUF5QixFQUM5QjtnQkFDSSxVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVU7Z0JBQzNCLFNBQVMsRUFBRSxDQUFDLFNBQVMsQ0FBQzthQUN6QixDQUNKLENBQUM7U0FDTDtRQUNELE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBRU8seUJBQXlCLENBQUMsT0FBb0M7UUFDbEUsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ3RCLElBQUksQ0FBQyxLQUFLLENBQUMsY0FBYztnQkFBRSxPQUFPO1lBRWxDLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQzNCLElBQUksQ0FBQyxFQUFFO2dCQUFFLE9BQU87WUFFaEIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDakQsSUFBSSxDQUFDLElBQUk7Z0JBQUUsT0FBTztZQUNsQixJQUFJLElBQUksQ0FBQyx3QkFBd0IsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQUUsT0FBTztZQUV2RSxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUUxQixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDO1lBQ3BDLE1BQU0sVUFBVSxHQUE0QixFQUFFLENBQUM7WUFDL0MsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtnQkFDckQsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3hDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLEVBQUU7b0JBQzlCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO29CQUM5RCxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztpQkFDaEM7YUFDSjtZQUVELElBQUksTUFBTSxHQUE0QjtnQkFDbEMsVUFBVSxFQUFFLEVBQUU7Z0JBQ2QsR0FBRyxVQUFVO2FBQ2hCLENBQUM7WUFFRixJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7Z0JBQ2hCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDdEQsSUFBSSxRQUFRLEtBQUssSUFBSTtvQkFBRSxPQUFPO2dCQUM5QixNQUFNLEdBQUcsUUFBUSxDQUFDO2FBQ3JCO1lBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBRWxDLElBQUksSUFBSSxDQUFDLHdCQUF3QixJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFO2dCQUNwRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO2FBQzdEO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU8sa0JBQWtCLENBQUMsU0FBMkI7UUFDbEQsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFO1lBQzNCLFFBQVEsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7Z0JBQ2pDLElBQUksSUFBSSxDQUFDLFFBQVEsS0FBSyxJQUFJLENBQUMsWUFBWTtvQkFBRSxPQUFPO2dCQUNoRCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQWUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFO29CQUN0QyxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDO29CQUM1QyxJQUFJLE9BQU8sRUFBRTt3QkFDVCxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQzt3QkFDOUIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7d0JBQ2pELElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFOzRCQUMzQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7eUJBQ3REO3FCQUNKO2dCQUNMLENBQUMsQ0FBQyxDQUFDO1lBQ1AsQ0FBQyxDQUFDLENBQUM7WUFFSCxRQUFRLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO2dCQUNuQyxJQUFJLElBQUksQ0FBQyxRQUFRLEtBQUssSUFBSSxDQUFDLFlBQVk7b0JBQUUsT0FBTztnQkFDaEQsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFlLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRTtvQkFDdEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQztvQkFDcEMsSUFBSSxPQUFPLEVBQUU7d0JBQ1QsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7d0JBQ2pELElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFOzRCQUMzQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUM7eUJBQ3hEO3FCQUNKO29CQUNELElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDO2dCQUMvQixDQUFDLENBQUMsQ0FBQztZQUNQLENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU8sWUFBWSxDQUFDLElBQWEsRUFBRSxRQUE4QjtRQUM5RCxJQUFJLElBQUksQ0FBQyxFQUFFLElBQUksSUFBSSxDQUFDLEVBQUUsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ3ZDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDckI7UUFDRCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDM0MsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1NBQ2pEO0lBQ0wsQ0FBQztJQUVPLGFBQWE7UUFDakIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQztRQUM5RSxJQUFJLENBQUMsWUFBWSxHQUFHLEVBQUUsQ0FBQztRQUN2QixJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTtZQUN2QixJQUFJLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDbkMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztTQUNoQztJQUNMLENBQUM7SUFFRCxNQUFNO1FBQ0YsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDNUIsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM5QixDQUFDO0NBQ0o7QUFyTkQsOENBcU5DIn0=
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { EventTracker } from './event-tracker';
|
|
2
|
+
export { OutboundLinkTracker } from './outbound-link-tracker';
|
|
3
|
+
export { OutboundFormTracker } from './outbound-form-tracker';
|
|
4
|
+
export { PageVisibilityTracker } from './page-visibility-tracker';
|
|
5
|
+
export { UrlChangeTracker } from './url-change-tracker';
|
|
6
|
+
export { ImpressionTracker } from './impression-tracker';
|
|
7
|
+
export { CleanUrlTracker } from './clean-url-tracker';
|
|
8
|
+
export { MediaQueryTracker } from './media-query-tracker';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MediaQueryTracker = exports.CleanUrlTracker = exports.ImpressionTracker = exports.UrlChangeTracker = exports.PageVisibilityTracker = exports.OutboundFormTracker = exports.OutboundLinkTracker = exports.EventTracker = void 0;
|
|
4
|
+
var event_tracker_1 = require("./event-tracker");
|
|
5
|
+
Object.defineProperty(exports, "EventTracker", { enumerable: true, get: function () { return event_tracker_1.EventTracker; } });
|
|
6
|
+
var outbound_link_tracker_1 = require("./outbound-link-tracker");
|
|
7
|
+
Object.defineProperty(exports, "OutboundLinkTracker", { enumerable: true, get: function () { return outbound_link_tracker_1.OutboundLinkTracker; } });
|
|
8
|
+
var outbound_form_tracker_1 = require("./outbound-form-tracker");
|
|
9
|
+
Object.defineProperty(exports, "OutboundFormTracker", { enumerable: true, get: function () { return outbound_form_tracker_1.OutboundFormTracker; } });
|
|
10
|
+
var page_visibility_tracker_1 = require("./page-visibility-tracker");
|
|
11
|
+
Object.defineProperty(exports, "PageVisibilityTracker", { enumerable: true, get: function () { return page_visibility_tracker_1.PageVisibilityTracker; } });
|
|
12
|
+
var url_change_tracker_1 = require("./url-change-tracker");
|
|
13
|
+
Object.defineProperty(exports, "UrlChangeTracker", { enumerable: true, get: function () { return url_change_tracker_1.UrlChangeTracker; } });
|
|
14
|
+
var impression_tracker_1 = require("./impression-tracker");
|
|
15
|
+
Object.defineProperty(exports, "ImpressionTracker", { enumerable: true, get: function () { return impression_tracker_1.ImpressionTracker; } });
|
|
16
|
+
var clean_url_tracker_1 = require("./clean-url-tracker");
|
|
17
|
+
Object.defineProperty(exports, "CleanUrlTracker", { enumerable: true, get: function () { return clean_url_tracker_1.CleanUrlTracker; } });
|
|
18
|
+
var media_query_tracker_1 = require("./media-query-tracker");
|
|
19
|
+
Object.defineProperty(exports, "MediaQueryTracker", { enumerable: true, get: function () { return media_query_tracker_1.MediaQueryTracker; } });
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcGx1Z2lucy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxpREFBK0M7QUFBdEMsNkdBQUEsWUFBWSxPQUFBO0FBQ3JCLGlFQUE4RDtBQUFyRCw0SEFBQSxtQkFBbUIsT0FBQTtBQUM1QixpRUFBOEQ7QUFBckQsNEhBQUEsbUJBQW1CLE9BQUE7QUFDNUIscUVBQWtFO0FBQXpELGdJQUFBLHFCQUFxQixPQUFBO0FBQzlCLDJEQUF3RDtBQUEvQyxzSEFBQSxnQkFBZ0IsT0FBQTtBQUN6QiwyREFBeUQ7QUFBaEQsdUhBQUEsaUJBQWlCLE9BQUE7QUFDMUIseURBQXNEO0FBQTdDLG9IQUFBLGVBQWUsT0FBQTtBQUN4Qiw2REFBMEQ7QUFBakQsd0hBQUEsaUJBQWlCLE9BQUEifQ==
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { GA4Plugin, SendFunction, MediaQueryTrackerOptions } from '../types/plugins';
|
|
2
|
+
/**
|
|
3
|
+
* Tracks CSS media query breakpoint matching and changes.
|
|
4
|
+
*
|
|
5
|
+
* Fires an event whenever the active breakpoint changes
|
|
6
|
+
* (e.g. from "mobile" to "desktop"), debounced to avoid
|
|
7
|
+
* rapid-fire events during window resizing.
|
|
8
|
+
*/
|
|
9
|
+
export declare class MediaQueryTracker implements GA4Plugin {
|
|
10
|
+
private send;
|
|
11
|
+
private changeTimeout;
|
|
12
|
+
private eventName;
|
|
13
|
+
private changeTemplate?;
|
|
14
|
+
private hitFilter?;
|
|
15
|
+
private trackedQueries;
|
|
16
|
+
private debouncedHandlers;
|
|
17
|
+
constructor(send: SendFunction, options?: MediaQueryTrackerOptions);
|
|
18
|
+
private trackDefinition;
|
|
19
|
+
remove(): void;
|
|
20
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MediaQueryTracker = void 0;
|
|
4
|
+
const debounce_1 = require("../helpers/debounce");
|
|
5
|
+
function getMatchingValue(definition) {
|
|
6
|
+
for (const item of definition.items) {
|
|
7
|
+
if (window.matchMedia(item.media).matches) {
|
|
8
|
+
return item.name;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return '(not set)';
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Tracks CSS media query breakpoint matching and changes.
|
|
15
|
+
*
|
|
16
|
+
* Fires an event whenever the active breakpoint changes
|
|
17
|
+
* (e.g. from "mobile" to "desktop"), debounced to avoid
|
|
18
|
+
* rapid-fire events during window resizing.
|
|
19
|
+
*/
|
|
20
|
+
class MediaQueryTracker {
|
|
21
|
+
send;
|
|
22
|
+
changeTimeout;
|
|
23
|
+
eventName;
|
|
24
|
+
changeTemplate;
|
|
25
|
+
hitFilter;
|
|
26
|
+
trackedQueries = [];
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
debouncedHandlers = [];
|
|
29
|
+
constructor(send, options) {
|
|
30
|
+
this.send = send;
|
|
31
|
+
this.changeTimeout = options?.changeTimeout ?? 1000;
|
|
32
|
+
this.eventName = options?.eventName ?? 'media_query_change';
|
|
33
|
+
this.changeTemplate = options?.changeTemplate;
|
|
34
|
+
this.hitFilter = options?.hitFilter;
|
|
35
|
+
if (typeof window.matchMedia !== 'function')
|
|
36
|
+
return;
|
|
37
|
+
const definitions = options?.definitions ?? [];
|
|
38
|
+
definitions.forEach((definition) => {
|
|
39
|
+
this.trackDefinition(definition);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
trackDefinition(definition) {
|
|
43
|
+
const initialValue = getMatchingValue(definition);
|
|
44
|
+
definition.items.forEach((item) => {
|
|
45
|
+
const mql = window.matchMedia(item.media);
|
|
46
|
+
const debouncedHandler = (0, debounce_1.debounce)(() => {
|
|
47
|
+
const newValue = getMatchingValue(definition);
|
|
48
|
+
const tracked = this.trackedQueries.find((tq) => tq.definition === definition);
|
|
49
|
+
if (!tracked || newValue === tracked.currentValue)
|
|
50
|
+
return;
|
|
51
|
+
const oldValue = tracked.currentValue;
|
|
52
|
+
tracked.currentValue = newValue;
|
|
53
|
+
const changeLabel = this.changeTemplate
|
|
54
|
+
? this.changeTemplate(oldValue, newValue)
|
|
55
|
+
: `${oldValue} => ${newValue}`;
|
|
56
|
+
let params = {
|
|
57
|
+
media_query_name: definition.name,
|
|
58
|
+
media_query_value: newValue,
|
|
59
|
+
media_query_change: changeLabel,
|
|
60
|
+
};
|
|
61
|
+
if (this.hitFilter) {
|
|
62
|
+
const filtered = this.hitFilter(params);
|
|
63
|
+
if (filtered === null)
|
|
64
|
+
return;
|
|
65
|
+
params = filtered;
|
|
66
|
+
}
|
|
67
|
+
this.send(this.eventName, params);
|
|
68
|
+
}, this.changeTimeout);
|
|
69
|
+
this.debouncedHandlers.push(debouncedHandler);
|
|
70
|
+
const listener = () => {
|
|
71
|
+
debouncedHandler();
|
|
72
|
+
};
|
|
73
|
+
if (typeof mql.addEventListener === 'function') {
|
|
74
|
+
mql.addEventListener('change', listener);
|
|
75
|
+
}
|
|
76
|
+
this.trackedQueries.push({
|
|
77
|
+
definition,
|
|
78
|
+
mql,
|
|
79
|
+
currentValue: initialValue,
|
|
80
|
+
listener,
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
remove() {
|
|
85
|
+
this.trackedQueries.forEach(({ mql, listener }) => {
|
|
86
|
+
if (typeof mql.removeEventListener === 'function') {
|
|
87
|
+
mql.removeEventListener('change', listener);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
this.debouncedHandlers.forEach((d) => d.cancel());
|
|
91
|
+
this.trackedQueries = [];
|
|
92
|
+
this.debouncedHandlers = [];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.MediaQueryTracker = MediaQueryTracker;
|
|
96
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVkaWEtcXVlcnktdHJhY2tlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wbHVnaW5zL21lZGlhLXF1ZXJ5LXRyYWNrZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0Esa0RBQWtFO0FBU2xFLFNBQVMsZ0JBQWdCLENBQUMsVUFBZ0M7SUFDdEQsS0FBSyxNQUFNLElBQUksSUFBSSxVQUFVLENBQUMsS0FBSyxFQUFFO1FBQ2pDLElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFO1lBQ3ZDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQztTQUNwQjtLQUNKO0lBQ0QsT0FBTyxXQUFXLENBQUM7QUFDdkIsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQWEsaUJBQWlCO0lBQ2xCLElBQUksQ0FBZTtJQUNuQixhQUFhLENBQVM7SUFDdEIsU0FBUyxDQUFTO0lBQ2xCLGNBQWMsQ0FBOEM7SUFDNUQsU0FBUyxDQUF5QztJQUNsRCxjQUFjLEdBQW1CLEVBQUUsQ0FBQztJQUM1Qyw4REFBOEQ7SUFDdEQsaUJBQWlCLEdBQTZCLEVBQUUsQ0FBQztJQUV6RCxZQUFZLElBQWtCLEVBQUUsT0FBa0M7UUFDOUQsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLGFBQWEsR0FBRyxPQUFPLEVBQUUsYUFBYSxJQUFJLElBQUksQ0FBQztRQUNwRCxJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sRUFBRSxTQUFTLElBQUksb0JBQW9CLENBQUM7UUFDNUQsSUFBSSxDQUFDLGNBQWMsR0FBRyxPQUFPLEVBQUUsY0FBYyxDQUFDO1FBQzlDLElBQUksQ0FBQyxTQUFTLEdBQUcsT0FBTyxFQUFFLFNBQVMsQ0FBQztRQUVwQyxJQUFJLE9BQU8sTUFBTSxDQUFDLFVBQVUsS0FBSyxVQUFVO1lBQUUsT0FBTztRQUVwRCxNQUFNLFdBQVcsR0FBRyxPQUFP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
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { GA4Plugin, SendFunction, OutboundFormTrackerOptions } from '../types/plugins';
|
|
2
|
+
/**
|
|
3
|
+
* Automatically tracks form submissions to external domains.
|
|
4
|
+
*
|
|
5
|
+
* Sends an event when a form's `action` attribute points to a
|
|
6
|
+
* different hostname than the current page.
|
|
7
|
+
*/
|
|
8
|
+
export declare class OutboundFormTracker implements GA4Plugin {
|
|
9
|
+
private delegateHandle;
|
|
10
|
+
private send;
|
|
11
|
+
private eventName;
|
|
12
|
+
private shouldTrackOutboundForm;
|
|
13
|
+
private hitFilter?;
|
|
14
|
+
constructor(send: SendFunction, options?: OutboundFormTrackerOptions);
|
|
15
|
+
private handleFormSubmit;
|
|
16
|
+
remove(): void;
|
|
17
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OutboundFormTracker = void 0;
|
|
4
|
+
const delegate_1 = require("../helpers/delegate");
|
|
5
|
+
const parse_url_1 = require("../helpers/parse-url");
|
|
6
|
+
function defaultShouldTrack(form, parseUrlFn) {
|
|
7
|
+
const action = form.action;
|
|
8
|
+
if (!action)
|
|
9
|
+
return false;
|
|
10
|
+
const url = parseUrlFn(action);
|
|
11
|
+
return url.hostname !== location.hostname && url.protocol.startsWith('http');
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Automatically tracks form submissions to external domains.
|
|
15
|
+
*
|
|
16
|
+
* Sends an event when a form's `action` attribute points to a
|
|
17
|
+
* different hostname than the current page.
|
|
18
|
+
*/
|
|
19
|
+
class OutboundFormTracker {
|
|
20
|
+
delegateHandle;
|
|
21
|
+
send;
|
|
22
|
+
eventName;
|
|
23
|
+
shouldTrackOutboundForm;
|
|
24
|
+
hitFilter;
|
|
25
|
+
constructor(send, options) {
|
|
26
|
+
this.send = send;
|
|
27
|
+
this.eventName = options?.eventName ?? 'outbound_form_submit';
|
|
28
|
+
this.shouldTrackOutboundForm = options?.shouldTrackOutboundForm ?? defaultShouldTrack;
|
|
29
|
+
this.hitFilter = options?.hitFilter;
|
|
30
|
+
const formSelector = options?.formSelector ?? 'form';
|
|
31
|
+
this.delegateHandle = (0, delegate_1.delegate)(document, 'submit', formSelector, (event, element) => this.handleFormSubmit(event, element), { composed: true, useCapture: true });
|
|
32
|
+
}
|
|
33
|
+
handleFormSubmit(event, form) {
|
|
34
|
+
if (!this.shouldTrackOutboundForm(form, parse_url_1.parseUrl))
|
|
35
|
+
return;
|
|
36
|
+
const url = (0, parse_url_1.parseUrl)(form.action);
|
|
37
|
+
let params = {
|
|
38
|
+
form_action: url.href,
|
|
39
|
+
form_domain: url.hostname,
|
|
40
|
+
outbound: true,
|
|
41
|
+
};
|
|
42
|
+
if (this.hitFilter) {
|
|
43
|
+
const filtered = this.hitFilter(params, form, event);
|
|
44
|
+
if (filtered === null)
|
|
45
|
+
return;
|
|
46
|
+
params = filtered;
|
|
47
|
+
}
|
|
48
|
+
this.send(this.eventName, params);
|
|
49
|
+
}
|
|
50
|
+
remove() {
|
|
51
|
+
this.delegateHandle.destroy();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.OutboundFormTracker = OutboundFormTracker;
|
|
55
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQtZm9ybS10cmFja2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3BsdWdpbnMvb3V0Ym91bmQtZm9ybS10cmFja2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLGtEQUErRDtBQUMvRCxvREFBZ0Q7QUFFaEQsU0FBUyxrQkFBa0IsQ0FBQyxJQUFxQixFQUFFLFVBQWlGO0lBQ2hJLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDM0IsSUFBSSxDQUFDLE1BQU07UUFBRSxPQUFPLEtBQUssQ0FBQztJQUMxQixNQUFNLEdBQUcsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDL0IsT0FBTyxHQUFHLENBQUMsUUFBUSxLQUFLLFFBQVEsQ0FBQyxRQUFRLElBQUksR0FBRyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDakYsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBYSxtQkFBbUI7SUFDcEIsY0FBYyxDQUFpQjtJQUMvQixJQUFJLENBQWU7SUFDbkIsU0FBUyxDQUFTO0lBQ2xCLHVCQUF1QixDQUFxRTtJQUM1RixTQUFTLENBQTJDO0lBRTVELFlBQVksSUFBa0IsRUFBRSxPQUFvQztRQUNoRSxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sRUFBRSxTQUFTLElBQUksc0JBQXNCLENBQUM7UUFDOUQsSUFBSSxDQUFDLHVCQUF1QixHQUFHLE9BQU8sRUFBRSx1QkFBdUIsSUFBSSxrQkFBa0IsQ0FBQztRQUN0RixJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sRUFBRSxTQUFTLENBQUM7UUFFcEMsTUFBTSxZQUFZLEdBQUcsT0FBTyxFQUFFLFlBQVksSUFBSSxNQUFNLENBQUM7UUFFckQsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFBLG1CQUFRLEVBQzFCLFFBQVEsRUFDUixRQUFRLEVBQ1IsWUFBWSxFQUNaLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxPQUEwQixDQUFDLEVBQzVFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLENBQ3ZDLENBQUM7SUFDTixDQUFDO0lBRU8sZ0JBQWdCLENBQUMsS0FBWSxFQUFFLElBQXFCO1FBQ3hELElBQUksQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsSUFBSSxFQUFFLG9CQUFRLENBQUM7WUFBRSxPQUFPO1FBRTFELE1BQU0sR0FBRyxHQUFHLElBQUEsb0JBQVEsRUFBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFbEMsSUFBSSxNQUFNLEdBQTRCO1lBQ2xDLFdBQVcsRUFBRSxHQUFHLENBQUMsSUFBSTtZQUNyQixXQUFXLEVBQUUsR0FBRyxDQUFDLFFBQVE7WUFDekIsUUFBUSxFQUFFLElBQUk7U0FDakIsQ0FBQztRQUVGLElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNoQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDckQsSUFBSSxRQUFRLEtBQUssSUFBSTtnQkFBRSxPQUFPO1lBQzlCLE1BQU0sR0FBRyxRQUFRLENBQUM7U0FDckI7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELE1BQU07UUFDRixJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2xDLENBQUM7Q0FDSjtBQS9DRCxrREErQ0MifQ==
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { GA4Plugin, SendFunction, OutboundLinkTrackerOptions } from '../types/plugins';
|
|
2
|
+
/**
|
|
3
|
+
* Automatically tracks clicks on outbound links (links to external domains).
|
|
4
|
+
*
|
|
5
|
+
* Sends an event when a user clicks a link whose hostname differs
|
|
6
|
+
* from the current page's hostname.
|
|
7
|
+
*/
|
|
8
|
+
export declare class OutboundLinkTracker implements GA4Plugin {
|
|
9
|
+
private delegates;
|
|
10
|
+
private send;
|
|
11
|
+
private events;
|
|
12
|
+
private linkSelector;
|
|
13
|
+
private eventName;
|
|
14
|
+
private shouldTrackOutboundLink;
|
|
15
|
+
private hitFilter?;
|
|
16
|
+
constructor(send: SendFunction, options?: OutboundLinkTrackerOptions);
|
|
17
|
+
private handleLinkInteraction;
|
|
18
|
+
remove(): void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OutboundLinkTracker = void 0;
|
|
4
|
+
const delegate_1 = require("../helpers/delegate");
|
|
5
|
+
const parse_url_1 = require("../helpers/parse-url");
|
|
6
|
+
function defaultShouldTrack(link, parseUrlFn) {
|
|
7
|
+
const href = link.getAttribute('href') || link.getAttribute('xlink:href');
|
|
8
|
+
if (!href)
|
|
9
|
+
return false;
|
|
10
|
+
const url = parseUrlFn(href);
|
|
11
|
+
return url.hostname !== location.hostname && url.protocol.startsWith('http');
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Automatically tracks clicks on outbound links (links to external domains).
|
|
15
|
+
*
|
|
16
|
+
* Sends an event when a user clicks a link whose hostname differs
|
|
17
|
+
* from the current page's hostname.
|
|
18
|
+
*/
|
|
19
|
+
class OutboundLinkTracker {
|
|
20
|
+
delegates = [];
|
|
21
|
+
send;
|
|
22
|
+
events;
|
|
23
|
+
linkSelector;
|
|
24
|
+
eventName;
|
|
25
|
+
shouldTrackOutboundLink;
|
|
26
|
+
hitFilter;
|
|
27
|
+
constructor(send, options) {
|
|
28
|
+
this.send = send;
|
|
29
|
+
this.events = options?.events ?? ['click'];
|
|
30
|
+
this.linkSelector = options?.linkSelector ?? 'a, area';
|
|
31
|
+
this.eventName = options?.eventName ?? 'outbound_link_click';
|
|
32
|
+
this.shouldTrackOutboundLink = options?.shouldTrackOutboundLink ?? defaultShouldTrack;
|
|
33
|
+
this.hitFilter = options?.hitFilter;
|
|
34
|
+
this.events.forEach((eventType) => {
|
|
35
|
+
const handle = (0, delegate_1.delegate)(document, eventType, this.linkSelector, (event, element) => this.handleLinkInteraction(event, element), { composed: true, useCapture: true });
|
|
36
|
+
this.delegates.push(handle);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
handleLinkInteraction(event, element) {
|
|
40
|
+
if (!this.shouldTrackOutboundLink(element, parse_url_1.parseUrl))
|
|
41
|
+
return;
|
|
42
|
+
const href = element.getAttribute('href') || element.getAttribute('xlink:href') || '';
|
|
43
|
+
const url = (0, parse_url_1.parseUrl)(href);
|
|
44
|
+
let params = {
|
|
45
|
+
link_url: url.href,
|
|
46
|
+
link_domain: url.hostname,
|
|
47
|
+
outbound: true,
|
|
48
|
+
};
|
|
49
|
+
if (this.hitFilter) {
|
|
50
|
+
const filtered = this.hitFilter(params, element, event);
|
|
51
|
+
if (filtered === null)
|
|
52
|
+
return;
|
|
53
|
+
params = filtered;
|
|
54
|
+
}
|
|
55
|
+
this.send(this.eventName, params);
|
|
56
|
+
}
|
|
57
|
+
remove() {
|
|
58
|
+
this.delegates.forEach((d) => d.destroy());
|
|
59
|
+
this.delegates = [];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.OutboundLinkTracker = OutboundLinkTracker;
|
|
63
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQtbGluay10cmFja2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3BsdWdpbnMvb3V0Ym91bmQtbGluay10cmFja2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLGtEQUErRDtBQUMvRCxvREFBZ0Q7QUFFaEQsU0FBUyxrQkFBa0IsQ0FBQyxJQUFhLEVBQUUsVUFBaUY7SUFDeEgsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQzFFLElBQUksQ0FBQyxJQUFJO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDeEIsTUFBTSxHQUFHLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdCLE9BQU8sR0FBRyxDQUFDLFFBQVEsS0FBSyxRQUFRLENBQUMsUUFBUSxJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ2pGLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQWEsbUJBQW1CO0lBQ3BCLFNBQVMsR0FBcUIsRUFBRSxDQUFDO0lBQ2pDLElBQUksQ0FBZTtJQUNuQixNQUFNLENBQVc7SUFDakIsWUFBWSxDQUFTO0lBQ3JCLFNBQVMsQ0FBUztJQUNsQix1QkFBdUIsQ0FBcUU7SUFDNUYsU0FBUyxDQUEyQztJQUU1RCxZQUFZLElBQWtCLEVBQUUsT0FBb0M7UUFDaEUsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLEVBQUUsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDM0MsSUFBSSxDQUFDLFlBQVksR0FBRyxPQUFPLEVBQUUsWUFBWSxJQUFJLFNBQVMsQ0FBQztRQUN2RCxJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sRUFBRSxTQUFTLElBQUkscUJBQXFCLENBQUM7UUFDN0QsSUFBSSxDQUFDLHVCQUF1QixHQUFHLE9BQU8sRUFBRSx1QkFBdUIsSUFBSSxrQkFBa0IsQ0FBQztRQUN0RixJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sRUFBRSxTQUFTLENBQUM7UUFFcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxTQUFTLEVBQUUsRUFBRTtZQUM5QixNQUFNLE1BQU0sR0FBRyxJQUFBLG1CQUFRLEVBQ25CLFFBQVEsRUFDUixTQUFTLEVBQ1QsSUFBSSxDQUFDLFlBQVksRUFDakIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMscUJBQXFCLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxFQUM5RCxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUN2QyxDQUFDO1lBQ0YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDaEMsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU8scUJBQXFCLENBQUMsS0FBWSxFQUFFLE9BQWdCO1FBQ3hELElBQUksQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsT0FBTyxFQUFFLG9CQUFRLENBQUM7WUFBRSxPQUFPO1FBRTdELE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdEYsTUFBTSxHQUFHLEdBQUcsSUFBQSxvQkFBUSxFQUFDLElBQUksQ0FBQyxDQUFDO1FBRTNCLElBQUksTUFBTSxHQUE0QjtZQUNsQyxRQUFRLEVBQUUsR0FBRyxDQUFDLElBQUk7WUFDbEIsV0FBVyxFQUFFLEdBQUcsQ0FBQyxRQUFRO1lBQ3pCLFFBQVEsRUFBRSxJQUFJO1NBQ2pCLENBQUM7UUFFRixJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDaEIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3hELElBQUksUUFBUSxLQUFLLElBQUk7Z0JBQUUsT0FBTztZQUM5QixNQUFNLEdBQUcsUUFBUSxDQUFDO1NBQ3JCO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFRCxNQUFNO1FBQ0YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO0lBQ3hCLENBQUM7Q0FDSjtBQXRERCxrREFzREMifQ==
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { GA4Plugin, SendFunction, PageVisibilityTrackerOptions } from '../types/plugins';
|
|
2
|
+
/**
|
|
3
|
+
* Tracks how long a page is in the visible state vs. hidden (background tab).
|
|
4
|
+
*
|
|
5
|
+
* Sends a `page_visibility` event each time the visibility state changes,
|
|
6
|
+
* reporting how long the page was in the previous state.
|
|
7
|
+
* Optionally sends a new `page_view` when the page becomes visible
|
|
8
|
+
* again after the session timeout has elapsed.
|
|
9
|
+
*/
|
|
10
|
+
export declare class PageVisibilityTracker implements GA4Plugin {
|
|
11
|
+
private send;
|
|
12
|
+
private sendInitialPageview;
|
|
13
|
+
private sessionTimeout;
|
|
14
|
+
private eventName;
|
|
15
|
+
private hitFilter?;
|
|
16
|
+
private lastChangeTime;
|
|
17
|
+
private isVisible;
|
|
18
|
+
private boundVisibilityChange;
|
|
19
|
+
private boundBeforeUnload;
|
|
20
|
+
constructor(send: SendFunction, options?: PageVisibilityTrackerOptions);
|
|
21
|
+
private onVisibilityChange;
|
|
22
|
+
private onBeforeUnload;
|
|
23
|
+
remove(): void;
|
|
24
|
+
}
|