@croct/sdk 0.21.1 → 0.22.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/constants.cjs +1 -1
- package/constants.d.cts +2 -2
- package/constants.d.ts +2 -2
- package/constants.js +1 -1
- package/container.cjs +8 -1
- package/container.d.cts +2 -0
- package/container.d.ts +2 -0
- package/container.js +8 -1
- package/facade/evaluatorFacade.cjs +4 -4
- package/facade/evaluatorFacade.d.cts +2 -1
- package/facade/evaluatorFacade.d.ts +2 -1
- package/facade/evaluatorFacade.js +4 -4
- package/facade/sdkFacade.cjs +8 -2
- package/facade/sdkFacade.js +8 -2
- package/interactionMonitor.cjs +181 -0
- package/interactionMonitor.d.cts +64 -0
- package/interactionMonitor.d.ts +64 -0
- package/interactionMonitor.js +158 -0
- package/package.json +1 -1
- package/schema/eventSchemas.cjs +46 -0
- package/schema/eventSchemas.d.cts +3 -1
- package/schema/eventSchemas.d.ts +3 -1
- package/schema/eventSchemas.js +44 -0
- package/schema/index.d.cts +1 -1
- package/schema/index.d.ts +1 -1
- package/sdk.cjs +3 -0
- package/sdk.d.cts +1 -0
- package/sdk.d.ts +1 -0
- package/sdk.js +3 -0
- package/tracker.cjs +9 -1
- package/tracker.d.cts +3 -0
- package/tracker.d.ts +3 -0
- package/tracker.js +9 -1
- package/trackingEvents.cjs +7 -0
- package/trackingEvents.d.cts +27 -2
- package/trackingEvents.d.ts +27 -2
- package/trackingEvents.js +6 -0
package/constants.cjs
CHANGED
|
@@ -25,7 +25,7 @@ __export(constants_exports, {
|
|
|
25
25
|
module.exports = __toCommonJS(constants_exports);
|
|
26
26
|
const BASE_ENDPOINT_URL = "https://api.croct.io";
|
|
27
27
|
const MAX_QUERY_LENGTH = parseInt("<@maxQueryLength@>", 10);
|
|
28
|
-
const VERSION = "0.
|
|
28
|
+
const VERSION = "0.22.0";
|
|
29
29
|
const CLIENT_LIBRARY = `Croct SDK JS v${VERSION}`;
|
|
30
30
|
// Annotate the CommonJS export names for ESM import in node:
|
|
31
31
|
0 && (module.exports = {
|
package/constants.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
declare const BASE_ENDPOINT_URL = "https://api.croct.io";
|
|
2
2
|
declare const MAX_QUERY_LENGTH: number;
|
|
3
|
-
declare const VERSION = "0.
|
|
4
|
-
declare const CLIENT_LIBRARY = "Croct SDK JS v0.
|
|
3
|
+
declare const VERSION = "0.22.0";
|
|
4
|
+
declare const CLIENT_LIBRARY = "Croct SDK JS v0.22.0";
|
|
5
5
|
|
|
6
6
|
export { BASE_ENDPOINT_URL, CLIENT_LIBRARY, MAX_QUERY_LENGTH, VERSION };
|
package/constants.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
declare const BASE_ENDPOINT_URL = "https://api.croct.io";
|
|
2
2
|
declare const MAX_QUERY_LENGTH: number;
|
|
3
|
-
declare const VERSION = "0.
|
|
4
|
-
declare const CLIENT_LIBRARY = "Croct SDK JS v0.
|
|
3
|
+
declare const VERSION = "0.22.0";
|
|
4
|
+
declare const CLIENT_LIBRARY = "Croct SDK JS v0.22.0";
|
|
5
5
|
|
|
6
6
|
export { BASE_ENDPOINT_URL, CLIENT_LIBRARY, MAX_QUERY_LENGTH, VERSION };
|
package/constants.js
CHANGED
package/container.cjs
CHANGED
|
@@ -47,6 +47,12 @@ const _Container = class _Container {
|
|
|
47
47
|
getConfiguration() {
|
|
48
48
|
return this.configuration;
|
|
49
49
|
}
|
|
50
|
+
getTimeZone() {
|
|
51
|
+
if (this.timeZone === void 0) {
|
|
52
|
+
this.timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone ?? null;
|
|
53
|
+
}
|
|
54
|
+
return this.timeZone;
|
|
55
|
+
}
|
|
50
56
|
getEvaluator() {
|
|
51
57
|
if (this.evaluator === void 0) {
|
|
52
58
|
this.evaluator = this.createEvaluator();
|
|
@@ -98,7 +104,8 @@ const _Container = class _Container {
|
|
|
98
104
|
inactivityRetryPolicy: new import_retry.ArbitraryPolicy([3e4, 3e4, 12e4, 12e4, 3e5, 3e5, 9e5]),
|
|
99
105
|
logger: this.getLogger("Tracker"),
|
|
100
106
|
channel: this.getBeaconChannel(),
|
|
101
|
-
eventMetadata: this.configuration.eventMetadata
|
|
107
|
+
eventMetadata: this.configuration.eventMetadata,
|
|
108
|
+
timeZone: this.getTimeZone() ?? void 0
|
|
102
109
|
});
|
|
103
110
|
const queue = this.getBeaconQueue();
|
|
104
111
|
queue.addCallback("halfEmpty", tracker.unsuspend);
|
package/container.d.cts
CHANGED
|
@@ -61,8 +61,10 @@ declare class Container {
|
|
|
61
61
|
private beaconQueue?;
|
|
62
62
|
private removeTokenSyncListener?;
|
|
63
63
|
private readonly eventManager;
|
|
64
|
+
private timeZone?;
|
|
64
65
|
constructor(configuration: Configuration);
|
|
65
66
|
getConfiguration(): Configuration;
|
|
67
|
+
getTimeZone(): string | null;
|
|
66
68
|
getEvaluator(): Evaluator;
|
|
67
69
|
private createEvaluator;
|
|
68
70
|
getContentFetcher(): ContentFetcher;
|
package/container.d.ts
CHANGED
|
@@ -61,8 +61,10 @@ declare class Container {
|
|
|
61
61
|
private beaconQueue?;
|
|
62
62
|
private removeTokenSyncListener?;
|
|
63
63
|
private readonly eventManager;
|
|
64
|
+
private timeZone?;
|
|
64
65
|
constructor(configuration: Configuration);
|
|
65
66
|
getConfiguration(): Configuration;
|
|
67
|
+
getTimeZone(): string | null;
|
|
66
68
|
getEvaluator(): Evaluator;
|
|
67
69
|
private createEvaluator;
|
|
68
70
|
getContentFetcher(): ContentFetcher;
|
package/container.js
CHANGED
|
@@ -25,6 +25,12 @@ const _Container = class _Container {
|
|
|
25
25
|
getConfiguration() {
|
|
26
26
|
return this.configuration;
|
|
27
27
|
}
|
|
28
|
+
getTimeZone() {
|
|
29
|
+
if (this.timeZone === void 0) {
|
|
30
|
+
this.timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone ?? null;
|
|
31
|
+
}
|
|
32
|
+
return this.timeZone;
|
|
33
|
+
}
|
|
28
34
|
getEvaluator() {
|
|
29
35
|
if (this.evaluator === void 0) {
|
|
30
36
|
this.evaluator = this.createEvaluator();
|
|
@@ -76,7 +82,8 @@ const _Container = class _Container {
|
|
|
76
82
|
inactivityRetryPolicy: new ArbitraryPolicy([3e4, 3e4, 12e4, 12e4, 3e5, 3e5, 9e5]),
|
|
77
83
|
logger: this.getLogger("Tracker"),
|
|
78
84
|
channel: this.getBeaconChannel(),
|
|
79
|
-
eventMetadata: this.configuration.eventMetadata
|
|
85
|
+
eventMetadata: this.configuration.eventMetadata,
|
|
86
|
+
timeZone: this.getTimeZone() ?? void 0
|
|
80
87
|
});
|
|
81
88
|
const queue = this.getBeaconQueue();
|
|
82
89
|
queue.addCallback("halfEmpty", tracker.unsuspend);
|
|
@@ -60,8 +60,9 @@ class MinimalContextFactory {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
class TabContextFactory {
|
|
63
|
-
constructor(tab) {
|
|
63
|
+
constructor(tab, timeZone) {
|
|
64
64
|
this.tab = tab;
|
|
65
|
+
this.timeZone = timeZone;
|
|
65
66
|
}
|
|
66
67
|
createContext(attributes) {
|
|
67
68
|
const url = new URL(this.tab.url);
|
|
@@ -75,9 +76,8 @@ class TabContextFactory {
|
|
|
75
76
|
page.referrer = referrer;
|
|
76
77
|
}
|
|
77
78
|
context.page = page;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
context.timeZone = timeZone;
|
|
79
|
+
if (this.timeZone !== void 0) {
|
|
80
|
+
context.timeZone = this.timeZone;
|
|
81
81
|
}
|
|
82
82
|
if (attributes !== void 0 && Object.keys(attributes).length > 0) {
|
|
83
83
|
context.attributes = attributes;
|
|
@@ -34,7 +34,8 @@ declare class MinimalContextFactory implements ContextFactory {
|
|
|
34
34
|
}
|
|
35
35
|
declare class TabContextFactory implements ContextFactory {
|
|
36
36
|
private readonly tab;
|
|
37
|
-
|
|
37
|
+
private readonly timeZone?;
|
|
38
|
+
constructor(tab: Tab, timeZone?: string);
|
|
38
39
|
createContext(attributes?: JsonObject): EvaluationContext;
|
|
39
40
|
}
|
|
40
41
|
|
|
@@ -34,7 +34,8 @@ declare class MinimalContextFactory implements ContextFactory {
|
|
|
34
34
|
}
|
|
35
35
|
declare class TabContextFactory implements ContextFactory {
|
|
36
36
|
private readonly tab;
|
|
37
|
-
|
|
37
|
+
private readonly timeZone?;
|
|
38
|
+
constructor(tab: Tab, timeZone?: string);
|
|
38
39
|
createContext(attributes?: JsonObject): EvaluationContext;
|
|
39
40
|
}
|
|
40
41
|
|
|
@@ -36,8 +36,9 @@ class MinimalContextFactory {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
class TabContextFactory {
|
|
39
|
-
constructor(tab) {
|
|
39
|
+
constructor(tab, timeZone) {
|
|
40
40
|
this.tab = tab;
|
|
41
|
+
this.timeZone = timeZone;
|
|
41
42
|
}
|
|
42
43
|
createContext(attributes) {
|
|
43
44
|
const url = new URL(this.tab.url);
|
|
@@ -51,9 +52,8 @@ class TabContextFactory {
|
|
|
51
52
|
page.referrer = referrer;
|
|
52
53
|
}
|
|
53
54
|
context.page = page;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
context.timeZone = timeZone;
|
|
55
|
+
if (this.timeZone !== void 0) {
|
|
56
|
+
context.timeZone = this.timeZone;
|
|
57
57
|
}
|
|
58
58
|
if (attributes !== void 0 && Object.keys(attributes).length > 0) {
|
|
59
59
|
context.attributes = attributes;
|
package/facade/sdkFacade.cjs
CHANGED
|
@@ -132,7 +132,10 @@ class SdkFacade {
|
|
|
132
132
|
if (this.evaluatorFacade === void 0) {
|
|
133
133
|
this.evaluatorFacade = new import_evaluatorFacade.EvaluatorFacade({
|
|
134
134
|
evaluator: this.sdk.evaluator,
|
|
135
|
-
contextFactory: new import_evaluatorFacade.TabContextFactory(
|
|
135
|
+
contextFactory: new import_evaluatorFacade.TabContextFactory(
|
|
136
|
+
this.sdk.context.getTab(),
|
|
137
|
+
this.sdk.timeZone ?? void 0
|
|
138
|
+
),
|
|
136
139
|
cidAssigner: this.sdk.cidAssigner,
|
|
137
140
|
userTokenProvider: this.sdk.userTokenStore
|
|
138
141
|
});
|
|
@@ -143,7 +146,10 @@ class SdkFacade {
|
|
|
143
146
|
if (this.contentFetcherFacade === void 0) {
|
|
144
147
|
this.contentFetcherFacade = new import_contentFetcherFacade.ContentFetcherFacade({
|
|
145
148
|
contentFetcher: this.sdk.contentFetcher,
|
|
146
|
-
contextFactory: new import_evaluatorFacade.TabContextFactory(
|
|
149
|
+
contextFactory: new import_evaluatorFacade.TabContextFactory(
|
|
150
|
+
this.sdk.context.getTab(),
|
|
151
|
+
this.sdk.timeZone ?? void 0
|
|
152
|
+
),
|
|
147
153
|
cidAssigner: this.sdk.cidAssigner,
|
|
148
154
|
previewTokenProvider: this.sdk.previewTokenStore,
|
|
149
155
|
userTokenProvider: this.sdk.userTokenStore
|
package/facade/sdkFacade.js
CHANGED
|
@@ -110,7 +110,10 @@ class SdkFacade {
|
|
|
110
110
|
if (this.evaluatorFacade === void 0) {
|
|
111
111
|
this.evaluatorFacade = new EvaluatorFacade({
|
|
112
112
|
evaluator: this.sdk.evaluator,
|
|
113
|
-
contextFactory: new TabContextFactory(
|
|
113
|
+
contextFactory: new TabContextFactory(
|
|
114
|
+
this.sdk.context.getTab(),
|
|
115
|
+
this.sdk.timeZone ?? void 0
|
|
116
|
+
),
|
|
114
117
|
cidAssigner: this.sdk.cidAssigner,
|
|
115
118
|
userTokenProvider: this.sdk.userTokenStore
|
|
116
119
|
});
|
|
@@ -121,7 +124,10 @@ class SdkFacade {
|
|
|
121
124
|
if (this.contentFetcherFacade === void 0) {
|
|
122
125
|
this.contentFetcherFacade = new ContentFetcherFacade({
|
|
123
126
|
contentFetcher: this.sdk.contentFetcher,
|
|
124
|
-
contextFactory: new TabContextFactory(
|
|
127
|
+
contextFactory: new TabContextFactory(
|
|
128
|
+
this.sdk.context.getTab(),
|
|
129
|
+
this.sdk.timeZone ?? void 0
|
|
130
|
+
),
|
|
125
131
|
cidAssigner: this.sdk.cidAssigner,
|
|
126
132
|
previewTokenProvider: this.sdk.previewTokenStore,
|
|
127
133
|
userTokenProvider: this.sdk.userTokenStore
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var interactionMonitor_exports = {};
|
|
19
|
+
__export(interactionMonitor_exports, {
|
|
20
|
+
InteractionMonitor: () => InteractionMonitor
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(interactionMonitor_exports);
|
|
23
|
+
var import_eventManager = require('./eventManager.cjs');
|
|
24
|
+
class InteractionMonitor {
|
|
25
|
+
constructor(options = {}) {
|
|
26
|
+
this.eventManager = new import_eventManager.SynchronousEventManager();
|
|
27
|
+
this.lastClickTime = 0;
|
|
28
|
+
this.enabled = false;
|
|
29
|
+
this.clickThrottleInterval = options.clickThrottleInterval ?? 500;
|
|
30
|
+
this.scrollDebounceInterval = options.scrollDebounceInterval ?? 250;
|
|
31
|
+
this.handleClick = this.handleClick.bind(this);
|
|
32
|
+
this.handleScroll = this.handleScroll.bind(this);
|
|
33
|
+
}
|
|
34
|
+
addListener(type, listener) {
|
|
35
|
+
this.eventManager.addListener(type, listener);
|
|
36
|
+
}
|
|
37
|
+
removeListener(type, listener) {
|
|
38
|
+
this.eventManager.removeListener(type, listener);
|
|
39
|
+
}
|
|
40
|
+
isEnabled() {
|
|
41
|
+
return this.enabled;
|
|
42
|
+
}
|
|
43
|
+
enable() {
|
|
44
|
+
if (this.enabled) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
this.enabled = true;
|
|
48
|
+
window.addEventListener("click", this.handleClick, true);
|
|
49
|
+
window.addEventListener("scroll", this.handleScroll, true);
|
|
50
|
+
}
|
|
51
|
+
disable() {
|
|
52
|
+
if (!this.enabled) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
this.enabled = false;
|
|
56
|
+
window.removeEventListener("click", this.handleClick, true);
|
|
57
|
+
window.removeEventListener("scroll", this.handleScroll, true);
|
|
58
|
+
this.flushPendingScroll();
|
|
59
|
+
}
|
|
60
|
+
handleClick(event) {
|
|
61
|
+
const currentTime = Date.now();
|
|
62
|
+
if (currentTime - this.lastClickTime < this.clickThrottleInterval) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
this.lastClickTime = currentTime;
|
|
66
|
+
this.eventManager.dispatch("userClicked", {
|
|
67
|
+
type: "userClicked",
|
|
68
|
+
point: {
|
|
69
|
+
x: Math.max(0, Math.round(event.pageX)),
|
|
70
|
+
y: Math.max(0, Math.round(event.pageY))
|
|
71
|
+
},
|
|
72
|
+
surfaceSize: {
|
|
73
|
+
width: document.documentElement.scrollWidth,
|
|
74
|
+
height: document.documentElement.scrollHeight
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
handleScroll() {
|
|
79
|
+
const currentPosition = {
|
|
80
|
+
x: Math.max(0, Math.round(window.scrollX)),
|
|
81
|
+
y: Math.max(0, Math.round(window.scrollY))
|
|
82
|
+
};
|
|
83
|
+
if (this.scrollState === void 0) {
|
|
84
|
+
this.scrollState = {
|
|
85
|
+
start: currentPosition,
|
|
86
|
+
lastPosition: currentPosition
|
|
87
|
+
};
|
|
88
|
+
} else if (this.hasDirectionChanged(this.scrollState, currentPosition)) {
|
|
89
|
+
const turningPoint = this.scrollState.lastPosition;
|
|
90
|
+
this.flushPendingScroll(turningPoint);
|
|
91
|
+
this.scrollState = {
|
|
92
|
+
start: turningPoint,
|
|
93
|
+
lastPosition: currentPosition
|
|
94
|
+
};
|
|
95
|
+
} else {
|
|
96
|
+
this.scrollState.lastPosition = currentPosition;
|
|
97
|
+
}
|
|
98
|
+
if (this.scrollDebounceTimer !== void 0) {
|
|
99
|
+
window.clearTimeout(this.scrollDebounceTimer);
|
|
100
|
+
}
|
|
101
|
+
this.scrollDebounceTimer = window.setTimeout(
|
|
102
|
+
() => this.flushPendingScroll(),
|
|
103
|
+
this.scrollDebounceInterval
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Determines whether the scroll direction has reversed on either axis.
|
|
108
|
+
*
|
|
109
|
+
* It compares two vectors:
|
|
110
|
+
* - The scroll direction: the overall direction from start to the previous position (start -> previous)
|
|
111
|
+
* - The movement direction: the direction of the latest movement (previous -> current)
|
|
112
|
+
*
|
|
113
|
+
* A reversal is detected when these two vectors point in opposite directions on the same axis.
|
|
114
|
+
* Axes with no movement (sign = 0) are ignored, so scrolling that simply stops on one axis
|
|
115
|
+
* without reversing does not trigger a flush.
|
|
116
|
+
*
|
|
117
|
+
* Example of vertical reversal:
|
|
118
|
+
* start = {y: 0}, previous = {y: 500}, current = {y: 400}
|
|
119
|
+
* scrollDirectionY = sign(500 - 0) = +1 (downward)
|
|
120
|
+
* movementDirectionY = sign(400 - 500) = -1 (upward)
|
|
121
|
+
* +1 !== -1 => reversed
|
|
122
|
+
*
|
|
123
|
+
* Example of no reversal (same direction):
|
|
124
|
+
* start = {y: 0}, previous = {y: 200}, current = {y: 500}
|
|
125
|
+
* scrollDirectionY = sign(200 - 0) = +1 (downward)
|
|
126
|
+
* movementDirectionY = sign(500 - 200) = +1 (downward)
|
|
127
|
+
* +1 === +1 => not reversed
|
|
128
|
+
*
|
|
129
|
+
* Example of horizontal stop ignored:
|
|
130
|
+
* start = {x: 0}, previous = {x: 300}, current = {x: 300}
|
|
131
|
+
* scrollDirectionX = sign(300 - 0) = +1
|
|
132
|
+
* movementDirectionX = sign(300 - 300) = 0 (no movement)
|
|
133
|
+
* movementDirectionX is 0 => ignored, not a reversal
|
|
134
|
+
*/
|
|
135
|
+
hasDirectionChanged(state, current) {
|
|
136
|
+
const { start, lastPosition: previous } = state;
|
|
137
|
+
const scrollDirectionX = Math.sign(previous.x - start.x);
|
|
138
|
+
const scrollDirectionY = Math.sign(previous.y - start.y);
|
|
139
|
+
const movementDirectionX = Math.sign(current.x - previous.x);
|
|
140
|
+
const movementDirectionY = Math.sign(current.y - previous.y);
|
|
141
|
+
return scrollDirectionX !== 0 && movementDirectionX !== 0 && scrollDirectionX !== movementDirectionX || scrollDirectionY !== 0 && movementDirectionY !== 0 && scrollDirectionY !== movementDirectionY;
|
|
142
|
+
}
|
|
143
|
+
flushPendingScroll(end) {
|
|
144
|
+
if (this.scrollDebounceTimer !== void 0) {
|
|
145
|
+
window.clearTimeout(this.scrollDebounceTimer);
|
|
146
|
+
this.scrollDebounceTimer = void 0;
|
|
147
|
+
}
|
|
148
|
+
if (this.scrollState === void 0) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const { start } = this.scrollState;
|
|
152
|
+
const destination = end ?? {
|
|
153
|
+
x: Math.max(0, Math.round(window.scrollX)),
|
|
154
|
+
y: Math.max(0, Math.round(window.scrollY))
|
|
155
|
+
};
|
|
156
|
+
this.scrollState = void 0;
|
|
157
|
+
if (start.x === destination.x && start.y === destination.y) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
this.eventManager.dispatch("userScrolled", {
|
|
161
|
+
type: "userScrolled",
|
|
162
|
+
start,
|
|
163
|
+
end: destination,
|
|
164
|
+
surfaceSize: {
|
|
165
|
+
width: document.documentElement.scrollWidth,
|
|
166
|
+
height: document.documentElement.scrollHeight
|
|
167
|
+
},
|
|
168
|
+
// Uses clientWidth/clientHeight instead of innerWidth/innerHeight to get the
|
|
169
|
+
// layout viewport size, which remains stable regardless of pinch-to-zoom level
|
|
170
|
+
// on mobile devices.
|
|
171
|
+
viewportSize: {
|
|
172
|
+
width: document.documentElement.clientWidth,
|
|
173
|
+
height: document.documentElement.clientHeight
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
179
|
+
0 && (module.exports = {
|
|
180
|
+
InteractionMonitor
|
|
181
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { EventListener } from './eventManager.cjs';
|
|
2
|
+
import { UserClicked, UserScrolled } from './trackingEvents.cjs';
|
|
3
|
+
import './patch.cjs';
|
|
4
|
+
import '@croct/json';
|
|
5
|
+
import './utilityTypes.cjs';
|
|
6
|
+
|
|
7
|
+
type InteractionEventMap = {
|
|
8
|
+
userClicked: UserClicked;
|
|
9
|
+
userScrolled: UserScrolled;
|
|
10
|
+
};
|
|
11
|
+
type Options = {
|
|
12
|
+
clickThrottleInterval?: number;
|
|
13
|
+
scrollDebounceInterval?: number;
|
|
14
|
+
};
|
|
15
|
+
declare class InteractionMonitor {
|
|
16
|
+
private readonly eventManager;
|
|
17
|
+
private readonly clickThrottleInterval;
|
|
18
|
+
private readonly scrollDebounceInterval;
|
|
19
|
+
private lastClickTime;
|
|
20
|
+
private scrollState?;
|
|
21
|
+
private scrollDebounceTimer?;
|
|
22
|
+
private enabled;
|
|
23
|
+
constructor(options?: Options);
|
|
24
|
+
addListener<T extends keyof InteractionEventMap>(type: T, listener: EventListener<InteractionEventMap[T]>): void;
|
|
25
|
+
removeListener<T extends keyof InteractionEventMap>(type: T, listener: EventListener<InteractionEventMap[T]>): void;
|
|
26
|
+
isEnabled(): boolean;
|
|
27
|
+
enable(): void;
|
|
28
|
+
disable(): void;
|
|
29
|
+
private handleClick;
|
|
30
|
+
private handleScroll;
|
|
31
|
+
/**
|
|
32
|
+
* Determines whether the scroll direction has reversed on either axis.
|
|
33
|
+
*
|
|
34
|
+
* It compares two vectors:
|
|
35
|
+
* - The scroll direction: the overall direction from start to the previous position (start -> previous)
|
|
36
|
+
* - The movement direction: the direction of the latest movement (previous -> current)
|
|
37
|
+
*
|
|
38
|
+
* A reversal is detected when these two vectors point in opposite directions on the same axis.
|
|
39
|
+
* Axes with no movement (sign = 0) are ignored, so scrolling that simply stops on one axis
|
|
40
|
+
* without reversing does not trigger a flush.
|
|
41
|
+
*
|
|
42
|
+
* Example of vertical reversal:
|
|
43
|
+
* start = {y: 0}, previous = {y: 500}, current = {y: 400}
|
|
44
|
+
* scrollDirectionY = sign(500 - 0) = +1 (downward)
|
|
45
|
+
* movementDirectionY = sign(400 - 500) = -1 (upward)
|
|
46
|
+
* +1 !== -1 => reversed
|
|
47
|
+
*
|
|
48
|
+
* Example of no reversal (same direction):
|
|
49
|
+
* start = {y: 0}, previous = {y: 200}, current = {y: 500}
|
|
50
|
+
* scrollDirectionY = sign(200 - 0) = +1 (downward)
|
|
51
|
+
* movementDirectionY = sign(500 - 200) = +1 (downward)
|
|
52
|
+
* +1 === +1 => not reversed
|
|
53
|
+
*
|
|
54
|
+
* Example of horizontal stop ignored:
|
|
55
|
+
* start = {x: 0}, previous = {x: 300}, current = {x: 300}
|
|
56
|
+
* scrollDirectionX = sign(300 - 0) = +1
|
|
57
|
+
* movementDirectionX = sign(300 - 300) = 0 (no movement)
|
|
58
|
+
* movementDirectionX is 0 => ignored, not a reversal
|
|
59
|
+
*/
|
|
60
|
+
private hasDirectionChanged;
|
|
61
|
+
private flushPendingScroll;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { InteractionMonitor };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { EventListener } from './eventManager.js';
|
|
2
|
+
import { UserClicked, UserScrolled } from './trackingEvents.js';
|
|
3
|
+
import './patch.js';
|
|
4
|
+
import '@croct/json';
|
|
5
|
+
import './utilityTypes.js';
|
|
6
|
+
|
|
7
|
+
type InteractionEventMap = {
|
|
8
|
+
userClicked: UserClicked;
|
|
9
|
+
userScrolled: UserScrolled;
|
|
10
|
+
};
|
|
11
|
+
type Options = {
|
|
12
|
+
clickThrottleInterval?: number;
|
|
13
|
+
scrollDebounceInterval?: number;
|
|
14
|
+
};
|
|
15
|
+
declare class InteractionMonitor {
|
|
16
|
+
private readonly eventManager;
|
|
17
|
+
private readonly clickThrottleInterval;
|
|
18
|
+
private readonly scrollDebounceInterval;
|
|
19
|
+
private lastClickTime;
|
|
20
|
+
private scrollState?;
|
|
21
|
+
private scrollDebounceTimer?;
|
|
22
|
+
private enabled;
|
|
23
|
+
constructor(options?: Options);
|
|
24
|
+
addListener<T extends keyof InteractionEventMap>(type: T, listener: EventListener<InteractionEventMap[T]>): void;
|
|
25
|
+
removeListener<T extends keyof InteractionEventMap>(type: T, listener: EventListener<InteractionEventMap[T]>): void;
|
|
26
|
+
isEnabled(): boolean;
|
|
27
|
+
enable(): void;
|
|
28
|
+
disable(): void;
|
|
29
|
+
private handleClick;
|
|
30
|
+
private handleScroll;
|
|
31
|
+
/**
|
|
32
|
+
* Determines whether the scroll direction has reversed on either axis.
|
|
33
|
+
*
|
|
34
|
+
* It compares two vectors:
|
|
35
|
+
* - The scroll direction: the overall direction from start to the previous position (start -> previous)
|
|
36
|
+
* - The movement direction: the direction of the latest movement (previous -> current)
|
|
37
|
+
*
|
|
38
|
+
* A reversal is detected when these two vectors point in opposite directions on the same axis.
|
|
39
|
+
* Axes with no movement (sign = 0) are ignored, so scrolling that simply stops on one axis
|
|
40
|
+
* without reversing does not trigger a flush.
|
|
41
|
+
*
|
|
42
|
+
* Example of vertical reversal:
|
|
43
|
+
* start = {y: 0}, previous = {y: 500}, current = {y: 400}
|
|
44
|
+
* scrollDirectionY = sign(500 - 0) = +1 (downward)
|
|
45
|
+
* movementDirectionY = sign(400 - 500) = -1 (upward)
|
|
46
|
+
* +1 !== -1 => reversed
|
|
47
|
+
*
|
|
48
|
+
* Example of no reversal (same direction):
|
|
49
|
+
* start = {y: 0}, previous = {y: 200}, current = {y: 500}
|
|
50
|
+
* scrollDirectionY = sign(200 - 0) = +1 (downward)
|
|
51
|
+
* movementDirectionY = sign(500 - 200) = +1 (downward)
|
|
52
|
+
* +1 === +1 => not reversed
|
|
53
|
+
*
|
|
54
|
+
* Example of horizontal stop ignored:
|
|
55
|
+
* start = {x: 0}, previous = {x: 300}, current = {x: 300}
|
|
56
|
+
* scrollDirectionX = sign(300 - 0) = +1
|
|
57
|
+
* movementDirectionX = sign(300 - 300) = 0 (no movement)
|
|
58
|
+
* movementDirectionX is 0 => ignored, not a reversal
|
|
59
|
+
*/
|
|
60
|
+
private hasDirectionChanged;
|
|
61
|
+
private flushPendingScroll;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { InteractionMonitor };
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { SynchronousEventManager } from "./eventManager.js";
|
|
2
|
+
class InteractionMonitor {
|
|
3
|
+
constructor(options = {}) {
|
|
4
|
+
this.eventManager = new SynchronousEventManager();
|
|
5
|
+
this.lastClickTime = 0;
|
|
6
|
+
this.enabled = false;
|
|
7
|
+
this.clickThrottleInterval = options.clickThrottleInterval ?? 500;
|
|
8
|
+
this.scrollDebounceInterval = options.scrollDebounceInterval ?? 250;
|
|
9
|
+
this.handleClick = this.handleClick.bind(this);
|
|
10
|
+
this.handleScroll = this.handleScroll.bind(this);
|
|
11
|
+
}
|
|
12
|
+
addListener(type, listener) {
|
|
13
|
+
this.eventManager.addListener(type, listener);
|
|
14
|
+
}
|
|
15
|
+
removeListener(type, listener) {
|
|
16
|
+
this.eventManager.removeListener(type, listener);
|
|
17
|
+
}
|
|
18
|
+
isEnabled() {
|
|
19
|
+
return this.enabled;
|
|
20
|
+
}
|
|
21
|
+
enable() {
|
|
22
|
+
if (this.enabled) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
this.enabled = true;
|
|
26
|
+
window.addEventListener("click", this.handleClick, true);
|
|
27
|
+
window.addEventListener("scroll", this.handleScroll, true);
|
|
28
|
+
}
|
|
29
|
+
disable() {
|
|
30
|
+
if (!this.enabled) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
this.enabled = false;
|
|
34
|
+
window.removeEventListener("click", this.handleClick, true);
|
|
35
|
+
window.removeEventListener("scroll", this.handleScroll, true);
|
|
36
|
+
this.flushPendingScroll();
|
|
37
|
+
}
|
|
38
|
+
handleClick(event) {
|
|
39
|
+
const currentTime = Date.now();
|
|
40
|
+
if (currentTime - this.lastClickTime < this.clickThrottleInterval) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
this.lastClickTime = currentTime;
|
|
44
|
+
this.eventManager.dispatch("userClicked", {
|
|
45
|
+
type: "userClicked",
|
|
46
|
+
point: {
|
|
47
|
+
x: Math.max(0, Math.round(event.pageX)),
|
|
48
|
+
y: Math.max(0, Math.round(event.pageY))
|
|
49
|
+
},
|
|
50
|
+
surfaceSize: {
|
|
51
|
+
width: document.documentElement.scrollWidth,
|
|
52
|
+
height: document.documentElement.scrollHeight
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
handleScroll() {
|
|
57
|
+
const currentPosition = {
|
|
58
|
+
x: Math.max(0, Math.round(window.scrollX)),
|
|
59
|
+
y: Math.max(0, Math.round(window.scrollY))
|
|
60
|
+
};
|
|
61
|
+
if (this.scrollState === void 0) {
|
|
62
|
+
this.scrollState = {
|
|
63
|
+
start: currentPosition,
|
|
64
|
+
lastPosition: currentPosition
|
|
65
|
+
};
|
|
66
|
+
} else if (this.hasDirectionChanged(this.scrollState, currentPosition)) {
|
|
67
|
+
const turningPoint = this.scrollState.lastPosition;
|
|
68
|
+
this.flushPendingScroll(turningPoint);
|
|
69
|
+
this.scrollState = {
|
|
70
|
+
start: turningPoint,
|
|
71
|
+
lastPosition: currentPosition
|
|
72
|
+
};
|
|
73
|
+
} else {
|
|
74
|
+
this.scrollState.lastPosition = currentPosition;
|
|
75
|
+
}
|
|
76
|
+
if (this.scrollDebounceTimer !== void 0) {
|
|
77
|
+
window.clearTimeout(this.scrollDebounceTimer);
|
|
78
|
+
}
|
|
79
|
+
this.scrollDebounceTimer = window.setTimeout(
|
|
80
|
+
() => this.flushPendingScroll(),
|
|
81
|
+
this.scrollDebounceInterval
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Determines whether the scroll direction has reversed on either axis.
|
|
86
|
+
*
|
|
87
|
+
* It compares two vectors:
|
|
88
|
+
* - The scroll direction: the overall direction from start to the previous position (start -> previous)
|
|
89
|
+
* - The movement direction: the direction of the latest movement (previous -> current)
|
|
90
|
+
*
|
|
91
|
+
* A reversal is detected when these two vectors point in opposite directions on the same axis.
|
|
92
|
+
* Axes with no movement (sign = 0) are ignored, so scrolling that simply stops on one axis
|
|
93
|
+
* without reversing does not trigger a flush.
|
|
94
|
+
*
|
|
95
|
+
* Example of vertical reversal:
|
|
96
|
+
* start = {y: 0}, previous = {y: 500}, current = {y: 400}
|
|
97
|
+
* scrollDirectionY = sign(500 - 0) = +1 (downward)
|
|
98
|
+
* movementDirectionY = sign(400 - 500) = -1 (upward)
|
|
99
|
+
* +1 !== -1 => reversed
|
|
100
|
+
*
|
|
101
|
+
* Example of no reversal (same direction):
|
|
102
|
+
* start = {y: 0}, previous = {y: 200}, current = {y: 500}
|
|
103
|
+
* scrollDirectionY = sign(200 - 0) = +1 (downward)
|
|
104
|
+
* movementDirectionY = sign(500 - 200) = +1 (downward)
|
|
105
|
+
* +1 === +1 => not reversed
|
|
106
|
+
*
|
|
107
|
+
* Example of horizontal stop ignored:
|
|
108
|
+
* start = {x: 0}, previous = {x: 300}, current = {x: 300}
|
|
109
|
+
* scrollDirectionX = sign(300 - 0) = +1
|
|
110
|
+
* movementDirectionX = sign(300 - 300) = 0 (no movement)
|
|
111
|
+
* movementDirectionX is 0 => ignored, not a reversal
|
|
112
|
+
*/
|
|
113
|
+
hasDirectionChanged(state, current) {
|
|
114
|
+
const { start, lastPosition: previous } = state;
|
|
115
|
+
const scrollDirectionX = Math.sign(previous.x - start.x);
|
|
116
|
+
const scrollDirectionY = Math.sign(previous.y - start.y);
|
|
117
|
+
const movementDirectionX = Math.sign(current.x - previous.x);
|
|
118
|
+
const movementDirectionY = Math.sign(current.y - previous.y);
|
|
119
|
+
return scrollDirectionX !== 0 && movementDirectionX !== 0 && scrollDirectionX !== movementDirectionX || scrollDirectionY !== 0 && movementDirectionY !== 0 && scrollDirectionY !== movementDirectionY;
|
|
120
|
+
}
|
|
121
|
+
flushPendingScroll(end) {
|
|
122
|
+
if (this.scrollDebounceTimer !== void 0) {
|
|
123
|
+
window.clearTimeout(this.scrollDebounceTimer);
|
|
124
|
+
this.scrollDebounceTimer = void 0;
|
|
125
|
+
}
|
|
126
|
+
if (this.scrollState === void 0) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const { start } = this.scrollState;
|
|
130
|
+
const destination = end ?? {
|
|
131
|
+
x: Math.max(0, Math.round(window.scrollX)),
|
|
132
|
+
y: Math.max(0, Math.round(window.scrollY))
|
|
133
|
+
};
|
|
134
|
+
this.scrollState = void 0;
|
|
135
|
+
if (start.x === destination.x && start.y === destination.y) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
this.eventManager.dispatch("userScrolled", {
|
|
139
|
+
type: "userScrolled",
|
|
140
|
+
start,
|
|
141
|
+
end: destination,
|
|
142
|
+
surfaceSize: {
|
|
143
|
+
width: document.documentElement.scrollWidth,
|
|
144
|
+
height: document.documentElement.scrollHeight
|
|
145
|
+
},
|
|
146
|
+
// Uses clientWidth/clientHeight instead of innerWidth/innerHeight to get the
|
|
147
|
+
// layout viewport size, which remains stable regardless of pinch-to-zoom level
|
|
148
|
+
// on mobile devices.
|
|
149
|
+
viewportSize: {
|
|
150
|
+
width: document.documentElement.clientWidth,
|
|
151
|
+
height: document.documentElement.clientHeight
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
export {
|
|
157
|
+
InteractionMonitor
|
|
158
|
+
};
|
package/package.json
CHANGED
package/schema/eventSchemas.cjs
CHANGED
|
@@ -28,6 +28,8 @@ __export(eventSchemas_exports, {
|
|
|
28
28
|
orderPlaced: () => orderPlaced,
|
|
29
29
|
postViewed: () => postViewed,
|
|
30
30
|
productViewed: () => productViewed,
|
|
31
|
+
userClicked: () => userClicked,
|
|
32
|
+
userScrolled: () => userScrolled,
|
|
31
33
|
userSignedUp: () => userSignedUp
|
|
32
34
|
});
|
|
33
35
|
module.exports = __toCommonJS(eventSchemas_exports);
|
|
@@ -146,6 +148,48 @@ const eventOccurred = new import_validation.ObjectType({
|
|
|
146
148
|
})
|
|
147
149
|
}
|
|
148
150
|
});
|
|
151
|
+
const point = new import_validation.ObjectType({
|
|
152
|
+
required: ["x", "y"],
|
|
153
|
+
properties: {
|
|
154
|
+
x: new import_validation.NumberType({
|
|
155
|
+
integer: true,
|
|
156
|
+
minimum: 0
|
|
157
|
+
}),
|
|
158
|
+
y: new import_validation.NumberType({
|
|
159
|
+
integer: true,
|
|
160
|
+
minimum: 0
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
const size = new import_validation.ObjectType({
|
|
165
|
+
required: ["width", "height"],
|
|
166
|
+
properties: {
|
|
167
|
+
width: new import_validation.NumberType({
|
|
168
|
+
integer: true,
|
|
169
|
+
minimum: 0
|
|
170
|
+
}),
|
|
171
|
+
height: new import_validation.NumberType({
|
|
172
|
+
integer: true,
|
|
173
|
+
minimum: 0
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
const userClicked = new import_validation.ObjectType({
|
|
178
|
+
required: ["point"],
|
|
179
|
+
properties: {
|
|
180
|
+
point,
|
|
181
|
+
surfaceSize: size
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
const userScrolled = new import_validation.ObjectType({
|
|
185
|
+
required: ["end"],
|
|
186
|
+
properties: {
|
|
187
|
+
start: point,
|
|
188
|
+
end: point,
|
|
189
|
+
surfaceSize: size,
|
|
190
|
+
viewportSize: size
|
|
191
|
+
}
|
|
192
|
+
});
|
|
149
193
|
const leadGenerated = new import_validation.ObjectType({
|
|
150
194
|
properties: {
|
|
151
195
|
leadId: new import_validation.StringType({
|
|
@@ -175,5 +219,7 @@ const leadGenerated = new import_validation.ObjectType({
|
|
|
175
219
|
orderPlaced,
|
|
176
220
|
postViewed,
|
|
177
221
|
productViewed,
|
|
222
|
+
userClicked,
|
|
223
|
+
userScrolled,
|
|
178
224
|
userSignedUp
|
|
179
225
|
});
|
|
@@ -12,6 +12,8 @@ declare const interestShown: ObjectType;
|
|
|
12
12
|
declare const postViewed: ObjectType;
|
|
13
13
|
declare const linkOpened: ObjectType;
|
|
14
14
|
declare const eventOccurred: ObjectType;
|
|
15
|
+
declare const userClicked: ObjectType;
|
|
16
|
+
declare const userScrolled: ObjectType;
|
|
15
17
|
declare const leadGenerated: ObjectType;
|
|
16
18
|
|
|
17
|
-
export { cartModified, cartViewed, checkoutStarted, eventOccurred, goalCompleted, interestShown, leadGenerated, linkOpened, orderPlaced, postViewed, productViewed, userSignedUp };
|
|
19
|
+
export { cartModified, cartViewed, checkoutStarted, eventOccurred, goalCompleted, interestShown, leadGenerated, linkOpened, orderPlaced, postViewed, productViewed, userClicked, userScrolled, userSignedUp };
|
package/schema/eventSchemas.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ declare const interestShown: ObjectType;
|
|
|
12
12
|
declare const postViewed: ObjectType;
|
|
13
13
|
declare const linkOpened: ObjectType;
|
|
14
14
|
declare const eventOccurred: ObjectType;
|
|
15
|
+
declare const userClicked: ObjectType;
|
|
16
|
+
declare const userScrolled: ObjectType;
|
|
15
17
|
declare const leadGenerated: ObjectType;
|
|
16
18
|
|
|
17
|
-
export { cartModified, cartViewed, checkoutStarted, eventOccurred, goalCompleted, interestShown, leadGenerated, linkOpened, orderPlaced, postViewed, productViewed, userSignedUp };
|
|
19
|
+
export { cartModified, cartViewed, checkoutStarted, eventOccurred, goalCompleted, interestShown, leadGenerated, linkOpened, orderPlaced, postViewed, productViewed, userClicked, userScrolled, userSignedUp };
|
package/schema/eventSchemas.js
CHANGED
|
@@ -121,6 +121,48 @@ const eventOccurred = new ObjectType({
|
|
|
121
121
|
})
|
|
122
122
|
}
|
|
123
123
|
});
|
|
124
|
+
const point = new ObjectType({
|
|
125
|
+
required: ["x", "y"],
|
|
126
|
+
properties: {
|
|
127
|
+
x: new NumberType({
|
|
128
|
+
integer: true,
|
|
129
|
+
minimum: 0
|
|
130
|
+
}),
|
|
131
|
+
y: new NumberType({
|
|
132
|
+
integer: true,
|
|
133
|
+
minimum: 0
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
const size = new ObjectType({
|
|
138
|
+
required: ["width", "height"],
|
|
139
|
+
properties: {
|
|
140
|
+
width: new NumberType({
|
|
141
|
+
integer: true,
|
|
142
|
+
minimum: 0
|
|
143
|
+
}),
|
|
144
|
+
height: new NumberType({
|
|
145
|
+
integer: true,
|
|
146
|
+
minimum: 0
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
const userClicked = new ObjectType({
|
|
151
|
+
required: ["point"],
|
|
152
|
+
properties: {
|
|
153
|
+
point,
|
|
154
|
+
surfaceSize: size
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
const userScrolled = new ObjectType({
|
|
158
|
+
required: ["end"],
|
|
159
|
+
properties: {
|
|
160
|
+
start: point,
|
|
161
|
+
end: point,
|
|
162
|
+
surfaceSize: size,
|
|
163
|
+
viewportSize: size
|
|
164
|
+
}
|
|
165
|
+
});
|
|
124
166
|
const leadGenerated = new ObjectType({
|
|
125
167
|
properties: {
|
|
126
168
|
leadId: new StringType({
|
|
@@ -149,5 +191,7 @@ export {
|
|
|
149
191
|
orderPlaced,
|
|
150
192
|
postViewed,
|
|
151
193
|
productViewed,
|
|
194
|
+
userClicked,
|
|
195
|
+
userScrolled,
|
|
152
196
|
userSignedUp
|
|
153
197
|
};
|
package/schema/index.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ export { tokenScopeSchema } from './contextSchemas.cjs';
|
|
|
2
2
|
export { cart, cartItem, order, orderItem, productDetails } from './ecommerceSchemas.cjs';
|
|
3
3
|
export { evaluationOptionsSchema } from './evaluatorSchemas.cjs';
|
|
4
4
|
export { fetchOptionsSchema } from './contentFetcherSchemas.cjs';
|
|
5
|
-
export { cartModified, cartViewed, checkoutStarted, eventOccurred, goalCompleted, interestShown, leadGenerated, linkOpened, orderPlaced, postViewed, productViewed, userSignedUp } from './eventSchemas.cjs';
|
|
5
|
+
export { cartModified, cartViewed, checkoutStarted, eventOccurred, goalCompleted, interestShown, leadGenerated, linkOpened, orderPlaced, postViewed, productViewed, userClicked, userScrolled, userSignedUp } from './eventSchemas.cjs';
|
|
6
6
|
export { loggerSchema } from './loggerSchema.cjs';
|
|
7
7
|
export { addOperation, clearOperation, combineOperation, decrementOperation, incrementOperation, mergeOperation, removeOperation, setOperation, unsetOperation } from './operationSchemas.cjs';
|
|
8
8
|
export { sdkFacadeConfigurationSchema } from './sdkFacadeSchemas.cjs';
|
package/schema/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { tokenScopeSchema } from './contextSchemas.js';
|
|
|
2
2
|
export { cart, cartItem, order, orderItem, productDetails } from './ecommerceSchemas.js';
|
|
3
3
|
export { evaluationOptionsSchema } from './evaluatorSchemas.js';
|
|
4
4
|
export { fetchOptionsSchema } from './contentFetcherSchemas.js';
|
|
5
|
-
export { cartModified, cartViewed, checkoutStarted, eventOccurred, goalCompleted, interestShown, leadGenerated, linkOpened, orderPlaced, postViewed, productViewed, userSignedUp } from './eventSchemas.js';
|
|
5
|
+
export { cartModified, cartViewed, checkoutStarted, eventOccurred, goalCompleted, interestShown, leadGenerated, linkOpened, orderPlaced, postViewed, productViewed, userClicked, userScrolled, userSignedUp } from './eventSchemas.js';
|
|
6
6
|
export { loggerSchema } from './loggerSchema.js';
|
|
7
7
|
export { addOperation, clearOperation, combineOperation, decrementOperation, incrementOperation, mergeOperation, removeOperation, setOperation, unsetOperation } from './operationSchemas.js';
|
|
8
8
|
export { sdkFacadeConfigurationSchema } from './sdkFacadeSchemas.js';
|
package/sdk.cjs
CHANGED
package/sdk.d.cts
CHANGED
|
@@ -49,6 +49,7 @@ declare class Sdk {
|
|
|
49
49
|
private constructor();
|
|
50
50
|
static init(configuration: Configuration): Sdk;
|
|
51
51
|
get appId(): string;
|
|
52
|
+
get timeZone(): string | null;
|
|
52
53
|
get cidAssigner(): CidAssigner;
|
|
53
54
|
get previewTokenStore(): TokenStore;
|
|
54
55
|
get userTokenStore(): TokenStore;
|
package/sdk.d.ts
CHANGED
|
@@ -49,6 +49,7 @@ declare class Sdk {
|
|
|
49
49
|
private constructor();
|
|
50
50
|
static init(configuration: Configuration): Sdk;
|
|
51
51
|
get appId(): string;
|
|
52
|
+
get timeZone(): string | null;
|
|
52
53
|
get cidAssigner(): CidAssigner;
|
|
53
54
|
get previewTokenStore(): TokenStore;
|
|
54
55
|
get userTokenStore(): TokenStore;
|
package/sdk.js
CHANGED
package/tracker.cjs
CHANGED
|
@@ -21,6 +21,7 @@ __export(tracker_exports, {
|
|
|
21
21
|
});
|
|
22
22
|
module.exports = __toCommonJS(tracker_exports);
|
|
23
23
|
var import_logging = require('./logging/index.cjs');
|
|
24
|
+
var import_interactionMonitor = require('./interactionMonitor.cjs');
|
|
24
25
|
var import_error = require('./error.cjs');
|
|
25
26
|
var import_trackingEvents = require('./trackingEvents.cjs');
|
|
26
27
|
const trackedEvents = {};
|
|
@@ -36,16 +37,20 @@ class Tracker {
|
|
|
36
37
|
this.inactivityTimer = {
|
|
37
38
|
since: 0
|
|
38
39
|
};
|
|
39
|
-
const { tab, tokenProvider, channel, logger, inactivityRetryPolicy, ...options } = config;
|
|
40
|
+
const { tab, tokenProvider, channel, logger, inactivityRetryPolicy, timeZone, ...options } = config;
|
|
40
41
|
this.tab = tab;
|
|
41
42
|
this.tokenProvider = tokenProvider;
|
|
42
43
|
this.inactivityRetryPolicy = inactivityRetryPolicy;
|
|
43
44
|
this.channel = channel;
|
|
45
|
+
this.timeZone = timeZone;
|
|
44
46
|
this.logger = logger ?? new import_logging.NullLogger();
|
|
45
47
|
this.options = {
|
|
46
48
|
...options,
|
|
47
49
|
eventMetadata: options.eventMetadata ?? {}
|
|
48
50
|
};
|
|
51
|
+
this.interactionMonitor = new import_interactionMonitor.InteractionMonitor();
|
|
52
|
+
this.interactionMonitor.addListener("userClicked", (event) => this.enqueue(event));
|
|
53
|
+
this.interactionMonitor.addListener("userScrolled", (event) => this.enqueue(event));
|
|
49
54
|
this.enable = this.enable.bind(this);
|
|
50
55
|
this.disable = this.disable.bind(this);
|
|
51
56
|
this.suspend = this.suspend.bind(this);
|
|
@@ -93,6 +98,7 @@ class Tracker {
|
|
|
93
98
|
this.tab.addListener("load", this.trackPageLoad);
|
|
94
99
|
this.tab.addListener("urlChange", this.trackTabUrlChange);
|
|
95
100
|
this.tab.addListener("visibilityChange", this.trackTabVisibilityChange);
|
|
101
|
+
this.interactionMonitor.enable();
|
|
96
102
|
}
|
|
97
103
|
disable() {
|
|
98
104
|
if (!this.state.enabled) {
|
|
@@ -103,6 +109,7 @@ class Tracker {
|
|
|
103
109
|
if (this.state.suspended) {
|
|
104
110
|
return;
|
|
105
111
|
}
|
|
112
|
+
this.interactionMonitor.disable();
|
|
106
113
|
this.tab.removeListener("load", this.trackPageLoad);
|
|
107
114
|
this.tab.removeListener("urlChange", this.trackTabUrlChange);
|
|
108
115
|
this.tab.removeListener("visibilityChange", this.trackTabVisibilityChange);
|
|
@@ -231,6 +238,7 @@ class Tracker {
|
|
|
231
238
|
const context = {
|
|
232
239
|
tabId: this.tab.id,
|
|
233
240
|
url: this.tab.url,
|
|
241
|
+
...this.timeZone !== void 0 ? { timeZone: this.timeZone } : {},
|
|
234
242
|
...Object.keys(metadata).length > 0 ? { metadata } : {}
|
|
235
243
|
};
|
|
236
244
|
return this.publish({
|
package/tracker.d.cts
CHANGED
|
@@ -23,6 +23,7 @@ type Configuration = Options & {
|
|
|
23
23
|
channel: OutputChannel<Beacon>;
|
|
24
24
|
logger?: Logger;
|
|
25
25
|
tab: Tab;
|
|
26
|
+
timeZone?: string;
|
|
26
27
|
tokenProvider: TokenProvider;
|
|
27
28
|
inactivityRetryPolicy: RetryPolicy<number>;
|
|
28
29
|
};
|
|
@@ -42,11 +43,13 @@ declare class Tracker {
|
|
|
42
43
|
private tab;
|
|
43
44
|
private tokenProvider;
|
|
44
45
|
private inactivityRetryPolicy;
|
|
46
|
+
private readonly timeZone?;
|
|
45
47
|
private readonly channel;
|
|
46
48
|
private readonly logger;
|
|
47
49
|
private readonly listeners;
|
|
48
50
|
private readonly pending;
|
|
49
51
|
private readonly state;
|
|
52
|
+
private readonly interactionMonitor;
|
|
50
53
|
private readonly inactivityTimer;
|
|
51
54
|
constructor(config: Configuration);
|
|
52
55
|
addListener(listener: EventListener): void;
|
package/tracker.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ type Configuration = Options & {
|
|
|
23
23
|
channel: OutputChannel<Beacon>;
|
|
24
24
|
logger?: Logger;
|
|
25
25
|
tab: Tab;
|
|
26
|
+
timeZone?: string;
|
|
26
27
|
tokenProvider: TokenProvider;
|
|
27
28
|
inactivityRetryPolicy: RetryPolicy<number>;
|
|
28
29
|
};
|
|
@@ -42,11 +43,13 @@ declare class Tracker {
|
|
|
42
43
|
private tab;
|
|
43
44
|
private tokenProvider;
|
|
44
45
|
private inactivityRetryPolicy;
|
|
46
|
+
private readonly timeZone?;
|
|
45
47
|
private readonly channel;
|
|
46
48
|
private readonly logger;
|
|
47
49
|
private readonly listeners;
|
|
48
50
|
private readonly pending;
|
|
49
51
|
private readonly state;
|
|
52
|
+
private readonly interactionMonitor;
|
|
50
53
|
private readonly inactivityTimer;
|
|
51
54
|
constructor(config: Configuration);
|
|
52
55
|
addListener(listener: EventListener): void;
|
package/tracker.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NullLogger } from "./logging/index.js";
|
|
2
|
+
import { InteractionMonitor } from "./interactionMonitor.js";
|
|
2
3
|
import { formatCause } from "./error.js";
|
|
3
4
|
import { isCartPartialEvent, isIdentifiedUserEvent } from "./trackingEvents.js";
|
|
4
5
|
const trackedEvents = {};
|
|
@@ -14,16 +15,20 @@ class Tracker {
|
|
|
14
15
|
this.inactivityTimer = {
|
|
15
16
|
since: 0
|
|
16
17
|
};
|
|
17
|
-
const { tab, tokenProvider, channel, logger, inactivityRetryPolicy, ...options } = config;
|
|
18
|
+
const { tab, tokenProvider, channel, logger, inactivityRetryPolicy, timeZone, ...options } = config;
|
|
18
19
|
this.tab = tab;
|
|
19
20
|
this.tokenProvider = tokenProvider;
|
|
20
21
|
this.inactivityRetryPolicy = inactivityRetryPolicy;
|
|
21
22
|
this.channel = channel;
|
|
23
|
+
this.timeZone = timeZone;
|
|
22
24
|
this.logger = logger ?? new NullLogger();
|
|
23
25
|
this.options = {
|
|
24
26
|
...options,
|
|
25
27
|
eventMetadata: options.eventMetadata ?? {}
|
|
26
28
|
};
|
|
29
|
+
this.interactionMonitor = new InteractionMonitor();
|
|
30
|
+
this.interactionMonitor.addListener("userClicked", (event) => this.enqueue(event));
|
|
31
|
+
this.interactionMonitor.addListener("userScrolled", (event) => this.enqueue(event));
|
|
27
32
|
this.enable = this.enable.bind(this);
|
|
28
33
|
this.disable = this.disable.bind(this);
|
|
29
34
|
this.suspend = this.suspend.bind(this);
|
|
@@ -71,6 +76,7 @@ class Tracker {
|
|
|
71
76
|
this.tab.addListener("load", this.trackPageLoad);
|
|
72
77
|
this.tab.addListener("urlChange", this.trackTabUrlChange);
|
|
73
78
|
this.tab.addListener("visibilityChange", this.trackTabVisibilityChange);
|
|
79
|
+
this.interactionMonitor.enable();
|
|
74
80
|
}
|
|
75
81
|
disable() {
|
|
76
82
|
if (!this.state.enabled) {
|
|
@@ -81,6 +87,7 @@ class Tracker {
|
|
|
81
87
|
if (this.state.suspended) {
|
|
82
88
|
return;
|
|
83
89
|
}
|
|
90
|
+
this.interactionMonitor.disable();
|
|
84
91
|
this.tab.removeListener("load", this.trackPageLoad);
|
|
85
92
|
this.tab.removeListener("urlChange", this.trackTabUrlChange);
|
|
86
93
|
this.tab.removeListener("visibilityChange", this.trackTabVisibilityChange);
|
|
@@ -209,6 +216,7 @@ class Tracker {
|
|
|
209
216
|
const context = {
|
|
210
217
|
tabId: this.tab.id,
|
|
211
218
|
url: this.tab.url,
|
|
219
|
+
...this.timeZone !== void 0 ? { timeZone: this.timeZone } : {},
|
|
212
220
|
...Object.keys(metadata).length > 0 ? { metadata } : {}
|
|
213
221
|
};
|
|
214
222
|
return this.publish({
|
package/trackingEvents.cjs
CHANGED
|
@@ -21,6 +21,7 @@ __export(trackingEvents_exports, {
|
|
|
21
21
|
ecommerceEventTypes: () => ecommerceEventTypes,
|
|
22
22
|
eventTypes: () => eventTypes,
|
|
23
23
|
identifiedUserEventTypes: () => identifiedUserEventTypes,
|
|
24
|
+
interactionEventTypes: () => interactionEventTypes,
|
|
24
25
|
isCartPartialEvent: () => isCartPartialEvent,
|
|
25
26
|
isIdentifiedUserEvent: () => isIdentifiedUserEvent,
|
|
26
27
|
miscEventTypes: () => miscEventTypes,
|
|
@@ -57,6 +58,10 @@ const userEventTypes = [
|
|
|
57
58
|
...identifiedUserEventTypes,
|
|
58
59
|
"userProfileChanged"
|
|
59
60
|
];
|
|
61
|
+
const interactionEventTypes = [
|
|
62
|
+
"userClicked",
|
|
63
|
+
"userScrolled"
|
|
64
|
+
];
|
|
60
65
|
const miscEventTypes = [
|
|
61
66
|
"nothingChanged",
|
|
62
67
|
"sessionAttributesChanged",
|
|
@@ -71,6 +76,7 @@ const eventTypes = [
|
|
|
71
76
|
...pageEventTypes,
|
|
72
77
|
...ecommerceEventTypes,
|
|
73
78
|
...userEventTypes,
|
|
79
|
+
...interactionEventTypes,
|
|
74
80
|
...miscEventTypes
|
|
75
81
|
];
|
|
76
82
|
function isIdentifiedUserEvent(event) {
|
|
@@ -85,6 +91,7 @@ function isCartPartialEvent(event) {
|
|
|
85
91
|
ecommerceEventTypes,
|
|
86
92
|
eventTypes,
|
|
87
93
|
identifiedUserEventTypes,
|
|
94
|
+
interactionEventTypes,
|
|
88
95
|
isCartPartialEvent,
|
|
89
96
|
isIdentifiedUserEvent,
|
|
90
97
|
miscEventTypes,
|
package/trackingEvents.d.cts
CHANGED
|
@@ -67,6 +67,14 @@ type Order = {
|
|
|
67
67
|
installments?: number;
|
|
68
68
|
status?: OrderStatus;
|
|
69
69
|
};
|
|
70
|
+
type Point = {
|
|
71
|
+
x: number;
|
|
72
|
+
y: number;
|
|
73
|
+
};
|
|
74
|
+
type Size = {
|
|
75
|
+
width: number;
|
|
76
|
+
height: number;
|
|
77
|
+
};
|
|
70
78
|
type Gender = 'male' | 'female' | 'neutral' | 'unknown';
|
|
71
79
|
declare const pageEventTypes: readonly ["pageLoaded", "pageOpened"];
|
|
72
80
|
declare const tabEventTypes: readonly ["tabOpened", "tabUrlChanged", "tabVisibilityChanged"];
|
|
@@ -74,8 +82,9 @@ declare const cartEventTypes: readonly ["cartModified", "cartViewed", "checkoutS
|
|
|
74
82
|
declare const ecommerceEventTypes: readonly ["cartModified", "cartViewed", "checkoutStarted", "orderPlaced", "productViewed"];
|
|
75
83
|
declare const identifiedUserEventTypes: string[];
|
|
76
84
|
declare const userEventTypes: readonly [...string[], "userProfileChanged"];
|
|
85
|
+
declare const interactionEventTypes: readonly ["userClicked", "userScrolled"];
|
|
77
86
|
declare const miscEventTypes: readonly ["nothingChanged", "sessionAttributesChanged", "goalCompleted", "interestShown", "postViewed", "eventOccurred", "linkOpened", "leadGenerated"];
|
|
78
|
-
declare const eventTypes: readonly ["pageLoaded", "pageOpened", "cartModified", "cartViewed", "checkoutStarted", "orderPlaced", "productViewed", ...string[], "userProfileChanged", "nothingChanged", "sessionAttributesChanged", "goalCompleted", "interestShown", "postViewed", "eventOccurred", "linkOpened", "leadGenerated"];
|
|
87
|
+
declare const eventTypes: readonly ["pageLoaded", "pageOpened", "cartModified", "cartViewed", "checkoutStarted", "orderPlaced", "productViewed", ...string[], "userProfileChanged", "userClicked", "userScrolled", "nothingChanged", "sessionAttributesChanged", "goalCompleted", "interestShown", "postViewed", "eventOccurred", "linkOpened", "leadGenerated"];
|
|
79
88
|
interface BaseEvent {
|
|
80
89
|
type: string;
|
|
81
90
|
}
|
|
@@ -195,6 +204,19 @@ interface PageLoaded extends BasePageEvent {
|
|
|
195
204
|
lastModifiedTime: number;
|
|
196
205
|
}
|
|
197
206
|
type PageEvent = PageLoaded | PageOpened;
|
|
207
|
+
interface UserClicked extends BaseEvent {
|
|
208
|
+
type: 'userClicked';
|
|
209
|
+
point: Point;
|
|
210
|
+
surfaceSize?: Size;
|
|
211
|
+
}
|
|
212
|
+
interface UserScrolled extends BaseEvent {
|
|
213
|
+
type: 'userScrolled';
|
|
214
|
+
start?: Point;
|
|
215
|
+
end: Point;
|
|
216
|
+
surfaceSize?: Size;
|
|
217
|
+
viewportSize?: Size;
|
|
218
|
+
}
|
|
219
|
+
type InteractionEvent = UserClicked | UserScrolled;
|
|
198
220
|
interface NothingChanged extends BaseEvent {
|
|
199
221
|
type: 'nothingChanged';
|
|
200
222
|
sinceTime: number;
|
|
@@ -256,6 +278,8 @@ type EventMap = {
|
|
|
256
278
|
userSignedOut: UserSignedOut;
|
|
257
279
|
userSignedUp: UserSignedUp;
|
|
258
280
|
userProfileChanged: UserProfileChanged;
|
|
281
|
+
userClicked: UserClicked;
|
|
282
|
+
userScrolled: UserScrolled;
|
|
259
283
|
productViewed: ProductViewed;
|
|
260
284
|
cartViewed: CartViewed;
|
|
261
285
|
cartModified: CartModified;
|
|
@@ -302,6 +326,7 @@ declare function isCartPartialEvent(event: PartialTrackingEvent): event is CartP
|
|
|
302
326
|
type TrackingEventContext = {
|
|
303
327
|
tabId: string;
|
|
304
328
|
url: string;
|
|
329
|
+
timeZone?: string;
|
|
305
330
|
metadata?: {
|
|
306
331
|
[key: string]: string;
|
|
307
332
|
};
|
|
@@ -318,4 +343,4 @@ type Beacon = {
|
|
|
318
343
|
payload: BeaconPayload;
|
|
319
344
|
};
|
|
320
345
|
|
|
321
|
-
export { type Beacon, type BeaconPayload, type Cart, type CartEvent, type CartEventType, type CartItem, type CartModified, type CartViewed, type CheckoutStarted, type EcommerceEvent, type EventOccurred, type ExternalTrackingEvent, type ExternalTrackingEventPayload, type ExternalTrackingEventType, type Gender, type GoalCompleted, type IdentifiedUserEvent, type InterestShown, type LeadGenerated, type LinkOpened, type MiscEvent, type NothingChanged, type Order, type OrderItem, type OrderPlaced, type OrderStatus, type PageEvent, type PageEventType, type PageLoaded, type PageOpened, type PartialTrackingEvent, type PostDetails, type PostViewed, type ProductDetails, type ProductViewed, type SessionAttributesChanged, type TabEvent, type TabEventType, type TabOpened, type TabUrlChanged, type TabVisibilityChanged, type TrackingEvent, type TrackingEventContext, type TrackingEventType, type UserEvent, type UserProfile, type UserProfileChanged, type UserSignedIn, type UserSignedOut, type UserSignedUp, cartEventTypes, ecommerceEventTypes, eventTypes, identifiedUserEventTypes, isCartPartialEvent, isIdentifiedUserEvent, miscEventTypes, pageEventTypes, tabEventTypes, userEventTypes };
|
|
346
|
+
export { type Beacon, type BeaconPayload, type Cart, type CartEvent, type CartEventType, type CartItem, type CartModified, type CartViewed, type CheckoutStarted, type EcommerceEvent, type EventOccurred, type ExternalTrackingEvent, type ExternalTrackingEventPayload, type ExternalTrackingEventType, type Gender, type GoalCompleted, type IdentifiedUserEvent, type InteractionEvent, type InterestShown, type LeadGenerated, type LinkOpened, type MiscEvent, type NothingChanged, type Order, type OrderItem, type OrderPlaced, type OrderStatus, type PageEvent, type PageEventType, type PageLoaded, type PageOpened, type PartialTrackingEvent, type Point, type PostDetails, type PostViewed, type ProductDetails, type ProductViewed, type SessionAttributesChanged, type Size, type TabEvent, type TabEventType, type TabOpened, type TabUrlChanged, type TabVisibilityChanged, type TrackingEvent, type TrackingEventContext, type TrackingEventType, type UserClicked, type UserEvent, type UserProfile, type UserProfileChanged, type UserScrolled, type UserSignedIn, type UserSignedOut, type UserSignedUp, cartEventTypes, ecommerceEventTypes, eventTypes, identifiedUserEventTypes, interactionEventTypes, isCartPartialEvent, isIdentifiedUserEvent, miscEventTypes, pageEventTypes, tabEventTypes, userEventTypes };
|
package/trackingEvents.d.ts
CHANGED
|
@@ -67,6 +67,14 @@ type Order = {
|
|
|
67
67
|
installments?: number;
|
|
68
68
|
status?: OrderStatus;
|
|
69
69
|
};
|
|
70
|
+
type Point = {
|
|
71
|
+
x: number;
|
|
72
|
+
y: number;
|
|
73
|
+
};
|
|
74
|
+
type Size = {
|
|
75
|
+
width: number;
|
|
76
|
+
height: number;
|
|
77
|
+
};
|
|
70
78
|
type Gender = 'male' | 'female' | 'neutral' | 'unknown';
|
|
71
79
|
declare const pageEventTypes: readonly ["pageLoaded", "pageOpened"];
|
|
72
80
|
declare const tabEventTypes: readonly ["tabOpened", "tabUrlChanged", "tabVisibilityChanged"];
|
|
@@ -74,8 +82,9 @@ declare const cartEventTypes: readonly ["cartModified", "cartViewed", "checkoutS
|
|
|
74
82
|
declare const ecommerceEventTypes: readonly ["cartModified", "cartViewed", "checkoutStarted", "orderPlaced", "productViewed"];
|
|
75
83
|
declare const identifiedUserEventTypes: string[];
|
|
76
84
|
declare const userEventTypes: readonly [...string[], "userProfileChanged"];
|
|
85
|
+
declare const interactionEventTypes: readonly ["userClicked", "userScrolled"];
|
|
77
86
|
declare const miscEventTypes: readonly ["nothingChanged", "sessionAttributesChanged", "goalCompleted", "interestShown", "postViewed", "eventOccurred", "linkOpened", "leadGenerated"];
|
|
78
|
-
declare const eventTypes: readonly ["pageLoaded", "pageOpened", "cartModified", "cartViewed", "checkoutStarted", "orderPlaced", "productViewed", ...string[], "userProfileChanged", "nothingChanged", "sessionAttributesChanged", "goalCompleted", "interestShown", "postViewed", "eventOccurred", "linkOpened", "leadGenerated"];
|
|
87
|
+
declare const eventTypes: readonly ["pageLoaded", "pageOpened", "cartModified", "cartViewed", "checkoutStarted", "orderPlaced", "productViewed", ...string[], "userProfileChanged", "userClicked", "userScrolled", "nothingChanged", "sessionAttributesChanged", "goalCompleted", "interestShown", "postViewed", "eventOccurred", "linkOpened", "leadGenerated"];
|
|
79
88
|
interface BaseEvent {
|
|
80
89
|
type: string;
|
|
81
90
|
}
|
|
@@ -195,6 +204,19 @@ interface PageLoaded extends BasePageEvent {
|
|
|
195
204
|
lastModifiedTime: number;
|
|
196
205
|
}
|
|
197
206
|
type PageEvent = PageLoaded | PageOpened;
|
|
207
|
+
interface UserClicked extends BaseEvent {
|
|
208
|
+
type: 'userClicked';
|
|
209
|
+
point: Point;
|
|
210
|
+
surfaceSize?: Size;
|
|
211
|
+
}
|
|
212
|
+
interface UserScrolled extends BaseEvent {
|
|
213
|
+
type: 'userScrolled';
|
|
214
|
+
start?: Point;
|
|
215
|
+
end: Point;
|
|
216
|
+
surfaceSize?: Size;
|
|
217
|
+
viewportSize?: Size;
|
|
218
|
+
}
|
|
219
|
+
type InteractionEvent = UserClicked | UserScrolled;
|
|
198
220
|
interface NothingChanged extends BaseEvent {
|
|
199
221
|
type: 'nothingChanged';
|
|
200
222
|
sinceTime: number;
|
|
@@ -256,6 +278,8 @@ type EventMap = {
|
|
|
256
278
|
userSignedOut: UserSignedOut;
|
|
257
279
|
userSignedUp: UserSignedUp;
|
|
258
280
|
userProfileChanged: UserProfileChanged;
|
|
281
|
+
userClicked: UserClicked;
|
|
282
|
+
userScrolled: UserScrolled;
|
|
259
283
|
productViewed: ProductViewed;
|
|
260
284
|
cartViewed: CartViewed;
|
|
261
285
|
cartModified: CartModified;
|
|
@@ -302,6 +326,7 @@ declare function isCartPartialEvent(event: PartialTrackingEvent): event is CartP
|
|
|
302
326
|
type TrackingEventContext = {
|
|
303
327
|
tabId: string;
|
|
304
328
|
url: string;
|
|
329
|
+
timeZone?: string;
|
|
305
330
|
metadata?: {
|
|
306
331
|
[key: string]: string;
|
|
307
332
|
};
|
|
@@ -318,4 +343,4 @@ type Beacon = {
|
|
|
318
343
|
payload: BeaconPayload;
|
|
319
344
|
};
|
|
320
345
|
|
|
321
|
-
export { type Beacon, type BeaconPayload, type Cart, type CartEvent, type CartEventType, type CartItem, type CartModified, type CartViewed, type CheckoutStarted, type EcommerceEvent, type EventOccurred, type ExternalTrackingEvent, type ExternalTrackingEventPayload, type ExternalTrackingEventType, type Gender, type GoalCompleted, type IdentifiedUserEvent, type InterestShown, type LeadGenerated, type LinkOpened, type MiscEvent, type NothingChanged, type Order, type OrderItem, type OrderPlaced, type OrderStatus, type PageEvent, type PageEventType, type PageLoaded, type PageOpened, type PartialTrackingEvent, type PostDetails, type PostViewed, type ProductDetails, type ProductViewed, type SessionAttributesChanged, type TabEvent, type TabEventType, type TabOpened, type TabUrlChanged, type TabVisibilityChanged, type TrackingEvent, type TrackingEventContext, type TrackingEventType, type UserEvent, type UserProfile, type UserProfileChanged, type UserSignedIn, type UserSignedOut, type UserSignedUp, cartEventTypes, ecommerceEventTypes, eventTypes, identifiedUserEventTypes, isCartPartialEvent, isIdentifiedUserEvent, miscEventTypes, pageEventTypes, tabEventTypes, userEventTypes };
|
|
346
|
+
export { type Beacon, type BeaconPayload, type Cart, type CartEvent, type CartEventType, type CartItem, type CartModified, type CartViewed, type CheckoutStarted, type EcommerceEvent, type EventOccurred, type ExternalTrackingEvent, type ExternalTrackingEventPayload, type ExternalTrackingEventType, type Gender, type GoalCompleted, type IdentifiedUserEvent, type InteractionEvent, type InterestShown, type LeadGenerated, type LinkOpened, type MiscEvent, type NothingChanged, type Order, type OrderItem, type OrderPlaced, type OrderStatus, type PageEvent, type PageEventType, type PageLoaded, type PageOpened, type PartialTrackingEvent, type Point, type PostDetails, type PostViewed, type ProductDetails, type ProductViewed, type SessionAttributesChanged, type Size, type TabEvent, type TabEventType, type TabOpened, type TabUrlChanged, type TabVisibilityChanged, type TrackingEvent, type TrackingEventContext, type TrackingEventType, type UserClicked, type UserEvent, type UserProfile, type UserProfileChanged, type UserScrolled, type UserSignedIn, type UserSignedOut, type UserSignedUp, cartEventTypes, ecommerceEventTypes, eventTypes, identifiedUserEventTypes, interactionEventTypes, isCartPartialEvent, isIdentifiedUserEvent, miscEventTypes, pageEventTypes, tabEventTypes, userEventTypes };
|
package/trackingEvents.js
CHANGED
|
@@ -26,6 +26,10 @@ const userEventTypes = [
|
|
|
26
26
|
...identifiedUserEventTypes,
|
|
27
27
|
"userProfileChanged"
|
|
28
28
|
];
|
|
29
|
+
const interactionEventTypes = [
|
|
30
|
+
"userClicked",
|
|
31
|
+
"userScrolled"
|
|
32
|
+
];
|
|
29
33
|
const miscEventTypes = [
|
|
30
34
|
"nothingChanged",
|
|
31
35
|
"sessionAttributesChanged",
|
|
@@ -40,6 +44,7 @@ const eventTypes = [
|
|
|
40
44
|
...pageEventTypes,
|
|
41
45
|
...ecommerceEventTypes,
|
|
42
46
|
...userEventTypes,
|
|
47
|
+
...interactionEventTypes,
|
|
43
48
|
...miscEventTypes
|
|
44
49
|
];
|
|
45
50
|
function isIdentifiedUserEvent(event) {
|
|
@@ -53,6 +58,7 @@ export {
|
|
|
53
58
|
ecommerceEventTypes,
|
|
54
59
|
eventTypes,
|
|
55
60
|
identifiedUserEventTypes,
|
|
61
|
+
interactionEventTypes,
|
|
56
62
|
isCartPartialEvent,
|
|
57
63
|
isIdentifiedUserEvent,
|
|
58
64
|
miscEventTypes,
|