@amplitude/plugin-autocapture-browser 1.10.1 → 1.10.2
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/lib/cjs/autocapture/track-rage-click.d.ts.map +1 -1
- package/lib/cjs/autocapture/track-rage-click.js +77 -29
- package/lib/cjs/autocapture/track-rage-click.js.map +1 -1
- package/lib/cjs/version.d.ts +1 -1
- package/lib/cjs/version.js +1 -1
- package/lib/cjs/version.js.map +1 -1
- package/lib/esm/autocapture/track-rage-click.d.ts.map +1 -1
- package/lib/esm/autocapture/track-rage-click.js +78 -30
- package/lib/esm/autocapture/track-rage-click.js.map +1 -1
- package/lib/esm/version.d.ts +1 -1
- package/lib/esm/version.js +1 -1
- package/lib/esm/version.js.map +1 -1
- package/lib/scripts/amplitude-min.js +1 -1
- package/lib/scripts/amplitude-min.js.gz +0 -0
- package/lib/scripts/amplitude-min.js.map +1 -1
- package/lib/scripts/amplitude-min.umd.js +1 -1
- package/lib/scripts/amplitude-min.umd.js.gz +0 -0
- package/lib/scripts/autocapture/track-rage-click.d.ts.map +1 -1
- package/lib/scripts/version.d.ts +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-rage-click.d.ts","sourceRoot":"","sources":["../../../src/autocapture/track-rage-click.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAA+B,gBAAgB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"track-rage-click.d.ts","sourceRoot":"","sources":["../../../src/autocapture/track-rage-click.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAA+B,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAqF3E,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,cAAc,EACd,oBAAoB,GACrB,EAAE;IACD,SAAS,EAAE,aAAa,CAAC;IACzB,cAAc,EAAE,oBAAoB,CAAC;IACrC,oBAAoB,EAAE,gBAAgB,CAAC;CACxC,+BAqFA"}
|
|
@@ -8,48 +8,96 @@ var constants_1 = require("../constants");
|
|
|
8
8
|
var analytics_core_1 = require("@amplitude/analytics-core");
|
|
9
9
|
var RAGE_CLICK_THRESHOLD = analytics_core_1.DEFAULT_RAGE_CLICK_THRESHOLD;
|
|
10
10
|
var RAGE_CLICK_WINDOW_MS = analytics_core_1.DEFAULT_RAGE_CLICK_WINDOW_MS;
|
|
11
|
+
var RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD = analytics_core_1.DEFAULT_RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD;
|
|
12
|
+
function addCoordinates(regionBox, click) {
|
|
13
|
+
var _a, _b, _c, _d;
|
|
14
|
+
var _e = click.event, clientX = _e.clientX, clientY = _e.clientY;
|
|
15
|
+
regionBox.yMin = Math.min((_a = regionBox.yMin) !== null && _a !== void 0 ? _a : clientY, clientY);
|
|
16
|
+
regionBox.yMax = Math.max((_b = regionBox.yMax) !== null && _b !== void 0 ? _b : clientY, clientY);
|
|
17
|
+
regionBox.xMin = Math.min((_c = regionBox.xMin) !== null && _c !== void 0 ? _c : clientX, clientX);
|
|
18
|
+
regionBox.xMax = Math.max((_d = regionBox.xMax) !== null && _d !== void 0 ? _d : clientX, clientX);
|
|
19
|
+
regionBox.isOutOfBounds =
|
|
20
|
+
regionBox.yMax - regionBox.yMin > RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD ||
|
|
21
|
+
regionBox.xMax - regionBox.xMin > RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD;
|
|
22
|
+
}
|
|
23
|
+
function getRageClickAnalyticsEvent(clickWindow) {
|
|
24
|
+
var firstClick = clickWindow[0];
|
|
25
|
+
var lastClick = clickWindow[clickWindow.length - 1];
|
|
26
|
+
var rageClickEvent = tslib_1.__assign({ '[Amplitude] Begin Time': new Date(firstClick.timestamp).toISOString(), '[Amplitude] End Time': new Date(lastClick.timestamp).toISOString(), '[Amplitude] Duration': lastClick.timestamp - firstClick.timestamp, '[Amplitude] Clicks': clickWindow.map(function (click) { return ({
|
|
27
|
+
X: click.event.clientX,
|
|
28
|
+
Y: click.event.clientY,
|
|
29
|
+
Time: click.timestamp,
|
|
30
|
+
}); }), '[Amplitude] Click Count': clickWindow.length }, firstClick.targetElementProperties);
|
|
31
|
+
return { rageClickEvent: rageClickEvent, time: firstClick.timestamp };
|
|
32
|
+
}
|
|
33
|
+
function isClickOutsideRageClickWindow(clickWindow, click) {
|
|
34
|
+
var firstIndex = Math.max(0, clickWindow.length - RAGE_CLICK_THRESHOLD + 1);
|
|
35
|
+
var firstClick = clickWindow[firstIndex];
|
|
36
|
+
return click.timestamp - firstClick.timestamp >= RAGE_CLICK_WINDOW_MS;
|
|
37
|
+
}
|
|
38
|
+
function isNewElement(clickWindow, click) {
|
|
39
|
+
return (clickWindow.length > 0 &&
|
|
40
|
+
clickWindow[clickWindow.length - 1].closestTrackedAncestor !== click.closestTrackedAncestor);
|
|
41
|
+
}
|
|
11
42
|
function trackRageClicks(_a) {
|
|
12
43
|
var amplitude = _a.amplitude, allObservables = _a.allObservables, shouldTrackRageClick = _a.shouldTrackRageClick;
|
|
13
44
|
var clickObservable = allObservables.clickObservable;
|
|
14
45
|
// Keep track of all clicks within the sliding window
|
|
15
46
|
var clickWindow = [];
|
|
47
|
+
// Keep track of the region box for all clicks, to determine when a rage click is out of bounds
|
|
48
|
+
var clickBoundingBox = {};
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
|
+
var triggerRageClickTimeout;
|
|
51
|
+
// helper function to reset the click window and region box
|
|
52
|
+
function resetClickWindow(click) {
|
|
53
|
+
clickWindow = [];
|
|
54
|
+
clickBoundingBox = {};
|
|
55
|
+
if (click) {
|
|
56
|
+
addCoordinates(clickBoundingBox, click);
|
|
57
|
+
clickWindow.push(click);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
16
60
|
return clickObservable
|
|
17
61
|
.pipe((0, rxjs_1.filter)(helpers_1.filterOutNonTrackableEvents), (0, rxjs_1.filter)(function (click) {
|
|
18
62
|
return shouldTrackRageClick('click', click.closestTrackedAncestor);
|
|
19
63
|
}), (0, rxjs_1.map)(function (click) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
64
|
+
// reset the click wait timer if it exists
|
|
65
|
+
if (triggerRageClickTimeout) {
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
67
|
+
clearTimeout(triggerRageClickTimeout);
|
|
68
|
+
}
|
|
69
|
+
// add click to bounding box
|
|
70
|
+
addCoordinates(clickBoundingBox, click);
|
|
71
|
+
// if there's just one click in the window, add it and return
|
|
72
|
+
if (clickWindow.length === 0) {
|
|
73
|
+
clickWindow.push(click);
|
|
74
|
+
return null;
|
|
26
75
|
}
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
76
|
+
// if current click is:
|
|
77
|
+
// 1. outside the rage click window
|
|
78
|
+
// 2. on a new element
|
|
79
|
+
// 3. out of bounds
|
|
80
|
+
// then start a new click window
|
|
81
|
+
if (isNewElement(clickWindow, click) ||
|
|
82
|
+
isClickOutsideRageClickWindow(clickWindow, click) ||
|
|
83
|
+
clickBoundingBox.isOutOfBounds) {
|
|
84
|
+
var returnValue = clickWindow.length >= RAGE_CLICK_THRESHOLD ? getRageClickAnalyticsEvent(clickWindow) : null;
|
|
85
|
+
resetClickWindow(click);
|
|
86
|
+
return returnValue;
|
|
33
87
|
}
|
|
34
|
-
|
|
35
|
-
// add the current click to the window
|
|
88
|
+
// add click to current window
|
|
36
89
|
clickWindow.push(click);
|
|
37
|
-
// if
|
|
38
|
-
|
|
39
|
-
|
|
90
|
+
// if we have enough clicks to be a rage click, set a timout to trigger the rage
|
|
91
|
+
// click event after the time threshold is reached.
|
|
92
|
+
// This will be cancelled if a new click is tracked.
|
|
93
|
+
if (clickWindow.length >= RAGE_CLICK_THRESHOLD) {
|
|
94
|
+
triggerRageClickTimeout = setTimeout(function () {
|
|
95
|
+
var _a = getRageClickAnalyticsEvent(clickWindow), rageClickEvent = _a.rageClickEvent, time = _a.time;
|
|
96
|
+
amplitude.track(constants_1.AMPLITUDE_ELEMENT_RAGE_CLICKED_EVENT, rageClickEvent, { time: time });
|
|
97
|
+
resetClickWindow();
|
|
98
|
+
}, RAGE_CLICK_WINDOW_MS);
|
|
40
99
|
}
|
|
41
|
-
|
|
42
|
-
// for it to be a rage click
|
|
43
|
-
var firstClick = clickWindow[0];
|
|
44
|
-
var lastClick = clickWindow[clickWindow.length - 1];
|
|
45
|
-
var rageClickEvent = tslib_1.__assign({ '[Amplitude] Begin Time': new Date(firstClick.timestamp).toISOString(), '[Amplitude] End Time': new Date(lastClick.timestamp).toISOString(), '[Amplitude] Duration': lastClick.timestamp - firstClick.timestamp, '[Amplitude] Clicks': clickWindow.map(function (click) { return ({
|
|
46
|
-
X: click.event.clientX,
|
|
47
|
-
Y: click.event.clientY,
|
|
48
|
-
Time: click.timestamp,
|
|
49
|
-
}); }), '[Amplitude] Click Count': clickWindow.length }, firstClick.targetElementProperties);
|
|
50
|
-
// restart the sliding window
|
|
51
|
-
clickWindow.splice(0, clickWindow.length);
|
|
52
|
-
return { rageClickEvent: rageClickEvent, time: firstClick.timestamp };
|
|
100
|
+
return null;
|
|
53
101
|
}), (0, rxjs_1.filter)(function (result) { return result !== null; }))
|
|
54
102
|
.subscribe(function (data) {
|
|
55
103
|
/* istanbul ignore if */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-rage-click.js","sourceRoot":"","sources":["../../../src/autocapture/track-rage-click.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllWindowObservables } from 'src/autocapture-plugin';\nimport { filter, map } from 'rxjs';\nimport { BrowserClient } from '@amplitude/analytics-core';\nimport { filterOutNonTrackableEvents, shouldTrackEvent } from '../helpers';\nimport { AMPLITUDE_ELEMENT_RAGE_CLICKED_EVENT } from '../constants';\nimport { DEFAULT_RAGE_CLICK_THRESHOLD, DEFAULT_RAGE_CLICK_WINDOW_MS } from '@amplitude/analytics-core';\n\nconst RAGE_CLICK_THRESHOLD = DEFAULT_RAGE_CLICK_THRESHOLD;\nconst RAGE_CLICK_WINDOW_MS = DEFAULT_RAGE_CLICK_WINDOW_MS;\n\ntype Click = {\n X: number;\n Y: number;\n Time: number;\n};\n\ntype EventRageClick = {\n '[Amplitude] Begin Time': string; // ISO-8601\n '[Amplitude] End Time': string; // ISO-8601\n '[Amplitude] Duration': number;\n '[Amplitude] Clicks': Array<Click>;\n '[Amplitude] Click Count': number;\n};\n\ntype ClickEvent = {\n event: MouseEvent | Event;\n timestamp: number;\n targetElementProperties: Record<string, any>;\n closestTrackedAncestor: Element | null;\n};\n\nexport function trackRageClicks({\n amplitude,\n allObservables,\n shouldTrackRageClick,\n}: {\n amplitude: BrowserClient;\n allObservables: AllWindowObservables;\n shouldTrackRageClick: shouldTrackEvent;\n}) {\n const { clickObservable } = allObservables;\n\n // Keep track of all clicks within the sliding window\n const clickWindow: ClickEvent[] = [];\n\n return clickObservable\n .pipe(\n filter(filterOutNonTrackableEvents),\n filter((click) => {\n return shouldTrackRageClick('click', click.closestTrackedAncestor);\n }),\n map((click) => {\n const now = click.timestamp;\n\n // if the current click isn't on the same element as the most recent click,\n // clear the sliding window and start over\n if (\n clickWindow.length > 0 &&\n clickWindow[clickWindow.length - 1].closestTrackedAncestor !== click.closestTrackedAncestor\n ) {\n clickWindow.splice(0, clickWindow.length);\n }\n\n // remove past clicks that are outside the sliding window\n let clickPtr = 0;\n for (; clickPtr < clickWindow.length; clickPtr++) {\n if (now - clickWindow[clickPtr].timestamp < RAGE_CLICK_WINDOW_MS) {\n break;\n }\n }\n clickWindow.splice(0, clickPtr);\n\n // add the current click to the window\n clickWindow.push(click);\n\n // if there's not enough clicks to be a rage click, return null\n if (clickWindow.length < RAGE_CLICK_THRESHOLD) {\n return null;\n }\n\n // if we've made it here, we have enough trailing clicks on the same element\n // for it to be a rage click\n const firstClick = clickWindow[0];\n const lastClick = clickWindow[clickWindow.length - 1];\n\n const rageClickEvent: EventRageClick = {\n '[Amplitude] Begin Time': new Date(firstClick.timestamp).toISOString(),\n '[Amplitude] End Time': new Date(lastClick.timestamp).toISOString(),\n '[Amplitude] Duration': lastClick.timestamp - firstClick.timestamp,\n '[Amplitude] Clicks': clickWindow.map((click) => ({\n X: (click.event as MouseEvent).clientX,\n Y: (click.event as MouseEvent).clientY,\n Time: click.timestamp,\n })),\n '[Amplitude] Click Count': clickWindow.length,\n ...firstClick.targetElementProperties,\n };\n\n // restart the sliding window\n clickWindow.splice(0, clickWindow.length);\n\n return { rageClickEvent, time: firstClick.timestamp };\n }),\n filter((result) => result !== null),\n )\n .subscribe((data: { rageClickEvent: EventRageClick; time: number } | null) => {\n /* istanbul ignore if */\n if (data === null) {\n return;\n }\n amplitude.track(AMPLITUDE_ELEMENT_RAGE_CLICKED_EVENT, data.rageClickEvent, { time: data.time });\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"track-rage-click.js","sourceRoot":"","sources":["../../../src/autocapture/track-rage-click.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllWindowObservables } from 'src/autocapture-plugin';\nimport { filter, map } from 'rxjs';\nimport { BrowserClient } from '@amplitude/analytics-core';\nimport { filterOutNonTrackableEvents, shouldTrackEvent } from '../helpers';\nimport { AMPLITUDE_ELEMENT_RAGE_CLICKED_EVENT } from '../constants';\nimport {\n DEFAULT_RAGE_CLICK_THRESHOLD,\n DEFAULT_RAGE_CLICK_WINDOW_MS,\n DEFAULT_RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD,\n} from '@amplitude/analytics-core';\n\nconst RAGE_CLICK_THRESHOLD = DEFAULT_RAGE_CLICK_THRESHOLD;\nconst RAGE_CLICK_WINDOW_MS = DEFAULT_RAGE_CLICK_WINDOW_MS;\nconst RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD = DEFAULT_RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD;\n\ntype Click = {\n X: number;\n Y: number;\n Time: number;\n};\n\ntype EventRageClick = {\n '[Amplitude] Begin Time': string; // ISO-8601\n '[Amplitude] End Time': string; // ISO-8601\n '[Amplitude] Duration': number;\n '[Amplitude] Clicks': Array<Click>;\n '[Amplitude] Click Count': number;\n};\n\ntype ClickEvent = {\n event: MouseEvent | Event;\n timestamp: number;\n targetElementProperties: Record<string, any>;\n closestTrackedAncestor: Element | null;\n};\n\ntype ClickRegionBoundingBox = {\n yMin?: number;\n yMax?: number;\n xMin?: number;\n xMax?: number;\n isOutOfBounds?: boolean;\n};\n\nfunction addCoordinates(regionBox: ClickRegionBoundingBox, click: ClickEvent) {\n const { clientX, clientY } = click.event as MouseEvent;\n regionBox.yMin = Math.min(regionBox.yMin ?? clientY, clientY);\n regionBox.yMax = Math.max(regionBox.yMax ?? clientY, clientY);\n regionBox.xMin = Math.min(regionBox.xMin ?? clientX, clientX);\n regionBox.xMax = Math.max(regionBox.xMax ?? clientX, clientX);\n regionBox.isOutOfBounds =\n regionBox.yMax - regionBox.yMin > RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD ||\n regionBox.xMax - regionBox.xMin > RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD;\n}\n\nfunction getRageClickAnalyticsEvent(clickWindow: ClickEvent[]) {\n const firstClick = clickWindow[0];\n const lastClick = clickWindow[clickWindow.length - 1];\n\n const rageClickEvent: EventRageClick = {\n '[Amplitude] Begin Time': new Date(firstClick.timestamp).toISOString(),\n '[Amplitude] End Time': new Date(lastClick.timestamp).toISOString(),\n '[Amplitude] Duration': lastClick.timestamp - firstClick.timestamp,\n '[Amplitude] Clicks': clickWindow.map((click) => ({\n X: (click.event as MouseEvent).clientX,\n Y: (click.event as MouseEvent).clientY,\n Time: click.timestamp,\n })),\n '[Amplitude] Click Count': clickWindow.length,\n ...firstClick.targetElementProperties,\n };\n\n return { rageClickEvent, time: firstClick.timestamp };\n}\n\nfunction isClickOutsideRageClickWindow(clickWindow: ClickEvent[], click: ClickEvent) {\n const firstIndex = Math.max(0, clickWindow.length - RAGE_CLICK_THRESHOLD + 1);\n const firstClick = clickWindow[firstIndex];\n return click.timestamp - firstClick.timestamp >= RAGE_CLICK_WINDOW_MS;\n}\n\nfunction isNewElement(clickWindow: ClickEvent[], click: ClickEvent) {\n return (\n clickWindow.length > 0 &&\n clickWindow[clickWindow.length - 1].closestTrackedAncestor !== click.closestTrackedAncestor\n );\n}\n\nexport function trackRageClicks({\n amplitude,\n allObservables,\n shouldTrackRageClick,\n}: {\n amplitude: BrowserClient;\n allObservables: AllWindowObservables;\n shouldTrackRageClick: shouldTrackEvent;\n}) {\n const { clickObservable } = allObservables;\n\n // Keep track of all clicks within the sliding window\n let clickWindow: ClickEvent[] = [];\n\n // Keep track of the region box for all clicks, to determine when a rage click is out of bounds\n let clickBoundingBox: ClickRegionBoundingBox = {};\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let triggerRageClickTimeout: any;\n\n // helper function to reset the click window and region box\n function resetClickWindow(click?: ClickEvent) {\n clickWindow = [];\n clickBoundingBox = {};\n if (click) {\n addCoordinates(clickBoundingBox, click);\n clickWindow.push(click);\n }\n }\n\n return clickObservable\n .pipe(\n filter(filterOutNonTrackableEvents),\n filter((click) => {\n return shouldTrackRageClick('click', click.closestTrackedAncestor);\n }),\n map((click) => {\n // reset the click wait timer if it exists\n if (triggerRageClickTimeout) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n clearTimeout(triggerRageClickTimeout);\n }\n\n // add click to bounding box\n addCoordinates(clickBoundingBox, click);\n\n // if there's just one click in the window, add it and return\n if (clickWindow.length === 0) {\n clickWindow.push(click);\n return null;\n }\n\n // if current click is:\n // 1. outside the rage click window\n // 2. on a new element\n // 3. out of bounds\n // then start a new click window\n if (\n isNewElement(clickWindow, click) ||\n isClickOutsideRageClickWindow(clickWindow, click) ||\n clickBoundingBox.isOutOfBounds\n ) {\n const returnValue =\n clickWindow.length >= RAGE_CLICK_THRESHOLD ? getRageClickAnalyticsEvent(clickWindow) : null;\n resetClickWindow(click);\n return returnValue;\n }\n\n // add click to current window\n clickWindow.push(click);\n\n // if we have enough clicks to be a rage click, set a timout to trigger the rage\n // click event after the time threshold is reached.\n // This will be cancelled if a new click is tracked.\n if (clickWindow.length >= RAGE_CLICK_THRESHOLD) {\n triggerRageClickTimeout = setTimeout(() => {\n const { rageClickEvent, time } = getRageClickAnalyticsEvent(clickWindow);\n amplitude.track(AMPLITUDE_ELEMENT_RAGE_CLICKED_EVENT, rageClickEvent, { time });\n resetClickWindow();\n }, RAGE_CLICK_WINDOW_MS);\n }\n\n return null;\n }),\n filter((result) => result !== null),\n )\n .subscribe((data: { rageClickEvent: EventRageClick; time: number } | null) => {\n /* istanbul ignore if */\n if (data === null) {\n return;\n }\n amplitude.track(AMPLITUDE_ELEMENT_RAGE_CLICKED_EVENT, data.rageClickEvent, { time: data.time });\n });\n}\n"]}
|
package/lib/cjs/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "1.10.
|
|
1
|
+
export declare const VERSION = "1.10.2";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/lib/cjs/version.js
CHANGED
package/lib/cjs/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":";;;AAAa,QAAA,OAAO,GAAG,QAAQ,CAAC","sourcesContent":["export const VERSION = '1.10.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":";;;AAAa,QAAA,OAAO,GAAG,QAAQ,CAAC","sourcesContent":["export const VERSION = '1.10.2';\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-rage-click.d.ts","sourceRoot":"","sources":["../../../src/autocapture/track-rage-click.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAA+B,gBAAgB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"track-rage-click.d.ts","sourceRoot":"","sources":["../../../src/autocapture/track-rage-click.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAA+B,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAqF3E,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,cAAc,EACd,oBAAoB,GACrB,EAAE;IACD,SAAS,EAAE,aAAa,CAAC;IACzB,cAAc,EAAE,oBAAoB,CAAC;IACrC,oBAAoB,EAAE,gBAAgB,CAAC;CACxC,+BAqFA"}
|
|
@@ -2,51 +2,99 @@ import { __assign } from "tslib";
|
|
|
2
2
|
import { filter, map } from 'rxjs';
|
|
3
3
|
import { filterOutNonTrackableEvents } from '../helpers';
|
|
4
4
|
import { AMPLITUDE_ELEMENT_RAGE_CLICKED_EVENT } from '../constants';
|
|
5
|
-
import { DEFAULT_RAGE_CLICK_THRESHOLD, DEFAULT_RAGE_CLICK_WINDOW_MS } from '@amplitude/analytics-core';
|
|
5
|
+
import { DEFAULT_RAGE_CLICK_THRESHOLD, DEFAULT_RAGE_CLICK_WINDOW_MS, DEFAULT_RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD, } from '@amplitude/analytics-core';
|
|
6
6
|
var RAGE_CLICK_THRESHOLD = DEFAULT_RAGE_CLICK_THRESHOLD;
|
|
7
7
|
var RAGE_CLICK_WINDOW_MS = DEFAULT_RAGE_CLICK_WINDOW_MS;
|
|
8
|
+
var RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD = DEFAULT_RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD;
|
|
9
|
+
function addCoordinates(regionBox, click) {
|
|
10
|
+
var _a, _b, _c, _d;
|
|
11
|
+
var _e = click.event, clientX = _e.clientX, clientY = _e.clientY;
|
|
12
|
+
regionBox.yMin = Math.min((_a = regionBox.yMin) !== null && _a !== void 0 ? _a : clientY, clientY);
|
|
13
|
+
regionBox.yMax = Math.max((_b = regionBox.yMax) !== null && _b !== void 0 ? _b : clientY, clientY);
|
|
14
|
+
regionBox.xMin = Math.min((_c = regionBox.xMin) !== null && _c !== void 0 ? _c : clientX, clientX);
|
|
15
|
+
regionBox.xMax = Math.max((_d = regionBox.xMax) !== null && _d !== void 0 ? _d : clientX, clientX);
|
|
16
|
+
regionBox.isOutOfBounds =
|
|
17
|
+
regionBox.yMax - regionBox.yMin > RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD ||
|
|
18
|
+
regionBox.xMax - regionBox.xMin > RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD;
|
|
19
|
+
}
|
|
20
|
+
function getRageClickAnalyticsEvent(clickWindow) {
|
|
21
|
+
var firstClick = clickWindow[0];
|
|
22
|
+
var lastClick = clickWindow[clickWindow.length - 1];
|
|
23
|
+
var rageClickEvent = __assign({ '[Amplitude] Begin Time': new Date(firstClick.timestamp).toISOString(), '[Amplitude] End Time': new Date(lastClick.timestamp).toISOString(), '[Amplitude] Duration': lastClick.timestamp - firstClick.timestamp, '[Amplitude] Clicks': clickWindow.map(function (click) { return ({
|
|
24
|
+
X: click.event.clientX,
|
|
25
|
+
Y: click.event.clientY,
|
|
26
|
+
Time: click.timestamp,
|
|
27
|
+
}); }), '[Amplitude] Click Count': clickWindow.length }, firstClick.targetElementProperties);
|
|
28
|
+
return { rageClickEvent: rageClickEvent, time: firstClick.timestamp };
|
|
29
|
+
}
|
|
30
|
+
function isClickOutsideRageClickWindow(clickWindow, click) {
|
|
31
|
+
var firstIndex = Math.max(0, clickWindow.length - RAGE_CLICK_THRESHOLD + 1);
|
|
32
|
+
var firstClick = clickWindow[firstIndex];
|
|
33
|
+
return click.timestamp - firstClick.timestamp >= RAGE_CLICK_WINDOW_MS;
|
|
34
|
+
}
|
|
35
|
+
function isNewElement(clickWindow, click) {
|
|
36
|
+
return (clickWindow.length > 0 &&
|
|
37
|
+
clickWindow[clickWindow.length - 1].closestTrackedAncestor !== click.closestTrackedAncestor);
|
|
38
|
+
}
|
|
8
39
|
export function trackRageClicks(_a) {
|
|
9
40
|
var amplitude = _a.amplitude, allObservables = _a.allObservables, shouldTrackRageClick = _a.shouldTrackRageClick;
|
|
10
41
|
var clickObservable = allObservables.clickObservable;
|
|
11
42
|
// Keep track of all clicks within the sliding window
|
|
12
43
|
var clickWindow = [];
|
|
44
|
+
// Keep track of the region box for all clicks, to determine when a rage click is out of bounds
|
|
45
|
+
var clickBoundingBox = {};
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
47
|
+
var triggerRageClickTimeout;
|
|
48
|
+
// helper function to reset the click window and region box
|
|
49
|
+
function resetClickWindow(click) {
|
|
50
|
+
clickWindow = [];
|
|
51
|
+
clickBoundingBox = {};
|
|
52
|
+
if (click) {
|
|
53
|
+
addCoordinates(clickBoundingBox, click);
|
|
54
|
+
clickWindow.push(click);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
13
57
|
return clickObservable
|
|
14
58
|
.pipe(filter(filterOutNonTrackableEvents), filter(function (click) {
|
|
15
59
|
return shouldTrackRageClick('click', click.closestTrackedAncestor);
|
|
16
60
|
}), map(function (click) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
61
|
+
// reset the click wait timer if it exists
|
|
62
|
+
if (triggerRageClickTimeout) {
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
64
|
+
clearTimeout(triggerRageClickTimeout);
|
|
65
|
+
}
|
|
66
|
+
// add click to bounding box
|
|
67
|
+
addCoordinates(clickBoundingBox, click);
|
|
68
|
+
// if there's just one click in the window, add it and return
|
|
69
|
+
if (clickWindow.length === 0) {
|
|
70
|
+
clickWindow.push(click);
|
|
71
|
+
return null;
|
|
23
72
|
}
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
73
|
+
// if current click is:
|
|
74
|
+
// 1. outside the rage click window
|
|
75
|
+
// 2. on a new element
|
|
76
|
+
// 3. out of bounds
|
|
77
|
+
// then start a new click window
|
|
78
|
+
if (isNewElement(clickWindow, click) ||
|
|
79
|
+
isClickOutsideRageClickWindow(clickWindow, click) ||
|
|
80
|
+
clickBoundingBox.isOutOfBounds) {
|
|
81
|
+
var returnValue = clickWindow.length >= RAGE_CLICK_THRESHOLD ? getRageClickAnalyticsEvent(clickWindow) : null;
|
|
82
|
+
resetClickWindow(click);
|
|
83
|
+
return returnValue;
|
|
30
84
|
}
|
|
31
|
-
|
|
32
|
-
// add the current click to the window
|
|
85
|
+
// add click to current window
|
|
33
86
|
clickWindow.push(click);
|
|
34
|
-
// if
|
|
35
|
-
|
|
36
|
-
|
|
87
|
+
// if we have enough clicks to be a rage click, set a timout to trigger the rage
|
|
88
|
+
// click event after the time threshold is reached.
|
|
89
|
+
// This will be cancelled if a new click is tracked.
|
|
90
|
+
if (clickWindow.length >= RAGE_CLICK_THRESHOLD) {
|
|
91
|
+
triggerRageClickTimeout = setTimeout(function () {
|
|
92
|
+
var _a = getRageClickAnalyticsEvent(clickWindow), rageClickEvent = _a.rageClickEvent, time = _a.time;
|
|
93
|
+
amplitude.track(AMPLITUDE_ELEMENT_RAGE_CLICKED_EVENT, rageClickEvent, { time: time });
|
|
94
|
+
resetClickWindow();
|
|
95
|
+
}, RAGE_CLICK_WINDOW_MS);
|
|
37
96
|
}
|
|
38
|
-
|
|
39
|
-
// for it to be a rage click
|
|
40
|
-
var firstClick = clickWindow[0];
|
|
41
|
-
var lastClick = clickWindow[clickWindow.length - 1];
|
|
42
|
-
var rageClickEvent = __assign({ '[Amplitude] Begin Time': new Date(firstClick.timestamp).toISOString(), '[Amplitude] End Time': new Date(lastClick.timestamp).toISOString(), '[Amplitude] Duration': lastClick.timestamp - firstClick.timestamp, '[Amplitude] Clicks': clickWindow.map(function (click) { return ({
|
|
43
|
-
X: click.event.clientX,
|
|
44
|
-
Y: click.event.clientY,
|
|
45
|
-
Time: click.timestamp,
|
|
46
|
-
}); }), '[Amplitude] Click Count': clickWindow.length }, firstClick.targetElementProperties);
|
|
47
|
-
// restart the sliding window
|
|
48
|
-
clickWindow.splice(0, clickWindow.length);
|
|
49
|
-
return { rageClickEvent: rageClickEvent, time: firstClick.timestamp };
|
|
97
|
+
return null;
|
|
50
98
|
}), filter(function (result) { return result !== null; }))
|
|
51
99
|
.subscribe(function (data) {
|
|
52
100
|
/* istanbul ignore if */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-rage-click.js","sourceRoot":"","sources":["../../../src/autocapture/track-rage-click.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllWindowObservables } from 'src/autocapture-plugin';\nimport { filter, map } from 'rxjs';\nimport { BrowserClient } from '@amplitude/analytics-core';\nimport { filterOutNonTrackableEvents, shouldTrackEvent } from '../helpers';\nimport { AMPLITUDE_ELEMENT_RAGE_CLICKED_EVENT } from '../constants';\nimport { DEFAULT_RAGE_CLICK_THRESHOLD, DEFAULT_RAGE_CLICK_WINDOW_MS } from '@amplitude/analytics-core';\n\nconst RAGE_CLICK_THRESHOLD = DEFAULT_RAGE_CLICK_THRESHOLD;\nconst RAGE_CLICK_WINDOW_MS = DEFAULT_RAGE_CLICK_WINDOW_MS;\n\ntype Click = {\n X: number;\n Y: number;\n Time: number;\n};\n\ntype EventRageClick = {\n '[Amplitude] Begin Time': string; // ISO-8601\n '[Amplitude] End Time': string; // ISO-8601\n '[Amplitude] Duration': number;\n '[Amplitude] Clicks': Array<Click>;\n '[Amplitude] Click Count': number;\n};\n\ntype ClickEvent = {\n event: MouseEvent | Event;\n timestamp: number;\n targetElementProperties: Record<string, any>;\n closestTrackedAncestor: Element | null;\n};\n\nexport function trackRageClicks({\n amplitude,\n allObservables,\n shouldTrackRageClick,\n}: {\n amplitude: BrowserClient;\n allObservables: AllWindowObservables;\n shouldTrackRageClick: shouldTrackEvent;\n}) {\n const { clickObservable } = allObservables;\n\n // Keep track of all clicks within the sliding window\n const clickWindow: ClickEvent[] = [];\n\n return clickObservable\n .pipe(\n filter(filterOutNonTrackableEvents),\n filter((click) => {\n return shouldTrackRageClick('click', click.closestTrackedAncestor);\n }),\n map((click) => {\n const now = click.timestamp;\n\n // if the current click isn't on the same element as the most recent click,\n // clear the sliding window and start over\n if (\n clickWindow.length > 0 &&\n clickWindow[clickWindow.length - 1].closestTrackedAncestor !== click.closestTrackedAncestor\n ) {\n clickWindow.splice(0, clickWindow.length);\n }\n\n // remove past clicks that are outside the sliding window\n let clickPtr = 0;\n for (; clickPtr < clickWindow.length; clickPtr++) {\n if (now - clickWindow[clickPtr].timestamp < RAGE_CLICK_WINDOW_MS) {\n break;\n }\n }\n clickWindow.splice(0, clickPtr);\n\n // add the current click to the window\n clickWindow.push(click);\n\n // if there's not enough clicks to be a rage click, return null\n if (clickWindow.length < RAGE_CLICK_THRESHOLD) {\n return null;\n }\n\n // if we've made it here, we have enough trailing clicks on the same element\n // for it to be a rage click\n const firstClick = clickWindow[0];\n const lastClick = clickWindow[clickWindow.length - 1];\n\n const rageClickEvent: EventRageClick = {\n '[Amplitude] Begin Time': new Date(firstClick.timestamp).toISOString(),\n '[Amplitude] End Time': new Date(lastClick.timestamp).toISOString(),\n '[Amplitude] Duration': lastClick.timestamp - firstClick.timestamp,\n '[Amplitude] Clicks': clickWindow.map((click) => ({\n X: (click.event as MouseEvent).clientX,\n Y: (click.event as MouseEvent).clientY,\n Time: click.timestamp,\n })),\n '[Amplitude] Click Count': clickWindow.length,\n ...firstClick.targetElementProperties,\n };\n\n // restart the sliding window\n clickWindow.splice(0, clickWindow.length);\n\n return { rageClickEvent, time: firstClick.timestamp };\n }),\n filter((result) => result !== null),\n )\n .subscribe((data: { rageClickEvent: EventRageClick; time: number } | null) => {\n /* istanbul ignore if */\n if (data === null) {\n return;\n }\n amplitude.track(AMPLITUDE_ELEMENT_RAGE_CLICKED_EVENT, data.rageClickEvent, { time: data.time });\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"track-rage-click.js","sourceRoot":"","sources":["../../../src/autocapture/track-rage-click.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllWindowObservables } from 'src/autocapture-plugin';\nimport { filter, map } from 'rxjs';\nimport { BrowserClient } from '@amplitude/analytics-core';\nimport { filterOutNonTrackableEvents, shouldTrackEvent } from '../helpers';\nimport { AMPLITUDE_ELEMENT_RAGE_CLICKED_EVENT } from '../constants';\nimport {\n DEFAULT_RAGE_CLICK_THRESHOLD,\n DEFAULT_RAGE_CLICK_WINDOW_MS,\n DEFAULT_RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD,\n} from '@amplitude/analytics-core';\n\nconst RAGE_CLICK_THRESHOLD = DEFAULT_RAGE_CLICK_THRESHOLD;\nconst RAGE_CLICK_WINDOW_MS = DEFAULT_RAGE_CLICK_WINDOW_MS;\nconst RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD = DEFAULT_RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD;\n\ntype Click = {\n X: number;\n Y: number;\n Time: number;\n};\n\ntype EventRageClick = {\n '[Amplitude] Begin Time': string; // ISO-8601\n '[Amplitude] End Time': string; // ISO-8601\n '[Amplitude] Duration': number;\n '[Amplitude] Clicks': Array<Click>;\n '[Amplitude] Click Count': number;\n};\n\ntype ClickEvent = {\n event: MouseEvent | Event;\n timestamp: number;\n targetElementProperties: Record<string, any>;\n closestTrackedAncestor: Element | null;\n};\n\ntype ClickRegionBoundingBox = {\n yMin?: number;\n yMax?: number;\n xMin?: number;\n xMax?: number;\n isOutOfBounds?: boolean;\n};\n\nfunction addCoordinates(regionBox: ClickRegionBoundingBox, click: ClickEvent) {\n const { clientX, clientY } = click.event as MouseEvent;\n regionBox.yMin = Math.min(regionBox.yMin ?? clientY, clientY);\n regionBox.yMax = Math.max(regionBox.yMax ?? clientY, clientY);\n regionBox.xMin = Math.min(regionBox.xMin ?? clientX, clientX);\n regionBox.xMax = Math.max(regionBox.xMax ?? clientX, clientX);\n regionBox.isOutOfBounds =\n regionBox.yMax - regionBox.yMin > RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD ||\n regionBox.xMax - regionBox.xMin > RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD;\n}\n\nfunction getRageClickAnalyticsEvent(clickWindow: ClickEvent[]) {\n const firstClick = clickWindow[0];\n const lastClick = clickWindow[clickWindow.length - 1];\n\n const rageClickEvent: EventRageClick = {\n '[Amplitude] Begin Time': new Date(firstClick.timestamp).toISOString(),\n '[Amplitude] End Time': new Date(lastClick.timestamp).toISOString(),\n '[Amplitude] Duration': lastClick.timestamp - firstClick.timestamp,\n '[Amplitude] Clicks': clickWindow.map((click) => ({\n X: (click.event as MouseEvent).clientX,\n Y: (click.event as MouseEvent).clientY,\n Time: click.timestamp,\n })),\n '[Amplitude] Click Count': clickWindow.length,\n ...firstClick.targetElementProperties,\n };\n\n return { rageClickEvent, time: firstClick.timestamp };\n}\n\nfunction isClickOutsideRageClickWindow(clickWindow: ClickEvent[], click: ClickEvent) {\n const firstIndex = Math.max(0, clickWindow.length - RAGE_CLICK_THRESHOLD + 1);\n const firstClick = clickWindow[firstIndex];\n return click.timestamp - firstClick.timestamp >= RAGE_CLICK_WINDOW_MS;\n}\n\nfunction isNewElement(clickWindow: ClickEvent[], click: ClickEvent) {\n return (\n clickWindow.length > 0 &&\n clickWindow[clickWindow.length - 1].closestTrackedAncestor !== click.closestTrackedAncestor\n );\n}\n\nexport function trackRageClicks({\n amplitude,\n allObservables,\n shouldTrackRageClick,\n}: {\n amplitude: BrowserClient;\n allObservables: AllWindowObservables;\n shouldTrackRageClick: shouldTrackEvent;\n}) {\n const { clickObservable } = allObservables;\n\n // Keep track of all clicks within the sliding window\n let clickWindow: ClickEvent[] = [];\n\n // Keep track of the region box for all clicks, to determine when a rage click is out of bounds\n let clickBoundingBox: ClickRegionBoundingBox = {};\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let triggerRageClickTimeout: any;\n\n // helper function to reset the click window and region box\n function resetClickWindow(click?: ClickEvent) {\n clickWindow = [];\n clickBoundingBox = {};\n if (click) {\n addCoordinates(clickBoundingBox, click);\n clickWindow.push(click);\n }\n }\n\n return clickObservable\n .pipe(\n filter(filterOutNonTrackableEvents),\n filter((click) => {\n return shouldTrackRageClick('click', click.closestTrackedAncestor);\n }),\n map((click) => {\n // reset the click wait timer if it exists\n if (triggerRageClickTimeout) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n clearTimeout(triggerRageClickTimeout);\n }\n\n // add click to bounding box\n addCoordinates(clickBoundingBox, click);\n\n // if there's just one click in the window, add it and return\n if (clickWindow.length === 0) {\n clickWindow.push(click);\n return null;\n }\n\n // if current click is:\n // 1. outside the rage click window\n // 2. on a new element\n // 3. out of bounds\n // then start a new click window\n if (\n isNewElement(clickWindow, click) ||\n isClickOutsideRageClickWindow(clickWindow, click) ||\n clickBoundingBox.isOutOfBounds\n ) {\n const returnValue =\n clickWindow.length >= RAGE_CLICK_THRESHOLD ? getRageClickAnalyticsEvent(clickWindow) : null;\n resetClickWindow(click);\n return returnValue;\n }\n\n // add click to current window\n clickWindow.push(click);\n\n // if we have enough clicks to be a rage click, set a timout to trigger the rage\n // click event after the time threshold is reached.\n // This will be cancelled if a new click is tracked.\n if (clickWindow.length >= RAGE_CLICK_THRESHOLD) {\n triggerRageClickTimeout = setTimeout(() => {\n const { rageClickEvent, time } = getRageClickAnalyticsEvent(clickWindow);\n amplitude.track(AMPLITUDE_ELEMENT_RAGE_CLICKED_EVENT, rageClickEvent, { time });\n resetClickWindow();\n }, RAGE_CLICK_WINDOW_MS);\n }\n\n return null;\n }),\n filter((result) => result !== null),\n )\n .subscribe((data: { rageClickEvent: EventRageClick; time: number } | null) => {\n /* istanbul ignore if */\n if (data === null) {\n return;\n }\n amplitude.track(AMPLITUDE_ELEMENT_RAGE_CLICKED_EVENT, data.rageClickEvent, { time: data.time });\n });\n}\n"]}
|
package/lib/esm/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "1.10.
|
|
1
|
+
export declare const VERSION = "1.10.2";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/lib/esm/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export var VERSION = '1.10.
|
|
1
|
+
export var VERSION = '1.10.2';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
package/lib/esm/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,IAAM,OAAO,GAAG,QAAQ,CAAC","sourcesContent":["export const VERSION = '1.10.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,IAAM,OAAO,GAAG,QAAQ,CAAC","sourcesContent":["export const VERSION = '1.10.2';\n"]}
|