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