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