mixpanel-browser 2.67.0 → 2.69.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 +5 -0
- package/dist/mixpanel-core.cjs.js +132 -6
- package/dist/mixpanel-recorder.js +186 -47
- package/dist/mixpanel-recorder.min.js +1 -1
- package/dist/mixpanel-recorder.min.js.map +1 -1
- package/dist/mixpanel-with-async-recorder.cjs.js +132 -6
- package/dist/mixpanel-with-recorder.js +308 -51
- package/dist/mixpanel-with-recorder.min.js +1 -1
- package/dist/mixpanel.amd.js +308 -51
- package/dist/mixpanel.cjs.js +308 -51
- package/dist/mixpanel.globals.js +132 -6
- package/dist/mixpanel.min.js +148 -146
- package/dist/mixpanel.module.js +308 -51
- package/dist/mixpanel.umd.js +308 -51
- package/dist/rrweb-compiled.js +190 -59
- package/package.json +14 -2
- package/rollup.config.mjs +2 -2
- package/src/autocapture/index.js +59 -1
- package/src/autocapture/rageclick.js +38 -0
- package/src/config.js +1 -1
- package/src/flags/index.js +22 -1
- package/src/index.d.ts +19 -0
- package/src/mixpanel-core.js +10 -2
- package/src/recorder/recorder.js +1 -1
- package/src/recorder/recording-registry.js +37 -2
- package/src/recorder/session-recording.js +2 -3
- package/src/request-queue.js +1 -1
- package/src/storage/indexed-db.js +4 -0
- package/src/storage/local-storage.js +4 -0
- package/src/storage/wrapper.js +1 -0
package/dist/mixpanel.umd.js
CHANGED
|
@@ -489,6 +489,30 @@
|
|
|
489
489
|
function mutationObserverCtor$1() {
|
|
490
490
|
return getUntaintedPrototype$1("MutationObserver").constructor;
|
|
491
491
|
}
|
|
492
|
+
function patch$1(source, name, replacement) {
|
|
493
|
+
try {
|
|
494
|
+
if (!(name in source)) {
|
|
495
|
+
return function() {};
|
|
496
|
+
}
|
|
497
|
+
var original = source[name];
|
|
498
|
+
var wrapped = replacement(original);
|
|
499
|
+
if (typeof wrapped === "function") {
|
|
500
|
+
wrapped.prototype = wrapped.prototype || {};
|
|
501
|
+
Object.defineProperties(wrapped, {
|
|
502
|
+
__rrweb_original__: {
|
|
503
|
+
enumerable: false,
|
|
504
|
+
value: original
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
source[name] = wrapped;
|
|
509
|
+
return function() {
|
|
510
|
+
source[name] = original;
|
|
511
|
+
};
|
|
512
|
+
} catch (e) {
|
|
513
|
+
return function() {};
|
|
514
|
+
}
|
|
515
|
+
}
|
|
492
516
|
var index$1 = {
|
|
493
517
|
childNodes: childNodes$1,
|
|
494
518
|
parentNode: parentNode$1,
|
|
@@ -501,7 +525,8 @@
|
|
|
501
525
|
shadowRoot: shadowRoot$1,
|
|
502
526
|
querySelector: querySelector$1,
|
|
503
527
|
querySelectorAll: querySelectorAll$1,
|
|
504
|
-
mutationObserver: mutationObserverCtor$1
|
|
528
|
+
mutationObserver: mutationObserverCtor$1,
|
|
529
|
+
patch: patch$1
|
|
505
530
|
};
|
|
506
531
|
function isElement(n2) {
|
|
507
532
|
return n2.nodeType === n2.ELEMENT_NODE;
|
|
@@ -752,26 +777,82 @@
|
|
|
752
777
|
return "url(" + maybeQuote + stack.join("/") + maybeQuote + ")";
|
|
753
778
|
});
|
|
754
779
|
}
|
|
755
|
-
function normalizeCssString(cssText) {
|
|
756
|
-
|
|
780
|
+
function normalizeCssString(cssText, _testNoPxNorm) {
|
|
781
|
+
if (_testNoPxNorm === void 0) _testNoPxNorm = false;
|
|
782
|
+
if (_testNoPxNorm) {
|
|
783
|
+
return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
|
|
784
|
+
} else {
|
|
785
|
+
return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "").replace(/0px/g, "0");
|
|
786
|
+
}
|
|
757
787
|
}
|
|
758
|
-
function splitCssText(cssText, style) {
|
|
788
|
+
function splitCssText(cssText, style, _testNoPxNorm) {
|
|
789
|
+
if (_testNoPxNorm === void 0) _testNoPxNorm = false;
|
|
759
790
|
var childNodes2 = Array.from(style.childNodes);
|
|
760
791
|
var splits = [];
|
|
792
|
+
var iterCount = 0;
|
|
761
793
|
if (childNodes2.length > 1 && cssText && typeof cssText === "string") {
|
|
762
|
-
var cssTextNorm = normalizeCssString(cssText);
|
|
794
|
+
var cssTextNorm = normalizeCssString(cssText, _testNoPxNorm);
|
|
795
|
+
var normFactor = cssTextNorm.length / cssText.length;
|
|
763
796
|
for(var i2 = 1; i2 < childNodes2.length; i2++){
|
|
764
797
|
if (childNodes2[i2].textContent && typeof childNodes2[i2].textContent === "string") {
|
|
765
|
-
var textContentNorm = normalizeCssString(childNodes2[i2].textContent);
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
798
|
+
var textContentNorm = normalizeCssString(childNodes2[i2].textContent, _testNoPxNorm);
|
|
799
|
+
var jLimit = 100;
|
|
800
|
+
var j = 3;
|
|
801
|
+
for(; j < textContentNorm.length; j++){
|
|
802
|
+
if (// keep consuming css identifiers (to get a decent chunk more quickly)
|
|
803
|
+
textContentNorm[j].match(/[a-zA-Z0-9]/) || // substring needs to be unique to this section
|
|
804
|
+
textContentNorm.indexOf(textContentNorm.substring(0, j), 1) !== -1) {
|
|
805
|
+
continue;
|
|
806
|
+
}
|
|
807
|
+
break;
|
|
808
|
+
}
|
|
809
|
+
for(; j < textContentNorm.length; j++){
|
|
810
|
+
var startSubstring = textContentNorm.substring(0, j);
|
|
811
|
+
var cssNormSplits = cssTextNorm.split(startSubstring);
|
|
812
|
+
var splitNorm = -1;
|
|
813
|
+
if (cssNormSplits.length === 2) {
|
|
814
|
+
splitNorm = cssNormSplits[0].length;
|
|
815
|
+
} else if (cssNormSplits.length > 2 && cssNormSplits[0] === "" && childNodes2[i2 - 1].textContent !== "") {
|
|
816
|
+
splitNorm = cssTextNorm.indexOf(startSubstring, 1);
|
|
817
|
+
} else if (cssNormSplits.length === 1) {
|
|
818
|
+
startSubstring = startSubstring.substring(0, startSubstring.length - 1);
|
|
819
|
+
cssNormSplits = cssTextNorm.split(startSubstring);
|
|
820
|
+
if (cssNormSplits.length <= 1) {
|
|
821
|
+
splits.push(cssText);
|
|
822
|
+
return splits;
|
|
823
|
+
}
|
|
824
|
+
j = jLimit + 1;
|
|
825
|
+
} else if (j === textContentNorm.length - 1) {
|
|
826
|
+
splitNorm = cssTextNorm.indexOf(startSubstring);
|
|
827
|
+
}
|
|
828
|
+
if (cssNormSplits.length >= 2 && j > jLimit) {
|
|
829
|
+
var prevTextContent = childNodes2[i2 - 1].textContent;
|
|
830
|
+
if (prevTextContent && typeof prevTextContent === "string") {
|
|
831
|
+
var prevMinLength = normalizeCssString(prevTextContent).length;
|
|
832
|
+
splitNorm = cssTextNorm.indexOf(startSubstring, prevMinLength);
|
|
833
|
+
}
|
|
834
|
+
if (splitNorm === -1) {
|
|
835
|
+
splitNorm = cssNormSplits[0].length;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
if (splitNorm !== -1) {
|
|
839
|
+
var k = Math.floor(splitNorm / normFactor);
|
|
840
|
+
for(; k > 0 && k < cssText.length;){
|
|
841
|
+
iterCount += 1;
|
|
842
|
+
if (iterCount > 50 * childNodes2.length) {
|
|
843
|
+
splits.push(cssText);
|
|
844
|
+
return splits;
|
|
845
|
+
}
|
|
846
|
+
var normPart = normalizeCssString(cssText.substring(0, k), _testNoPxNorm);
|
|
847
|
+
if (normPart.length === splitNorm) {
|
|
772
848
|
splits.push(cssText.substring(0, k));
|
|
773
849
|
cssText = cssText.substring(k);
|
|
850
|
+
cssTextNorm = cssTextNorm.substring(splitNorm);
|
|
774
851
|
break;
|
|
852
|
+
} else if (normPart.length < splitNorm) {
|
|
853
|
+
k += Math.max(1, Math.floor((splitNorm - normPart.length) / normFactor));
|
|
854
|
+
} else {
|
|
855
|
+
k -= Math.max(1, Math.floor((normPart.length - splitNorm) * normFactor));
|
|
775
856
|
}
|
|
776
857
|
}
|
|
777
858
|
break;
|
|
@@ -1288,7 +1369,7 @@
|
|
|
1288
1369
|
} else if (sn.type === NodeType$3.Element) {
|
|
1289
1370
|
if (slimDOMOptions.script && // script tag
|
|
1290
1371
|
(sn.tagName === "script" || // (module)preload link
|
|
1291
|
-
sn.tagName === "link" && (sn.attributes.rel === "preload"
|
|
1372
|
+
sn.tagName === "link" && (sn.attributes.rel === "preload" && sn.attributes.as === "script" || sn.attributes.rel === "modulepreload") || // prefetch link
|
|
1292
1373
|
sn.tagName === "link" && sn.attributes.rel === "prefetch" && typeof sn.attributes.href === "string" && extractFileExtension(sn.attributes.href) === "js")) {
|
|
1293
1374
|
return true;
|
|
1294
1375
|
} else if (slimDOMOptions.headFavicon && (sn.tagName === "link" && sn.attributes.rel === "shortcut icon" || sn.tagName === "meta" && (lowerIfExists(sn.attributes.name).match(/^msapplication-tile(image|color)$/) || lowerIfExists(sn.attributes.name) === "application-name" || lowerIfExists(sn.attributes.rel) === "icon" || lowerIfExists(sn.attributes.rel) === "apple-touch-icon" || lowerIfExists(sn.attributes.rel) === "shortcut icon"))) {
|
|
@@ -10039,6 +10120,30 @@
|
|
|
10039
10120
|
function mutationObserverCtor() {
|
|
10040
10121
|
return getUntaintedPrototype("MutationObserver").constructor;
|
|
10041
10122
|
}
|
|
10123
|
+
function patch(source, name, replacement) {
|
|
10124
|
+
try {
|
|
10125
|
+
if (!(name in source)) {
|
|
10126
|
+
return function() {};
|
|
10127
|
+
}
|
|
10128
|
+
var original = source[name];
|
|
10129
|
+
var wrapped = replacement(original);
|
|
10130
|
+
if (typeof wrapped === "function") {
|
|
10131
|
+
wrapped.prototype = wrapped.prototype || {};
|
|
10132
|
+
Object.defineProperties(wrapped, {
|
|
10133
|
+
__rrweb_original__: {
|
|
10134
|
+
enumerable: false,
|
|
10135
|
+
value: original
|
|
10136
|
+
}
|
|
10137
|
+
});
|
|
10138
|
+
}
|
|
10139
|
+
source[name] = wrapped;
|
|
10140
|
+
return function() {
|
|
10141
|
+
source[name] = original;
|
|
10142
|
+
};
|
|
10143
|
+
} catch (e) {
|
|
10144
|
+
return function() {};
|
|
10145
|
+
}
|
|
10146
|
+
}
|
|
10042
10147
|
var index = {
|
|
10043
10148
|
childNodes: childNodes,
|
|
10044
10149
|
parentNode: parentNode,
|
|
@@ -10051,7 +10156,8 @@
|
|
|
10051
10156
|
shadowRoot: shadowRoot,
|
|
10052
10157
|
querySelector: querySelector,
|
|
10053
10158
|
querySelectorAll: querySelectorAll,
|
|
10054
|
-
mutationObserver: mutationObserverCtor
|
|
10159
|
+
mutationObserver: mutationObserverCtor,
|
|
10160
|
+
patch: patch
|
|
10055
10161
|
};
|
|
10056
10162
|
function on(type, fn, target) {
|
|
10057
10163
|
if (target === void 0) target = document;
|
|
@@ -10144,30 +10250,6 @@
|
|
|
10144
10250
|
return hookSetter(target, key, original || {}, true);
|
|
10145
10251
|
};
|
|
10146
10252
|
}
|
|
10147
|
-
function patch(source, name, replacement) {
|
|
10148
|
-
try {
|
|
10149
|
-
if (!(name in source)) {
|
|
10150
|
-
return function() {};
|
|
10151
|
-
}
|
|
10152
|
-
var original = source[name];
|
|
10153
|
-
var wrapped = replacement(original);
|
|
10154
|
-
if (typeof wrapped === "function") {
|
|
10155
|
-
wrapped.prototype = wrapped.prototype || {};
|
|
10156
|
-
Object.defineProperties(wrapped, {
|
|
10157
|
-
__rrweb_original__: {
|
|
10158
|
-
enumerable: false,
|
|
10159
|
-
value: original
|
|
10160
|
-
}
|
|
10161
|
-
});
|
|
10162
|
-
}
|
|
10163
|
-
source[name] = wrapped;
|
|
10164
|
-
return function() {
|
|
10165
|
-
source[name] = original;
|
|
10166
|
-
};
|
|
10167
|
-
} catch (e) {
|
|
10168
|
-
return function() {};
|
|
10169
|
-
}
|
|
10170
|
-
}
|
|
10171
10253
|
var nowTimestamp = Date.now;
|
|
10172
10254
|
if (!/* @__PURE__ */ /[1-9][0-9]{12}/.test(Date.now().toString())) {
|
|
10173
10255
|
nowTimestamp = function() {
|
|
@@ -10758,9 +10840,17 @@
|
|
|
10758
10840
|
_this.attributes.push(item);
|
|
10759
10841
|
_this.attributeMap.set(textarea, item);
|
|
10760
10842
|
}
|
|
10761
|
-
|
|
10843
|
+
var value = Array.from(index.childNodes(textarea), function(cn) {
|
|
10762
10844
|
return index.textContent(cn) || "";
|
|
10763
10845
|
}).join("");
|
|
10846
|
+
item.attributes.value = maskInputValue({
|
|
10847
|
+
element: textarea,
|
|
10848
|
+
maskInputOptions: _this.maskInputOptions,
|
|
10849
|
+
tagName: textarea.tagName,
|
|
10850
|
+
type: getInputType(textarea),
|
|
10851
|
+
value: value,
|
|
10852
|
+
maskInputFn: _this.maskInputFn
|
|
10853
|
+
});
|
|
10764
10854
|
});
|
|
10765
10855
|
__publicField(this, "processMutation", function(m) {
|
|
10766
10856
|
if (isIgnored(m.target, _this.mirror, _this.slimDOMOptions)) {
|
|
@@ -13541,8 +13631,15 @@
|
|
|
13541
13631
|
}, window));
|
|
13542
13632
|
}
|
|
13543
13633
|
return function() {
|
|
13544
|
-
handlers.forEach(function(
|
|
13545
|
-
|
|
13634
|
+
handlers.forEach(function(handler) {
|
|
13635
|
+
try {
|
|
13636
|
+
handler();
|
|
13637
|
+
} catch (error) {
|
|
13638
|
+
var msg = String(error).toLowerCase();
|
|
13639
|
+
if (!msg.includes("cross-origin")) {
|
|
13640
|
+
console.warn(error);
|
|
13641
|
+
}
|
|
13642
|
+
}
|
|
13546
13643
|
});
|
|
13547
13644
|
processedNodeManager.destroy();
|
|
13548
13645
|
recording = false;
|
|
@@ -13948,7 +14045,7 @@
|
|
|
13948
14045
|
|
|
13949
14046
|
var Config = {
|
|
13950
14047
|
DEBUG: false,
|
|
13951
|
-
LIB_VERSION: '2.
|
|
14048
|
+
LIB_VERSION: '2.69.0'
|
|
13952
14049
|
};
|
|
13953
14050
|
|
|
13954
14051
|
/* eslint camelcase: "off", eqeqeq: "off" */
|
|
@@ -15748,6 +15845,10 @@
|
|
|
15748
15845
|
});
|
|
15749
15846
|
};
|
|
15750
15847
|
|
|
15848
|
+
IDBStorageWrapper.prototype.isInitialized = function () {
|
|
15849
|
+
return !!this.dbPromise;
|
|
15850
|
+
};
|
|
15851
|
+
|
|
15751
15852
|
/**
|
|
15752
15853
|
* @param {IDBTransactionMode} mode
|
|
15753
15854
|
* @param {function(IDBObjectStore): void} storeCb
|
|
@@ -16272,6 +16373,10 @@
|
|
|
16272
16373
|
return PromisePolyfill.resolve();
|
|
16273
16374
|
};
|
|
16274
16375
|
|
|
16376
|
+
LocalStorageWrapper.prototype.isInitialized = function () {
|
|
16377
|
+
return true;
|
|
16378
|
+
};
|
|
16379
|
+
|
|
16275
16380
|
LocalStorageWrapper.prototype.setItem = function (key, value) {
|
|
16276
16381
|
return new PromisePolyfill(_.bind(function (resolve, reject) {
|
|
16277
16382
|
try {
|
|
@@ -16352,7 +16457,7 @@
|
|
|
16352
16457
|
};
|
|
16353
16458
|
|
|
16354
16459
|
RequestQueue.prototype.ensureInit = function () {
|
|
16355
|
-
if (this.initialized) {
|
|
16460
|
+
if (this.initialized || !this.usePersistence) {
|
|
16356
16461
|
return PromisePolyfill.resolve();
|
|
16357
16462
|
}
|
|
16358
16463
|
|
|
@@ -17104,10 +17209,9 @@
|
|
|
17104
17209
|
|
|
17105
17210
|
// disable persistence if localStorage is not supported
|
|
17106
17211
|
// request-queue will automatically disable persistence if indexedDB fails to initialize
|
|
17107
|
-
var usePersistence = localStorageSupported(options.sharedLockStorage, true);
|
|
17212
|
+
var usePersistence = localStorageSupported(options.sharedLockStorage, true) && !this.getConfig('disable_persistence');
|
|
17108
17213
|
|
|
17109
17214
|
// each replay has its own batcher key to avoid conflicts between rrweb events of different recordings
|
|
17110
|
-
// this will be important when persistence is introduced
|
|
17111
17215
|
this.batcherKey = '__mprec_' + this.getConfig('name') + '_' + this.getConfig('token') + '_' + this.replayId;
|
|
17112
17216
|
this.queueStorage = new IDBStorageWrapper(RECORDING_EVENTS_STORE_NAME);
|
|
17113
17217
|
this.batcher = new RequestBatcher(this.batcherKey, {
|
|
@@ -17488,12 +17592,17 @@
|
|
|
17488
17592
|
* Makes sure that only one tab can be recording at a time.
|
|
17489
17593
|
*/
|
|
17490
17594
|
var RecordingRegistry = function (options) {
|
|
17595
|
+
/** @type {IDBStorageWrapper} */
|
|
17491
17596
|
this.idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
|
|
17492
17597
|
this.errorReporter = options.errorReporter;
|
|
17493
17598
|
this.mixpanelInstance = options.mixpanelInstance;
|
|
17494
17599
|
this.sharedLockStorage = options.sharedLockStorage;
|
|
17495
17600
|
};
|
|
17496
17601
|
|
|
17602
|
+
RecordingRegistry.prototype.isPersistenceEnabled = function() {
|
|
17603
|
+
return !this.mixpanelInstance.get_config('disable_persistence');
|
|
17604
|
+
};
|
|
17605
|
+
|
|
17497
17606
|
RecordingRegistry.prototype.handleError = function (err) {
|
|
17498
17607
|
this.errorReporter('IndexedDB error: ', err);
|
|
17499
17608
|
};
|
|
@@ -17502,6 +17611,10 @@
|
|
|
17502
17611
|
* @param {import('./session-recording').SerializedRecording} serializedRecording
|
|
17503
17612
|
*/
|
|
17504
17613
|
RecordingRegistry.prototype.setActiveRecording = function (serializedRecording) {
|
|
17614
|
+
if (!this.isPersistenceEnabled()) {
|
|
17615
|
+
return PromisePolyfill.resolve();
|
|
17616
|
+
}
|
|
17617
|
+
|
|
17505
17618
|
var tabId = serializedRecording['tabId'];
|
|
17506
17619
|
if (!tabId) {
|
|
17507
17620
|
console.warn('No tab ID is set, cannot persist recording metadata.');
|
|
@@ -17519,6 +17632,10 @@
|
|
|
17519
17632
|
* @returns {Promise<import('./session-recording').SerializedRecording>}
|
|
17520
17633
|
*/
|
|
17521
17634
|
RecordingRegistry.prototype.getActiveRecording = function () {
|
|
17635
|
+
if (!this.isPersistenceEnabled()) {
|
|
17636
|
+
return PromisePolyfill.resolve(null);
|
|
17637
|
+
}
|
|
17638
|
+
|
|
17522
17639
|
return this.idb.init()
|
|
17523
17640
|
.then(function () {
|
|
17524
17641
|
return this.idb.getItem(this.mixpanelInstance.get_tab_id());
|
|
@@ -17530,8 +17647,16 @@
|
|
|
17530
17647
|
};
|
|
17531
17648
|
|
|
17532
17649
|
RecordingRegistry.prototype.clearActiveRecording = function () {
|
|
17533
|
-
|
|
17534
|
-
|
|
17650
|
+
if (this.isPersistenceEnabled()) {
|
|
17651
|
+
// mark recording as expired instead of deleting it in case the page unloads mid-flush and doesn't make it to ingestion.
|
|
17652
|
+
// this will ensure the next pageload will flush the remaining events, but not try to continue the recording.
|
|
17653
|
+
return this.markActiveRecordingExpired();
|
|
17654
|
+
} else {
|
|
17655
|
+
return this.deleteActiveRecording();
|
|
17656
|
+
}
|
|
17657
|
+
};
|
|
17658
|
+
|
|
17659
|
+
RecordingRegistry.prototype.markActiveRecordingExpired = function () {
|
|
17535
17660
|
return this.getActiveRecording()
|
|
17536
17661
|
.then(function (serializedRecording) {
|
|
17537
17662
|
if (serializedRecording) {
|
|
@@ -17542,11 +17667,25 @@
|
|
|
17542
17667
|
.catch(this.handleError.bind(this));
|
|
17543
17668
|
};
|
|
17544
17669
|
|
|
17670
|
+
RecordingRegistry.prototype.deleteActiveRecording = function () {
|
|
17671
|
+
// avoid initializing IDB if this registry instance hasn't already written a recording
|
|
17672
|
+
if (this.idb.isInitialized()) {
|
|
17673
|
+
return this.idb.removeItem(this.mixpanelInstance.get_tab_id())
|
|
17674
|
+
.catch(this.handleError.bind(this));
|
|
17675
|
+
} else {
|
|
17676
|
+
return PromisePolyfill.resolve();
|
|
17677
|
+
}
|
|
17678
|
+
};
|
|
17679
|
+
|
|
17545
17680
|
/**
|
|
17546
17681
|
* Flush any inactive recordings from the registry to minimize data loss.
|
|
17547
17682
|
* The main idea here is that we can flush remaining rrweb events on the next page load if a tab is closed mid-batch.
|
|
17548
17683
|
*/
|
|
17549
17684
|
RecordingRegistry.prototype.flushInactiveRecordings = function () {
|
|
17685
|
+
if (!this.isPersistenceEnabled()) {
|
|
17686
|
+
return PromisePolyfill.resolve([]);
|
|
17687
|
+
}
|
|
17688
|
+
|
|
17550
17689
|
return this.idb.init()
|
|
17551
17690
|
.then(function() {
|
|
17552
17691
|
return this.idb.getAll();
|
|
@@ -18233,6 +18372,38 @@
|
|
|
18233
18372
|
return true;
|
|
18234
18373
|
}
|
|
18235
18374
|
|
|
18375
|
+
/** @const */ var DEFAULT_RAGE_CLICK_THRESHOLD_PX = 30;
|
|
18376
|
+
/** @const */ var DEFAULT_RAGE_CLICK_TIMEOUT_MS = 1000;
|
|
18377
|
+
/** @const */ var DEFAULT_RAGE_CLICK_CLICK_COUNT = 4;
|
|
18378
|
+
|
|
18379
|
+
function RageClickTracker() {
|
|
18380
|
+
this.clicks = [];
|
|
18381
|
+
}
|
|
18382
|
+
|
|
18383
|
+
RageClickTracker.prototype.isRageClick = function(x, y, options) {
|
|
18384
|
+
options = options || {};
|
|
18385
|
+
var thresholdPx = options['threshold_px'] || DEFAULT_RAGE_CLICK_THRESHOLD_PX;
|
|
18386
|
+
var timeoutMs = options['timeout_ms'] || DEFAULT_RAGE_CLICK_TIMEOUT_MS;
|
|
18387
|
+
var clickCount = options['click_count'] || DEFAULT_RAGE_CLICK_CLICK_COUNT;
|
|
18388
|
+
var timestamp = Date.now();
|
|
18389
|
+
|
|
18390
|
+
var lastClick = this.clicks[this.clicks.length - 1];
|
|
18391
|
+
if (
|
|
18392
|
+
lastClick &&
|
|
18393
|
+
timestamp - lastClick.timestamp < timeoutMs &&
|
|
18394
|
+
Math.sqrt(Math.pow(x - lastClick.x, 2) + Math.pow(y - lastClick.y, 2)) < thresholdPx
|
|
18395
|
+
) {
|
|
18396
|
+
this.clicks.push({ x: x, y: y, timestamp: timestamp });
|
|
18397
|
+
if (this.clicks.length >= clickCount) {
|
|
18398
|
+
this.clicks = [];
|
|
18399
|
+
return true;
|
|
18400
|
+
}
|
|
18401
|
+
} else {
|
|
18402
|
+
this.clicks = [{ x: x, y: y, timestamp: timestamp }];
|
|
18403
|
+
}
|
|
18404
|
+
return false;
|
|
18405
|
+
};
|
|
18406
|
+
|
|
18236
18407
|
var AUTOCAPTURE_CONFIG_KEY = 'autocapture';
|
|
18237
18408
|
var LEGACY_PAGEVIEW_CONFIG_KEY = 'track_pageview';
|
|
18238
18409
|
|
|
@@ -18254,6 +18425,7 @@
|
|
|
18254
18425
|
var CONFIG_TRACK_CLICK = 'click';
|
|
18255
18426
|
var CONFIG_TRACK_INPUT = 'input';
|
|
18256
18427
|
var CONFIG_TRACK_PAGEVIEW = 'pageview';
|
|
18428
|
+
var CONFIG_TRACK_RAGE_CLICK = 'rage_click';
|
|
18257
18429
|
var CONFIG_TRACK_SCROLL = 'scroll';
|
|
18258
18430
|
var CONFIG_TRACK_SUBMIT = 'submit';
|
|
18259
18431
|
|
|
@@ -18271,6 +18443,7 @@
|
|
|
18271
18443
|
CONFIG_DEFAULTS$1[CONFIG_TRACK_CLICK] = true;
|
|
18272
18444
|
CONFIG_DEFAULTS$1[CONFIG_TRACK_INPUT] = true;
|
|
18273
18445
|
CONFIG_DEFAULTS$1[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
|
|
18446
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_RAGE_CLICK] = true;
|
|
18274
18447
|
CONFIG_DEFAULTS$1[CONFIG_TRACK_SCROLL] = true;
|
|
18275
18448
|
CONFIG_DEFAULTS$1[CONFIG_TRACK_SUBMIT] = true;
|
|
18276
18449
|
|
|
@@ -18280,6 +18453,7 @@
|
|
|
18280
18453
|
|
|
18281
18454
|
var MP_EV_CLICK = '$mp_click';
|
|
18282
18455
|
var MP_EV_INPUT = '$mp_input_change';
|
|
18456
|
+
var MP_EV_RAGE_CLICK = '$mp_rage_click';
|
|
18283
18457
|
var MP_EV_SCROLL = '$mp_scroll';
|
|
18284
18458
|
var MP_EV_SUBMIT = '$mp_submit';
|
|
18285
18459
|
|
|
@@ -18302,6 +18476,7 @@
|
|
|
18302
18476
|
this.initInputTracking();
|
|
18303
18477
|
this.initScrollTracking();
|
|
18304
18478
|
this.initSubmitTracking();
|
|
18479
|
+
this.initRageClickTracking();
|
|
18305
18480
|
};
|
|
18306
18481
|
|
|
18307
18482
|
Autocapture.prototype.getFullConfig = function() {
|
|
@@ -18380,6 +18555,11 @@
|
|
|
18380
18555
|
return;
|
|
18381
18556
|
}
|
|
18382
18557
|
|
|
18558
|
+
var isCapturedForHeatMap = this.mp.is_recording_heatmap_data() && (
|
|
18559
|
+
(mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK)) ||
|
|
18560
|
+
(mpEventName === MP_EV_RAGE_CLICK && !this._getRageClickConfig())
|
|
18561
|
+
);
|
|
18562
|
+
|
|
18383
18563
|
var props = getPropsForDOMEvent(ev, {
|
|
18384
18564
|
allowElementCallback: this.getConfig(CONFIG_ALLOW_ELEMENT_CALLBACK),
|
|
18385
18565
|
allowSelectors: this.getConfig(CONFIG_ALLOW_SELECTORS),
|
|
@@ -18388,7 +18568,7 @@
|
|
|
18388
18568
|
blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
|
|
18389
18569
|
captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
|
|
18390
18570
|
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT),
|
|
18391
|
-
capturedForHeatMap:
|
|
18571
|
+
capturedForHeatMap: isCapturedForHeatMap,
|
|
18392
18572
|
});
|
|
18393
18573
|
if (props) {
|
|
18394
18574
|
_.extend(props, DEFAULT_PROPS);
|
|
@@ -18396,6 +18576,24 @@
|
|
|
18396
18576
|
}
|
|
18397
18577
|
};
|
|
18398
18578
|
|
|
18579
|
+
Autocapture.prototype._getRageClickConfig = function() {
|
|
18580
|
+
var config = this.getConfig(CONFIG_TRACK_RAGE_CLICK);
|
|
18581
|
+
|
|
18582
|
+
if (!config) {
|
|
18583
|
+
return null; // rage click tracking disabled
|
|
18584
|
+
}
|
|
18585
|
+
|
|
18586
|
+
if (config === true) {
|
|
18587
|
+
return {}; // use defaults
|
|
18588
|
+
}
|
|
18589
|
+
|
|
18590
|
+
if (typeof config === 'object') {
|
|
18591
|
+
return config; // use custom configuration
|
|
18592
|
+
}
|
|
18593
|
+
|
|
18594
|
+
return {}; // fallback to defaults for any other truthy value
|
|
18595
|
+
};
|
|
18596
|
+
|
|
18399
18597
|
Autocapture.prototype.initClickTracking = function() {
|
|
18400
18598
|
win.removeEventListener(EV_CLICK, this.listenerClick);
|
|
18401
18599
|
|
|
@@ -18497,6 +18695,36 @@
|
|
|
18497
18695
|
}.bind(this)));
|
|
18498
18696
|
};
|
|
18499
18697
|
|
|
18698
|
+
Autocapture.prototype.initRageClickTracking = function() {
|
|
18699
|
+
win.removeEventListener(EV_CLICK, this.listenerRageClick);
|
|
18700
|
+
|
|
18701
|
+
var rageClickConfig = this._getRageClickConfig();
|
|
18702
|
+
if (!rageClickConfig && !this.mp.get_config('record_heatmap_data')) {
|
|
18703
|
+
return;
|
|
18704
|
+
}
|
|
18705
|
+
|
|
18706
|
+
logger$1.log('Initializing rage click tracking');
|
|
18707
|
+
if (!this._rageClickTracker) {
|
|
18708
|
+
this._rageClickTracker = new RageClickTracker();
|
|
18709
|
+
}
|
|
18710
|
+
|
|
18711
|
+
this.listenerRageClick = function(ev) {
|
|
18712
|
+
var currentRageClickConfig = this._getRageClickConfig();
|
|
18713
|
+
if (!currentRageClickConfig && !this.mp.is_recording_heatmap_data()) {
|
|
18714
|
+
return;
|
|
18715
|
+
}
|
|
18716
|
+
|
|
18717
|
+
if (this.currentUrlBlocked()) {
|
|
18718
|
+
return;
|
|
18719
|
+
}
|
|
18720
|
+
|
|
18721
|
+
if (this._rageClickTracker.isRageClick(ev['pageX'], ev['pageY'], currentRageClickConfig)) {
|
|
18722
|
+
this.trackDomEvent(ev, MP_EV_RAGE_CLICK);
|
|
18723
|
+
}
|
|
18724
|
+
}.bind(this);
|
|
18725
|
+
win.addEventListener(EV_CLICK, this.listenerRageClick);
|
|
18726
|
+
};
|
|
18727
|
+
|
|
18500
18728
|
Autocapture.prototype.initScrollTracking = function() {
|
|
18501
18729
|
win.removeEventListener(EV_SCROLLEND, this.listenerScroll);
|
|
18502
18730
|
|
|
@@ -18583,6 +18811,7 @@
|
|
|
18583
18811
|
var FeatureFlagManager = function(initOptions) {
|
|
18584
18812
|
this.getFullApiRoute = initOptions.getFullApiRoute;
|
|
18585
18813
|
this.getMpConfig = initOptions.getConfigFunc;
|
|
18814
|
+
this.setMpConfig = initOptions.setConfigFunc;
|
|
18586
18815
|
this.getMpProperty = initOptions.getPropertyFunc;
|
|
18587
18816
|
this.track = initOptions.trackingFunc;
|
|
18588
18817
|
};
|
|
@@ -18620,6 +18849,23 @@
|
|
|
18620
18849
|
return !!this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
18621
18850
|
};
|
|
18622
18851
|
|
|
18852
|
+
FeatureFlagManager.prototype.updateContext = function(newContext, options) {
|
|
18853
|
+
if (!this.isSystemEnabled()) {
|
|
18854
|
+
logger.critical('Feature Flags not enabled, cannot update context');
|
|
18855
|
+
return Promise.resolve();
|
|
18856
|
+
}
|
|
18857
|
+
|
|
18858
|
+
var ffConfig = this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
18859
|
+
if (!_.isObject(ffConfig)) {
|
|
18860
|
+
ffConfig = {};
|
|
18861
|
+
}
|
|
18862
|
+
var oldContext = (options && options['replace']) ? {} : this.getConfig(CONFIG_CONTEXT);
|
|
18863
|
+
ffConfig[CONFIG_CONTEXT] = _.extend({}, oldContext, newContext);
|
|
18864
|
+
|
|
18865
|
+
this.setMpConfig(FLAGS_CONFIG_KEY, ffConfig);
|
|
18866
|
+
return this.fetchFlags();
|
|
18867
|
+
};
|
|
18868
|
+
|
|
18623
18869
|
FeatureFlagManager.prototype.areFlagsReady = function() {
|
|
18624
18870
|
if (!this.isSystemEnabled()) {
|
|
18625
18871
|
logger.error('Feature Flags not enabled');
|
|
@@ -18629,7 +18875,7 @@
|
|
|
18629
18875
|
|
|
18630
18876
|
FeatureFlagManager.prototype.fetchFlags = function() {
|
|
18631
18877
|
if (!this.isSystemEnabled()) {
|
|
18632
|
-
return;
|
|
18878
|
+
return Promise.resolve();
|
|
18633
18879
|
}
|
|
18634
18880
|
|
|
18635
18881
|
var distinctId = this.getMpProperty('distinct_id');
|
|
@@ -18669,6 +18915,8 @@
|
|
|
18669
18915
|
this.markFetchComplete();
|
|
18670
18916
|
logger.error(error);
|
|
18671
18917
|
}.bind(this));
|
|
18918
|
+
|
|
18919
|
+
return this.fetchPromise;
|
|
18672
18920
|
};
|
|
18673
18921
|
|
|
18674
18922
|
FeatureFlagManager.prototype.markFetchComplete = function() {
|
|
@@ -18781,6 +19029,7 @@
|
|
|
18781
19029
|
FeatureFlagManager.prototype['get_variant_value_sync'] = FeatureFlagManager.prototype.getVariantValueSync;
|
|
18782
19030
|
FeatureFlagManager.prototype['is_enabled'] = FeatureFlagManager.prototype.isEnabled;
|
|
18783
19031
|
FeatureFlagManager.prototype['is_enabled_sync'] = FeatureFlagManager.prototype.isEnabledSync;
|
|
19032
|
+
FeatureFlagManager.prototype['update_context'] = FeatureFlagManager.prototype.updateContext;
|
|
18784
19033
|
|
|
18785
19034
|
// Deprecated method
|
|
18786
19035
|
FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
|
|
@@ -20241,7 +20490,7 @@
|
|
|
20241
20490
|
'batch_autostart': true,
|
|
20242
20491
|
'hooks': {},
|
|
20243
20492
|
'record_block_class': new RegExp('^(mp-block|fs-exclude|amp-block|rr-block|ph-no-capture)$'),
|
|
20244
|
-
'record_block_selector': 'img, video',
|
|
20493
|
+
'record_block_selector': 'img, video, audio',
|
|
20245
20494
|
'record_canvas': false,
|
|
20246
20495
|
'record_collect_fonts': false,
|
|
20247
20496
|
'record_heatmap_data': false,
|
|
@@ -20465,6 +20714,7 @@
|
|
|
20465
20714
|
return this.get_api_host('flags') + '/' + this.get_config('api_routes')['flags'];
|
|
20466
20715
|
}, this),
|
|
20467
20716
|
getConfigFunc: _.bind(this.get_config, this),
|
|
20717
|
+
setConfigFunc: _.bind(this.set_config, this),
|
|
20468
20718
|
getPropertyFunc: _.bind(this.get_property, this),
|
|
20469
20719
|
trackingFunc: _.bind(this.track, this)
|
|
20470
20720
|
});
|
|
@@ -20483,7 +20733,9 @@
|
|
|
20483
20733
|
* This is primarily used for session recording, where data must be isolated to the current tab.
|
|
20484
20734
|
*/
|
|
20485
20735
|
MixpanelLib.prototype._init_tab_id = function() {
|
|
20486
|
-
if (
|
|
20736
|
+
if (this.get_config('disable_persistence')) {
|
|
20737
|
+
console$1.log('Tab ID initialization skipped due to disable_persistence config');
|
|
20738
|
+
} else if (_.sessionStorage.is_supported()) {
|
|
20487
20739
|
try {
|
|
20488
20740
|
var key_suffix = this.get_config('name') + '_' + this.get_config('token');
|
|
20489
20741
|
var tab_id_key = 'mp_tab_id_' + key_suffix;
|
|
@@ -20517,6 +20769,11 @@
|
|
|
20517
20769
|
};
|
|
20518
20770
|
|
|
20519
20771
|
MixpanelLib.prototype._should_load_recorder = function () {
|
|
20772
|
+
if (this.get_config('disable_persistence')) {
|
|
20773
|
+
console$1.log('Load recorder check skipped due to disable_persistence config');
|
|
20774
|
+
return Promise.resolve(false);
|
|
20775
|
+
}
|
|
20776
|
+
|
|
20520
20777
|
var recording_registry_idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
|
|
20521
20778
|
var tab_id = this.get_tab_id();
|
|
20522
20779
|
return recording_registry_idb.init()
|