mixpanel-browser 2.69.1 → 2.71.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/CHANGELOG.md +11 -0
- package/build.sh +1 -0
- package/dist/mixpanel-core.cjs.d.ts +440 -0
- package/dist/mixpanel-core.cjs.js +857 -56
- package/dist/mixpanel-recorder.js +5 -3
- 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 +440 -0
- package/dist/mixpanel-with-async-recorder.cjs.js +857 -56
- package/dist/mixpanel-with-recorder.d.ts +440 -0
- package/dist/mixpanel-with-recorder.js +861 -58
- package/dist/mixpanel-with-recorder.min.d.ts +440 -0
- package/dist/mixpanel-with-recorder.min.js +1 -1
- package/dist/mixpanel.amd.d.ts +440 -0
- package/dist/mixpanel.amd.js +861 -58
- package/dist/mixpanel.cjs.d.ts +440 -0
- package/dist/mixpanel.cjs.js +861 -58
- package/dist/mixpanel.globals.js +857 -56
- package/dist/mixpanel.min.js +170 -152
- package/dist/mixpanel.module.d.ts +440 -0
- package/dist/mixpanel.module.js +861 -58
- package/dist/mixpanel.umd.d.ts +440 -0
- package/dist/mixpanel.umd.js +861 -58
- package/dist/rrweb-compiled.js +4 -2
- package/package.json +2 -19
- package/rollup.config.mjs +28 -4
- package/src/autocapture/deadclick.js +254 -0
- package/src/autocapture/index.js +237 -41
- package/src/autocapture/shadow-dom-observer.js +100 -0
- package/src/autocapture/utils.js +230 -3
- package/src/config.js +1 -1
- package/src/flags/index.js +43 -18
- package/src/index.d.ts +16 -3
- package/src/loaders/loader-module-core.d.ts +1 -0
- package/src/loaders/loader-module-with-async-recorder.d.ts +1 -0
- package/src/loaders/loader-module.d.ts +1 -0
- package/src/utils.js +15 -0
package/src/autocapture/utils.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
// stateless utils
|
|
2
2
|
// mostly from https://github.com/mixpanel/mixpanel-js/blob/989ada50f518edab47b9c4fd9535f9fbd5ec5fc0/src/autotrack-utils.js
|
|
3
3
|
|
|
4
|
-
import { _, console_with_prefix, document } from '../utils'; // eslint-disable-line camelcase
|
|
4
|
+
import { _, console_with_prefix, document, safewrap } from '../utils'; // eslint-disable-line camelcase
|
|
5
5
|
import { window } from '../window';
|
|
6
6
|
|
|
7
7
|
var EV_CHANGE = 'change';
|
|
8
8
|
var EV_CLICK = 'click';
|
|
9
9
|
var EV_HASHCHANGE = 'hashchange';
|
|
10
|
+
var EV_INPUT = 'input';
|
|
11
|
+
var EV_LOAD = 'load';
|
|
10
12
|
var EV_MP_LOCATION_CHANGE = 'mp_locationchange';
|
|
11
13
|
var EV_POPSTATE = 'popstate';
|
|
12
14
|
// TODO scrollend isn't available in Safari: document or polyfill?
|
|
13
15
|
var EV_SCROLLEND = 'scrollend';
|
|
16
|
+
var EV_SCROLL = 'scroll';
|
|
17
|
+
var EV_SELECT = 'select';
|
|
14
18
|
var EV_SUBMIT = 'submit';
|
|
19
|
+
var EV_TOGGLE = 'toggle';
|
|
20
|
+
var EV_VISIBILITYCHANGE = 'visibilitychange';
|
|
15
21
|
|
|
16
22
|
var CLICK_EVENT_PROPS = [
|
|
17
23
|
'clientX', 'clientY',
|
|
@@ -28,6 +34,77 @@ var TRACKED_ATTRS = [
|
|
|
28
34
|
'href', 'name', 'role', 'title', 'type'
|
|
29
35
|
];
|
|
30
36
|
|
|
37
|
+
var INTERACTIVE_ARIA_ROLES = {
|
|
38
|
+
'button': true,
|
|
39
|
+
'checkbox': true,
|
|
40
|
+
'combobox': true,
|
|
41
|
+
'grid': true,
|
|
42
|
+
'link': true,
|
|
43
|
+
'listbox': true,
|
|
44
|
+
'menu': true,
|
|
45
|
+
'menubar': true,
|
|
46
|
+
'menuitem': true,
|
|
47
|
+
'menuitemcheckbox': true,
|
|
48
|
+
'menuitemradio': true,
|
|
49
|
+
'navigation': true,
|
|
50
|
+
'option': true,
|
|
51
|
+
'radio': true,
|
|
52
|
+
'radiogroup': true,
|
|
53
|
+
'searchbox': true,
|
|
54
|
+
'slider': true,
|
|
55
|
+
'spinbutton': true,
|
|
56
|
+
'switch': true,
|
|
57
|
+
'tab': true,
|
|
58
|
+
'tablist': true,
|
|
59
|
+
'textbox': true,
|
|
60
|
+
'tree': true,
|
|
61
|
+
'treegrid': true,
|
|
62
|
+
'treeitem': true
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
var ALWAYS_NON_INTERACTIVE_TAGS = {
|
|
66
|
+
// Document metadata
|
|
67
|
+
'base': true,
|
|
68
|
+
'head': true,
|
|
69
|
+
'html': true,
|
|
70
|
+
'link': true,
|
|
71
|
+
'meta': true,
|
|
72
|
+
'script': true,
|
|
73
|
+
'style': true,
|
|
74
|
+
'title': true,
|
|
75
|
+
// Text formatting
|
|
76
|
+
'br': true,
|
|
77
|
+
'hr': true,
|
|
78
|
+
'wbr': true,
|
|
79
|
+
// Other
|
|
80
|
+
'noscript': true,
|
|
81
|
+
'picture': true,
|
|
82
|
+
'source': true,
|
|
83
|
+
'template': true,
|
|
84
|
+
'track': true
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Common container tags that need additional checks
|
|
88
|
+
var TEXT_CONTAINER_TAGS = {
|
|
89
|
+
'article': true,
|
|
90
|
+
'div': true,
|
|
91
|
+
'h1': true,
|
|
92
|
+
'h2': true,
|
|
93
|
+
'h3': true,
|
|
94
|
+
'h4': true,
|
|
95
|
+
'h5': true,
|
|
96
|
+
'h6': true,
|
|
97
|
+
'p': true,
|
|
98
|
+
'section': true,
|
|
99
|
+
'span': true
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
var EVENT_HANDLER_ATTRIBUTES = [
|
|
103
|
+
'onclick', 'onmousedown', 'onmouseup', 'onpointerdown', 'onpointerup', 'ontouchend', 'ontouchstart'
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
var MAX_DEPTH = 5;
|
|
107
|
+
|
|
31
108
|
var logger = console_with_prefix('autocapture');
|
|
32
109
|
|
|
33
110
|
|
|
@@ -395,6 +472,10 @@ function minDOMApisSupported() {
|
|
|
395
472
|
}
|
|
396
473
|
}
|
|
397
474
|
|
|
475
|
+
function weakSetSupported() {
|
|
476
|
+
return typeof WeakSet !== 'undefined';
|
|
477
|
+
}
|
|
478
|
+
|
|
398
479
|
/*
|
|
399
480
|
* Check whether a DOM event should be "tracked" or if it may contain sensitive data
|
|
400
481
|
* using a variety of heuristics.
|
|
@@ -520,12 +601,158 @@ function shouldTrackValue(value) {
|
|
|
520
601
|
return true;
|
|
521
602
|
}
|
|
522
603
|
|
|
604
|
+
/**
|
|
605
|
+
* Creates a cross-browser compatible scroll end function with appropriate event listener.
|
|
606
|
+
* For browsers that support scrollend, returns the original function with scrollend event.
|
|
607
|
+
* For browsers without scrollend support, returns a debounced function that triggers
|
|
608
|
+
* 100ms after the last scroll event to simulate scrollend behavior.
|
|
609
|
+
* @param {Function} originalFunction - The function to call when scrolling ends
|
|
610
|
+
* @returns {Object} Object containing listener function and eventType string
|
|
611
|
+
* @returns {Function} returns.listener - The wrapped function to use as event listener
|
|
612
|
+
* @returns {string} returns.eventType - The event type to listen for ('scrollend' or 'scroll')
|
|
613
|
+
*/
|
|
614
|
+
function getPolyfillScrollEndFunction(originalFunction) {
|
|
615
|
+
var supportsScrollEnd = 'onscrollend' in window;
|
|
616
|
+
var polyfillFunction = safewrap(originalFunction);
|
|
617
|
+
var polyfillEvent = EV_SCROLLEND;
|
|
618
|
+
if (!supportsScrollEnd) {
|
|
619
|
+
// Polyfill for browsers without scrollend support: wait 100ms after the last scroll event
|
|
620
|
+
// https://developer.chrome.com/blog/scrollend-a-new-javascript-event
|
|
621
|
+
var scrollTimer = null;
|
|
622
|
+
var scrollDelayMs = 100;
|
|
623
|
+
|
|
624
|
+
polyfillFunction = safewrap(function() {
|
|
625
|
+
clearTimeout(scrollTimer);
|
|
626
|
+
scrollTimer = setTimeout(originalFunction, scrollDelayMs);
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
polyfillEvent = EV_SCROLL;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
return {
|
|
633
|
+
listener: polyfillFunction,
|
|
634
|
+
eventType: polyfillEvent
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
function hasInlineEventHandlers(element) {
|
|
639
|
+
for (var i = 0; i < EVENT_HANDLER_ATTRIBUTES.length; i++) {
|
|
640
|
+
if (element.hasAttribute(EVENT_HANDLER_ATTRIBUTES[i])) {
|
|
641
|
+
return true;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
function hasInteractiveAriaRole(element) {
|
|
648
|
+
var role = element.getAttribute('role');
|
|
649
|
+
if (!role) return false;
|
|
650
|
+
|
|
651
|
+
// Handle invalid markup where multiple roles might be specified
|
|
652
|
+
// Only the first token is recognized per ARIA spec
|
|
653
|
+
var primaryRole = role.trim().split(/\s+/)[0].toLowerCase();
|
|
654
|
+
|
|
655
|
+
return INTERACTIVE_ARIA_ROLES[primaryRole];
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
function hasAnyInteractivityIndicators(element) {
|
|
659
|
+
var tagName = element.tagName.toLowerCase();
|
|
660
|
+
|
|
661
|
+
// Check for interactive HTML elements
|
|
662
|
+
if (tagName === 'button' ||
|
|
663
|
+
tagName === 'input' ||
|
|
664
|
+
tagName === 'select' ||
|
|
665
|
+
tagName === 'textarea' ||
|
|
666
|
+
tagName === 'details' ||
|
|
667
|
+
tagName === 'dialog') {
|
|
668
|
+
return true;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
if (element.isContentEditable) {
|
|
672
|
+
return true;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
if (element.onclick || element.onmousedown || element.onmouseup || element.ontouchstart || element.ontouchend) {
|
|
676
|
+
return true;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
if (hasInlineEventHandlers(element)) {
|
|
680
|
+
return true;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
if (hasInteractiveAriaRole(element)) {
|
|
684
|
+
return true;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
if (tagName === 'a' && element.hasAttribute('href')) {
|
|
688
|
+
return true;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
if (element.hasAttribute('tabindex')) {
|
|
692
|
+
return true;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
function isDefinitelyNonInteractive(element) {
|
|
700
|
+
if (!element || !element.tagName) {
|
|
701
|
+
return true;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
var tagName = element.tagName.toLowerCase();
|
|
705
|
+
|
|
706
|
+
// These tags are definitely non-interactive
|
|
707
|
+
if (ALWAYS_NON_INTERACTIVE_TAGS[tagName]) {
|
|
708
|
+
return true;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// For all other elements, we can only be certain they're non-interactive if they lack ALL indicators of interactivity
|
|
712
|
+
// Check for any signs of interactivity
|
|
713
|
+
if (hasAnyInteractivityIndicators(element)) {
|
|
714
|
+
return false;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// Check parent chain for interactive context
|
|
718
|
+
var parent = element.parentElement;
|
|
719
|
+
var depth = 0;
|
|
720
|
+
|
|
721
|
+
while (parent && depth < MAX_DEPTH) {
|
|
722
|
+
if (hasAnyInteractivityIndicators(parent)) {
|
|
723
|
+
return false; // Element is inside an interactive parent
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
if (parent.getRootNode && parent.getRootNode() !== document) {
|
|
727
|
+
var root = parent.getRootNode();
|
|
728
|
+
if (root.host && hasAnyInteractivityIndicators(root.host)) {
|
|
729
|
+
return false; // Inside an interactive shadow host
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
parent = parent.parentElement;
|
|
734
|
+
depth++;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// Pure text containers without any interactive context
|
|
738
|
+
if (TEXT_CONTAINER_TAGS[tagName]) {
|
|
739
|
+
// These are non-interactive ONLY if they have no interactive indicators (already checked as part of hasAnyInteractivityIndicators)
|
|
740
|
+
return true;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// Default: we can't be certain it's non-interactive
|
|
744
|
+
return false;
|
|
745
|
+
}
|
|
746
|
+
|
|
523
747
|
export {
|
|
748
|
+
EV_CHANGE, EV_CLICK, EV_HASHCHANGE, EV_INPUT, EV_LOAD,EV_MP_LOCATION_CHANGE, EV_POPSTATE,
|
|
749
|
+
EV_SCROLL, EV_SCROLLEND, EV_SELECT, EV_SUBMIT, EV_TOGGLE, EV_VISIBILITYCHANGE,
|
|
750
|
+
getPolyfillScrollEndFunction,
|
|
524
751
|
getPropsForDOMEvent,
|
|
525
752
|
getSafeText,
|
|
753
|
+
isDefinitelyNonInteractive,
|
|
526
754
|
logger,
|
|
527
755
|
minDOMApisSupported,
|
|
528
756
|
shouldTrackDomEvent, shouldTrackElementDetails, shouldTrackValue,
|
|
529
|
-
|
|
530
|
-
EV_SCROLLEND, EV_SUBMIT
|
|
757
|
+
weakSetSupported
|
|
531
758
|
};
|
package/src/config.js
CHANGED
package/src/flags/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { _, console_with_prefix, safewrapClass } from '../utils'; // eslint-disable-line camelcase
|
|
1
|
+
import { _, console_with_prefix, generateTraceparent, safewrapClass } from '../utils'; // eslint-disable-line camelcase
|
|
2
2
|
import { window } from '../window';
|
|
3
|
+
import Config from '../config';
|
|
3
4
|
|
|
4
|
-
var fetch = window['fetch'];
|
|
5
5
|
var logger = console_with_prefix('flags');
|
|
6
6
|
|
|
7
7
|
var FLAGS_CONFIG_KEY = 'flags';
|
|
@@ -15,6 +15,7 @@ CONFIG_DEFAULTS[CONFIG_CONTEXT] = {};
|
|
|
15
15
|
* @constructor
|
|
16
16
|
*/
|
|
17
17
|
var FeatureFlagManager = function(initOptions) {
|
|
18
|
+
this.fetch = window['fetch'];
|
|
18
19
|
this.getFullApiRoute = initOptions.getFullApiRoute;
|
|
19
20
|
this.getMpConfig = initOptions.getConfigFunc;
|
|
20
21
|
this.setMpConfig = initOptions.setConfigFunc;
|
|
@@ -23,7 +24,7 @@ var FeatureFlagManager = function(initOptions) {
|
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
FeatureFlagManager.prototype.init = function() {
|
|
26
|
-
if (!minApisSupported()) {
|
|
27
|
+
if (!this.minApisSupported()) {
|
|
27
28
|
logger.critical('Feature Flags unavailable: missing minimum required APIs');
|
|
28
29
|
return;
|
|
29
30
|
}
|
|
@@ -86,18 +87,24 @@ FeatureFlagManager.prototype.fetchFlags = function() {
|
|
|
86
87
|
|
|
87
88
|
var distinctId = this.getMpProperty('distinct_id');
|
|
88
89
|
var deviceId = this.getMpProperty('$device_id');
|
|
90
|
+
var traceparent = generateTraceparent();
|
|
89
91
|
logger.log('Fetching flags for distinct ID: ' + distinctId);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
|
|
93
|
+
var context = _.extend({'distinct_id': distinctId, 'device_id': deviceId}, this.getConfig(CONFIG_CONTEXT));
|
|
94
|
+
var searchParams = new URLSearchParams();
|
|
95
|
+
searchParams.set('context', JSON.stringify(context));
|
|
96
|
+
searchParams.set('token', this.getMpConfig('token'));
|
|
97
|
+
searchParams.set('mp_lib', 'web');
|
|
98
|
+
searchParams.set('$lib_version', Config.LIB_VERSION);
|
|
99
|
+
var url = this.getFullApiRoute() + '?' + searchParams.toString();
|
|
100
|
+
|
|
93
101
|
this._fetchInProgressStartTime = Date.now();
|
|
94
|
-
this.fetchPromise =
|
|
95
|
-
'method': '
|
|
102
|
+
this.fetchPromise = this.fetch.call(window, url, {
|
|
103
|
+
'method': 'GET',
|
|
96
104
|
'headers': {
|
|
97
105
|
'Authorization': 'Basic ' + btoa(this.getMpConfig('token') + ':'),
|
|
98
|
-
'
|
|
99
|
-
}
|
|
100
|
-
'body': JSON.stringify(reqParams)
|
|
106
|
+
'traceparent': traceparent
|
|
107
|
+
}
|
|
101
108
|
}).then(function(response) {
|
|
102
109
|
this.markFetchComplete();
|
|
103
110
|
return response.json().then(function(responseBody) {
|
|
@@ -109,10 +116,14 @@ FeatureFlagManager.prototype.fetchFlags = function() {
|
|
|
109
116
|
_.each(responseFlags, function(data, key) {
|
|
110
117
|
flags.set(key, {
|
|
111
118
|
'key': data['variant_key'],
|
|
112
|
-
'value': data['variant_value']
|
|
119
|
+
'value': data['variant_value'],
|
|
120
|
+
'experiment_id': data['experiment_id'],
|
|
121
|
+
'is_experiment_active': data['is_experiment_active'],
|
|
122
|
+
'is_qa_tester': data['is_qa_tester']
|
|
113
123
|
});
|
|
114
124
|
});
|
|
115
125
|
this.flags = flags;
|
|
126
|
+
this._traceparent = traceparent;
|
|
116
127
|
}.bind(this)).catch(function(error) {
|
|
117
128
|
this.markFetchComplete();
|
|
118
129
|
logger.error(error);
|
|
@@ -209,22 +220,36 @@ FeatureFlagManager.prototype.trackFeatureCheck = function(featureName, feature)
|
|
|
209
220
|
return;
|
|
210
221
|
}
|
|
211
222
|
this.trackedFeatures.add(featureName);
|
|
212
|
-
|
|
223
|
+
|
|
224
|
+
var trackingProperties = {
|
|
213
225
|
'Experiment name': featureName,
|
|
214
226
|
'Variant name': feature['key'],
|
|
215
227
|
'$experiment_type': 'feature_flag',
|
|
216
228
|
'Variant fetch start time': new Date(this._fetchStartTime).toISOString(),
|
|
217
229
|
'Variant fetch complete time': new Date(this._fetchCompleteTime).toISOString(),
|
|
218
|
-
'Variant fetch latency (ms)': this._fetchLatency
|
|
219
|
-
|
|
230
|
+
'Variant fetch latency (ms)': this._fetchLatency,
|
|
231
|
+
'Variant fetch traceparent': this._traceparent,
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
if (feature['experiment_id'] !== 'undefined') {
|
|
235
|
+
trackingProperties['$experiment_id'] = feature['experiment_id'];
|
|
236
|
+
}
|
|
237
|
+
if (feature['is_experiment_active'] !== 'undefined') {
|
|
238
|
+
trackingProperties['$is_experiment_active'] = feature['is_experiment_active'];
|
|
239
|
+
}
|
|
240
|
+
if (feature['is_qa_tester'] !== 'undefined') {
|
|
241
|
+
trackingProperties['$is_qa_tester'] = feature['is_qa_tester'];
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
this.track('$experiment_started', trackingProperties);
|
|
220
245
|
};
|
|
221
246
|
|
|
222
|
-
function
|
|
223
|
-
return !!fetch &&
|
|
247
|
+
FeatureFlagManager.prototype.minApisSupported = function() {
|
|
248
|
+
return !!this.fetch &&
|
|
224
249
|
typeof Promise !== 'undefined' &&
|
|
225
250
|
typeof Map !== 'undefined' &&
|
|
226
251
|
typeof Set !== 'undefined';
|
|
227
|
-
}
|
|
252
|
+
};
|
|
228
253
|
|
|
229
254
|
safewrapClass(FeatureFlagManager);
|
|
230
255
|
|
package/src/index.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export interface OutTrackingOptions extends ClearOptOutInOutOptions {
|
|
|
40
40
|
delete_user: boolean;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
export type RageClickConfig =
|
|
43
|
+
export type RageClickConfig =
|
|
44
44
|
| boolean
|
|
45
45
|
| {
|
|
46
46
|
/** Distance threshold in pixels for clicks to be considered within the same area (default: 30) */
|
|
@@ -51,6 +51,13 @@ export type RageClickConfig =
|
|
|
51
51
|
click_count?: number;
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
+
export type DeadClickConfig =
|
|
55
|
+
| boolean
|
|
56
|
+
| {
|
|
57
|
+
/** Time in milliseconds to wait after a click before qualifying it as dead (default: 500) */
|
|
58
|
+
timeout_ms?: number;
|
|
59
|
+
};
|
|
60
|
+
|
|
54
61
|
export interface RegisterOptions {
|
|
55
62
|
persistent: boolean;
|
|
56
63
|
}
|
|
@@ -83,6 +90,12 @@ export interface AutocaptureConfig {
|
|
|
83
90
|
* @default true
|
|
84
91
|
*/
|
|
85
92
|
rage_click?: RageClickConfig;
|
|
93
|
+
/**
|
|
94
|
+
* When set to `true`, Mixpanel will track dead clicks (clicks that produce no response).
|
|
95
|
+
* Can also be configured as an object to customize dead click detection parameters.
|
|
96
|
+
* @default true
|
|
97
|
+
*/
|
|
98
|
+
dead_click?: DeadClickConfig;
|
|
86
99
|
/**
|
|
87
100
|
* When set, Mixpanel will collect page scrolls at specified scroll intervals.
|
|
88
101
|
* @default true
|
|
@@ -191,12 +204,12 @@ export interface Config {
|
|
|
191
204
|
batch_size: number;
|
|
192
205
|
batch_flush_interval_ms: number;
|
|
193
206
|
batch_request_timeout_ms: number;
|
|
194
|
-
record_block_class: string;
|
|
207
|
+
record_block_class: string | RegExp;
|
|
195
208
|
record_block_selector: string;
|
|
196
209
|
record_collect_fonts: boolean;
|
|
197
210
|
record_idle_timeout_ms: number;
|
|
198
211
|
record_inline_images: boolean;
|
|
199
|
-
record_mask_text_class: string;
|
|
212
|
+
record_mask_text_class: string | RegExp;
|
|
200
213
|
record_mask_text_selector: string;
|
|
201
214
|
record_min_ms: number;
|
|
202
215
|
record_max_ms: number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../index';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../index';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../index';
|
package/src/utils.js
CHANGED
|
@@ -1677,6 +1677,20 @@ var cheap_guid = function(maxlen) {
|
|
|
1677
1677
|
return maxlen ? guid.substring(0, maxlen) : guid;
|
|
1678
1678
|
};
|
|
1679
1679
|
|
|
1680
|
+
/**
|
|
1681
|
+
* Generates a W3C traceparent header for easy interop with distributed tracing systems i.e Open Telemetry
|
|
1682
|
+
* https://www.w3.org/TR/trace-context/#traceparent-header
|
|
1683
|
+
*/
|
|
1684
|
+
var generateTraceparent = function() {
|
|
1685
|
+
var traceID = _.UUID().replace(/-/g, '');
|
|
1686
|
+
var parentID = _.UUID().replace(/-/g, '').substring(0, 16);
|
|
1687
|
+
|
|
1688
|
+
// Sampled trace
|
|
1689
|
+
var traceFlags = '01';
|
|
1690
|
+
|
|
1691
|
+
return '00-' + traceID + '-' + parentID + '-' + traceFlags;
|
|
1692
|
+
};
|
|
1693
|
+
|
|
1680
1694
|
// naive way to extract domain name (example.com) from full hostname (my.sub.example.com)
|
|
1681
1695
|
var SIMPLE_DOMAIN_MATCH_REGEX = /[a-z0-9][a-z0-9-]*\.[a-z]+$/i;
|
|
1682
1696
|
// this next one attempts to account for some ccSLDs, e.g. extracting oxford.ac.uk from www.oxford.ac.uk
|
|
@@ -1746,6 +1760,7 @@ export {
|
|
|
1746
1760
|
console,
|
|
1747
1761
|
document,
|
|
1748
1762
|
extract_domain,
|
|
1763
|
+
generateTraceparent,
|
|
1749
1764
|
JSONParse,
|
|
1750
1765
|
JSONStringify,
|
|
1751
1766
|
isOnline,
|