@technoapple/ga4 1.0.4 → 1.1.1
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,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.delegate = void 0;
|
|
4
|
+
function delegate(target, eventType, selector, handler, options) {
|
|
5
|
+
const useCapture = options?.useCapture ?? false;
|
|
6
|
+
const listener = (event) => {
|
|
7
|
+
let element = event.target;
|
|
8
|
+
// Handle composed events (shadow DOM)
|
|
9
|
+
if (options?.composed && typeof event.composedPath === 'function') {
|
|
10
|
+
const path = event.composedPath();
|
|
11
|
+
for (const node of path) {
|
|
12
|
+
if (node === target)
|
|
13
|
+
break;
|
|
14
|
+
if (node instanceof Element && node.matches(selector)) {
|
|
15
|
+
handler(event, node);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
while (element && element !== target) {
|
|
22
|
+
if (element.matches(selector)) {
|
|
23
|
+
handler(event, element);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
element = element.parentElement;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
target.addEventListener(eventType, listener, useCapture);
|
|
30
|
+
return {
|
|
31
|
+
destroy() {
|
|
32
|
+
target.removeEventListener(eventType, listener, useCapture);
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
exports.delegate = delegate;
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVsZWdhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaGVscGVycy9kZWxlZ2F0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFTQSxTQUFnQixRQUFRLENBQ3BCLE1BQW1CLEVBQ25CLFNBQWlCLEVBQ2pCLFFBQWdCLEVBQ2hCLE9BQWlELEVBQ2pELE9BQXlCO0lBRXpCLE1BQU0sVUFBVSxHQUFHLE9BQU8sRUFBRSxVQUFVLElBQUksS0FBSyxDQUFDO0lBRWhELE1BQU0sUUFBUSxHQUFHLENBQUMsS0FBWSxFQUFFLEVBQUU7UUFDOUIsSUFBSSxPQUFPLEdBQW1CLEtBQUssQ0FBQyxNQUF3QixDQUFDO1FBRTdELHNDQUFzQztRQUN0QyxJQUFJLE9BQU8sRUFBRSxRQUFRLElBQUksT0FBTyxLQUFLLENBQUMsWUFBWSxLQUFLLFVBQVUsRUFBRTtZQUMvRCxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDbEMsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLEVBQUU7Z0JBQ3JCLElBQUksSUFBSSxLQUFLLE1BQU07b0JBQUUsTUFBTTtnQkFDM0IsSUFBSSxJQUFJLFlBQVksT0FBTyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUU7b0JBQ25ELE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7b0JBQ3JCLE9BQU87aUJBQ1Y7YUFDSjtZQUNELE9BQU87U0FDVjtRQUVELE9BQU8sT0FBTyxJQUFJLE9BQU8sS0FBSyxNQUFNLEVBQUU7WUFDbEMsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFO2dCQUMzQixPQUFPLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUN4QixPQUFPO2FBQ1Y7WUFDRCxPQUFPLEdBQUcsT0FBTyxDQUFDLGFBQWEsQ0FBQztTQUNuQztJQUNMLENBQUMsQ0FBQztJQUVGLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBRXpELE9BQU87UUFDSCxPQUFPO1lBQ0gsTUFBTSxDQUFDLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDaEUsQ0FBQztLQUNKLENBQUM7QUFDTixDQUFDO0FBekNELDRCQXlDQyJ9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function domReady(callback: () => void): void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.domReady = void 0;
|
|
4
|
+
function domReady(callback) {
|
|
5
|
+
if (document.readyState === 'loading') {
|
|
6
|
+
document.addEventListener('DOMContentLoaded', callback, { once: true });
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
callback();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.domReady = domReady;
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9tLXJlYWR5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2hlbHBlcnMvZG9tLXJlYWR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLFNBQWdCLFFBQVEsQ0FBQyxRQUFvQjtJQUN6QyxJQUFJLFFBQVEsQ0FBQyxVQUFVLEtBQUssU0FBUyxFQUFFO1FBQ25DLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRSxRQUFRLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztLQUMzRTtTQUFNO1FBQ0gsUUFBUSxFQUFFLENBQUM7S0FDZDtBQUNMLENBQUM7QUFORCw0QkFNQyJ9
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseUrl = void 0;
|
|
4
|
+
function parseUrl(url) {
|
|
5
|
+
try {
|
|
6
|
+
const parsed = new URL(url, location.href);
|
|
7
|
+
return {
|
|
8
|
+
href: parsed.href,
|
|
9
|
+
protocol: parsed.protocol,
|
|
10
|
+
hostname: parsed.hostname,
|
|
11
|
+
port: parsed.port,
|
|
12
|
+
pathname: parsed.pathname,
|
|
13
|
+
search: parsed.search,
|
|
14
|
+
hash: parsed.hash,
|
|
15
|
+
origin: parsed.origin,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return {
|
|
20
|
+
href: url,
|
|
21
|
+
protocol: '',
|
|
22
|
+
hostname: '',
|
|
23
|
+
port: '',
|
|
24
|
+
pathname: url,
|
|
25
|
+
search: '',
|
|
26
|
+
hash: '',
|
|
27
|
+
origin: '',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.parseUrl = parseUrl;
|
|
32
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2UtdXJsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2hlbHBlcnMvcGFyc2UtdXJsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQVdBLFNBQWdCLFFBQVEsQ0FBQyxHQUFXO0lBQ2hDLElBQUk7UUFDQSxNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzNDLE9BQU87WUFDSCxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7WUFDakIsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRO1lBQ3pCLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUTtZQUN6QixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7WUFDakIsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRO1lBQ3pCLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTTtZQUNyQixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7WUFDakIsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNO1NBQ3hCLENBQUM7S0FDTDtJQUFDLE1BQU07UUFDSixPQUFPO1lBQ0gsSUFBSSxFQUFFLEdBQUc7WUFDVCxRQUFRLEVBQUUsRUFBRTtZQUNaLFFBQVEsRUFBRSxFQUFFO1lBQ1osSUFBSSxFQUFFLEVBQUU7WUFDUixRQUFRLEVBQUUsR0FBRztZQUNiLE1BQU0sRUFBRSxFQUFFO1lBQ1YsSUFBSSxFQUFFLEVBQUU7WUFDUixNQUFNLEVBQUUsRUFBRTtTQUNiLENBQUM7S0FDTDtBQUNMLENBQUM7QUF6QkQsNEJBeUJDIn0=
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function isSessionExpired(key: string, timeoutMinutes: number): boolean;
|
|
2
|
+
export declare function updateSessionTimestamp(key: string): void;
|
|
3
|
+
export declare function getSessionValue<T>(key: string): T | null;
|
|
4
|
+
export declare function setSessionValue(key: string, value: unknown): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setSessionValue = exports.getSessionValue = exports.updateSessionTimestamp = exports.isSessionExpired = void 0;
|
|
4
|
+
const SESSION_KEY_PREFIX = 'ga4_session_';
|
|
5
|
+
function isSessionExpired(key, timeoutMinutes) {
|
|
6
|
+
try {
|
|
7
|
+
const stored = sessionStorage.getItem(SESSION_KEY_PREFIX + key);
|
|
8
|
+
if (!stored)
|
|
9
|
+
return true;
|
|
10
|
+
const timestamp = parseInt(stored, 10);
|
|
11
|
+
if (isNaN(timestamp))
|
|
12
|
+
return true;
|
|
13
|
+
return (Date.now() - timestamp) > timeoutMinutes * 60 * 1000;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.isSessionExpired = isSessionExpired;
|
|
20
|
+
function updateSessionTimestamp(key) {
|
|
21
|
+
try {
|
|
22
|
+
sessionStorage.setItem(SESSION_KEY_PREFIX + key, String(Date.now()));
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// sessionStorage may be unavailable or full
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.updateSessionTimestamp = updateSessionTimestamp;
|
|
29
|
+
function getSessionValue(key) {
|
|
30
|
+
try {
|
|
31
|
+
const stored = sessionStorage.getItem(SESSION_KEY_PREFIX + key);
|
|
32
|
+
if (stored === null)
|
|
33
|
+
return null;
|
|
34
|
+
return JSON.parse(stored);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.getSessionValue = getSessionValue;
|
|
41
|
+
function setSessionValue(key, value) {
|
|
42
|
+
try {
|
|
43
|
+
sessionStorage.setItem(SESSION_KEY_PREFIX + key, JSON.stringify(value));
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// sessionStorage may be unavailable or full
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.setSessionValue = setSessionValue;
|
|
50
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Vzc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9oZWxwZXJzL3Nlc3Npb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsTUFBTSxrQkFBa0IsR0FBRyxjQUFjLENBQUM7QUFFMUMsU0FBZ0IsZ0JBQWdCLENBQUMsR0FBVyxFQUFFLGNBQXNCO0lBQ2hFLElBQUk7UUFDQSxNQUFNLE1BQU0sR0FBRyxjQUFjLENBQUMsT0FBTyxDQUFDLGtCQUFrQixHQUFHLEdBQUcsQ0FBQyxDQUFDO1FBQ2hFLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFDekIsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN2QyxJQUFJLEtBQUssQ0FBQyxTQUFTLENBQUM7WUFBRSxPQUFPLElBQUksQ0FBQztRQUNsQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLFNBQVMsQ0FBQyxHQUFHLGNBQWMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0tBQ2hFO0lBQUMsTUFBTTtRQUNKLE9BQU8sSUFBSSxDQUFDO0tBQ2Y7QUFDTCxDQUFDO0FBVkQsNENBVUM7QUFFRCxTQUFnQixzQkFBc0IsQ0FBQyxHQUFXO0lBQzlDLElBQUk7UUFDQSxjQUFjLENBQUMsT0FBTyxDQUFDLGtCQUFrQixHQUFHLEdBQUcsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztLQUN4RTtJQUFDLE1BQU07UUFDSiw0Q0FBNEM7S0FDL0M7QUFDTCxDQUFDO0FBTkQsd0RBTUM7QUFFRCxTQUFnQixlQUFlLENBQUksR0FBVztJQUMxQyxJQUFJO1FBQ0EsTUFBTSxNQUFNLEdBQUcsY0FBYyxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsR0FBRyxHQUFHLENBQUMsQ0FBQztRQUNoRSxJQUFJLE1BQU0sS0FBSyxJQUFJO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFDakMsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBTSxDQUFDO0tBQ2xDO0lBQUMsTUFBTTtRQUNKLE9BQU8sSUFBSSxDQUFDO0tBQ2Y7QUFDTCxDQUFDO0FBUkQsMENBUUM7QUFFRCxTQUFnQixlQUFlLENBQUMsR0FBVyxFQUFFLEtBQWM7SUFDdkQsSUFBSTtRQUNBLGNBQWMsQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEdBQUcsR0FBRyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztLQUMzRTtJQUFDLE1BQU07UUFDSiw0Q0FBNEM7S0FDL0M7QUFDTCxDQUFDO0FBTkQsMENBTUMifQ==
|
package/build/main/index.d.ts
CHANGED
|
@@ -4,3 +4,12 @@ declare const dataLayerHelper: {
|
|
|
4
4
|
};
|
|
5
5
|
declare const ga4: import("./ga4/ga4").ga4;
|
|
6
6
|
export { ga4, dataLayerHelper };
|
|
7
|
+
export { EventTracker } from './plugins/event-tracker';
|
|
8
|
+
export { OutboundLinkTracker } from './plugins/outbound-link-tracker';
|
|
9
|
+
export { OutboundFormTracker } from './plugins/outbound-form-tracker';
|
|
10
|
+
export { PageVisibilityTracker } from './plugins/page-visibility-tracker';
|
|
11
|
+
export { UrlChangeTracker } from './plugins/url-change-tracker';
|
|
12
|
+
export { ImpressionTracker } from './plugins/impression-tracker';
|
|
13
|
+
export { CleanUrlTracker } from './plugins/clean-url-tracker';
|
|
14
|
+
export { MediaQueryTracker } from './plugins/media-query-tracker';
|
|
15
|
+
export type { GA4Plugin, SendFunction, EventTrackerOptions, OutboundLinkTrackerOptions, OutboundFormTrackerOptions, PageVisibilityTrackerOptions, UrlChangeTrackerOptions, ImpressionTrackerOptions, ImpressionElementConfig, CleanUrlTrackerOptions, MediaQueryTrackerOptions, MediaQueryDefinition, MediaQueryDefinitionItem, } from './types/plugins';
|
package/build/main/index.js
CHANGED
|
@@ -1,10 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.dataLayerHelper = exports.ga4 = void 0;
|
|
3
|
+
exports.MediaQueryTracker = exports.CleanUrlTracker = exports.ImpressionTracker = exports.UrlChangeTracker = exports.PageVisibilityTracker = exports.OutboundFormTracker = exports.OutboundLinkTracker = exports.EventTracker = exports.dataLayerHelper = exports.ga4 = void 0;
|
|
4
4
|
const index_1 = require("./ga4/index");
|
|
5
5
|
const dataLayer_1 = require("./dataLayer");
|
|
6
6
|
const dataLayerHelper = { get: dataLayer_1.get };
|
|
7
7
|
exports.dataLayerHelper = dataLayerHelper;
|
|
8
8
|
const ga4 = index_1.ga;
|
|
9
9
|
exports.ga4 = ga4;
|
|
10
|
-
|
|
10
|
+
// Plugin exports
|
|
11
|
+
var event_tracker_1 = require("./plugins/event-tracker");
|
|
12
|
+
Object.defineProperty(exports, "EventTracker", { enumerable: true, get: function () { return event_tracker_1.EventTracker; } });
|
|
13
|
+
var outbound_link_tracker_1 = require("./plugins/outbound-link-tracker");
|
|
14
|
+
Object.defineProperty(exports, "OutboundLinkTracker", { enumerable: true, get: function () { return outbound_link_tracker_1.OutboundLinkTracker; } });
|
|
15
|
+
var outbound_form_tracker_1 = require("./plugins/outbound-form-tracker");
|
|
16
|
+
Object.defineProperty(exports, "OutboundFormTracker", { enumerable: true, get: function () { return outbound_form_tracker_1.OutboundFormTracker; } });
|
|
17
|
+
var page_visibility_tracker_1 = require("./plugins/page-visibility-tracker");
|
|
18
|
+
Object.defineProperty(exports, "PageVisibilityTracker", { enumerable: true, get: function () { return page_visibility_tracker_1.PageVisibilityTracker; } });
|
|
19
|
+
var url_change_tracker_1 = require("./plugins/url-change-tracker");
|
|
20
|
+
Object.defineProperty(exports, "UrlChangeTracker", { enumerable: true, get: function () { return url_change_tracker_1.UrlChangeTracker; } });
|
|
21
|
+
var impression_tracker_1 = require("./plugins/impression-tracker");
|
|
22
|
+
Object.defineProperty(exports, "ImpressionTracker", { enumerable: true, get: function () { return impression_tracker_1.ImpressionTracker; } });
|
|
23
|
+
var clean_url_tracker_1 = require("./plugins/clean-url-tracker");
|
|
24
|
+
Object.defineProperty(exports, "CleanUrlTracker", { enumerable: true, get: function () { return clean_url_tracker_1.CleanUrlTracker; } });
|
|
25
|
+
var media_query_tracker_1 = require("./plugins/media-query-tracker");
|
|
26
|
+
Object.defineProperty(exports, "MediaQueryTracker", { enumerable: true, get: function () { return media_query_tracker_1.MediaQueryTracker; } });
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsdUNBQStCO0FBQy9CLDJDQUFnQztBQUVoQyxNQUFNLGVBQWUsR0FBRyxFQUFFLEdBQUcsRUFBSCxlQUFHLEVBQUUsQ0FBQztBQUduQiwwQ0FBZTtBQUY1QixNQUFNLEdBQUcsR0FBRyxVQUFFLENBQUM7QUFFUCxrQkFBRztBQUVYLGlCQUFpQjtBQUNqQix5REFBdUQ7QUFBOUMsNkdBQUEsWUFBWSxPQUFBO0FBQ3JCLHlFQUFzRTtBQUE3RCw0SEFBQSxtQkFBbUIsT0FBQTtBQUM1Qix5RUFBc0U7QUFBN0QsNEhBQUEsbUJBQW1CLE9BQUE7QUFDNUIsNkVBQTBFO0FBQWpFLGdJQUFBLHFCQUFxQixPQUFBO0FBQzlCLG1FQUFnRTtBQUF2RCxzSEFBQSxnQkFBZ0IsT0FBQTtBQUN6QixtRUFBaUU7QUFBeEQsdUhBQUEsaUJBQWlCLE9BQUE7QUFDMUIsaUVBQThEO0FBQXJELG9IQUFBLGVBQWUsT0FBQTtBQUN4QixxRUFBa0U7QUFBekQsd0hBQUEsaUJBQWlCLE9BQUEifQ==
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { GA4Plugin, SendFunction, CleanUrlTrackerOptions } from '../types/plugins';
|
|
2
|
+
/**
|
|
3
|
+
* Normalizes URLs before they are sent with `page_view` events.
|
|
4
|
+
*
|
|
5
|
+
* Intercepts `gtag()` calls for `config` and `page_view` events
|
|
6
|
+
* and cleans the `page_location` and `page_path` parameters
|
|
7
|
+
* (strip query params, normalize trailing slashes, apply custom filters).
|
|
8
|
+
*/
|
|
9
|
+
export declare class CleanUrlTracker implements GA4Plugin {
|
|
10
|
+
private opts;
|
|
11
|
+
private originalGtag;
|
|
12
|
+
constructor(_send: SendFunction, options?: CleanUrlTrackerOptions);
|
|
13
|
+
private cleanParams;
|
|
14
|
+
cleanUrl(url: string): string;
|
|
15
|
+
cleanPath(path: string): string;
|
|
16
|
+
remove(): void;
|
|
17
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CleanUrlTracker = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Normalizes URLs before they are sent with `page_view` events.
|
|
6
|
+
*
|
|
7
|
+
* Intercepts `gtag()` calls for `config` and `page_view` events
|
|
8
|
+
* and cleans the `page_location` and `page_path` parameters
|
|
9
|
+
* (strip query params, normalize trailing slashes, apply custom filters).
|
|
10
|
+
*/
|
|
11
|
+
class CleanUrlTracker {
|
|
12
|
+
opts;
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
14
|
+
originalGtag = null;
|
|
15
|
+
constructor(_send, options) {
|
|
16
|
+
this.opts = {
|
|
17
|
+
stripQuery: options?.stripQuery ?? false,
|
|
18
|
+
queryParamsAllowlist: options?.queryParamsAllowlist,
|
|
19
|
+
queryParamsDenylist: options?.queryParamsDenylist,
|
|
20
|
+
trailingSlash: options?.trailingSlash,
|
|
21
|
+
urlFilter: options?.urlFilter,
|
|
22
|
+
};
|
|
23
|
+
if (typeof window !== 'undefined' && window.gtag) {
|
|
24
|
+
this.originalGtag = window.gtag;
|
|
25
|
+
const self = this;
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
window.gtag = function () {
|
|
28
|
+
// eslint-disable-next-line prefer-rest-params
|
|
29
|
+
const args = Array.prototype.slice.call(arguments);
|
|
30
|
+
if (args.length >= 3 && typeof args[2] === 'object' && args[2] !== null) {
|
|
31
|
+
const isPageView = args[0] === 'event' && args[1] === 'page_view';
|
|
32
|
+
const isConfig = args[0] === 'config';
|
|
33
|
+
if (isPageView || isConfig) {
|
|
34
|
+
args[2] = self.cleanParams({ ...args[2] });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return self.originalGtag.apply(window, args);
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
cleanParams(params) {
|
|
42
|
+
if (typeof params.page_location === 'string') {
|
|
43
|
+
params.page_location = this.cleanUrl(params.page_location);
|
|
44
|
+
}
|
|
45
|
+
if (typeof params.page_path === 'string') {
|
|
46
|
+
params.page_path = this.cleanPath(params.page_path);
|
|
47
|
+
}
|
|
48
|
+
return params;
|
|
49
|
+
}
|
|
50
|
+
cleanUrl(url) {
|
|
51
|
+
try {
|
|
52
|
+
const u = new URL(url);
|
|
53
|
+
u.pathname = this.cleanPath(u.pathname);
|
|
54
|
+
if (this.opts.stripQuery) {
|
|
55
|
+
if (this.opts.queryParamsAllowlist && this.opts.queryParamsAllowlist.length > 0) {
|
|
56
|
+
const allowed = new URLSearchParams();
|
|
57
|
+
this.opts.queryParamsAllowlist.forEach((param) => {
|
|
58
|
+
if (u.searchParams.has(param)) {
|
|
59
|
+
allowed.set(param, u.searchParams.get(param));
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
u.search = allowed.toString() ? '?' + allowed.toString() : '';
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
u.search = '';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else if (this.opts.queryParamsDenylist && this.opts.queryParamsDenylist.length > 0) {
|
|
69
|
+
this.opts.queryParamsDenylist.forEach((param) => {
|
|
70
|
+
u.searchParams.delete(param);
|
|
71
|
+
});
|
|
72
|
+
u.search = u.searchParams.toString() ? '?' + u.searchParams.toString() : '';
|
|
73
|
+
}
|
|
74
|
+
let result = u.toString();
|
|
75
|
+
if (this.opts.urlFilter) {
|
|
76
|
+
result = this.opts.urlFilter(result);
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return url;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
cleanPath(path) {
|
|
85
|
+
let result = path;
|
|
86
|
+
if (this.opts.trailingSlash === 'remove') {
|
|
87
|
+
result = result.length > 1 ? result.replace(/\/+$/, '') : result;
|
|
88
|
+
}
|
|
89
|
+
else if (this.opts.trailingSlash === 'add') {
|
|
90
|
+
if (!result.endsWith('/') && !result.split('/').pop()?.includes('.')) {
|
|
91
|
+
result += '/';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
remove() {
|
|
97
|
+
if (this.originalGtag) {
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
99
|
+
window.gtag = this.originalGtag;
|
|
100
|
+
this.originalGtag = null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.CleanUrlTracker = CleanUrlTracker;
|
|
105
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xlYW4tdXJsLXRyYWNrZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcGx1Z2lucy9jbGVhbi11cmwtdHJhY2tlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQTs7Ozs7O0dBTUc7QUFDSCxNQUFhLGVBQWU7SUFDaEIsSUFBSSxDQUF5QjtJQUNyQyxzRUFBc0U7SUFDOUQsWUFBWSxHQUFvQixJQUFJLENBQUM7SUFFN0MsWUFBWSxLQUFtQixFQUFFLE9BQWdDO1FBQzdELElBQUksQ0FBQyxJQUFJLEdBQUc7WUFDUixVQUFVLEVBQUUsT0FBTyxFQUFFLFVBQVUsSUFBSSxLQUFLO1lBQ3hDLG9CQUFvQixFQUFFLE9BQU8sRUFBRSxvQkFBb0I7WUFDbkQsbUJBQW1CLEVBQUUsT0FBTyxFQUFFLG1CQUFtQjtZQUNqRCxhQUFhLEVBQUUsT0FBTyxFQUFFLGFBQWE7WUFDckMsU0FBUyxFQUFFLE9BQU8sRUFBRSxTQUFTO1NBQ2hDLENBQUM7UUFFRixJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVcsSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFFO1lBQzlDLElBQUksQ0FBQyxZQUFZLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQztZQUNoQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7WUFFbEIsOERBQThEO1lBQzdELE1BQWMsQ0FBQyxJQUFJLEdBQUc7Z0JBQ25CLDhDQUE4QztnQkFDOUMsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUVuRCxJQUFJLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLFFBQVEsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUFFO29CQUNyRSxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssT0FBTyxJQUFJ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
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { GA4Plugin, SendFunction, EventTrackerOptions } from '../types/plugins';
|
|
2
|
+
/**
|
|
3
|
+
* Declarative event tracking via HTML `data-ga4-*` attributes.
|
|
4
|
+
*
|
|
5
|
+
* Listens for DOM events on elements with `data-ga4-on` attributes
|
|
6
|
+
* and sends GA4 events based on attribute values.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```html
|
|
10
|
+
* <button
|
|
11
|
+
* data-ga4-on="click"
|
|
12
|
+
* data-ga4-event-name="video_play"
|
|
13
|
+
* data-ga4-video-title="My Video">
|
|
14
|
+
* Play
|
|
15
|
+
* </button>
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare class EventTracker implements GA4Plugin {
|
|
19
|
+
private delegates;
|
|
20
|
+
private send;
|
|
21
|
+
private events;
|
|
22
|
+
private attributePrefix;
|
|
23
|
+
private hitFilter?;
|
|
24
|
+
constructor(send: SendFunction, options?: EventTrackerOptions);
|
|
25
|
+
private handleEvent;
|
|
26
|
+
remove(): void;
|
|
27
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventTracker = void 0;
|
|
4
|
+
const delegate_1 = require("../helpers/delegate");
|
|
5
|
+
function kebabToSnake(str) {
|
|
6
|
+
return str.replace(/-/g, '_');
|
|
7
|
+
}
|
|
8
|
+
function getAttributeParams(element, prefix) {
|
|
9
|
+
const params = {};
|
|
10
|
+
const reservedSuffixes = ['on', 'event-name'];
|
|
11
|
+
for (let i = 0; i < element.attributes.length; i++) {
|
|
12
|
+
const attr = element.attributes[i];
|
|
13
|
+
if (!attr.name.startsWith(prefix))
|
|
14
|
+
continue;
|
|
15
|
+
const suffix = attr.name.slice(prefix.length);
|
|
16
|
+
if (reservedSuffixes.includes(suffix))
|
|
17
|
+
continue;
|
|
18
|
+
params[kebabToSnake(suffix)] = attr.value;
|
|
19
|
+
}
|
|
20
|
+
return params;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Declarative event tracking via HTML `data-ga4-*` attributes.
|
|
24
|
+
*
|
|
25
|
+
* Listens for DOM events on elements with `data-ga4-on` attributes
|
|
26
|
+
* and sends GA4 events based on attribute values.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```html
|
|
30
|
+
* <button
|
|
31
|
+
* data-ga4-on="click"
|
|
32
|
+
* data-ga4-event-name="video_play"
|
|
33
|
+
* data-ga4-video-title="My Video">
|
|
34
|
+
* Play
|
|
35
|
+
* </button>
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
class EventTracker {
|
|
39
|
+
delegates = [];
|
|
40
|
+
send;
|
|
41
|
+
events;
|
|
42
|
+
attributePrefix;
|
|
43
|
+
hitFilter;
|
|
44
|
+
constructor(send, options) {
|
|
45
|
+
this.send = send;
|
|
46
|
+
this.events = options?.events ?? ['click'];
|
|
47
|
+
this.attributePrefix = options?.attributePrefix ?? 'data-ga4-';
|
|
48
|
+
this.hitFilter = options?.hitFilter;
|
|
49
|
+
const selector = `[${this.attributePrefix}on]`;
|
|
50
|
+
this.events.forEach((eventType) => {
|
|
51
|
+
const handle = (0, delegate_1.delegate)(document, eventType, selector, (event, element) => this.handleEvent(event, element), { composed: true, useCapture: true });
|
|
52
|
+
this.delegates.push(handle);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
handleEvent(event, element) {
|
|
56
|
+
const prefix = this.attributePrefix;
|
|
57
|
+
const onAttr = element.getAttribute(`${prefix}on`);
|
|
58
|
+
if (onAttr !== event.type)
|
|
59
|
+
return;
|
|
60
|
+
const eventName = element.getAttribute(`${prefix}event-name`) || event.type;
|
|
61
|
+
let params = getAttributeParams(element, prefix);
|
|
62
|
+
if (this.hitFilter) {
|
|
63
|
+
const filtered = this.hitFilter(params, element, event);
|
|
64
|
+
if (filtered === null)
|
|
65
|
+
return;
|
|
66
|
+
params = filtered;
|
|
67
|
+
}
|
|
68
|
+
this.send(eventName, params);
|
|
69
|
+
}
|
|
70
|
+
remove() {
|
|
71
|
+
this.delegates.forEach((d) => d.destroy());
|
|
72
|
+
this.delegates = [];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.EventTracker = EventTracker;
|
|
76
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnQtdHJhY2tlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wbHVnaW5zL2V2ZW50LXRyYWNrZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0Esa0RBQStEO0FBRS9ELFNBQVMsWUFBWSxDQUFDLEdBQVc7SUFDN0IsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztBQUNsQyxDQUFDO0FBRUQsU0FBUyxrQkFBa0IsQ0FBQyxPQUFnQixFQUFFLE1BQWM7SUFDeEQsTUFBTSxNQUFNLEdBQTRCLEVBQUUsQ0FBQztJQUMzQyxNQUFNLGdCQUFnQixHQUFHLENBQUMsSUFBSSxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBRTlDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUNoRCxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25DLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7WUFBRSxTQUFTO1FBRTVDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM5QyxJQUFJLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUM7WUFBRSxTQUFTO1FBRWhELE1BQU0sQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO0tBQzdDO0lBRUQsT0FBTyxNQUFNLENBQUM7QUFDbEIsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUNILE1BQWEsWUFBWTtJQUNiLFNBQVMsR0FBcUIsRUFBRSxDQUFDO0lBQ2pDLElBQUksQ0FBZTtJQUNuQixNQUFNLENBQVc7SUFDakIsZUFBZSxDQUFTO0lBQ3hCLFNBQVMsQ0FBb0M7SUFFckQsWUFBWSxJQUFrQixFQUFFLE9BQTZCO1FBQ3pELElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxFQUFFLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxlQUFlLEdBQUcsT0FBTyxFQUFFLGVBQWUsSUFBSSxXQUFXLENBQUM7UUFDL0QsSUFBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLEVBQUUsU0FBUyxDQUFDO1FBRXBDLE1BQU0sUUFBUSxHQUFHLElBQUksSUFBSSxDQUFDLGVBQWUsS0FBSyxDQUFDO1FBRS9DLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUU7WUFDOUIsTUFBTSxNQUFNLEdBQUcsSUFBQSxtQkFBUSxFQUNuQixRQUFRLEVBQ1IsU0FBUyxFQUNULFFBQVEsRUFDUixDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxFQUNwRCxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUN2QyxDQUFDO1lBQ0YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDaEMsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU8sV0FBVyxDQUFDLEtBQVksRUFBRSxPQUFnQjtRQUM5QyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDO1FBQ3BDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxDQUFDO1FBRW5ELElBQUksTUFBTSxLQUFLLEtBQUssQ0FBQyxJQUFJO1lBQUUsT0FBTztRQUVsQyxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLEdBQUcsTUFBTSxZQUFZLENBQUMsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDO1FBQzVFLElBQUksTUFBTSxHQUFHLGtCQUFrQixDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztRQUVqRCxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDaEIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3hELElBQUksUUFBUSxLQUFLLElBQUk7Z0JBQUUsT0FBTztZQUM5QixNQUFNLEdBQUcsUUFBUSxDQUFDO1NBQ3JCO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDakMsQ0FBQztJQUVELE1BQU07UUFDRixJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDM0MsSUFBSSxDQUFDLFNBQVMsR0FBRyxFQUFFLENBQUM7SUFDeEIsQ0FBQztDQUNKO0FBakRELG9DQWlEQyJ9
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { GA4Plugin, SendFunction, ImpressionTrackerOptions, ImpressionElementConfig } from '../types/plugins';
|
|
2
|
+
/**
|
|
3
|
+
* Tracks when specific DOM elements become visible in the viewport
|
|
4
|
+
* using `IntersectionObserver`.
|
|
5
|
+
*
|
|
6
|
+
* Useful for tracking ad impressions, CTA visibility, or any
|
|
7
|
+
* element that enters the user's viewport.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ImpressionTracker implements GA4Plugin {
|
|
10
|
+
private send;
|
|
11
|
+
private rootMargin;
|
|
12
|
+
private attributePrefix;
|
|
13
|
+
private eventName;
|
|
14
|
+
private hitFilter?;
|
|
15
|
+
private items;
|
|
16
|
+
private elementMap;
|
|
17
|
+
private thresholdMap;
|
|
18
|
+
private mutationObserver;
|
|
19
|
+
private impressedIds;
|
|
20
|
+
private supported;
|
|
21
|
+
constructor(send: SendFunction, options?: ImpressionTrackerOptions);
|
|
22
|
+
observeElements(elements: Array<string | ImpressionElementConfig>): void;
|
|
23
|
+
unobserveElements(elements: Array<string | ImpressionElementConfig>): void;
|
|
24
|
+
unobserveAllElements(): void;
|
|
25
|
+
private normalizeElements;
|
|
26
|
+
private getObserverForThreshold;
|
|
27
|
+
private handleIntersectionChanges;
|
|
28
|
+
private handleDomMutations;
|
|
29
|
+
private walkNodeTree;
|
|
30
|
+
private disconnectAll;
|
|
31
|
+
remove(): void;
|
|
32
|
+
}
|