@amplitude/plugin-autocapture-browser 1.23.7 → 1.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/autocapture/track-click.d.ts.map +1 -1
- package/lib/cjs/autocapture/track-click.js.map +1 -1
- package/lib/cjs/autocapture/track-exposure.d.ts +12 -0
- package/lib/cjs/autocapture/track-exposure.d.ts.map +1 -0
- package/lib/cjs/autocapture/track-exposure.js +56 -0
- package/lib/cjs/autocapture/track-exposure.js.map +1 -0
- package/lib/cjs/autocapture/track-scroll.d.ts +15 -0
- package/lib/cjs/autocapture/track-scroll.d.ts.map +1 -0
- package/lib/cjs/autocapture/track-scroll.js +34 -0
- package/lib/cjs/autocapture/track-scroll.js.map +1 -0
- package/lib/cjs/autocapture/track-thrashed-cursor.js +1 -1
- package/lib/cjs/autocapture/track-thrashed-cursor.js.map +1 -1
- package/lib/cjs/autocapture/track-viewport-content-updated.d.ts +25 -0
- package/lib/cjs/autocapture/track-viewport-content-updated.d.ts.map +1 -0
- package/lib/cjs/autocapture/track-viewport-content-updated.js +71 -0
- package/lib/cjs/autocapture/track-viewport-content-updated.js.map +1 -0
- package/lib/cjs/autocapture-plugin.d.ts +4 -0
- package/lib/cjs/autocapture-plugin.d.ts.map +1 -1
- package/lib/cjs/autocapture-plugin.js +109 -14
- package/lib/cjs/autocapture-plugin.js.map +1 -1
- package/lib/cjs/constants.d.ts +7 -0
- package/lib/cjs/constants.d.ts.map +1 -1
- package/lib/cjs/constants.js +9 -1
- package/lib/cjs/constants.js.map +1 -1
- package/lib/cjs/data-extractor.d.ts +1 -0
- package/lib/cjs/data-extractor.d.ts.map +1 -1
- package/lib/cjs/data-extractor.js +19 -0
- package/lib/cjs/data-extractor.js.map +1 -1
- package/lib/cjs/helpers.d.ts +1 -0
- package/lib/cjs/helpers.d.ts.map +1 -1
- package/lib/cjs/helpers.js +22 -1
- package/lib/cjs/helpers.js.map +1 -1
- package/lib/cjs/libs/element-path.d.ts +2 -0
- package/lib/cjs/libs/element-path.d.ts.map +1 -0
- package/lib/cjs/libs/element-path.js +177 -0
- package/lib/cjs/libs/element-path.js.map +1 -0
- package/lib/cjs/observables.d.ts +3 -0
- package/lib/cjs/observables.d.ts.map +1 -1
- package/lib/cjs/observables.js +70 -3
- package/lib/cjs/observables.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-click.d.ts.map +1 -1
- package/lib/esm/autocapture/track-click.js.map +1 -1
- package/lib/esm/autocapture/track-exposure.d.ts +12 -0
- package/lib/esm/autocapture/track-exposure.d.ts.map +1 -0
- package/lib/esm/autocapture/track-exposure.js +52 -0
- package/lib/esm/autocapture/track-exposure.js.map +1 -0
- package/lib/esm/autocapture/track-scroll.d.ts +15 -0
- package/lib/esm/autocapture/track-scroll.d.ts.map +1 -0
- package/lib/esm/autocapture/track-scroll.js +30 -0
- package/lib/esm/autocapture/track-scroll.js.map +1 -0
- package/lib/esm/autocapture/track-thrashed-cursor.js +1 -1
- package/lib/esm/autocapture/track-thrashed-cursor.js.map +1 -1
- package/lib/esm/autocapture/track-viewport-content-updated.d.ts +25 -0
- package/lib/esm/autocapture/track-viewport-content-updated.d.ts.map +1 -0
- package/lib/esm/autocapture/track-viewport-content-updated.js +65 -0
- package/lib/esm/autocapture/track-viewport-content-updated.js.map +1 -0
- package/lib/esm/autocapture-plugin.d.ts +4 -0
- package/lib/esm/autocapture-plugin.d.ts.map +1 -1
- package/lib/esm/autocapture-plugin.js +111 -16
- package/lib/esm/autocapture-plugin.js.map +1 -1
- package/lib/esm/constants.d.ts +7 -0
- package/lib/esm/constants.d.ts.map +1 -1
- package/lib/esm/constants.js +8 -0
- package/lib/esm/constants.js.map +1 -1
- package/lib/esm/data-extractor.d.ts +1 -0
- package/lib/esm/data-extractor.d.ts.map +1 -1
- package/lib/esm/data-extractor.js +20 -1
- package/lib/esm/data-extractor.js.map +1 -1
- package/lib/esm/helpers.d.ts +1 -0
- package/lib/esm/helpers.d.ts.map +1 -1
- package/lib/esm/helpers.js +21 -1
- package/lib/esm/helpers.js.map +1 -1
- package/lib/esm/libs/element-path.d.ts +2 -0
- package/lib/esm/libs/element-path.d.ts.map +1 -0
- package/lib/esm/libs/element-path.js +173 -0
- package/lib/esm/libs/element-path.js.map +1 -0
- package/lib/esm/observables.d.ts +3 -0
- package/lib/esm/observables.d.ts.map +1 -1
- package/lib/esm/observables.js +67 -2
- package/lib/esm/observables.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-click.d.ts.map +1 -1
- package/lib/scripts/autocapture/track-exposure.d.ts +12 -0
- package/lib/scripts/autocapture/track-exposure.d.ts.map +1 -0
- package/lib/scripts/autocapture/track-scroll.d.ts +15 -0
- package/lib/scripts/autocapture/track-scroll.d.ts.map +1 -0
- package/lib/scripts/autocapture/track-viewport-content-updated.d.ts +25 -0
- package/lib/scripts/autocapture/track-viewport-content-updated.d.ts.map +1 -0
- package/lib/scripts/autocapture-plugin.d.ts +4 -0
- package/lib/scripts/autocapture-plugin.d.ts.map +1 -1
- package/lib/scripts/constants.d.ts +7 -0
- package/lib/scripts/constants.d.ts.map +1 -1
- package/lib/scripts/data-extractor.d.ts +1 -0
- package/lib/scripts/data-extractor.d.ts.map +1 -1
- package/lib/scripts/helpers.d.ts +1 -0
- package/lib/scripts/helpers.d.ts.map +1 -1
- package/lib/scripts/libs/element-path.d.ts +2 -0
- package/lib/scripts/libs/element-path.d.ts.map +1 -0
- package/lib/scripts/observables.d.ts +3 -0
- package/lib/scripts/observables.d.ts.map +1 -1
- package/lib/scripts/version.d.ts +1 -1
- package/package.json +2 -2
- package/lib/cjs/libs/finder.d.ts +0 -13
- package/lib/cjs/libs/finder.d.ts.map +0 -1
- package/lib/cjs/libs/finder.js +0 -348
- package/lib/cjs/libs/finder.js.map +0 -1
- package/lib/esm/libs/finder.d.ts +0 -13
- package/lib/esm/libs/finder.d.ts.map +0 -1
- package/lib/esm/libs/finder.js +0 -344
- package/lib/esm/libs/finder.js.map +0 -1
- package/lib/scripts/libs/finder.d.ts +0 -13
- package/lib/scripts/libs/finder.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-click.d.ts","sourceRoot":"","sources":["../../../src/autocapture/track-click.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,
|
|
1
|
+
{"version":3,"file":"track-click.d.ts","sourceRoot":"","sources":["../../../src/autocapture/track-click.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAwD,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC3G,OAAO,EAAc,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAA+B,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG3E,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,gBAAgB,GACjB,EAAE;IACD,SAAS,EAAE,aAAa,CAAC;IACzB,cAAc,EAAE,oBAAoB,CAAC;IACrC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,gBAAgB,EAAE,kBAAkB,CAAC;CACtC,8BAkBA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-click.js","sourceRoot":"","sources":["../../../src/autocapture/track-click.ts"],"names":[],"mappings":";;;AAGA,sCAA2E;AAC3E,0CAA+D;AAE/D,SAAgB,WAAW,CAAC,EAU3B;QATC,SAAS,eAAA,EACT,cAAc,oBAAA,EACd,gBAAgB,sBAAA,EAChB,gBAAgB,sBAAA;IAOR,IAAA,eAAe,GAAK,cAAc,gBAAnB,CAAoB;IAE3C,IAAM,uBAAuB,GAAG,eAAe;SAC5C,MAAM,CAAC,qCAA2B,CAAC;SACnC,MAAM,CAAC,UAAC,
|
|
1
|
+
{"version":3,"file":"track-click.js","sourceRoot":"","sources":["../../../src/autocapture/track-click.ts"],"names":[],"mappings":";;;AAGA,sCAA2E;AAC3E,0CAA+D;AAE/D,SAAgB,WAAW,CAAC,EAU3B;QATC,SAAS,eAAA,EACT,cAAc,oBAAA,EACd,gBAAgB,sBAAA,EAChB,gBAAgB,sBAAA;IAOR,IAAA,eAAe,GAAK,cAAc,gBAAnB,CAAoB;IAE3C,IAAM,uBAAuB,GAAG,eAAe;SAC5C,MAAM,CAAC,qCAA2B,CAAC;SACnC,MAAM,CAAC,UAAC,KAA+C;QACtD,wDAAwD;QACxD,OAAO,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,sBAAsB,CAAC,CAAC;IACjE,CAAC,CAAC;SACD,GAAG,CAAC,UAAC,KAA+C,IAAK,OAAA,gBAAgB,CAAC,KAAK,CAAC,EAAvB,CAAuB,CAAC,CAAC;IAErF,IAAM,MAAM,GACV,uBAAuB,CAAC;IAE1B,OAAO,MAAM,CAAC,SAAS,CAAC,UAAC,KAAsD;QAC7E,0BAA0B;QAC1B,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,KAAK,CAAC,2CAA+B,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;AACL,CAAC;AA5BD,kCA4BC","sourcesContent":["import { AllWindowObservables } from '../autocapture-plugin';\nimport { ElementBasedEvent, type ElementBasedTimestampedEvent, type evaluateTriggersFn } from '../helpers';\nimport { Observable, BrowserClient } from '@amplitude/analytics-core';\nimport { filterOutNonTrackableEvents, shouldTrackEvent } from '../helpers';\nimport { AMPLITUDE_ELEMENT_CLICKED_EVENT } from '../constants';\n\nexport function trackClicks({\n amplitude,\n allObservables,\n shouldTrackEvent,\n evaluateTriggers,\n}: {\n amplitude: BrowserClient;\n allObservables: AllWindowObservables;\n shouldTrackEvent: shouldTrackEvent;\n evaluateTriggers: evaluateTriggersFn;\n}) {\n const { clickObservable } = allObservables;\n\n const clickObservableFiltered = clickObservable\n .filter(filterOutNonTrackableEvents)\n .filter((click: ElementBasedTimestampedEvent<MouseEvent>) => {\n // Only track clicks on elements that should be tracked,\n return shouldTrackEvent('click', click.closestTrackedAncestor);\n })\n .map((click: ElementBasedTimestampedEvent<MouseEvent>) => evaluateTriggers(click));\n\n const clicks: Observable<typeof clickObservableFiltered extends Observable<infer U> ? U : never> =\n clickObservableFiltered;\n\n return clicks.subscribe((click: ElementBasedTimestampedEvent<ElementBasedEvent>) => {\n /* istanbul ignore next */\n amplitude?.track(AMPLITUDE_ELEMENT_CLICKED_EVENT, click.targetElementProperties);\n });\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AllWindowObservables } from '../autocapture-plugin';
|
|
2
|
+
import { DataExtractor } from '../data-extractor';
|
|
3
|
+
export declare function trackExposure({ allObservables, onExposure, dataExtractor, exposureDuration, }: {
|
|
4
|
+
allObservables: AllWindowObservables;
|
|
5
|
+
onExposure: (elementPath: string) => void;
|
|
6
|
+
dataExtractor: DataExtractor;
|
|
7
|
+
exposureDuration?: number;
|
|
8
|
+
}): {
|
|
9
|
+
unsubscribe: () => void;
|
|
10
|
+
reset: () => void;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=track-exposure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-exposure.d.ts","sourceRoot":"","sources":["../../../src/autocapture/track-exposure.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,wBAAgB,aAAa,CAAC,EAC5B,cAAc,EACd,UAAU,EACV,aAAa,EACb,gBAA4C,GAC7C,EAAE;IACD,cAAc,EAAE,oBAAoB,CAAC;IACrC,UAAU,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,aAAa,EAAE,aAAa,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;;;EAsDA"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.trackExposure = void 0;
|
|
4
|
+
/* eslint-disable no-restricted-globals */
|
|
5
|
+
var analytics_core_1 = require("@amplitude/analytics-core");
|
|
6
|
+
function trackExposure(_a) {
|
|
7
|
+
var allObservables = _a.allObservables, onExposure = _a.onExposure, dataExtractor = _a.dataExtractor, _b = _a.exposureDuration, exposureDuration = _b === void 0 ? analytics_core_1.DEFAULT_EXPOSURE_DURATION : _b;
|
|
8
|
+
// Track which elements have been marked as exposed (per-element state)
|
|
9
|
+
var exposureMap = new Map();
|
|
10
|
+
// Track active timers for elements that are currently visible but not yet exposed
|
|
11
|
+
var exposureTimerMap = new Map();
|
|
12
|
+
var exposureObservable = allObservables.exposureObservable;
|
|
13
|
+
var exposureSubscription = exposureObservable.subscribe(function (event) {
|
|
14
|
+
var entry = event;
|
|
15
|
+
var element = entry.target;
|
|
16
|
+
if (entry.isIntersecting) {
|
|
17
|
+
// Element became visible - start exposure timer if not already exposed
|
|
18
|
+
if (!exposureMap.get(element)) {
|
|
19
|
+
var timer = setTimeout(function () {
|
|
20
|
+
// Element has been visible for exposureDuration - mark as exposed
|
|
21
|
+
exposureMap.set(element, true);
|
|
22
|
+
// Record the CSS selector path in the shared exposure state
|
|
23
|
+
var elementPath = dataExtractor.getElementPath(element);
|
|
24
|
+
onExposure(elementPath);
|
|
25
|
+
// Clear the timer reference
|
|
26
|
+
exposureTimerMap.set(element, null);
|
|
27
|
+
}, exposureDuration);
|
|
28
|
+
exposureTimerMap.set(element, timer);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else if (!entry.isIntersecting && entry.intersectionRatio < 1.0) {
|
|
32
|
+
// Element left viewport - cancel exposure timer if one exists
|
|
33
|
+
var timer = exposureTimerMap.get(element);
|
|
34
|
+
if (timer) {
|
|
35
|
+
clearTimeout(timer);
|
|
36
|
+
exposureTimerMap.set(element, null);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return {
|
|
41
|
+
unsubscribe: function () {
|
|
42
|
+
exposureSubscription.unsubscribe();
|
|
43
|
+
},
|
|
44
|
+
reset: function () {
|
|
45
|
+
exposureTimerMap.forEach(function (timer) {
|
|
46
|
+
if (timer) {
|
|
47
|
+
clearTimeout(timer);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
exposureTimerMap.clear();
|
|
51
|
+
exposureMap.clear();
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
exports.trackExposure = trackExposure;
|
|
56
|
+
//# sourceMappingURL=track-exposure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-exposure.js","sourceRoot":"","sources":["../../../src/autocapture/track-exposure.ts"],"names":[],"mappings":";;;AAAA,0CAA0C;AAC1C,4DAAsE;AAItE,SAAgB,aAAa,CAAC,EAU7B;QATC,cAAc,oBAAA,EACd,UAAU,gBAAA,EACV,aAAa,mBAAA,EACb,wBAA4C,EAA5C,gBAAgB,mBAAG,0CAAyB,KAAA;IAO5C,uEAAuE;IACvE,IAAM,WAAW,GAAG,IAAI,GAAG,EAAoB,CAAC;IAEhD,kFAAkF;IAClF,IAAM,gBAAgB,GAAG,IAAI,GAAG,EAA6D,CAAC;IAEtF,IAAA,kBAAkB,GAAK,cAAc,mBAAnB,CAAoB;IAE9C,IAAM,oBAAoB,GAAG,kBAAkB,CAAC,SAAS,CAAC,UAAC,KAAK;QAC9D,IAAM,KAAK,GAAG,KAA6C,CAAC;QAC5D,IAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC;QAE7B,IAAI,KAAK,CAAC,cAAc,EAAE;YACxB,uEAAuE;YACvE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;gBAC7B,IAAM,KAAK,GAAG,UAAU,CAAC;oBACvB,kEAAkE;oBAClE,WAAW,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;oBAE/B,4DAA4D;oBAC5D,IAAM,WAAW,GAAG,aAAa,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;oBAC1D,UAAU,CAAC,WAAW,CAAC,CAAC;oBAExB,4BAA4B;oBAC5B,gBAAgB,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBACtC,CAAC,EAAE,gBAAgB,CAAC,CAAC;gBAErB,gBAAgB,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;aACtC;SACF;aAAM,IAAI,CAAC,KAAK,CAAC,cAAc,IAAI,KAAK,CAAC,iBAAiB,GAAG,GAAG,EAAE;YACjE,8DAA8D;YAC9D,IAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5C,IAAI,KAAK,EAAE;gBACT,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,gBAAgB,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;aACrC;SACF;IACH,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,WAAW,EAAE;YACX,oBAAoB,CAAC,WAAW,EAAE,CAAC;QACrC,CAAC;QACD,KAAK,EAAE;YACL,gBAAgB,CAAC,OAAO,CAAC,UAAC,KAAK;gBAC7B,IAAI,KAAK,EAAE;oBACT,YAAY,CAAC,KAAK,CAAC,CAAC;iBACrB;YACH,CAAC,CAAC,CAAC;YACH,gBAAgB,CAAC,KAAK,EAAE,CAAC;YACzB,WAAW,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC;AAhED,sCAgEC","sourcesContent":["/* eslint-disable no-restricted-globals */\nimport { DEFAULT_EXPOSURE_DURATION } from '@amplitude/analytics-core';\nimport { AllWindowObservables } from '../autocapture-plugin';\nimport { DataExtractor } from '../data-extractor';\n\nexport function trackExposure({\n allObservables,\n onExposure,\n dataExtractor,\n exposureDuration = DEFAULT_EXPOSURE_DURATION,\n}: {\n allObservables: AllWindowObservables;\n onExposure: (elementPath: string) => void;\n dataExtractor: DataExtractor;\n exposureDuration?: number;\n}) {\n // Track which elements have been marked as exposed (per-element state)\n const exposureMap = new Map<Element, boolean>();\n\n // Track active timers for elements that are currently visible but not yet exposed\n const exposureTimerMap = new Map<Element, ReturnType<typeof setTimeout> | null | undefined>();\n\n const { exposureObservable } = allObservables;\n\n const exposureSubscription = exposureObservable.subscribe((event) => {\n const entry = event as unknown as IntersectionObserverEntry;\n const element = entry.target;\n\n if (entry.isIntersecting) {\n // Element became visible - start exposure timer if not already exposed\n if (!exposureMap.get(element)) {\n const timer = setTimeout(() => {\n // Element has been visible for exposureDuration - mark as exposed\n exposureMap.set(element, true);\n\n // Record the CSS selector path in the shared exposure state\n const elementPath = dataExtractor.getElementPath(element);\n onExposure(elementPath);\n\n // Clear the timer reference\n exposureTimerMap.set(element, null);\n }, exposureDuration);\n\n exposureTimerMap.set(element, timer);\n }\n } else if (!entry.isIntersecting && entry.intersectionRatio < 1.0) {\n // Element left viewport - cancel exposure timer if one exists\n const timer = exposureTimerMap.get(element);\n if (timer) {\n clearTimeout(timer);\n exposureTimerMap.set(element, null);\n }\n }\n });\n\n return {\n unsubscribe: () => {\n exposureSubscription.unsubscribe();\n },\n reset: () => {\n exposureTimerMap.forEach((timer) => {\n if (timer) {\n clearTimeout(timer);\n }\n });\n exposureTimerMap.clear();\n exposureMap.clear();\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AllWindowObservables } from '../autocapture-plugin';
|
|
2
|
+
import { BrowserClient } from '@amplitude/analytics-core';
|
|
3
|
+
export interface ScrollState {
|
|
4
|
+
maxX: number;
|
|
5
|
+
maxY: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function trackScroll({ amplitude, allObservables, }: {
|
|
8
|
+
amplitude: BrowserClient;
|
|
9
|
+
allObservables: AllWindowObservables;
|
|
10
|
+
}): {
|
|
11
|
+
unsubscribe: () => void;
|
|
12
|
+
getState: () => ScrollState;
|
|
13
|
+
reset: () => void;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=track-scroll.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-scroll.d.ts","sourceRoot":"","sources":["../../../src/autocapture/track-scroll.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAkB,MAAM,2BAA2B,CAAC;AAE1E,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,cAAc,GACf,EAAE;IACD,SAAS,EAAE,aAAa,CAAC;IACzB,cAAc,EAAE,oBAAoB,CAAC;CACtC;;;;EA6BA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.trackScroll = void 0;
|
|
4
|
+
var analytics_core_1 = require("@amplitude/analytics-core");
|
|
5
|
+
function trackScroll(_a) {
|
|
6
|
+
var amplitude = _a.amplitude, allObservables = _a.allObservables;
|
|
7
|
+
// amplitude is reserved for future periodic scroll event tracking
|
|
8
|
+
void amplitude;
|
|
9
|
+
var scrollObservable = allObservables.scrollObservable;
|
|
10
|
+
var state = { maxX: 0, maxY: 0 };
|
|
11
|
+
var scrollSubscription = scrollObservable.subscribe(function () {
|
|
12
|
+
var _a, _b, _c, _d;
|
|
13
|
+
var globalScope = (0, analytics_core_1.getGlobalScope)();
|
|
14
|
+
/* istanbul ignore next */
|
|
15
|
+
var currentX = Math.floor((_b = (_a = globalScope === null || globalScope === void 0 ? void 0 : globalScope.scrollX) !== null && _a !== void 0 ? _a : globalScope === null || globalScope === void 0 ? void 0 : globalScope.pageXOffset) !== null && _b !== void 0 ? _b : 0);
|
|
16
|
+
/* istanbul ignore next */
|
|
17
|
+
var currentY = Math.floor((_d = (_c = globalScope === null || globalScope === void 0 ? void 0 : globalScope.scrollY) !== null && _c !== void 0 ? _c : globalScope === null || globalScope === void 0 ? void 0 : globalScope.pageYOffset) !== null && _d !== void 0 ? _d : 0);
|
|
18
|
+
// Update page-level max positions for Page View End event (never resets during page lifetime)
|
|
19
|
+
state.maxX = Math.max(state.maxX, currentX);
|
|
20
|
+
state.maxY = Math.max(state.maxY, currentY);
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
unsubscribe: function () {
|
|
24
|
+
scrollSubscription.unsubscribe();
|
|
25
|
+
},
|
|
26
|
+
getState: function () { return state; },
|
|
27
|
+
reset: function () {
|
|
28
|
+
state.maxX = 0;
|
|
29
|
+
state.maxY = 0;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
exports.trackScroll = trackScroll;
|
|
34
|
+
//# sourceMappingURL=track-scroll.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-scroll.js","sourceRoot":"","sources":["../../../src/autocapture/track-scroll.ts"],"names":[],"mappings":";;;AACA,4DAA0E;AAO1E,SAAgB,WAAW,CAAC,EAM3B;QALC,SAAS,eAAA,EACT,cAAc,oBAAA;IAKd,kEAAkE;IAClE,KAAK,SAAS,CAAC;IAEP,IAAA,gBAAgB,GAAK,cAAc,iBAAnB,CAAoB;IAC5C,IAAM,KAAK,GAAgB,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAEhD,IAAM,kBAAkB,GAAG,gBAAgB,CAAC,SAAS,CAAC;;QACpD,IAAM,WAAW,GAAG,IAAA,+BAAc,GAAE,CAAC;QACrC,0BAA0B;QAC1B,IAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAA,MAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,OAAO,mCAAI,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,WAAW,mCAAI,CAAC,CAAC,CAAC;QACnF,0BAA0B;QAC1B,IAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAA,MAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,OAAO,mCAAI,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,WAAW,mCAAI,CAAC,CAAC,CAAC;QAEnF,8FAA8F;QAC9F,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC5C,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,WAAW,EAAE;YACX,kBAAkB,CAAC,WAAW,EAAE,CAAC;QACnC,CAAC;QACD,QAAQ,EAAE,cAAM,OAAA,KAAK,EAAL,CAAK;QACrB,KAAK,EAAE;YACL,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;QACjB,CAAC;KACF,CAAC;AACJ,CAAC;AAnCD,kCAmCC","sourcesContent":["import { AllWindowObservables } from '../autocapture-plugin';\nimport { BrowserClient, getGlobalScope } from '@amplitude/analytics-core';\n\nexport interface ScrollState {\n maxX: number;\n maxY: number;\n}\n\nexport function trackScroll({\n amplitude,\n allObservables,\n}: {\n amplitude: BrowserClient;\n allObservables: AllWindowObservables;\n}) {\n // amplitude is reserved for future periodic scroll event tracking\n void amplitude;\n\n const { scrollObservable } = allObservables;\n const state: ScrollState = { maxX: 0, maxY: 0 };\n\n const scrollSubscription = scrollObservable.subscribe(() => {\n const globalScope = getGlobalScope();\n /* istanbul ignore next */\n const currentX = Math.floor(globalScope?.scrollX ?? globalScope?.pageXOffset ?? 0);\n /* istanbul ignore next */\n const currentY = Math.floor(globalScope?.scrollY ?? globalScope?.pageYOffset ?? 0);\n\n // Update page-level max positions for Page View End event (never resets during page lifetime)\n state.maxX = Math.max(state.maxX, currentX);\n state.maxY = Math.max(state.maxY, currentY);\n });\n\n return {\n unsubscribe: () => {\n scrollSubscription.unsubscribe();\n },\n getState: () => state,\n reset: () => {\n state.maxX = 0;\n state.maxY = 0;\n },\n };\n}\n"]}
|
|
@@ -109,7 +109,7 @@ function getPendingThrashedCursor(directionChangesX, directionChangesY) {
|
|
|
109
109
|
}
|
|
110
110
|
return startTime;
|
|
111
111
|
}
|
|
112
|
-
var DEFAULT_THRESHOLD =
|
|
112
|
+
var DEFAULT_THRESHOLD = 20;
|
|
113
113
|
var DEFAULT_WINDOW_MS = 2000;
|
|
114
114
|
var createThrashedCursorObservable = function (_a) {
|
|
115
115
|
var mouseDirectionChangeObservable = _a.mouseDirectionChangeObservable, _b = _a.directionChanges, directionChanges = _b === void 0 ? DEFAULT_THRESHOLD : _b, _c = _a.thresholdMs, thresholdMs = _c === void 0 ? DEFAULT_WINDOW_MS : _c;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-thrashed-cursor.js","sourceRoot":"","sources":["../../../src/autocapture/track-thrashed-cursor.ts"],"names":[],"mappings":"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","sourcesContent":["import { BrowserClient, ElementInteractionsOptions, Observable } from '@amplitude/analytics-core';\nimport { AllWindowObservables } from '../frustration-plugin';\nimport { AMPLITUDE_THRASHED_CURSOR_EVENT } from '../constants';\nimport { isUrlAllowed } from '../helpers';\n\ntype Position = {\n x: number;\n y: number;\n};\n\nenum Direction {\n INCREASING = 'increasing',\n DECREASING = 'decreasing',\n}\n\nenum Axis {\n X = 'x',\n Y = 'y',\n}\n\nexport const createMouseDirectionChangeObservable = ({\n allWindowObservables,\n}: {\n allWindowObservables: AllWindowObservables;\n}): Observable<Axis> => {\n const { mouseMoveObservable } = allWindowObservables;\n return new Observable<Axis>((observer) => {\n let lastPosition: Position | null = null;\n let xDirection: Direction | null = null;\n let yDirection: Direction | null = null;\n return mouseMoveObservable.subscribe((event) => {\n const currentPosition = { x: event.clientX, y: event.clientY };\n if (lastPosition === null) {\n lastPosition = currentPosition;\n return;\n }\n if (currentPosition.x > lastPosition.x) {\n if (xDirection === Direction.DECREASING) {\n observer.next(Axis.X);\n }\n xDirection = Direction.INCREASING;\n } else if (currentPosition.x < lastPosition.x) {\n if (xDirection === Direction.INCREASING) {\n observer.next(Axis.X);\n }\n xDirection = Direction.DECREASING;\n }\n\n if (currentPosition.y > lastPosition.y) {\n if (yDirection === Direction.DECREASING) {\n observer.next(Axis.Y);\n }\n yDirection = Direction.INCREASING;\n } else if (currentPosition.y < lastPosition.y) {\n if (yDirection === Direction.INCREASING) {\n observer.next(Axis.Y);\n }\n yDirection = Direction.DECREASING;\n }\n lastPosition = currentPosition;\n });\n });\n};\n\ntype DirectionChangeSeries = {\n // number of direction changes to be considered a thrashed cursor\n changesThreshold: number;\n // timestamps of direction changes (limited to \"changesThreshold\" to avoid memory leaks)\n changes: number[];\n // window duration in milliseconds\n thresholdMs: number;\n // when the series of direction changes started\n startTime?: number;\n};\n\nfunction addDirectionChange(directionChangeSeries: DirectionChangeSeries) {\n const now = +Date.now();\n\n directionChangeSeries.startTime = directionChangeSeries.startTime || now;\n\n // add this direction change to the series (fixed length array to avoid memory leaks)\n const { changes, changesThreshold } = directionChangeSeries;\n changes.push(now);\n if (changes.length > changesThreshold) changes.shift();\n}\n\n// checks if there are enough direction changes within window + threshold\n// for it to be considered a thrashed cursor\nfunction isThrashedCursor(directionChanges: DirectionChangeSeries): boolean {\n const { changes, changesThreshold, thresholdMs } = directionChanges;\n if (changes.length < changesThreshold) return false;\n const delta = changes[changes.length - 1] - changes[0];\n return delta < thresholdMs;\n}\n\nfunction resetDirectionChangeSeries(directionChangeSeries: DirectionChangeSeries) {\n directionChangeSeries.changes = [];\n directionChangeSeries.startTime = undefined;\n}\n\n// if the time between first and last change is greater than the threshold,\n// shift the window to the right until it is below the threshold\nfunction adjustWindow(directionChanges: DirectionChangeSeries) {\n const { changes, thresholdMs } = directionChanges;\n\n // find the first change that is within the threshold\n let leftPtr = 0;\n const lastChange = changes[changes.length - 1];\n for (; leftPtr < changes.length; leftPtr++) {\n const delta = lastChange - changes[leftPtr];\n if (delta < thresholdMs) {\n break;\n }\n }\n if (leftPtr === 0) return;\n\n directionChanges.startTime = changes[leftPtr];\n directionChanges.changes.splice(0, leftPtr);\n}\n\nfunction getPendingThrashedCursor(\n directionChangesX: DirectionChangeSeries,\n directionChangesY: DirectionChangeSeries,\n): number | undefined {\n let startTime = undefined;\n if (isThrashedCursor(directionChangesX)) {\n startTime = directionChangesX.startTime;\n }\n if (isThrashedCursor(directionChangesY)) {\n const startTimeY = directionChangesY.startTime;\n if (startTimeY && (!startTime || startTimeY < startTime)) {\n startTime = startTimeY;\n }\n }\n return startTime;\n}\n\nconst DEFAULT_THRESHOLD = 10;\nconst DEFAULT_WINDOW_MS = 2_000;\n\nexport const createThrashedCursorObservable = ({\n mouseDirectionChangeObservable,\n directionChanges = DEFAULT_THRESHOLD,\n thresholdMs = DEFAULT_WINDOW_MS,\n}: {\n mouseDirectionChangeObservable: Observable<Axis>;\n directionChanges?: number;\n thresholdMs?: number;\n}): Observable<number> => {\n return new Observable<number>((observer) => {\n const xDirectionChanges: DirectionChangeSeries = { changes: [], changesThreshold: directionChanges, thresholdMs };\n const yDirectionChanges: DirectionChangeSeries = { changes: [], changesThreshold: directionChanges, thresholdMs };\n let pendingThrashedCursor: number | undefined = undefined;\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n function emitPendingThrashedCursor() {\n if (pendingThrashedCursor !== undefined) {\n observer.next(pendingThrashedCursor);\n pendingThrashedCursor = undefined;\n\n // reset window\n if (timer !== null) clearTimeout(timer);\n resetDirectionChangeSeries(xDirectionChanges);\n resetDirectionChangeSeries(yDirectionChanges);\n }\n }\n\n return mouseDirectionChangeObservable.subscribe((axis) => {\n if (timer !== null) clearTimeout(timer);\n addDirectionChange(axis === Axis.X ? xDirectionChanges : yDirectionChanges);\n\n const nextPendingThrashedCursor = getPendingThrashedCursor(xDirectionChanges, yDirectionChanges);\n if (nextPendingThrashedCursor) {\n // if we're in a thrashed cursor window, debounce it for \"thresholdMs\" duration\n // this is so that we do not restart the window if more direction changes are\n // detected in this series\n pendingThrashedCursor = pendingThrashedCursor || nextPendingThrashedCursor;\n timer = setTimeout(() => {\n emitPendingThrashedCursor();\n timer = null;\n }, thresholdMs);\n } else {\n emitPendingThrashedCursor();\n }\n\n adjustWindow(xDirectionChanges);\n adjustWindow(yDirectionChanges);\n\n /* istanbul ignore next */\n return () => {\n /* istanbul ignore if */\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n };\n });\n });\n};\n\nexport const trackThrashedCursor = ({\n amplitude,\n options,\n allObservables,\n directionChanges = DEFAULT_THRESHOLD,\n thresholdMs = DEFAULT_WINDOW_MS,\n}: {\n amplitude: BrowserClient;\n options: ElementInteractionsOptions;\n allObservables: AllWindowObservables;\n directionChanges?: number;\n thresholdMs?: number;\n}) => {\n const mouseDirectionChangeObservable = createMouseDirectionChangeObservable({ allWindowObservables: allObservables });\n const thrashedCursorObservable = createThrashedCursorObservable({\n mouseDirectionChangeObservable,\n directionChanges,\n thresholdMs,\n });\n return thrashedCursorObservable.subscribe((time) => {\n if (!isUrlAllowed(options)) {\n return;\n }\n amplitude.track(AMPLITUDE_THRASHED_CURSOR_EVENT, undefined, { time });\n });\n};\n"]}
|
|
1
|
+
{"version":3,"file":"track-thrashed-cursor.js","sourceRoot":"","sources":["../../../src/autocapture/track-thrashed-cursor.ts"],"names":[],"mappings":"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","sourcesContent":["import { BrowserClient, ElementInteractionsOptions, Observable } from '@amplitude/analytics-core';\nimport { AllWindowObservables } from '../frustration-plugin';\nimport { AMPLITUDE_THRASHED_CURSOR_EVENT } from '../constants';\nimport { isUrlAllowed } from '../helpers';\n\ntype Position = {\n x: number;\n y: number;\n};\n\nenum Direction {\n INCREASING = 'increasing',\n DECREASING = 'decreasing',\n}\n\nenum Axis {\n X = 'x',\n Y = 'y',\n}\n\nexport const createMouseDirectionChangeObservable = ({\n allWindowObservables,\n}: {\n allWindowObservables: AllWindowObservables;\n}): Observable<Axis> => {\n const { mouseMoveObservable } = allWindowObservables;\n return new Observable<Axis>((observer) => {\n let lastPosition: Position | null = null;\n let xDirection: Direction | null = null;\n let yDirection: Direction | null = null;\n return mouseMoveObservable.subscribe((event) => {\n const currentPosition = { x: event.clientX, y: event.clientY };\n if (lastPosition === null) {\n lastPosition = currentPosition;\n return;\n }\n if (currentPosition.x > lastPosition.x) {\n if (xDirection === Direction.DECREASING) {\n observer.next(Axis.X);\n }\n xDirection = Direction.INCREASING;\n } else if (currentPosition.x < lastPosition.x) {\n if (xDirection === Direction.INCREASING) {\n observer.next(Axis.X);\n }\n xDirection = Direction.DECREASING;\n }\n\n if (currentPosition.y > lastPosition.y) {\n if (yDirection === Direction.DECREASING) {\n observer.next(Axis.Y);\n }\n yDirection = Direction.INCREASING;\n } else if (currentPosition.y < lastPosition.y) {\n if (yDirection === Direction.INCREASING) {\n observer.next(Axis.Y);\n }\n yDirection = Direction.DECREASING;\n }\n lastPosition = currentPosition;\n });\n });\n};\n\ntype DirectionChangeSeries = {\n // number of direction changes to be considered a thrashed cursor\n changesThreshold: number;\n // timestamps of direction changes (limited to \"changesThreshold\" to avoid memory leaks)\n changes: number[];\n // window duration in milliseconds\n thresholdMs: number;\n // when the series of direction changes started\n startTime?: number;\n};\n\nfunction addDirectionChange(directionChangeSeries: DirectionChangeSeries) {\n const now = +Date.now();\n\n directionChangeSeries.startTime = directionChangeSeries.startTime || now;\n\n // add this direction change to the series (fixed length array to avoid memory leaks)\n const { changes, changesThreshold } = directionChangeSeries;\n changes.push(now);\n if (changes.length > changesThreshold) changes.shift();\n}\n\n// checks if there are enough direction changes within window + threshold\n// for it to be considered a thrashed cursor\nfunction isThrashedCursor(directionChanges: DirectionChangeSeries): boolean {\n const { changes, changesThreshold, thresholdMs } = directionChanges;\n if (changes.length < changesThreshold) return false;\n const delta = changes[changes.length - 1] - changes[0];\n return delta < thresholdMs;\n}\n\nfunction resetDirectionChangeSeries(directionChangeSeries: DirectionChangeSeries) {\n directionChangeSeries.changes = [];\n directionChangeSeries.startTime = undefined;\n}\n\n// if the time between first and last change is greater than the threshold,\n// shift the window to the right until it is below the threshold\nfunction adjustWindow(directionChanges: DirectionChangeSeries) {\n const { changes, thresholdMs } = directionChanges;\n\n // find the first change that is within the threshold\n let leftPtr = 0;\n const lastChange = changes[changes.length - 1];\n for (; leftPtr < changes.length; leftPtr++) {\n const delta = lastChange - changes[leftPtr];\n if (delta < thresholdMs) {\n break;\n }\n }\n if (leftPtr === 0) return;\n\n directionChanges.startTime = changes[leftPtr];\n directionChanges.changes.splice(0, leftPtr);\n}\n\nfunction getPendingThrashedCursor(\n directionChangesX: DirectionChangeSeries,\n directionChangesY: DirectionChangeSeries,\n): number | undefined {\n let startTime = undefined;\n if (isThrashedCursor(directionChangesX)) {\n startTime = directionChangesX.startTime;\n }\n if (isThrashedCursor(directionChangesY)) {\n const startTimeY = directionChangesY.startTime;\n if (startTimeY && (!startTime || startTimeY < startTime)) {\n startTime = startTimeY;\n }\n }\n return startTime;\n}\n\nconst DEFAULT_THRESHOLD = 20;\nconst DEFAULT_WINDOW_MS = 2_000;\n\nexport const createThrashedCursorObservable = ({\n mouseDirectionChangeObservable,\n directionChanges = DEFAULT_THRESHOLD,\n thresholdMs = DEFAULT_WINDOW_MS,\n}: {\n mouseDirectionChangeObservable: Observable<Axis>;\n directionChanges?: number;\n thresholdMs?: number;\n}): Observable<number> => {\n return new Observable<number>((observer) => {\n const xDirectionChanges: DirectionChangeSeries = { changes: [], changesThreshold: directionChanges, thresholdMs };\n const yDirectionChanges: DirectionChangeSeries = { changes: [], changesThreshold: directionChanges, thresholdMs };\n let pendingThrashedCursor: number | undefined = undefined;\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n function emitPendingThrashedCursor() {\n if (pendingThrashedCursor !== undefined) {\n observer.next(pendingThrashedCursor);\n pendingThrashedCursor = undefined;\n\n // reset window\n if (timer !== null) clearTimeout(timer);\n resetDirectionChangeSeries(xDirectionChanges);\n resetDirectionChangeSeries(yDirectionChanges);\n }\n }\n\n return mouseDirectionChangeObservable.subscribe((axis) => {\n if (timer !== null) clearTimeout(timer);\n addDirectionChange(axis === Axis.X ? xDirectionChanges : yDirectionChanges);\n\n const nextPendingThrashedCursor = getPendingThrashedCursor(xDirectionChanges, yDirectionChanges);\n if (nextPendingThrashedCursor) {\n // if we're in a thrashed cursor window, debounce it for \"thresholdMs\" duration\n // this is so that we do not restart the window if more direction changes are\n // detected in this series\n pendingThrashedCursor = pendingThrashedCursor || nextPendingThrashedCursor;\n timer = setTimeout(() => {\n emitPendingThrashedCursor();\n timer = null;\n }, thresholdMs);\n } else {\n emitPendingThrashedCursor();\n }\n\n adjustWindow(xDirectionChanges);\n adjustWindow(yDirectionChanges);\n\n /* istanbul ignore next */\n return () => {\n /* istanbul ignore if */\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n };\n });\n });\n};\n\nexport const trackThrashedCursor = ({\n amplitude,\n options,\n allObservables,\n directionChanges = DEFAULT_THRESHOLD,\n thresholdMs = DEFAULT_WINDOW_MS,\n}: {\n amplitude: BrowserClient;\n options: ElementInteractionsOptions;\n allObservables: AllWindowObservables;\n directionChanges?: number;\n thresholdMs?: number;\n}) => {\n const mouseDirectionChangeObservable = createMouseDirectionChangeObservable({ allWindowObservables: allObservables });\n const thrashedCursorObservable = createThrashedCursorObservable({\n mouseDirectionChangeObservable,\n directionChanges,\n thresholdMs,\n });\n return thrashedCursorObservable.subscribe((time) => {\n if (!isUrlAllowed(options)) {\n return;\n }\n amplitude.track(AMPLITUDE_THRASHED_CURSOR_EVENT, undefined, { time });\n });\n};\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BrowserClient } from '@amplitude/analytics-core';
|
|
2
|
+
export interface ScrollTracker {
|
|
3
|
+
getState: () => {
|
|
4
|
+
maxX: number;
|
|
5
|
+
maxY: number;
|
|
6
|
+
};
|
|
7
|
+
reset: () => void;
|
|
8
|
+
}
|
|
9
|
+
export interface ExposureTracker {
|
|
10
|
+
reset: () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function fireViewportContentUpdated({ amplitude, scrollTracker, currentElementExposed, elementExposedForPage, exposureTracker, isPageEnd, lastScroll, }: {
|
|
13
|
+
amplitude: BrowserClient;
|
|
14
|
+
scrollTracker: ScrollTracker;
|
|
15
|
+
currentElementExposed: Set<string>;
|
|
16
|
+
elementExposedForPage: Set<string>;
|
|
17
|
+
exposureTracker: ExposureTracker | undefined;
|
|
18
|
+
isPageEnd: boolean;
|
|
19
|
+
lastScroll: {
|
|
20
|
+
maxX: undefined | number;
|
|
21
|
+
maxY: undefined | number;
|
|
22
|
+
};
|
|
23
|
+
}): void;
|
|
24
|
+
export declare function onExposure(elementPath: string, elementExposedForPage: Set<string>, currentElementExposed: Set<string>, fireViewportContentUpdatedCallback: (isPageEnd: boolean) => void): void;
|
|
25
|
+
//# sourceMappingURL=track-viewport-content-updated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-viewport-content-updated.d.ts","sourceRoot":"","sources":["../../../src/autocapture/track-viewport-content-updated.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAkB,MAAM,2BAA2B,CAAC;AAI1E,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,wBAAgB,0BAA0B,CAAC,EACzC,SAAS,EACT,aAAa,EACb,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,SAAS,EACT,UAAU,GACX,EAAE;IACD,SAAS,EAAE,aAAa,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;IAC7B,qBAAqB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnC,qBAAqB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnC,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IAC7C,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE;QAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAA;KAAE,CAAC;CACpE,GAAG,IAAI,CAqDP;AAED,wBAAgB,UAAU,CACxB,WAAW,EAAE,MAAM,EACnB,qBAAqB,EAAE,GAAG,CAAC,MAAM,CAAC,EAClC,qBAAqB,EAAE,GAAG,CAAC,MAAM,CAAC,EAClC,kCAAkC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,QAejE"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.onExposure = exports.fireViewportContentUpdated = void 0;
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
5
|
+
var analytics_core_1 = require("@amplitude/analytics-core");
|
|
6
|
+
var constants = tslib_1.__importStar(require("../constants"));
|
|
7
|
+
var helpers_1 = require("../helpers");
|
|
8
|
+
function fireViewportContentUpdated(_a) {
|
|
9
|
+
var _b;
|
|
10
|
+
var _c, _d, _e;
|
|
11
|
+
var amplitude = _a.amplitude, scrollTracker = _a.scrollTracker, currentElementExposed = _a.currentElementExposed, elementExposedForPage = _a.elementExposedForPage, exposureTracker = _a.exposureTracker, isPageEnd = _a.isPageEnd, lastScroll = _a.lastScroll;
|
|
12
|
+
var pageScrollMaxState = scrollTracker.getState();
|
|
13
|
+
var globalScope = (0, analytics_core_1.getGlobalScope)();
|
|
14
|
+
/* istanbul ignore next */
|
|
15
|
+
var viewportWidth = (_c = globalScope === null || globalScope === void 0 ? void 0 : globalScope.innerWidth) !== null && _c !== void 0 ? _c : 0;
|
|
16
|
+
/* istanbul ignore next */
|
|
17
|
+
var viewportHeight = (_d = globalScope === null || globalScope === void 0 ? void 0 : globalScope.innerHeight) !== null && _d !== void 0 ? _d : 0;
|
|
18
|
+
var eventProperties = (_b = {},
|
|
19
|
+
_b[constants.AMPLITUDE_EVENT_PROP_PAGE_URL] =
|
|
20
|
+
/* istanbul ignore next */
|
|
21
|
+
(_e = globalScope === null || globalScope === void 0 ? void 0 : globalScope.location) === null || _e === void 0 ? void 0 : _e.href,
|
|
22
|
+
_b[constants.AMPLITUDE_EVENT_PROP_MAX_PAGE_X] = pageScrollMaxState.maxX + viewportWidth,
|
|
23
|
+
_b[constants.AMPLITUDE_EVENT_PROP_MAX_PAGE_Y] = pageScrollMaxState.maxY + viewportHeight,
|
|
24
|
+
_b[constants.AMPLITUDE_EVENT_PROP_VIEWPORT_HEIGHT] = viewportHeight,
|
|
25
|
+
_b[constants.AMPLITUDE_EVENT_PROP_VIEWPORT_WIDTH] = viewportWidth,
|
|
26
|
+
_b['[Amplitude] Element Exposed'] = Array.from(currentElementExposed),
|
|
27
|
+
_b);
|
|
28
|
+
var pageViewId = (0, helpers_1.getCurrentPageViewId)();
|
|
29
|
+
if (pageViewId) {
|
|
30
|
+
eventProperties[constants.AMPLITUDE_EVENT_PROP_PAGE_VIEW_ID] = pageViewId;
|
|
31
|
+
}
|
|
32
|
+
// If elements exposed is empty and max scroll is same as last event, don't track
|
|
33
|
+
if (currentElementExposed.size === 0 &&
|
|
34
|
+
pageScrollMaxState.maxX === lastScroll.maxX &&
|
|
35
|
+
pageScrollMaxState.maxY === lastScroll.maxY) {
|
|
36
|
+
if (isPageEnd) {
|
|
37
|
+
scrollTracker.reset();
|
|
38
|
+
elementExposedForPage.clear();
|
|
39
|
+
exposureTracker === null || exposureTracker === void 0 ? void 0 : exposureTracker.reset();
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
/* istanbul ignore next */
|
|
44
|
+
amplitude === null || amplitude === void 0 ? void 0 : amplitude.track('[Amplitude] Viewport Content Updated', eventProperties);
|
|
45
|
+
lastScroll.maxX = pageScrollMaxState.maxX;
|
|
46
|
+
lastScroll.maxY = pageScrollMaxState.maxY;
|
|
47
|
+
// Clear current batch
|
|
48
|
+
currentElementExposed.clear();
|
|
49
|
+
if (isPageEnd) {
|
|
50
|
+
// Reset state for next page view
|
|
51
|
+
scrollTracker.reset();
|
|
52
|
+
elementExposedForPage.clear();
|
|
53
|
+
exposureTracker === null || exposureTracker === void 0 ? void 0 : exposureTracker.reset();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.fireViewportContentUpdated = fireViewportContentUpdated;
|
|
57
|
+
function onExposure(elementPath, elementExposedForPage, currentElementExposed, fireViewportContentUpdatedCallback) {
|
|
58
|
+
if (elementExposedForPage.has(elementPath)) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
elementExposedForPage.add(elementPath);
|
|
62
|
+
currentElementExposed.add(elementPath);
|
|
63
|
+
// Check if current set size exceeds 18k chars
|
|
64
|
+
var exposedArray = Array.from(currentElementExposed);
|
|
65
|
+
var exposedString = JSON.stringify(exposedArray);
|
|
66
|
+
if (exposedString.length >= constants.MAX_ELEMENT_EXPOSED_STR_LENGTH) {
|
|
67
|
+
fireViewportContentUpdatedCallback(false);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.onExposure = onExposure;
|
|
71
|
+
//# sourceMappingURL=track-viewport-content-updated.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-viewport-content-updated.js","sourceRoot":"","sources":["../../../src/autocapture/track-viewport-content-updated.ts"],"names":[],"mappings":"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","sourcesContent":["import { BrowserClient, getGlobalScope } from '@amplitude/analytics-core';\nimport * as constants from '../constants';\nimport { getCurrentPageViewId } from '../helpers';\n\nexport interface ScrollTracker {\n getState: () => { maxX: number; maxY: number };\n reset: () => void;\n}\n\nexport interface ExposureTracker {\n reset: () => void;\n}\n\nexport function fireViewportContentUpdated({\n amplitude,\n scrollTracker,\n currentElementExposed,\n elementExposedForPage,\n exposureTracker,\n isPageEnd,\n lastScroll,\n}: {\n amplitude: BrowserClient;\n scrollTracker: ScrollTracker;\n currentElementExposed: Set<string>;\n elementExposedForPage: Set<string>;\n exposureTracker: ExposureTracker | undefined;\n isPageEnd: boolean;\n lastScroll: { maxX: undefined | number; maxY: undefined | number };\n}): void {\n const pageScrollMaxState = scrollTracker.getState();\n const globalScope = getGlobalScope();\n\n /* istanbul ignore next */\n const viewportWidth = globalScope?.innerWidth ?? 0;\n /* istanbul ignore next */\n const viewportHeight = globalScope?.innerHeight ?? 0;\n\n const eventProperties: Record<string, unknown> = {\n [constants.AMPLITUDE_EVENT_PROP_PAGE_URL]:\n /* istanbul ignore next */\n globalScope?.location?.href,\n [constants.AMPLITUDE_EVENT_PROP_MAX_PAGE_X]: pageScrollMaxState.maxX + viewportWidth,\n [constants.AMPLITUDE_EVENT_PROP_MAX_PAGE_Y]: pageScrollMaxState.maxY + viewportHeight,\n [constants.AMPLITUDE_EVENT_PROP_VIEWPORT_HEIGHT]: viewportHeight,\n [constants.AMPLITUDE_EVENT_PROP_VIEWPORT_WIDTH]: viewportWidth,\n '[Amplitude] Element Exposed': Array.from(currentElementExposed),\n };\n\n const pageViewId = getCurrentPageViewId();\n if (pageViewId) {\n eventProperties[constants.AMPLITUDE_EVENT_PROP_PAGE_VIEW_ID] = pageViewId;\n }\n\n // If elements exposed is empty and max scroll is same as last event, don't track\n if (\n currentElementExposed.size === 0 &&\n pageScrollMaxState.maxX === lastScroll.maxX &&\n pageScrollMaxState.maxY === lastScroll.maxY\n ) {\n if (isPageEnd) {\n scrollTracker.reset();\n elementExposedForPage.clear();\n exposureTracker?.reset();\n }\n return;\n }\n\n /* istanbul ignore next */\n amplitude?.track('[Amplitude] Viewport Content Updated', eventProperties);\n lastScroll.maxX = pageScrollMaxState.maxX;\n lastScroll.maxY = pageScrollMaxState.maxY;\n\n // Clear current batch\n currentElementExposed.clear();\n\n if (isPageEnd) {\n // Reset state for next page view\n scrollTracker.reset();\n elementExposedForPage.clear();\n exposureTracker?.reset();\n }\n}\n\nexport function onExposure(\n elementPath: string,\n elementExposedForPage: Set<string>,\n currentElementExposed: Set<string>,\n fireViewportContentUpdatedCallback: (isPageEnd: boolean) => void,\n) {\n if (elementExposedForPage.has(elementPath)) {\n return;\n }\n elementExposedForPage.add(elementPath);\n currentElementExposed.add(elementPath);\n\n // Check if current set size exceeds 18k chars\n const exposedArray = Array.from(currentElementExposed);\n const exposedString = JSON.stringify(exposedArray);\n\n if (exposedString.length >= constants.MAX_ELEMENT_EXPOSED_STR_LENGTH) {\n fireViewportContentUpdatedCallback(false);\n }\n}\n"]}
|
|
@@ -17,6 +17,8 @@ export declare enum ObservablesEnum {
|
|
|
17
17
|
ChangeObservable = "changeObservable",
|
|
18
18
|
NavigateObservable = "navigateObservable",
|
|
19
19
|
MutationObservable = "mutationObservable",
|
|
20
|
+
ScrollObservable = "scrollObservable",
|
|
21
|
+
ExposureObservable = "exposureObservable",
|
|
20
22
|
BrowserErrorObservable = "browserErrorObservable",
|
|
21
23
|
SelectionObservable = "selectionObservable",
|
|
22
24
|
MouseMoveObservable = "mouseMoveObservable"
|
|
@@ -26,6 +28,8 @@ export interface AllWindowObservables {
|
|
|
26
28
|
[ObservablesEnum.ClickObservable]: Observable<ElementBasedTimestampedEvent<MouseEvent>>;
|
|
27
29
|
[ObservablesEnum.MutationObservable]: Observable<TimestampedEvent<MutationRecord[]>>;
|
|
28
30
|
[ObservablesEnum.NavigateObservable]?: Observable<TimestampedEvent<NavigateEvent>>;
|
|
31
|
+
[ObservablesEnum.ScrollObservable]: Observable<Event>;
|
|
32
|
+
[ObservablesEnum.ExposureObservable]: Observable<Event>;
|
|
29
33
|
[ObservablesEnum.SelectionObservable]?: Observable<void>;
|
|
30
34
|
}
|
|
31
35
|
export declare const autocapturePlugin: (options?: ElementInteractionsOptions, context?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autocapture-plugin.d.ts","sourceRoot":"","sources":["../../src/autocapture-plugin.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,0BAA0B,
|
|
1
|
+
{"version":3,"file":"autocapture-plugin.d.ts","sourceRoot":"","sources":["../../src/autocapture-plugin.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,0BAA0B,EAK/B,kBAAkB,EAKnB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAEL,KAAK,4BAA4B,EACjC,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,WAAW,CAAC;AAoBnB,OAAO,EAAE,UAAU,EAAkB,MAAM,2BAA2B,CAAC;AAIvE,KAAK,cAAc,GAAG;IACpB,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,kCAAkC,KAAK,IAAI,CAAC;IACvF,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,kCAAkC,KAAK,IAAI,CAAC;CAC3F,CAAC;AAEF,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,UAAU,EAAE,cAAc,CAAC;KAC5B;CACF;AAED,KAAK,uBAAuB,GAAG,gBAAgB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AAE9E,MAAM,MAAM,8BAA8B,GAAG,QAAQ,CACnD,IAAI,CAAC,0BAA0B,EAAE,cAAc,GAAG,sBAAsB,GAAG,sBAAsB,CAAC,CACnG,GACC,0BAA0B,CAAC;AAE7B,oBAAY,eAAe;IACzB,eAAe,oBAAoB;IACnC,gBAAgB,qBAAqB;IACrC,kBAAkB,uBAAuB;IACzC,kBAAkB,uBAAuB;IACzC,gBAAgB,qBAAqB;IACrC,kBAAkB,uBAAuB;IACzC,sBAAsB,2BAA2B;IACjD,mBAAmB,wBAAwB;IAC3C,mBAAmB,wBAAwB;CAC5C;AAED,MAAM,WAAW,oBAAoB;IACnC,CAAC,eAAe,CAAC,gBAAgB,CAAC,EAAE,UAAU,CAAC,4BAA4B,CAAC,KAAK,CAAC,CAAC,CAAC;IAEpF,CAAC,eAAe,CAAC,eAAe,CAAC,EAAE,UAAU,CAAC,4BAA4B,CAAC,UAAU,CAAC,CAAC,CAAC;IACxF,CAAC,eAAe,CAAC,kBAAkB,CAAC,EAAE,UAAU,CAAC,gBAAgB,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;IACrF,CAAC,eAAe,CAAC,kBAAkB,CAAC,CAAC,EAAE,UAAU,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC;IACnF,CAAC,eAAe,CAAC,gBAAgB,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IACtD,CAAC,eAAe,CAAC,kBAAkB,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED,eAAO,MAAM,iBAAiB,aACnB,0BAA0B,YACzB;IAAE,iBAAiB,EAAE,kBAAkB,CAAA;CAAE,KAClD,uBA6XF,CAAC"}
|
|
@@ -11,34 +11,40 @@ var messenger_1 = require("./libs/messenger");
|
|
|
11
11
|
var track_click_1 = require("./autocapture/track-click");
|
|
12
12
|
var track_change_1 = require("./autocapture/track-change");
|
|
13
13
|
var track_action_click_1 = require("./autocapture/track-action-click");
|
|
14
|
+
var track_scroll_1 = require("./autocapture/track-scroll");
|
|
14
15
|
var observables_1 = require("./observables");
|
|
15
16
|
var triggers_1 = require("./pageActions/triggers");
|
|
16
17
|
var data_extractor_1 = require("./data-extractor");
|
|
17
18
|
var analytics_core_2 = require("@amplitude/analytics-core");
|
|
19
|
+
var track_exposure_1 = require("./autocapture/track-exposure");
|
|
20
|
+
var track_viewport_content_updated_1 = require("./autocapture/track-viewport-content-updated");
|
|
18
21
|
var ObservablesEnum;
|
|
19
22
|
(function (ObservablesEnum) {
|
|
20
23
|
ObservablesEnum["ClickObservable"] = "clickObservable";
|
|
21
24
|
ObservablesEnum["ChangeObservable"] = "changeObservable";
|
|
22
|
-
// ErrorObservable = 'errorObservable',
|
|
23
25
|
ObservablesEnum["NavigateObservable"] = "navigateObservable";
|
|
24
26
|
ObservablesEnum["MutationObservable"] = "mutationObservable";
|
|
27
|
+
ObservablesEnum["ScrollObservable"] = "scrollObservable";
|
|
28
|
+
ObservablesEnum["ExposureObservable"] = "exposureObservable";
|
|
25
29
|
ObservablesEnum["BrowserErrorObservable"] = "browserErrorObservable";
|
|
26
30
|
ObservablesEnum["SelectionObservable"] = "selectionObservable";
|
|
27
31
|
ObservablesEnum["MouseMoveObservable"] = "mouseMoveObservable";
|
|
28
32
|
})(ObservablesEnum = exports.ObservablesEnum || (exports.ObservablesEnum = {}));
|
|
29
33
|
var autocapturePlugin = function (options, context) {
|
|
30
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
34
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
31
35
|
if (options === void 0) { options = {}; }
|
|
32
36
|
// Set the plugin version tag
|
|
33
37
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
34
38
|
context === null || context === void 0 ? void 0 : context.diagnosticsClient.setTag('plugin.autocapture.version', version_1.VERSION);
|
|
35
|
-
var
|
|
39
|
+
var _m = options.dataAttributePrefix, dataAttributePrefix = _m === void 0 ? analytics_core_1.DEFAULT_DATA_ATTRIBUTE_PREFIX : _m, _o = options.visualTaggingOptions, visualTaggingOptions = _o === void 0 ? {
|
|
36
40
|
enabled: true,
|
|
37
|
-
} :
|
|
41
|
+
} : _o;
|
|
38
42
|
options.cssSelectorAllowlist = (_a = options.cssSelectorAllowlist) !== null && _a !== void 0 ? _a : analytics_core_1.DEFAULT_CSS_SELECTOR_ALLOWLIST;
|
|
39
43
|
options.actionClickAllowlist = (_b = options.actionClickAllowlist) !== null && _b !== void 0 ? _b : analytics_core_1.DEFAULT_ACTION_CLICK_ALLOWLIST;
|
|
40
44
|
options.debounceTime = (_c = options.debounceTime) !== null && _c !== void 0 ? _c : 0;
|
|
41
|
-
|
|
45
|
+
var resolvedExposureDuration = (_f = (_e = (_d = options.viewportContentUpdated) === null || _d === void 0 ? void 0 : _d.exposureDuration) !== null && _e !== void 0 ? _e : options.exposureDuration) !== null && _f !== void 0 ? _f : analytics_core_1.DEFAULT_EXPOSURE_DURATION;
|
|
46
|
+
options.viewportContentUpdated = tslib_1.__assign(tslib_1.__assign({}, options.viewportContentUpdated), { exposureDuration: resolvedExposureDuration });
|
|
47
|
+
options.pageUrlExcludelist = (_g = options.pageUrlExcludelist) === null || _g === void 0 ? void 0 : _g.reduce(function (acc, excludePattern) {
|
|
42
48
|
if (typeof excludePattern === 'string') {
|
|
43
49
|
acc.push(excludePattern);
|
|
44
50
|
}
|
|
@@ -59,9 +65,13 @@ var autocapturePlugin = function (options, context) {
|
|
|
59
65
|
var name = constants.PLUGIN_NAME;
|
|
60
66
|
var type = 'enrichment';
|
|
61
67
|
var subscriptions = [];
|
|
62
|
-
// Create data extractor based on options
|
|
63
68
|
var dataExtractor = new data_extractor_1.DataExtractor(options, context);
|
|
64
|
-
//
|
|
69
|
+
// Page-level state shared across trackers, emitted in a single Page View End event on beforeunload
|
|
70
|
+
// elementExposedForPage holds the total set of elements seen during the entire page view lifetime
|
|
71
|
+
var elementExposedForPage = new Set();
|
|
72
|
+
// currentElementExposed only holds the set of elements that will be flushed during the next [Amplitude] Viewport Content Updated event
|
|
73
|
+
var currentElementExposed = new Set();
|
|
74
|
+
var beforeUnloadCleanup;
|
|
65
75
|
var createObservables = function () {
|
|
66
76
|
var _a;
|
|
67
77
|
var clickObservable = (0, analytics_core_1.multicast)((0, observables_1.createClickObservable)().map(function (click) {
|
|
@@ -78,10 +88,6 @@ var autocapturePlugin = function (options, context) {
|
|
|
78
88
|
/* istanbul ignore next */
|
|
79
89
|
return function () { var _a; return (_a = (0, analytics_core_1.getGlobalScope)()) === null || _a === void 0 ? void 0 : _a.document.removeEventListener('change', handler); };
|
|
80
90
|
}));
|
|
81
|
-
// Create Observable from unhandled errors
|
|
82
|
-
// const errorObservable = fromEvent<ErrorEvent>(window, 'error').pipe(
|
|
83
|
-
// map((error) => addAdditionalEventProperties(error, 'error')),
|
|
84
|
-
// );
|
|
85
91
|
// Create observable for URL changes
|
|
86
92
|
var navigateObservable;
|
|
87
93
|
/* istanbul ignore next */
|
|
@@ -100,17 +106,21 @@ var autocapturePlugin = function (options, context) {
|
|
|
100
106
|
var mutationObservable = (0, analytics_core_1.multicast)((0, observables_1.createMutationObservable)().map(function (mutation) {
|
|
101
107
|
return dataExtractor.addAdditionalEventProperties(mutation, 'mutation', options.cssSelectorAllowlist, dataAttributePrefix);
|
|
102
108
|
}));
|
|
109
|
+
var scrollObservable = (0, observables_1.createScrollObservable)();
|
|
110
|
+
var exposureObservable = (0, observables_1.createExposureObservable)(mutationObservable, options.cssSelectorAllowlist);
|
|
103
111
|
return _a = {},
|
|
104
112
|
_a[ObservablesEnum.ChangeObservable] = changeObservable,
|
|
105
113
|
// [ObservablesEnum.ErrorObservable]: errorObservable,
|
|
106
114
|
_a[ObservablesEnum.ClickObservable] = clickObservable,
|
|
107
115
|
_a[ObservablesEnum.MutationObservable] = mutationObservable,
|
|
108
116
|
_a[ObservablesEnum.NavigateObservable] = navigateObservable,
|
|
117
|
+
_a[ObservablesEnum.ScrollObservable] = scrollObservable,
|
|
118
|
+
_a[ObservablesEnum.ExposureObservable] = exposureObservable,
|
|
109
119
|
_a;
|
|
110
120
|
};
|
|
111
121
|
// Group labeled events by event type (eg. click, change)
|
|
112
|
-
var groupedLabeledEvents = (0, triggers_1.groupLabeledEventIdsByEventType)(Object.values((
|
|
113
|
-
var labeledEventToTriggerMap = (0, triggers_1.createLabeledEventToTriggerMap)((
|
|
122
|
+
var groupedLabeledEvents = (0, triggers_1.groupLabeledEventIdsByEventType)(Object.values((_j = (_h = options.pageActions) === null || _h === void 0 ? void 0 : _h.labeledEvents) !== null && _j !== void 0 ? _j : {}));
|
|
123
|
+
var labeledEventToTriggerMap = (0, triggers_1.createLabeledEventToTriggerMap)((_l = (_k = options.pageActions) === null || _k === void 0 ? void 0 : _k.triggers) !== null && _l !== void 0 ? _l : []);
|
|
114
124
|
// Evaluate triggers for the given event by running the actions associated with the matching triggers
|
|
115
125
|
var evaluateTriggers = (0, triggers_1.createTriggerEvaluator)(groupedLabeledEvents, labeledEventToTriggerMap, dataExtractor, options);
|
|
116
126
|
// Function to recalculate internal variables when remote config is updated
|
|
@@ -127,13 +137,15 @@ var autocapturePlugin = function (options, context) {
|
|
|
127
137
|
}
|
|
128
138
|
};
|
|
129
139
|
var setup = function (config, amplitude) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
|
|
130
|
-
var shouldTrackEvent, shouldTrackActionClick, allObservables, clickTrackingSubscription, changeSubscription, actionClickSubscription, allowlist, actionClickAllowlist, messenger;
|
|
140
|
+
var pageViewEndFired, lastScroll, shouldTrackEvent, shouldTrackActionClick, allObservables, clickTrackingSubscription, changeSubscription, actionClickSubscription, scrollTracker, trackers, globalScope, handleViewportContentUpdated, handleExposure, beforeUnloadHandler, navigateObservable, popstateHandler_1, originalPushState_1, allowlist, actionClickAllowlist, messenger;
|
|
131
141
|
var _a;
|
|
132
142
|
return tslib_1.__generator(this, function (_b) {
|
|
133
143
|
/* istanbul ignore if */
|
|
134
144
|
if (typeof document === 'undefined') {
|
|
135
145
|
return [2 /*return*/];
|
|
136
146
|
}
|
|
147
|
+
pageViewEndFired = false;
|
|
148
|
+
lastScroll = { maxX: undefined, maxY: undefined };
|
|
137
149
|
// Fetch remote config for pageActions in a non-blocking manner
|
|
138
150
|
if (config.fetchRemoteConfig) {
|
|
139
151
|
if (!config.remoteConfigClient) {
|
|
@@ -187,6 +199,89 @@ var autocapturePlugin = function (options, context) {
|
|
|
187
199
|
if (actionClickSubscription) {
|
|
188
200
|
subscriptions.push(actionClickSubscription);
|
|
189
201
|
}
|
|
202
|
+
scrollTracker = (0, track_scroll_1.trackScroll)({
|
|
203
|
+
allObservables: allObservables,
|
|
204
|
+
amplitude: amplitude,
|
|
205
|
+
});
|
|
206
|
+
subscriptions.push(scrollTracker);
|
|
207
|
+
trackers = {};
|
|
208
|
+
globalScope = (0, analytics_core_1.getGlobalScope)();
|
|
209
|
+
handleViewportContentUpdated = function (isPageEnd) {
|
|
210
|
+
if (isPageEnd && pageViewEndFired) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
setTimeout(function () {
|
|
214
|
+
pageViewEndFired = false;
|
|
215
|
+
}, 100);
|
|
216
|
+
pageViewEndFired = true;
|
|
217
|
+
(0, track_viewport_content_updated_1.fireViewportContentUpdated)({
|
|
218
|
+
amplitude: amplitude,
|
|
219
|
+
scrollTracker: scrollTracker,
|
|
220
|
+
currentElementExposed: currentElementExposed,
|
|
221
|
+
elementExposedForPage: elementExposedForPage,
|
|
222
|
+
exposureTracker: trackers.exposure,
|
|
223
|
+
isPageEnd: isPageEnd,
|
|
224
|
+
lastScroll: lastScroll,
|
|
225
|
+
});
|
|
226
|
+
};
|
|
227
|
+
handleExposure = function (elementPath) {
|
|
228
|
+
(0, track_viewport_content_updated_1.onExposure)(elementPath, elementExposedForPage, currentElementExposed, handleViewportContentUpdated);
|
|
229
|
+
};
|
|
230
|
+
trackers.exposure = (0, track_exposure_1.trackExposure)({
|
|
231
|
+
allObservables: allObservables,
|
|
232
|
+
onExposure: handleExposure,
|
|
233
|
+
dataExtractor: dataExtractor,
|
|
234
|
+
exposureDuration: resolvedExposureDuration,
|
|
235
|
+
});
|
|
236
|
+
if (trackers.exposure) {
|
|
237
|
+
subscriptions.push(trackers.exposure);
|
|
238
|
+
}
|
|
239
|
+
beforeUnloadHandler = function () {
|
|
240
|
+
handleViewportContentUpdated(true);
|
|
241
|
+
};
|
|
242
|
+
/* istanbul ignore next */
|
|
243
|
+
globalScope === null || globalScope === void 0 ? void 0 : globalScope.addEventListener('beforeunload', beforeUnloadHandler);
|
|
244
|
+
beforeUnloadCleanup = function () {
|
|
245
|
+
/* istanbul ignore next */
|
|
246
|
+
globalScope === null || globalScope === void 0 ? void 0 : globalScope.removeEventListener('beforeunload', beforeUnloadHandler);
|
|
247
|
+
};
|
|
248
|
+
// Ensure cleanup on teardown as well
|
|
249
|
+
subscriptions.push({ unsubscribe: function () { return beforeUnloadCleanup(); } });
|
|
250
|
+
navigateObservable = allObservables[ObservablesEnum.NavigateObservable];
|
|
251
|
+
if (navigateObservable) {
|
|
252
|
+
subscriptions.push(navigateObservable.subscribe(function () {
|
|
253
|
+
handleViewportContentUpdated(true);
|
|
254
|
+
}));
|
|
255
|
+
}
|
|
256
|
+
else if (globalScope) {
|
|
257
|
+
popstateHandler_1 = function () {
|
|
258
|
+
handleViewportContentUpdated(true);
|
|
259
|
+
};
|
|
260
|
+
/* istanbul ignore next */
|
|
261
|
+
// Fallback for SPA tracking when Navigation API is not available
|
|
262
|
+
globalScope.addEventListener('popstate', popstateHandler_1);
|
|
263
|
+
originalPushState_1 = globalScope.history.pushState;
|
|
264
|
+
if (globalScope.history && originalPushState_1) {
|
|
265
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
266
|
+
globalScope.history.pushState = new Proxy(originalPushState_1, {
|
|
267
|
+
apply: function (target, thisArg, _a) {
|
|
268
|
+
var _b = tslib_1.__read(_a, 3), state = _b[0], unused = _b[1], url = _b[2];
|
|
269
|
+
target.apply(thisArg, [state, unused, url]);
|
|
270
|
+
handleViewportContentUpdated(true);
|
|
271
|
+
},
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
subscriptions.push({
|
|
275
|
+
unsubscribe: function () {
|
|
276
|
+
/* istanbul ignore next */
|
|
277
|
+
globalScope.removeEventListener('popstate', popstateHandler_1);
|
|
278
|
+
/* istanbul ignore next */
|
|
279
|
+
if (globalScope.history && originalPushState_1) {
|
|
280
|
+
globalScope.history.pushState = originalPushState_1;
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
}
|
|
190
285
|
/* istanbul ignore next */
|
|
191
286
|
(_a = config === null || config === void 0 ? void 0 : config.loggerProvider) === null || _a === void 0 ? void 0 : _a.log("".concat(name, " has been successfully added."));
|
|
192
287
|
// Setup visual tagging and background capture on the shared messenger singleton.
|