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
|
@@ -486,6 +486,30 @@
|
|
|
486
486
|
function mutationObserverCtor$1() {
|
|
487
487
|
return getUntaintedPrototype$1("MutationObserver").constructor;
|
|
488
488
|
}
|
|
489
|
+
function patch$1(source, name, replacement) {
|
|
490
|
+
try {
|
|
491
|
+
if (!(name in source)) {
|
|
492
|
+
return function() {};
|
|
493
|
+
}
|
|
494
|
+
var original = source[name];
|
|
495
|
+
var wrapped = replacement(original);
|
|
496
|
+
if (typeof wrapped === "function") {
|
|
497
|
+
wrapped.prototype = wrapped.prototype || {};
|
|
498
|
+
Object.defineProperties(wrapped, {
|
|
499
|
+
__rrweb_original__: {
|
|
500
|
+
enumerable: false,
|
|
501
|
+
value: original
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
source[name] = wrapped;
|
|
506
|
+
return function() {
|
|
507
|
+
source[name] = original;
|
|
508
|
+
};
|
|
509
|
+
} catch (e) {
|
|
510
|
+
return function() {};
|
|
511
|
+
}
|
|
512
|
+
}
|
|
489
513
|
var index$1 = {
|
|
490
514
|
childNodes: childNodes$1,
|
|
491
515
|
parentNode: parentNode$1,
|
|
@@ -498,7 +522,8 @@
|
|
|
498
522
|
shadowRoot: shadowRoot$1,
|
|
499
523
|
querySelector: querySelector$1,
|
|
500
524
|
querySelectorAll: querySelectorAll$1,
|
|
501
|
-
mutationObserver: mutationObserverCtor$1
|
|
525
|
+
mutationObserver: mutationObserverCtor$1,
|
|
526
|
+
patch: patch$1
|
|
502
527
|
};
|
|
503
528
|
function isElement(n2) {
|
|
504
529
|
return n2.nodeType === n2.ELEMENT_NODE;
|
|
@@ -749,26 +774,82 @@
|
|
|
749
774
|
return "url(" + maybeQuote + stack.join("/") + maybeQuote + ")";
|
|
750
775
|
});
|
|
751
776
|
}
|
|
752
|
-
function normalizeCssString(cssText) {
|
|
753
|
-
|
|
777
|
+
function normalizeCssString(cssText, _testNoPxNorm) {
|
|
778
|
+
if (_testNoPxNorm === void 0) _testNoPxNorm = false;
|
|
779
|
+
if (_testNoPxNorm) {
|
|
780
|
+
return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
|
|
781
|
+
} else {
|
|
782
|
+
return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "").replace(/0px/g, "0");
|
|
783
|
+
}
|
|
754
784
|
}
|
|
755
|
-
function splitCssText(cssText, style) {
|
|
785
|
+
function splitCssText(cssText, style, _testNoPxNorm) {
|
|
786
|
+
if (_testNoPxNorm === void 0) _testNoPxNorm = false;
|
|
756
787
|
var childNodes2 = Array.from(style.childNodes);
|
|
757
788
|
var splits = [];
|
|
789
|
+
var iterCount = 0;
|
|
758
790
|
if (childNodes2.length > 1 && cssText && typeof cssText === "string") {
|
|
759
|
-
var cssTextNorm = normalizeCssString(cssText);
|
|
791
|
+
var cssTextNorm = normalizeCssString(cssText, _testNoPxNorm);
|
|
792
|
+
var normFactor = cssTextNorm.length / cssText.length;
|
|
760
793
|
for(var i2 = 1; i2 < childNodes2.length; i2++){
|
|
761
794
|
if (childNodes2[i2].textContent && typeof childNodes2[i2].textContent === "string") {
|
|
762
|
-
var textContentNorm = normalizeCssString(childNodes2[i2].textContent);
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
795
|
+
var textContentNorm = normalizeCssString(childNodes2[i2].textContent, _testNoPxNorm);
|
|
796
|
+
var jLimit = 100;
|
|
797
|
+
var j = 3;
|
|
798
|
+
for(; j < textContentNorm.length; j++){
|
|
799
|
+
if (// keep consuming css identifiers (to get a decent chunk more quickly)
|
|
800
|
+
textContentNorm[j].match(/[a-zA-Z0-9]/) || // substring needs to be unique to this section
|
|
801
|
+
textContentNorm.indexOf(textContentNorm.substring(0, j), 1) !== -1) {
|
|
802
|
+
continue;
|
|
803
|
+
}
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
for(; j < textContentNorm.length; j++){
|
|
807
|
+
var startSubstring = textContentNorm.substring(0, j);
|
|
808
|
+
var cssNormSplits = cssTextNorm.split(startSubstring);
|
|
809
|
+
var splitNorm = -1;
|
|
810
|
+
if (cssNormSplits.length === 2) {
|
|
811
|
+
splitNorm = cssNormSplits[0].length;
|
|
812
|
+
} else if (cssNormSplits.length > 2 && cssNormSplits[0] === "" && childNodes2[i2 - 1].textContent !== "") {
|
|
813
|
+
splitNorm = cssTextNorm.indexOf(startSubstring, 1);
|
|
814
|
+
} else if (cssNormSplits.length === 1) {
|
|
815
|
+
startSubstring = startSubstring.substring(0, startSubstring.length - 1);
|
|
816
|
+
cssNormSplits = cssTextNorm.split(startSubstring);
|
|
817
|
+
if (cssNormSplits.length <= 1) {
|
|
818
|
+
splits.push(cssText);
|
|
819
|
+
return splits;
|
|
820
|
+
}
|
|
821
|
+
j = jLimit + 1;
|
|
822
|
+
} else if (j === textContentNorm.length - 1) {
|
|
823
|
+
splitNorm = cssTextNorm.indexOf(startSubstring);
|
|
824
|
+
}
|
|
825
|
+
if (cssNormSplits.length >= 2 && j > jLimit) {
|
|
826
|
+
var prevTextContent = childNodes2[i2 - 1].textContent;
|
|
827
|
+
if (prevTextContent && typeof prevTextContent === "string") {
|
|
828
|
+
var prevMinLength = normalizeCssString(prevTextContent).length;
|
|
829
|
+
splitNorm = cssTextNorm.indexOf(startSubstring, prevMinLength);
|
|
830
|
+
}
|
|
831
|
+
if (splitNorm === -1) {
|
|
832
|
+
splitNorm = cssNormSplits[0].length;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
if (splitNorm !== -1) {
|
|
836
|
+
var k = Math.floor(splitNorm / normFactor);
|
|
837
|
+
for(; k > 0 && k < cssText.length;){
|
|
838
|
+
iterCount += 1;
|
|
839
|
+
if (iterCount > 50 * childNodes2.length) {
|
|
840
|
+
splits.push(cssText);
|
|
841
|
+
return splits;
|
|
842
|
+
}
|
|
843
|
+
var normPart = normalizeCssString(cssText.substring(0, k), _testNoPxNorm);
|
|
844
|
+
if (normPart.length === splitNorm) {
|
|
769
845
|
splits.push(cssText.substring(0, k));
|
|
770
846
|
cssText = cssText.substring(k);
|
|
847
|
+
cssTextNorm = cssTextNorm.substring(splitNorm);
|
|
771
848
|
break;
|
|
849
|
+
} else if (normPart.length < splitNorm) {
|
|
850
|
+
k += Math.max(1, Math.floor((splitNorm - normPart.length) / normFactor));
|
|
851
|
+
} else {
|
|
852
|
+
k -= Math.max(1, Math.floor((normPart.length - splitNorm) * normFactor));
|
|
772
853
|
}
|
|
773
854
|
}
|
|
774
855
|
break;
|
|
@@ -1285,7 +1366,7 @@
|
|
|
1285
1366
|
} else if (sn.type === NodeType$3.Element) {
|
|
1286
1367
|
if (slimDOMOptions.script && // script tag
|
|
1287
1368
|
(sn.tagName === "script" || // (module)preload link
|
|
1288
|
-
sn.tagName === "link" && (sn.attributes.rel === "preload"
|
|
1369
|
+
sn.tagName === "link" && (sn.attributes.rel === "preload" && sn.attributes.as === "script" || sn.attributes.rel === "modulepreload") || // prefetch link
|
|
1289
1370
|
sn.tagName === "link" && sn.attributes.rel === "prefetch" && typeof sn.attributes.href === "string" && extractFileExtension(sn.attributes.href) === "js")) {
|
|
1290
1371
|
return true;
|
|
1291
1372
|
} 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"))) {
|
|
@@ -10036,6 +10117,30 @@
|
|
|
10036
10117
|
function mutationObserverCtor() {
|
|
10037
10118
|
return getUntaintedPrototype("MutationObserver").constructor;
|
|
10038
10119
|
}
|
|
10120
|
+
function patch(source, name, replacement) {
|
|
10121
|
+
try {
|
|
10122
|
+
if (!(name in source)) {
|
|
10123
|
+
return function() {};
|
|
10124
|
+
}
|
|
10125
|
+
var original = source[name];
|
|
10126
|
+
var wrapped = replacement(original);
|
|
10127
|
+
if (typeof wrapped === "function") {
|
|
10128
|
+
wrapped.prototype = wrapped.prototype || {};
|
|
10129
|
+
Object.defineProperties(wrapped, {
|
|
10130
|
+
__rrweb_original__: {
|
|
10131
|
+
enumerable: false,
|
|
10132
|
+
value: original
|
|
10133
|
+
}
|
|
10134
|
+
});
|
|
10135
|
+
}
|
|
10136
|
+
source[name] = wrapped;
|
|
10137
|
+
return function() {
|
|
10138
|
+
source[name] = original;
|
|
10139
|
+
};
|
|
10140
|
+
} catch (e) {
|
|
10141
|
+
return function() {};
|
|
10142
|
+
}
|
|
10143
|
+
}
|
|
10039
10144
|
var index = {
|
|
10040
10145
|
childNodes: childNodes,
|
|
10041
10146
|
parentNode: parentNode,
|
|
@@ -10048,7 +10153,8 @@
|
|
|
10048
10153
|
shadowRoot: shadowRoot,
|
|
10049
10154
|
querySelector: querySelector,
|
|
10050
10155
|
querySelectorAll: querySelectorAll,
|
|
10051
|
-
mutationObserver: mutationObserverCtor
|
|
10156
|
+
mutationObserver: mutationObserverCtor,
|
|
10157
|
+
patch: patch
|
|
10052
10158
|
};
|
|
10053
10159
|
function on(type, fn, target) {
|
|
10054
10160
|
if (target === void 0) target = document;
|
|
@@ -10141,30 +10247,6 @@
|
|
|
10141
10247
|
return hookSetter(target, key, original || {}, true);
|
|
10142
10248
|
};
|
|
10143
10249
|
}
|
|
10144
|
-
function patch(source, name, replacement) {
|
|
10145
|
-
try {
|
|
10146
|
-
if (!(name in source)) {
|
|
10147
|
-
return function() {};
|
|
10148
|
-
}
|
|
10149
|
-
var original = source[name];
|
|
10150
|
-
var wrapped = replacement(original);
|
|
10151
|
-
if (typeof wrapped === "function") {
|
|
10152
|
-
wrapped.prototype = wrapped.prototype || {};
|
|
10153
|
-
Object.defineProperties(wrapped, {
|
|
10154
|
-
__rrweb_original__: {
|
|
10155
|
-
enumerable: false,
|
|
10156
|
-
value: original
|
|
10157
|
-
}
|
|
10158
|
-
});
|
|
10159
|
-
}
|
|
10160
|
-
source[name] = wrapped;
|
|
10161
|
-
return function() {
|
|
10162
|
-
source[name] = original;
|
|
10163
|
-
};
|
|
10164
|
-
} catch (e) {
|
|
10165
|
-
return function() {};
|
|
10166
|
-
}
|
|
10167
|
-
}
|
|
10168
10250
|
var nowTimestamp = Date.now;
|
|
10169
10251
|
if (!/* @__PURE__ */ /[1-9][0-9]{12}/.test(Date.now().toString())) {
|
|
10170
10252
|
nowTimestamp = function() {
|
|
@@ -10755,9 +10837,17 @@
|
|
|
10755
10837
|
_this.attributes.push(item);
|
|
10756
10838
|
_this.attributeMap.set(textarea, item);
|
|
10757
10839
|
}
|
|
10758
|
-
|
|
10840
|
+
var value = Array.from(index.childNodes(textarea), function(cn) {
|
|
10759
10841
|
return index.textContent(cn) || "";
|
|
10760
10842
|
}).join("");
|
|
10843
|
+
item.attributes.value = maskInputValue({
|
|
10844
|
+
element: textarea,
|
|
10845
|
+
maskInputOptions: _this.maskInputOptions,
|
|
10846
|
+
tagName: textarea.tagName,
|
|
10847
|
+
type: getInputType(textarea),
|
|
10848
|
+
value: value,
|
|
10849
|
+
maskInputFn: _this.maskInputFn
|
|
10850
|
+
});
|
|
10761
10851
|
});
|
|
10762
10852
|
__publicField(this, "processMutation", function(m) {
|
|
10763
10853
|
if (isIgnored(m.target, _this.mirror, _this.slimDOMOptions)) {
|
|
@@ -13538,8 +13628,15 @@
|
|
|
13538
13628
|
}, window));
|
|
13539
13629
|
}
|
|
13540
13630
|
return function() {
|
|
13541
|
-
handlers.forEach(function(
|
|
13542
|
-
|
|
13631
|
+
handlers.forEach(function(handler) {
|
|
13632
|
+
try {
|
|
13633
|
+
handler();
|
|
13634
|
+
} catch (error) {
|
|
13635
|
+
var msg = String(error).toLowerCase();
|
|
13636
|
+
if (!msg.includes("cross-origin")) {
|
|
13637
|
+
console.warn(error);
|
|
13638
|
+
}
|
|
13639
|
+
}
|
|
13543
13640
|
});
|
|
13544
13641
|
processedNodeManager.destroy();
|
|
13545
13642
|
recording = false;
|
|
@@ -13945,7 +14042,7 @@
|
|
|
13945
14042
|
|
|
13946
14043
|
var Config = {
|
|
13947
14044
|
DEBUG: false,
|
|
13948
|
-
LIB_VERSION: '2.
|
|
14045
|
+
LIB_VERSION: '2.69.0'
|
|
13949
14046
|
};
|
|
13950
14047
|
|
|
13951
14048
|
/* eslint camelcase: "off", eqeqeq: "off" */
|
|
@@ -15745,6 +15842,10 @@
|
|
|
15745
15842
|
});
|
|
15746
15843
|
};
|
|
15747
15844
|
|
|
15845
|
+
IDBStorageWrapper.prototype.isInitialized = function () {
|
|
15846
|
+
return !!this.dbPromise;
|
|
15847
|
+
};
|
|
15848
|
+
|
|
15748
15849
|
/**
|
|
15749
15850
|
* @param {IDBTransactionMode} mode
|
|
15750
15851
|
* @param {function(IDBObjectStore): void} storeCb
|
|
@@ -16269,6 +16370,10 @@
|
|
|
16269
16370
|
return PromisePolyfill.resolve();
|
|
16270
16371
|
};
|
|
16271
16372
|
|
|
16373
|
+
LocalStorageWrapper.prototype.isInitialized = function () {
|
|
16374
|
+
return true;
|
|
16375
|
+
};
|
|
16376
|
+
|
|
16272
16377
|
LocalStorageWrapper.prototype.setItem = function (key, value) {
|
|
16273
16378
|
return new PromisePolyfill(_.bind(function (resolve, reject) {
|
|
16274
16379
|
try {
|
|
@@ -16349,7 +16454,7 @@
|
|
|
16349
16454
|
};
|
|
16350
16455
|
|
|
16351
16456
|
RequestQueue.prototype.ensureInit = function () {
|
|
16352
|
-
if (this.initialized) {
|
|
16457
|
+
if (this.initialized || !this.usePersistence) {
|
|
16353
16458
|
return PromisePolyfill.resolve();
|
|
16354
16459
|
}
|
|
16355
16460
|
|
|
@@ -17101,10 +17206,9 @@
|
|
|
17101
17206
|
|
|
17102
17207
|
// disable persistence if localStorage is not supported
|
|
17103
17208
|
// request-queue will automatically disable persistence if indexedDB fails to initialize
|
|
17104
|
-
var usePersistence = localStorageSupported(options.sharedLockStorage, true);
|
|
17209
|
+
var usePersistence = localStorageSupported(options.sharedLockStorage, true) && !this.getConfig('disable_persistence');
|
|
17105
17210
|
|
|
17106
17211
|
// each replay has its own batcher key to avoid conflicts between rrweb events of different recordings
|
|
17107
|
-
// this will be important when persistence is introduced
|
|
17108
17212
|
this.batcherKey = '__mprec_' + this.getConfig('name') + '_' + this.getConfig('token') + '_' + this.replayId;
|
|
17109
17213
|
this.queueStorage = new IDBStorageWrapper(RECORDING_EVENTS_STORE_NAME);
|
|
17110
17214
|
this.batcher = new RequestBatcher(this.batcherKey, {
|
|
@@ -17485,12 +17589,17 @@
|
|
|
17485
17589
|
* Makes sure that only one tab can be recording at a time.
|
|
17486
17590
|
*/
|
|
17487
17591
|
var RecordingRegistry = function (options) {
|
|
17592
|
+
/** @type {IDBStorageWrapper} */
|
|
17488
17593
|
this.idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
|
|
17489
17594
|
this.errorReporter = options.errorReporter;
|
|
17490
17595
|
this.mixpanelInstance = options.mixpanelInstance;
|
|
17491
17596
|
this.sharedLockStorage = options.sharedLockStorage;
|
|
17492
17597
|
};
|
|
17493
17598
|
|
|
17599
|
+
RecordingRegistry.prototype.isPersistenceEnabled = function() {
|
|
17600
|
+
return !this.mixpanelInstance.get_config('disable_persistence');
|
|
17601
|
+
};
|
|
17602
|
+
|
|
17494
17603
|
RecordingRegistry.prototype.handleError = function (err) {
|
|
17495
17604
|
this.errorReporter('IndexedDB error: ', err);
|
|
17496
17605
|
};
|
|
@@ -17499,6 +17608,10 @@
|
|
|
17499
17608
|
* @param {import('./session-recording').SerializedRecording} serializedRecording
|
|
17500
17609
|
*/
|
|
17501
17610
|
RecordingRegistry.prototype.setActiveRecording = function (serializedRecording) {
|
|
17611
|
+
if (!this.isPersistenceEnabled()) {
|
|
17612
|
+
return PromisePolyfill.resolve();
|
|
17613
|
+
}
|
|
17614
|
+
|
|
17502
17615
|
var tabId = serializedRecording['tabId'];
|
|
17503
17616
|
if (!tabId) {
|
|
17504
17617
|
console.warn('No tab ID is set, cannot persist recording metadata.');
|
|
@@ -17516,6 +17629,10 @@
|
|
|
17516
17629
|
* @returns {Promise<import('./session-recording').SerializedRecording>}
|
|
17517
17630
|
*/
|
|
17518
17631
|
RecordingRegistry.prototype.getActiveRecording = function () {
|
|
17632
|
+
if (!this.isPersistenceEnabled()) {
|
|
17633
|
+
return PromisePolyfill.resolve(null);
|
|
17634
|
+
}
|
|
17635
|
+
|
|
17519
17636
|
return this.idb.init()
|
|
17520
17637
|
.then(function () {
|
|
17521
17638
|
return this.idb.getItem(this.mixpanelInstance.get_tab_id());
|
|
@@ -17527,8 +17644,16 @@
|
|
|
17527
17644
|
};
|
|
17528
17645
|
|
|
17529
17646
|
RecordingRegistry.prototype.clearActiveRecording = function () {
|
|
17530
|
-
|
|
17531
|
-
|
|
17647
|
+
if (this.isPersistenceEnabled()) {
|
|
17648
|
+
// mark recording as expired instead of deleting it in case the page unloads mid-flush and doesn't make it to ingestion.
|
|
17649
|
+
// this will ensure the next pageload will flush the remaining events, but not try to continue the recording.
|
|
17650
|
+
return this.markActiveRecordingExpired();
|
|
17651
|
+
} else {
|
|
17652
|
+
return this.deleteActiveRecording();
|
|
17653
|
+
}
|
|
17654
|
+
};
|
|
17655
|
+
|
|
17656
|
+
RecordingRegistry.prototype.markActiveRecordingExpired = function () {
|
|
17532
17657
|
return this.getActiveRecording()
|
|
17533
17658
|
.then(function (serializedRecording) {
|
|
17534
17659
|
if (serializedRecording) {
|
|
@@ -17539,11 +17664,25 @@
|
|
|
17539
17664
|
.catch(this.handleError.bind(this));
|
|
17540
17665
|
};
|
|
17541
17666
|
|
|
17667
|
+
RecordingRegistry.prototype.deleteActiveRecording = function () {
|
|
17668
|
+
// avoid initializing IDB if this registry instance hasn't already written a recording
|
|
17669
|
+
if (this.idb.isInitialized()) {
|
|
17670
|
+
return this.idb.removeItem(this.mixpanelInstance.get_tab_id())
|
|
17671
|
+
.catch(this.handleError.bind(this));
|
|
17672
|
+
} else {
|
|
17673
|
+
return PromisePolyfill.resolve();
|
|
17674
|
+
}
|
|
17675
|
+
};
|
|
17676
|
+
|
|
17542
17677
|
/**
|
|
17543
17678
|
* Flush any inactive recordings from the registry to minimize data loss.
|
|
17544
17679
|
* The main idea here is that we can flush remaining rrweb events on the next page load if a tab is closed mid-batch.
|
|
17545
17680
|
*/
|
|
17546
17681
|
RecordingRegistry.prototype.flushInactiveRecordings = function () {
|
|
17682
|
+
if (!this.isPersistenceEnabled()) {
|
|
17683
|
+
return PromisePolyfill.resolve([]);
|
|
17684
|
+
}
|
|
17685
|
+
|
|
17547
17686
|
return this.idb.init()
|
|
17548
17687
|
.then(function() {
|
|
17549
17688
|
return this.idb.getAll();
|
|
@@ -18230,6 +18369,38 @@
|
|
|
18230
18369
|
return true;
|
|
18231
18370
|
}
|
|
18232
18371
|
|
|
18372
|
+
/** @const */ var DEFAULT_RAGE_CLICK_THRESHOLD_PX = 30;
|
|
18373
|
+
/** @const */ var DEFAULT_RAGE_CLICK_TIMEOUT_MS = 1000;
|
|
18374
|
+
/** @const */ var DEFAULT_RAGE_CLICK_CLICK_COUNT = 4;
|
|
18375
|
+
|
|
18376
|
+
function RageClickTracker() {
|
|
18377
|
+
this.clicks = [];
|
|
18378
|
+
}
|
|
18379
|
+
|
|
18380
|
+
RageClickTracker.prototype.isRageClick = function(x, y, options) {
|
|
18381
|
+
options = options || {};
|
|
18382
|
+
var thresholdPx = options['threshold_px'] || DEFAULT_RAGE_CLICK_THRESHOLD_PX;
|
|
18383
|
+
var timeoutMs = options['timeout_ms'] || DEFAULT_RAGE_CLICK_TIMEOUT_MS;
|
|
18384
|
+
var clickCount = options['click_count'] || DEFAULT_RAGE_CLICK_CLICK_COUNT;
|
|
18385
|
+
var timestamp = Date.now();
|
|
18386
|
+
|
|
18387
|
+
var lastClick = this.clicks[this.clicks.length - 1];
|
|
18388
|
+
if (
|
|
18389
|
+
lastClick &&
|
|
18390
|
+
timestamp - lastClick.timestamp < timeoutMs &&
|
|
18391
|
+
Math.sqrt(Math.pow(x - lastClick.x, 2) + Math.pow(y - lastClick.y, 2)) < thresholdPx
|
|
18392
|
+
) {
|
|
18393
|
+
this.clicks.push({ x: x, y: y, timestamp: timestamp });
|
|
18394
|
+
if (this.clicks.length >= clickCount) {
|
|
18395
|
+
this.clicks = [];
|
|
18396
|
+
return true;
|
|
18397
|
+
}
|
|
18398
|
+
} else {
|
|
18399
|
+
this.clicks = [{ x: x, y: y, timestamp: timestamp }];
|
|
18400
|
+
}
|
|
18401
|
+
return false;
|
|
18402
|
+
};
|
|
18403
|
+
|
|
18233
18404
|
var AUTOCAPTURE_CONFIG_KEY = 'autocapture';
|
|
18234
18405
|
var LEGACY_PAGEVIEW_CONFIG_KEY = 'track_pageview';
|
|
18235
18406
|
|
|
@@ -18251,6 +18422,7 @@
|
|
|
18251
18422
|
var CONFIG_TRACK_CLICK = 'click';
|
|
18252
18423
|
var CONFIG_TRACK_INPUT = 'input';
|
|
18253
18424
|
var CONFIG_TRACK_PAGEVIEW = 'pageview';
|
|
18425
|
+
var CONFIG_TRACK_RAGE_CLICK = 'rage_click';
|
|
18254
18426
|
var CONFIG_TRACK_SCROLL = 'scroll';
|
|
18255
18427
|
var CONFIG_TRACK_SUBMIT = 'submit';
|
|
18256
18428
|
|
|
@@ -18268,6 +18440,7 @@
|
|
|
18268
18440
|
CONFIG_DEFAULTS$1[CONFIG_TRACK_CLICK] = true;
|
|
18269
18441
|
CONFIG_DEFAULTS$1[CONFIG_TRACK_INPUT] = true;
|
|
18270
18442
|
CONFIG_DEFAULTS$1[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
|
|
18443
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_RAGE_CLICK] = true;
|
|
18271
18444
|
CONFIG_DEFAULTS$1[CONFIG_TRACK_SCROLL] = true;
|
|
18272
18445
|
CONFIG_DEFAULTS$1[CONFIG_TRACK_SUBMIT] = true;
|
|
18273
18446
|
|
|
@@ -18277,6 +18450,7 @@
|
|
|
18277
18450
|
|
|
18278
18451
|
var MP_EV_CLICK = '$mp_click';
|
|
18279
18452
|
var MP_EV_INPUT = '$mp_input_change';
|
|
18453
|
+
var MP_EV_RAGE_CLICK = '$mp_rage_click';
|
|
18280
18454
|
var MP_EV_SCROLL = '$mp_scroll';
|
|
18281
18455
|
var MP_EV_SUBMIT = '$mp_submit';
|
|
18282
18456
|
|
|
@@ -18299,6 +18473,7 @@
|
|
|
18299
18473
|
this.initInputTracking();
|
|
18300
18474
|
this.initScrollTracking();
|
|
18301
18475
|
this.initSubmitTracking();
|
|
18476
|
+
this.initRageClickTracking();
|
|
18302
18477
|
};
|
|
18303
18478
|
|
|
18304
18479
|
Autocapture.prototype.getFullConfig = function() {
|
|
@@ -18377,6 +18552,11 @@
|
|
|
18377
18552
|
return;
|
|
18378
18553
|
}
|
|
18379
18554
|
|
|
18555
|
+
var isCapturedForHeatMap = this.mp.is_recording_heatmap_data() && (
|
|
18556
|
+
(mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK)) ||
|
|
18557
|
+
(mpEventName === MP_EV_RAGE_CLICK && !this._getRageClickConfig())
|
|
18558
|
+
);
|
|
18559
|
+
|
|
18380
18560
|
var props = getPropsForDOMEvent(ev, {
|
|
18381
18561
|
allowElementCallback: this.getConfig(CONFIG_ALLOW_ELEMENT_CALLBACK),
|
|
18382
18562
|
allowSelectors: this.getConfig(CONFIG_ALLOW_SELECTORS),
|
|
@@ -18385,7 +18565,7 @@
|
|
|
18385
18565
|
blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
|
|
18386
18566
|
captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
|
|
18387
18567
|
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT),
|
|
18388
|
-
capturedForHeatMap:
|
|
18568
|
+
capturedForHeatMap: isCapturedForHeatMap,
|
|
18389
18569
|
});
|
|
18390
18570
|
if (props) {
|
|
18391
18571
|
_.extend(props, DEFAULT_PROPS);
|
|
@@ -18393,6 +18573,24 @@
|
|
|
18393
18573
|
}
|
|
18394
18574
|
};
|
|
18395
18575
|
|
|
18576
|
+
Autocapture.prototype._getRageClickConfig = function() {
|
|
18577
|
+
var config = this.getConfig(CONFIG_TRACK_RAGE_CLICK);
|
|
18578
|
+
|
|
18579
|
+
if (!config) {
|
|
18580
|
+
return null; // rage click tracking disabled
|
|
18581
|
+
}
|
|
18582
|
+
|
|
18583
|
+
if (config === true) {
|
|
18584
|
+
return {}; // use defaults
|
|
18585
|
+
}
|
|
18586
|
+
|
|
18587
|
+
if (typeof config === 'object') {
|
|
18588
|
+
return config; // use custom configuration
|
|
18589
|
+
}
|
|
18590
|
+
|
|
18591
|
+
return {}; // fallback to defaults for any other truthy value
|
|
18592
|
+
};
|
|
18593
|
+
|
|
18396
18594
|
Autocapture.prototype.initClickTracking = function() {
|
|
18397
18595
|
win.removeEventListener(EV_CLICK, this.listenerClick);
|
|
18398
18596
|
|
|
@@ -18494,6 +18692,36 @@
|
|
|
18494
18692
|
}.bind(this)));
|
|
18495
18693
|
};
|
|
18496
18694
|
|
|
18695
|
+
Autocapture.prototype.initRageClickTracking = function() {
|
|
18696
|
+
win.removeEventListener(EV_CLICK, this.listenerRageClick);
|
|
18697
|
+
|
|
18698
|
+
var rageClickConfig = this._getRageClickConfig();
|
|
18699
|
+
if (!rageClickConfig && !this.mp.get_config('record_heatmap_data')) {
|
|
18700
|
+
return;
|
|
18701
|
+
}
|
|
18702
|
+
|
|
18703
|
+
logger$1.log('Initializing rage click tracking');
|
|
18704
|
+
if (!this._rageClickTracker) {
|
|
18705
|
+
this._rageClickTracker = new RageClickTracker();
|
|
18706
|
+
}
|
|
18707
|
+
|
|
18708
|
+
this.listenerRageClick = function(ev) {
|
|
18709
|
+
var currentRageClickConfig = this._getRageClickConfig();
|
|
18710
|
+
if (!currentRageClickConfig && !this.mp.is_recording_heatmap_data()) {
|
|
18711
|
+
return;
|
|
18712
|
+
}
|
|
18713
|
+
|
|
18714
|
+
if (this.currentUrlBlocked()) {
|
|
18715
|
+
return;
|
|
18716
|
+
}
|
|
18717
|
+
|
|
18718
|
+
if (this._rageClickTracker.isRageClick(ev['pageX'], ev['pageY'], currentRageClickConfig)) {
|
|
18719
|
+
this.trackDomEvent(ev, MP_EV_RAGE_CLICK);
|
|
18720
|
+
}
|
|
18721
|
+
}.bind(this);
|
|
18722
|
+
win.addEventListener(EV_CLICK, this.listenerRageClick);
|
|
18723
|
+
};
|
|
18724
|
+
|
|
18497
18725
|
Autocapture.prototype.initScrollTracking = function() {
|
|
18498
18726
|
win.removeEventListener(EV_SCROLLEND, this.listenerScroll);
|
|
18499
18727
|
|
|
@@ -18580,6 +18808,7 @@
|
|
|
18580
18808
|
var FeatureFlagManager = function(initOptions) {
|
|
18581
18809
|
this.getFullApiRoute = initOptions.getFullApiRoute;
|
|
18582
18810
|
this.getMpConfig = initOptions.getConfigFunc;
|
|
18811
|
+
this.setMpConfig = initOptions.setConfigFunc;
|
|
18583
18812
|
this.getMpProperty = initOptions.getPropertyFunc;
|
|
18584
18813
|
this.track = initOptions.trackingFunc;
|
|
18585
18814
|
};
|
|
@@ -18617,6 +18846,23 @@
|
|
|
18617
18846
|
return !!this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
18618
18847
|
};
|
|
18619
18848
|
|
|
18849
|
+
FeatureFlagManager.prototype.updateContext = function(newContext, options) {
|
|
18850
|
+
if (!this.isSystemEnabled()) {
|
|
18851
|
+
logger.critical('Feature Flags not enabled, cannot update context');
|
|
18852
|
+
return Promise.resolve();
|
|
18853
|
+
}
|
|
18854
|
+
|
|
18855
|
+
var ffConfig = this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
18856
|
+
if (!_.isObject(ffConfig)) {
|
|
18857
|
+
ffConfig = {};
|
|
18858
|
+
}
|
|
18859
|
+
var oldContext = (options && options['replace']) ? {} : this.getConfig(CONFIG_CONTEXT);
|
|
18860
|
+
ffConfig[CONFIG_CONTEXT] = _.extend({}, oldContext, newContext);
|
|
18861
|
+
|
|
18862
|
+
this.setMpConfig(FLAGS_CONFIG_KEY, ffConfig);
|
|
18863
|
+
return this.fetchFlags();
|
|
18864
|
+
};
|
|
18865
|
+
|
|
18620
18866
|
FeatureFlagManager.prototype.areFlagsReady = function() {
|
|
18621
18867
|
if (!this.isSystemEnabled()) {
|
|
18622
18868
|
logger.error('Feature Flags not enabled');
|
|
@@ -18626,7 +18872,7 @@
|
|
|
18626
18872
|
|
|
18627
18873
|
FeatureFlagManager.prototype.fetchFlags = function() {
|
|
18628
18874
|
if (!this.isSystemEnabled()) {
|
|
18629
|
-
return;
|
|
18875
|
+
return Promise.resolve();
|
|
18630
18876
|
}
|
|
18631
18877
|
|
|
18632
18878
|
var distinctId = this.getMpProperty('distinct_id');
|
|
@@ -18666,6 +18912,8 @@
|
|
|
18666
18912
|
this.markFetchComplete();
|
|
18667
18913
|
logger.error(error);
|
|
18668
18914
|
}.bind(this));
|
|
18915
|
+
|
|
18916
|
+
return this.fetchPromise;
|
|
18669
18917
|
};
|
|
18670
18918
|
|
|
18671
18919
|
FeatureFlagManager.prototype.markFetchComplete = function() {
|
|
@@ -18778,6 +19026,7 @@
|
|
|
18778
19026
|
FeatureFlagManager.prototype['get_variant_value_sync'] = FeatureFlagManager.prototype.getVariantValueSync;
|
|
18779
19027
|
FeatureFlagManager.prototype['is_enabled'] = FeatureFlagManager.prototype.isEnabled;
|
|
18780
19028
|
FeatureFlagManager.prototype['is_enabled_sync'] = FeatureFlagManager.prototype.isEnabledSync;
|
|
19029
|
+
FeatureFlagManager.prototype['update_context'] = FeatureFlagManager.prototype.updateContext;
|
|
18781
19030
|
|
|
18782
19031
|
// Deprecated method
|
|
18783
19032
|
FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
|
|
@@ -20238,7 +20487,7 @@
|
|
|
20238
20487
|
'batch_autostart': true,
|
|
20239
20488
|
'hooks': {},
|
|
20240
20489
|
'record_block_class': new RegExp('^(mp-block|fs-exclude|amp-block|rr-block|ph-no-capture)$'),
|
|
20241
|
-
'record_block_selector': 'img, video',
|
|
20490
|
+
'record_block_selector': 'img, video, audio',
|
|
20242
20491
|
'record_canvas': false,
|
|
20243
20492
|
'record_collect_fonts': false,
|
|
20244
20493
|
'record_heatmap_data': false,
|
|
@@ -20462,6 +20711,7 @@
|
|
|
20462
20711
|
return this.get_api_host('flags') + '/' + this.get_config('api_routes')['flags'];
|
|
20463
20712
|
}, this),
|
|
20464
20713
|
getConfigFunc: _.bind(this.get_config, this),
|
|
20714
|
+
setConfigFunc: _.bind(this.set_config, this),
|
|
20465
20715
|
getPropertyFunc: _.bind(this.get_property, this),
|
|
20466
20716
|
trackingFunc: _.bind(this.track, this)
|
|
20467
20717
|
});
|
|
@@ -20480,7 +20730,9 @@
|
|
|
20480
20730
|
* This is primarily used for session recording, where data must be isolated to the current tab.
|
|
20481
20731
|
*/
|
|
20482
20732
|
MixpanelLib.prototype._init_tab_id = function() {
|
|
20483
|
-
if (
|
|
20733
|
+
if (this.get_config('disable_persistence')) {
|
|
20734
|
+
console$1.log('Tab ID initialization skipped due to disable_persistence config');
|
|
20735
|
+
} else if (_.sessionStorage.is_supported()) {
|
|
20484
20736
|
try {
|
|
20485
20737
|
var key_suffix = this.get_config('name') + '_' + this.get_config('token');
|
|
20486
20738
|
var tab_id_key = 'mp_tab_id_' + key_suffix;
|
|
@@ -20514,6 +20766,11 @@
|
|
|
20514
20766
|
};
|
|
20515
20767
|
|
|
20516
20768
|
MixpanelLib.prototype._should_load_recorder = function () {
|
|
20769
|
+
if (this.get_config('disable_persistence')) {
|
|
20770
|
+
console$1.log('Load recorder check skipped due to disable_persistence config');
|
|
20771
|
+
return Promise.resolve(false);
|
|
20772
|
+
}
|
|
20773
|
+
|
|
20517
20774
|
var recording_registry_idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
|
|
20518
20775
|
var tab_id = this.get_tab_id();
|
|
20519
20776
|
return recording_registry_idb.init()
|