mixpanel-browser 2.71.1 → 2.72.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/tests.yml +1 -0
- package/CHANGELOG.md +7 -0
- package/dist/mixpanel-core.cjs.d.ts +47 -10
- package/dist/mixpanel-core.cjs.js +51 -17
- package/dist/mixpanel-recorder.js +681 -113
- package/dist/mixpanel-recorder.min.js +1 -1
- package/dist/mixpanel-recorder.min.js.map +1 -1
- package/dist/mixpanel-with-async-recorder.cjs.d.ts +47 -10
- package/dist/mixpanel-with-async-recorder.cjs.js +51 -17
- package/dist/mixpanel-with-recorder.d.ts +47 -10
- package/dist/mixpanel-with-recorder.js +731 -129
- package/dist/mixpanel-with-recorder.min.d.ts +47 -10
- package/dist/mixpanel-with-recorder.min.js +1 -1
- package/dist/mixpanel.amd.d.ts +47 -10
- package/dist/mixpanel.amd.js +731 -129
- package/dist/mixpanel.cjs.d.ts +47 -10
- package/dist/mixpanel.cjs.js +731 -129
- package/dist/mixpanel.globals.js +51 -17
- package/dist/mixpanel.min.js +144 -144
- package/dist/mixpanel.module.d.ts +47 -10
- package/dist/mixpanel.module.js +731 -129
- package/dist/mixpanel.umd.d.ts +47 -10
- package/dist/mixpanel.umd.js +731 -129
- package/dist/rrweb-bundled.js +12760 -0
- package/dist/rrweb-compiled.js +2496 -7176
- package/package.json +3 -2
- package/rollup.config.mjs +15 -4
- package/src/autocapture/index.js +1 -1
- package/src/autocapture/rageclick.js +20 -1
- package/src/autocapture/shadow-dom-observer.js +3 -15
- package/src/autocapture/utils.js +30 -0
- package/src/config.js +1 -1
- package/src/index.d.ts +47 -10
- package/src/mixpanel-core.js +1 -0
- package/src/recorder/recorder.js +1 -1
- package/src/recorder/rrweb-entrypoint.js +6 -0
- package/src/recorder/session-recording.js +69 -12
- package/src/utils.js +24 -0
|
@@ -43,20 +43,22 @@ export interface OutTrackingOptions extends ClearOptOutInOutOptions {
|
|
|
43
43
|
export type RageClickConfig =
|
|
44
44
|
| boolean
|
|
45
45
|
| {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
/** Distance threshold in pixels for clicks to be considered within the same area (default: 30) */
|
|
47
|
+
threshold_px?: number;
|
|
48
|
+
/** Time window in milliseconds for clicks to be considered rapid (default: 1000) */
|
|
49
|
+
timeout_ms?: number;
|
|
50
|
+
/** Number of clicks required to trigger a rage click event (default: 3) */
|
|
51
|
+
click_count?: number;
|
|
52
|
+
/** Whether to only track rage clicks on interactive elements like buttons, links, inputs (default: false) */
|
|
53
|
+
interactive_elements_only?: boolean;
|
|
54
|
+
};
|
|
53
55
|
|
|
54
56
|
export type DeadClickConfig =
|
|
55
57
|
| boolean
|
|
56
58
|
| {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
/** Time in milliseconds to wait after a click before qualifying it as dead (default: 500) */
|
|
60
|
+
timeout_ms?: number;
|
|
61
|
+
};
|
|
60
62
|
|
|
61
63
|
export interface RegisterOptions {
|
|
62
64
|
persistent: boolean;
|
|
@@ -149,6 +151,10 @@ export interface AutocaptureConfig {
|
|
|
149
151
|
block_element_callback?: (element: Element, event: Event) => boolean;
|
|
150
152
|
}
|
|
151
153
|
|
|
154
|
+
export interface FlagsConfig {
|
|
155
|
+
context: Dict;
|
|
156
|
+
}
|
|
157
|
+
|
|
152
158
|
export interface Config {
|
|
153
159
|
api_host: string;
|
|
154
160
|
api_routes: {
|
|
@@ -165,6 +171,7 @@ export interface Config {
|
|
|
165
171
|
cookie_domain: string;
|
|
166
172
|
cross_site_cookie: boolean;
|
|
167
173
|
cross_subdomain_cookie: boolean;
|
|
174
|
+
flags: boolean | FlagsConfig;
|
|
168
175
|
persistence: Persistence;
|
|
169
176
|
persistence_name: string;
|
|
170
177
|
cookie_name: string;
|
|
@@ -277,11 +284,41 @@ export interface Group {
|
|
|
277
284
|
unset(prop: string, callback?: Callback): void;
|
|
278
285
|
}
|
|
279
286
|
|
|
287
|
+
export interface FlagsVariant {
|
|
288
|
+
key: string;
|
|
289
|
+
value: any;
|
|
290
|
+
experiment_id?: string;
|
|
291
|
+
is_experiment_active?: boolean;
|
|
292
|
+
is_qa_tester?: boolean;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export interface FlagsUpdateContextOptions {
|
|
296
|
+
replace?: boolean;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export interface FlagsManager {
|
|
300
|
+
are_flags_ready(): boolean;
|
|
301
|
+
get_variant(
|
|
302
|
+
featureName: string,
|
|
303
|
+
fallback: FlagsVariant
|
|
304
|
+
): Promise<FlagsVariant>;
|
|
305
|
+
get_variant_sync(featureName: string, fallback: FlagsVariant): FlagsVariant;
|
|
306
|
+
get_variant_value(featureName: string, fallbackValue: any): Promise<any>;
|
|
307
|
+
get_variant_value_sync(featureName: string, fallbackValue: any): any;
|
|
308
|
+
is_enabled(featureName: string, fallbackValue?: boolean): Promise<boolean>;
|
|
309
|
+
is_enabled_sync(featureName: string, fallbackValue?: boolean): boolean;
|
|
310
|
+
update_context(
|
|
311
|
+
context: Dict,
|
|
312
|
+
options?: FlagsUpdateContextOptions
|
|
313
|
+
): Promise<void>;
|
|
314
|
+
}
|
|
315
|
+
|
|
280
316
|
export interface Mixpanel {
|
|
281
317
|
add_group(group_key: string, group_id: string, callback?: Callback): void;
|
|
282
318
|
alias(alias: string, original?: string): void;
|
|
283
319
|
clear_opt_in_out_tracking(options?: Partial<ClearOptOutInOutOptions>): void;
|
|
284
320
|
disable(events?: string[]): void;
|
|
321
|
+
flags: FlagsManager;
|
|
285
322
|
get_config(prop_name?: string): any;
|
|
286
323
|
get_distinct_id(): any;
|
|
287
324
|
get_group(group_key: string, group_id: string): Group;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var Config = {
|
|
4
4
|
DEBUG: false,
|
|
5
|
-
LIB_VERSION: '2.
|
|
5
|
+
LIB_VERSION: '2.72.0'
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
|
|
@@ -2892,20 +2892,65 @@ function isDefinitelyNonInteractive(element) {
|
|
|
2892
2892
|
return false;
|
|
2893
2893
|
}
|
|
2894
2894
|
|
|
2895
|
+
/**
|
|
2896
|
+
* Get the composed path of a click event for elements embedded in shadow DOM.
|
|
2897
|
+
* @param {Event} event - event to get the composed path from
|
|
2898
|
+
* @returns {Array} the composed path of the click event
|
|
2899
|
+
*/
|
|
2900
|
+
function getClickEventComposedPath(event) {
|
|
2901
|
+
if ('composedPath' in event) {
|
|
2902
|
+
return event['composedPath']();
|
|
2903
|
+
}
|
|
2904
|
+
|
|
2905
|
+
return [];
|
|
2906
|
+
}
|
|
2907
|
+
|
|
2908
|
+
/**
|
|
2909
|
+
* Get the element from a click event, accounting for elements embedded in shadow DOM.
|
|
2910
|
+
* @param {Event} event - event to get the target from
|
|
2911
|
+
* @returns {Element | null} the element that was the target of the click event
|
|
2912
|
+
*/
|
|
2913
|
+
function getClickEventTargetElement(event) {
|
|
2914
|
+
var path = getClickEventComposedPath(event);
|
|
2915
|
+
|
|
2916
|
+
if (path && path.length > 0) {
|
|
2917
|
+
return path[0];
|
|
2918
|
+
}
|
|
2919
|
+
|
|
2920
|
+
return event['target'] || event['srcElement'];
|
|
2921
|
+
}
|
|
2922
|
+
|
|
2895
2923
|
/** @const */ var DEFAULT_RAGE_CLICK_THRESHOLD_PX = 30;
|
|
2896
2924
|
/** @const */ var DEFAULT_RAGE_CLICK_TIMEOUT_MS = 1000;
|
|
2897
2925
|
/** @const */ var DEFAULT_RAGE_CLICK_CLICK_COUNT = 4;
|
|
2926
|
+
/** @const */ var DEFAULT_RAGE_CLICK_INTERACTIVE_ELEMENTS_ONLY = false;
|
|
2898
2927
|
|
|
2899
2928
|
function RageClickTracker() {
|
|
2900
2929
|
this.clicks = [];
|
|
2901
2930
|
}
|
|
2902
2931
|
|
|
2903
|
-
|
|
2932
|
+
/**
|
|
2933
|
+
* Determines if a click event is part of a rage click sequence.
|
|
2934
|
+
* @param {Event} event - the original click event.
|
|
2935
|
+
* @param {import('../index.d.ts').RageClickConfig} options - configuration options for rage click detection.
|
|
2936
|
+
* @returns {boolean} - true if the click is considered a rage click, false otherwise.
|
|
2937
|
+
*/
|
|
2938
|
+
RageClickTracker.prototype.isRageClick = function(event, options) {
|
|
2904
2939
|
options = options || {};
|
|
2905
2940
|
var thresholdPx = options['threshold_px'] || DEFAULT_RAGE_CLICK_THRESHOLD_PX;
|
|
2906
2941
|
var timeoutMs = options['timeout_ms'] || DEFAULT_RAGE_CLICK_TIMEOUT_MS;
|
|
2907
2942
|
var clickCount = options['click_count'] || DEFAULT_RAGE_CLICK_CLICK_COUNT;
|
|
2943
|
+
var interactiveElementsOnly = options['interactive_elements_only'] || DEFAULT_RAGE_CLICK_INTERACTIVE_ELEMENTS_ONLY;
|
|
2944
|
+
|
|
2945
|
+
if (interactiveElementsOnly) {
|
|
2946
|
+
var target = getClickEventTargetElement(event);
|
|
2947
|
+
if (!target || isDefinitelyNonInteractive(target)) {
|
|
2948
|
+
return false;
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
|
|
2908
2952
|
var timestamp = Date.now();
|
|
2953
|
+
var x = event['pageX'], y = event['pageY'];
|
|
2909
2954
|
|
|
2910
2955
|
var lastClick = this.clicks[this.clicks.length - 1];
|
|
2911
2956
|
if (
|
|
@@ -2936,28 +2981,16 @@ ShadowDOMObserver.prototype.getEventTarget = function(event) {
|
|
|
2936
2981
|
if (!this.observedShadowRoots) {
|
|
2937
2982
|
return;
|
|
2938
2983
|
}
|
|
2939
|
-
var path = this.getComposedPath(event);
|
|
2940
|
-
if (path && path.length) {
|
|
2941
|
-
return path[0];
|
|
2942
|
-
}
|
|
2943
2984
|
|
|
2944
|
-
return event
|
|
2985
|
+
return getClickEventTargetElement(event);
|
|
2945
2986
|
};
|
|
2946
2987
|
|
|
2947
|
-
|
|
2948
|
-
ShadowDOMObserver.prototype.getComposedPath = function(event) {
|
|
2949
|
-
if ('composedPath' in event) {
|
|
2950
|
-
return event['composedPath']();
|
|
2951
|
-
}
|
|
2952
|
-
|
|
2953
|
-
return [];
|
|
2954
|
-
};
|
|
2955
2988
|
ShadowDOMObserver.prototype.observeFromEvent = function(event) {
|
|
2956
2989
|
if (!this.observedShadowRoots) {
|
|
2957
2990
|
return;
|
|
2958
2991
|
}
|
|
2959
2992
|
|
|
2960
|
-
var path =
|
|
2993
|
+
var path = getClickEventComposedPath(event);
|
|
2961
2994
|
|
|
2962
2995
|
// Check each element in path for shadow roots
|
|
2963
2996
|
for (var i = 0; i < path.length; i++) {
|
|
@@ -3709,7 +3742,7 @@ Autocapture.prototype.initRageClickTracking = function() {
|
|
|
3709
3742
|
return;
|
|
3710
3743
|
}
|
|
3711
3744
|
|
|
3712
|
-
if (this._rageClickTracker.isRageClick(ev
|
|
3745
|
+
if (this._rageClickTracker.isRageClick(ev, currentRageClickConfig)) {
|
|
3713
3746
|
this.trackDomEvent(ev, MP_EV_RAGE_CLICK);
|
|
3714
3747
|
}
|
|
3715
3748
|
}.bind(this);
|
|
@@ -6897,6 +6930,7 @@ var DEFAULT_CONFIG = {
|
|
|
6897
6930
|
'record_block_selector': 'img, video, audio',
|
|
6898
6931
|
'record_canvas': false,
|
|
6899
6932
|
'record_collect_fonts': false,
|
|
6933
|
+
'record_console': true,
|
|
6900
6934
|
'record_heatmap_data': false,
|
|
6901
6935
|
'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
|
|
6902
6936
|
'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'),
|
|
@@ -43,20 +43,22 @@ export interface OutTrackingOptions extends ClearOptOutInOutOptions {
|
|
|
43
43
|
export type RageClickConfig =
|
|
44
44
|
| boolean
|
|
45
45
|
| {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
/** Distance threshold in pixels for clicks to be considered within the same area (default: 30) */
|
|
47
|
+
threshold_px?: number;
|
|
48
|
+
/** Time window in milliseconds for clicks to be considered rapid (default: 1000) */
|
|
49
|
+
timeout_ms?: number;
|
|
50
|
+
/** Number of clicks required to trigger a rage click event (default: 3) */
|
|
51
|
+
click_count?: number;
|
|
52
|
+
/** Whether to only track rage clicks on interactive elements like buttons, links, inputs (default: false) */
|
|
53
|
+
interactive_elements_only?: boolean;
|
|
54
|
+
};
|
|
53
55
|
|
|
54
56
|
export type DeadClickConfig =
|
|
55
57
|
| boolean
|
|
56
58
|
| {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
/** Time in milliseconds to wait after a click before qualifying it as dead (default: 500) */
|
|
60
|
+
timeout_ms?: number;
|
|
61
|
+
};
|
|
60
62
|
|
|
61
63
|
export interface RegisterOptions {
|
|
62
64
|
persistent: boolean;
|
|
@@ -149,6 +151,10 @@ export interface AutocaptureConfig {
|
|
|
149
151
|
block_element_callback?: (element: Element, event: Event) => boolean;
|
|
150
152
|
}
|
|
151
153
|
|
|
154
|
+
export interface FlagsConfig {
|
|
155
|
+
context: Dict;
|
|
156
|
+
}
|
|
157
|
+
|
|
152
158
|
export interface Config {
|
|
153
159
|
api_host: string;
|
|
154
160
|
api_routes: {
|
|
@@ -165,6 +171,7 @@ export interface Config {
|
|
|
165
171
|
cookie_domain: string;
|
|
166
172
|
cross_site_cookie: boolean;
|
|
167
173
|
cross_subdomain_cookie: boolean;
|
|
174
|
+
flags: boolean | FlagsConfig;
|
|
168
175
|
persistence: Persistence;
|
|
169
176
|
persistence_name: string;
|
|
170
177
|
cookie_name: string;
|
|
@@ -277,11 +284,41 @@ export interface Group {
|
|
|
277
284
|
unset(prop: string, callback?: Callback): void;
|
|
278
285
|
}
|
|
279
286
|
|
|
287
|
+
export interface FlagsVariant {
|
|
288
|
+
key: string;
|
|
289
|
+
value: any;
|
|
290
|
+
experiment_id?: string;
|
|
291
|
+
is_experiment_active?: boolean;
|
|
292
|
+
is_qa_tester?: boolean;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export interface FlagsUpdateContextOptions {
|
|
296
|
+
replace?: boolean;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export interface FlagsManager {
|
|
300
|
+
are_flags_ready(): boolean;
|
|
301
|
+
get_variant(
|
|
302
|
+
featureName: string,
|
|
303
|
+
fallback: FlagsVariant
|
|
304
|
+
): Promise<FlagsVariant>;
|
|
305
|
+
get_variant_sync(featureName: string, fallback: FlagsVariant): FlagsVariant;
|
|
306
|
+
get_variant_value(featureName: string, fallbackValue: any): Promise<any>;
|
|
307
|
+
get_variant_value_sync(featureName: string, fallbackValue: any): any;
|
|
308
|
+
is_enabled(featureName: string, fallbackValue?: boolean): Promise<boolean>;
|
|
309
|
+
is_enabled_sync(featureName: string, fallbackValue?: boolean): boolean;
|
|
310
|
+
update_context(
|
|
311
|
+
context: Dict,
|
|
312
|
+
options?: FlagsUpdateContextOptions
|
|
313
|
+
): Promise<void>;
|
|
314
|
+
}
|
|
315
|
+
|
|
280
316
|
export interface Mixpanel {
|
|
281
317
|
add_group(group_key: string, group_id: string, callback?: Callback): void;
|
|
282
318
|
alias(alias: string, original?: string): void;
|
|
283
319
|
clear_opt_in_out_tracking(options?: Partial<ClearOptOutInOutOptions>): void;
|
|
284
320
|
disable(events?: string[]): void;
|
|
321
|
+
flags: FlagsManager;
|
|
285
322
|
get_config(prop_name?: string): any;
|
|
286
323
|
get_distinct_id(): any;
|
|
287
324
|
get_group(group_key: string, group_id: string): Group;
|