From e0ea8860eaa310073fadc13f473af1de48b649e2 Mon Sep 17 00:00:00 2001 From: Carlos Trevino <35301701+carlosdanieltt@users.noreply.github.com> Date: Mon, 29 Jul 2024 17:52:04 +0000 Subject: [PATCH 01/21] Added minimum recording duration --- src/mixpanel-core.js | 3 ++- src/recorder/index.js | 25 +++++++++++++++++++++---- src/utils.js | 3 +++ tests/test.js | 30 ++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/mixpanel-core.js b/src/mixpanel-core.js index c3575933..d113cb17 100644 --- a/src/mixpanel-core.js +++ b/src/mixpanel-core.js @@ -1,6 +1,6 @@ /* eslint camelcase: "off" */ import Config from './config'; -import { MAX_RECORDING_MS, _, console, userAgent, window, document, navigator, slice } from './utils'; +import { MAX_RECORDING_MS, MIN_RECORDING_MS, _, console, userAgent, window, document, navigator, slice } from './utils'; import { FormTracker, LinkTracker } from './dom-trackers'; import { RequestBatcher } from './request-batcher'; import { MixpanelGroup } from './mixpanel-group'; @@ -152,6 +152,7 @@ var DEFAULT_CONFIG = { 'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'), 'record_mask_text_selector': '*', 'record_max_ms': MAX_RECORDING_MS, + 'record_min_ms': MIN_RECORDING_MS, 'record_sessions_percent': 0, 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js' }; diff --git a/src/recorder/index.js b/src/recorder/index.js index 21125054..2a11faa8 100644 --- a/src/recorder/index.js +++ b/src/recorder/index.js @@ -1,7 +1,7 @@ import { record } from 'rrweb'; import { IncrementalSource, EventType } from '@rrweb/types'; -import { MAX_RECORDING_MS, console_with_prefix, _, window} from '../utils'; // eslint-disable-line camelcase +import { MAX_RECORDING_MS, MIN_RECORDING_MS, console_with_prefix, _, window} from '../utils'; // eslint-disable-line camelcase import { addOptOutCheckMixpanelLib } from '../gdpr-utils'; import { RequestBatcher } from '../request-batcher'; @@ -47,6 +47,7 @@ var MixpanelRecorder = function(mixpanelInstance) { this.maxTimeoutId = null; this.recordMaxMs = MAX_RECORDING_MS; + this.recordMinMs = MIN_RECORDING_MS; this._initBatcher(); }; @@ -78,6 +79,12 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { logger.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.'); } + this.recordMinMs = this.get_config('record_min_ms'); + if (this.recordMinMs > MIN_RECORDING_MS) { + this.recordMinMs = MIN_RECORDING_MS; + logger.critical('record_min_ms cannot be greater than ' + MIN_RECORDING_MS + 'ms. Capping value.'); + } + this.recEvents = []; this.seqNo = 0; this.replayStartTime = null; @@ -101,6 +108,11 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { }, this), this.get_config('record_idle_timeout_ms')); }, this); + var blockSelector = this.get_config('record_block_selector'); + if (blockSelector === '' || blockSelector === null) { + blockSelector = undefined; + } + this._stopRecording = record({ 'emit': _.bind(function (ev) { this.batcher.enqueue(ev); @@ -113,7 +125,7 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { } }, this), 'blockClass': this.get_config('record_block_class'), - 'blockSelector': this.get_config('record_block_selector'), + 'blockSelector': blockSelector, 'collectFonts': this.get_config('record_collect_fonts'), 'inlineImages': this.get_config('record_inline_images'), 'maskAllInputs': true, @@ -141,8 +153,13 @@ MixpanelRecorder.prototype.stopRecording = function () { // never got user activity to flush after reset, so just clear the batcher this.batcher.clear(); } else { - // flush any remaining events from running batcher - this.batcher.flush(); + if (new Date().getTime() - this.replayStartTime > this.recordMinMs) { + // flush any remaining events from running batcher + this.batcher.flush(); + } else { + this.batcher.clear(); + logger.log('Recording duration did not meet minimum duration requirement, skipping flush.'); + } this.batcher.stop(); } this.replayId = null; diff --git a/src/utils.js b/src/utils.js index af6a76db..cefb8d78 100644 --- a/src/utils.js +++ b/src/utils.js @@ -22,6 +22,8 @@ if (typeof(window) === 'undefined') { // Maximum allowed session recording length var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours +// Default minimum session recording length +var MIN_RECORDING_MS = 5 * 1000; // 5 seconds /* * Saved references to long variable names, so that closure compiler can @@ -1725,6 +1727,7 @@ _['info']['properties'] = _.info.properties; export { MAX_RECORDING_MS, + MIN_RECORDING_MS, _, userAgent, console, diff --git a/tests/test.js b/tests/test.js index 195b76c4..a0177b30 100644 --- a/tests/test.js +++ b/tests/test.js @@ -5640,6 +5640,36 @@ }); }); + asyncTest('respects minimum session length setting', function () { + this.randomStub.returns(0.02); + this.initMixpanelRecorder({record_sessions_percent: 1, record_min_ms: 5000}); + ok(this.getRecorderScript() === null); + + this.clock.tick(10 * 1000); + same(this.fetchStub.getCalls().length, 0, 'no /record call has been made since the user did not fall into the sample.'); + + mixpanel.recordertest.start_session_recording(); + + this.afterRecorderLoaded.call(this, function () { + simulateMouseClick(document.body); + this.clock.tick(5 * 1000); + + mixpanel.recordertest.stop_session_recording(); + + stop(); + untilDone(_.bind(function(done) { + same(this.fetchStub.getCalls().length, 0, 'does not flush events if session is too short'); + + simulateMouseClick(document.body); + this.clock.tick(20 * 1000); + realSetTimeout(_.bind(function() { + same(this.fetchStub.getCalls().length, 0, 'no fetch requests after recording is stopped'); + done(); + }, this), 2); + }, this)); + }); + }); + asyncTest('resets after idle timeout', 14, function () { this.randomStub.returns(0.02); this.initMixpanelRecorder({record_sessions_percent: 10}); From 266be32a1688f49ad0de2fd9811d733d0ee5fc60 Mon Sep 17 00:00:00 2001 From: Carlos Trevino <35301701+carlosdanieltt@users.noreply.github.com> Date: Mon, 5 Aug 2024 17:27:13 +0000 Subject: [PATCH 02/21] Code review --- src/recorder/index.js | 8 ++++---- src/utils.js | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/recorder/index.js b/src/recorder/index.js index 2a11faa8..4a19a119 100644 --- a/src/recorder/index.js +++ b/src/recorder/index.js @@ -1,7 +1,7 @@ import { record } from 'rrweb'; import { IncrementalSource, EventType } from '@rrweb/types'; -import { MAX_RECORDING_MS, MIN_RECORDING_MS, console_with_prefix, _, window} from '../utils'; // eslint-disable-line camelcase +import { MAX_RECORDING_MS, MAX_MIN_RECORDING_MS, MIN_RECORDING_MS, console_with_prefix, _, window} from '../utils'; // eslint-disable-line camelcase import { addOptOutCheckMixpanelLib } from '../gdpr-utils'; import { RequestBatcher } from '../request-batcher'; @@ -80,9 +80,9 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { } this.recordMinMs = this.get_config('record_min_ms'); - if (this.recordMinMs > MIN_RECORDING_MS) { - this.recordMinMs = MIN_RECORDING_MS; - logger.critical('record_min_ms cannot be greater than ' + MIN_RECORDING_MS + 'ms. Capping value.'); + if (this.recordMinMs > MAX_MIN_RECORDING_MS) { + this.recordMinMs = MAX_MIN_RECORDING_MS; + logger.critical('record_min_ms cannot be greater than ' + MAX_MIN_RECORDING_MS + 'ms. Capping value.'); } this.recEvents = []; diff --git a/src/utils.js b/src/utils.js index cefb8d78..275a9bc2 100644 --- a/src/utils.js +++ b/src/utils.js @@ -23,7 +23,9 @@ if (typeof(window) === 'undefined') { // Maximum allowed session recording length var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours // Default minimum session recording length -var MIN_RECORDING_MS = 5 * 1000; // 5 seconds +var MIN_RECORDING_MS = 0; // 0 seconds +// Maximum allowed value for minimum session recording length +var MAX_MIN_RECORDING_MS = 8 * 1000; // 8 seconds /* * Saved references to long variable names, so that closure compiler can @@ -1727,6 +1729,7 @@ _['info']['properties'] = _.info.properties; export { MAX_RECORDING_MS, + MAX_MIN_RECORDING_MS, MIN_RECORDING_MS, _, userAgent, From 5c593612d5e3581c9106fd96960d484dd58e85f2 Mon Sep 17 00:00:00 2001 From: Carlos Trevino <35301701+carlosdanieltt@users.noreply.github.com> Date: Mon, 5 Aug 2024 22:27:30 +0000 Subject: [PATCH 03/21] Code review --- src/recorder/index.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/recorder/index.js b/src/recorder/index.js index 4a19a119..9b9a703f 100644 --- a/src/recorder/index.js +++ b/src/recorder/index.js @@ -91,7 +91,7 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { this.replayId = _.UUID(); - if (shouldStopBatcher) { + if (shouldStopBatcher || this.recordMinMs > 0) { // this is the case when we're starting recording after a reset // and don't want to send anything over the network until there's // actual user activity @@ -117,7 +117,7 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { 'emit': _.bind(function (ev) { this.batcher.enqueue(ev); if (isUserEvent(ev)) { - if (this.batcher.stopped) { + if (this.batcher.stopped && new Date().getTime() - this.replayStartTime > this.recordMinMs) { // start flushing again after user activity this.batcher.start(); } @@ -153,13 +153,8 @@ MixpanelRecorder.prototype.stopRecording = function () { // never got user activity to flush after reset, so just clear the batcher this.batcher.clear(); } else { - if (new Date().getTime() - this.replayStartTime > this.recordMinMs) { - // flush any remaining events from running batcher - this.batcher.flush(); - } else { - this.batcher.clear(); - logger.log('Recording duration did not meet minimum duration requirement, skipping flush.'); - } + // flush any remaining events from running batcher + this.batcher.flush(); this.batcher.stop(); } this.replayId = null; From 374c935bd80c1bd836cb305cde43ada62256b415 Mon Sep 17 00:00:00 2001 From: Carlos Trevino <35301701+carlosdanieltt@users.noreply.github.com> Date: Tue, 13 Aug 2024 21:26:47 +0000 Subject: [PATCH 04/21] Code review --- src/mixpanel-core.js | 4 ++-- src/recorder/index.js | 16 +++++++++------- src/utils.js | 7 ++----- tests/test.js | 9 ++------- 4 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/mixpanel-core.js b/src/mixpanel-core.js index d113cb17..7f6c3cbd 100644 --- a/src/mixpanel-core.js +++ b/src/mixpanel-core.js @@ -1,6 +1,6 @@ /* eslint camelcase: "off" */ import Config from './config'; -import { MAX_RECORDING_MS, MIN_RECORDING_MS, _, console, userAgent, window, document, navigator, slice } from './utils'; +import { MAX_RECORDING_MS, _, console, userAgent, window, document, navigator, slice } from './utils'; import { FormTracker, LinkTracker } from './dom-trackers'; import { RequestBatcher } from './request-batcher'; import { MixpanelGroup } from './mixpanel-group'; @@ -152,7 +152,7 @@ var DEFAULT_CONFIG = { 'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'), 'record_mask_text_selector': '*', 'record_max_ms': MAX_RECORDING_MS, - 'record_min_ms': MIN_RECORDING_MS, + 'record_min_ms': 0, 'record_sessions_percent': 0, 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js' }; diff --git a/src/recorder/index.js b/src/recorder/index.js index 9b9a703f..e97f0447 100644 --- a/src/recorder/index.js +++ b/src/recorder/index.js @@ -1,7 +1,7 @@ import { record } from 'rrweb'; import { IncrementalSource, EventType } from '@rrweb/types'; -import { MAX_RECORDING_MS, MAX_MIN_RECORDING_MS, MIN_RECORDING_MS, console_with_prefix, _, window} from '../utils'; // eslint-disable-line camelcase +import { MAX_RECORDING_MS, MAX_VALUE_FOR_MIN_RECORDING_MS, console_with_prefix, _, window} from '../utils'; // eslint-disable-line camelcase import { addOptOutCheckMixpanelLib } from '../gdpr-utils'; import { RequestBatcher } from '../request-batcher'; @@ -47,7 +47,7 @@ var MixpanelRecorder = function(mixpanelInstance) { this.maxTimeoutId = null; this.recordMaxMs = MAX_RECORDING_MS; - this.recordMinMs = MIN_RECORDING_MS; + this.recordMinMs = 0; this._initBatcher(); }; @@ -80,9 +80,9 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { } this.recordMinMs = this.get_config('record_min_ms'); - if (this.recordMinMs > MAX_MIN_RECORDING_MS) { - this.recordMinMs = MAX_MIN_RECORDING_MS; - logger.critical('record_min_ms cannot be greater than ' + MAX_MIN_RECORDING_MS + 'ms. Capping value.'); + if (this.recordMinMs > MAX_VALUE_FOR_MIN_RECORDING_MS) { + this.recordMinMs = MAX_VALUE_FOR_MIN_RECORDING_MS; + logger.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.'); } this.recEvents = []; @@ -92,9 +92,11 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { this.replayId = _.UUID(); if (shouldStopBatcher || this.recordMinMs > 0) { - // this is the case when we're starting recording after a reset + // the primary case for shouldStopBatcher is when we're starting recording after a reset // and don't want to send anything over the network until there's // actual user activity + // this also applies if the minimum recording length has not been hit yet + // so that we don't send data until we know the recording will be long enough this.batcher.stop(); } else { this.batcher.start(); @@ -117,7 +119,7 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { 'emit': _.bind(function (ev) { this.batcher.enqueue(ev); if (isUserEvent(ev)) { - if (this.batcher.stopped && new Date().getTime() - this.replayStartTime > this.recordMinMs) { + if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) { // start flushing again after user activity this.batcher.start(); } diff --git a/src/utils.js b/src/utils.js index 275a9bc2..e8204b75 100644 --- a/src/utils.js +++ b/src/utils.js @@ -22,10 +22,8 @@ if (typeof(window) === 'undefined') { // Maximum allowed session recording length var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours -// Default minimum session recording length -var MIN_RECORDING_MS = 0; // 0 seconds // Maximum allowed value for minimum session recording length -var MAX_MIN_RECORDING_MS = 8 * 1000; // 8 seconds +var MAX_VALUE_FOR_MIN_RECORDING_MS = 8 * 1000; // 8 seconds /* * Saved references to long variable names, so that closure compiler can @@ -1729,8 +1727,7 @@ _['info']['properties'] = _.info.properties; export { MAX_RECORDING_MS, - MAX_MIN_RECORDING_MS, - MIN_RECORDING_MS, + MAX_VALUE_FOR_MIN_RECORDING_MS, _, userAgent, console, diff --git a/tests/test.js b/tests/test.js index a0177b30..972f04bc 100644 --- a/tests/test.js +++ b/tests/test.js @@ -5642,13 +5642,8 @@ asyncTest('respects minimum session length setting', function () { this.randomStub.returns(0.02); - this.initMixpanelRecorder({record_sessions_percent: 1, record_min_ms: 5000}); - ok(this.getRecorderScript() === null); - - this.clock.tick(10 * 1000); - same(this.fetchStub.getCalls().length, 0, 'no /record call has been made since the user did not fall into the sample.'); - - mixpanel.recordertest.start_session_recording(); + this.initMixpanelRecorder({record_sessions_percent: 10, record_min_ms: 5000}); + this.assertRecorderScript(true) this.afterRecorderLoaded.call(this, function () { simulateMouseClick(document.body); From 34439727b0deed2b05006b6381c377ed1d77f062 Mon Sep 17 00:00:00 2001 From: Jakub Grzegorzewski Date: Thu, 15 Aug 2024 14:48:01 +0000 Subject: [PATCH 05/21] fix seqNo and add test for race --- src/recorder/index.js | 13 ++++----- tests/test.js | 61 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/recorder/index.js b/src/recorder/index.js index 21125054..e0ce29ad 100644 --- a/src/recorder/index.js +++ b/src/recorder/index.js @@ -167,14 +167,14 @@ MixpanelRecorder.prototype._onOptOut = function (code) { } }; -MixpanelRecorder.prototype._sendRequest = function(reqParams, reqBody, callback) { +MixpanelRecorder.prototype._sendRequest = function(currentReplayId, reqParams, reqBody, callback) { var onSuccess = _.bind(function (response, responseBody) { // Increment sequence counter only if the request was successful to guarantee ordering. // RequestBatcher will always flush the next batch after the previous one succeeds. - if (response.status === 200) { + // extra check to see if the replay ID has changed so that we don't increment the seqNo on the wrong replay + if (response.status === 200 && this.replayId === currentReplayId) { this.seqNo++; } - callback({ status: 0, httpStatusCode: response.status, @@ -205,6 +205,7 @@ MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da const numEvents = data.length; if (numEvents > 0) { + var replayId = this.replayId; // each rrweb event has a timestamp - leverage those to get time properties var batchStartTime = data[0].timestamp; if (this.seqNo === 0) { @@ -216,7 +217,7 @@ MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da 'distinct_id': String(this._mixpanel.get_distinct_id()), 'seq': this.seqNo, 'batch_start_time': batchStartTime / 1000, - 'replay_id': this.replayId, + 'replay_id': replayId, 'replay_length_ms': replayLengthMs, 'replay_start_time': this.replayStartTime / 1000 }; @@ -239,11 +240,11 @@ MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da .blob() .then(_.bind(function(compressedBlob) { reqParams['format'] = 'gzip'; - this._sendRequest(reqParams, compressedBlob, callback); + this._sendRequest(replayId, reqParams, compressedBlob, callback); }, this)); } else { reqParams['format'] = 'body'; - this._sendRequest(reqParams, eventsJson, callback); + this._sendRequest(replayId, reqParams, eventsJson, callback); } } }); diff --git a/tests/test.js b/tests/test.js index 195b76c4..de432b45 100644 --- a/tests/test.js +++ b/tests/test.js @@ -5243,7 +5243,7 @@ } } - function makeFakeFetchResponse(status, body, cb) { + function makeFakeFetchResponse(status, body) { body = body || {} var response = new Response({}, { status: status, @@ -5262,11 +5262,19 @@ ); } + function makeDelayedFetchResponse(status, body, delay) { + return new Promise(function(resolve) { + setTimeout(function() { + resolve(makeFakeFetchResponse(status, body)); + }, delay || 0); + }); + } + module('recorder', { setup: function () { this.token = rand_name(); - this.clock = sinon.useFakeTimers(); + this.clock = sinon.useFakeTimers(new Date().getTime()); this.randomStub = sinon.stub(Math, 'random'); this.fetchStub = sinon.stub(window, 'fetch'); @@ -5661,7 +5669,11 @@ same(urlParams.get('seq'), '0', 'sends first sequence'); var replayId1 = urlParams.get('replay_id'); - this.clock.tick(33 * 60 * 1000); + this.clock.tick(16 * 60 * 1000); + // simulate a mutation event to make sure it doesn't make a request + document.body.appendChild(document.createElement('div')); + this.clock.tick(16 * 60 * 1000); + same(this.fetchStub.getCalls().length, 1, 'no new record requests after idle timeout'); simulateMouseClick(document.body); @@ -5675,6 +5687,49 @@ mixpanel.recordertest.stop_session_recording(); }); }); + + + asyncTest('handles race condition where the recording resets while a request is in flight', 12, function () { + this.randomStub.returns(0.02); + this.initMixpanelRecorder({record_sessions_percent: 10}); + this.assertRecorderScript(true); + this.randomStub.restore(); // restore the random stub after script is loaded for batcher uuid dedupe + + this.responseBlobStub = sinon.stub(window.Response.prototype, 'blob'); + this.responseBlobStub.returns(fakePromiseWrap(new Blob())); + this.fetchStub.onFirstCall() + .returns(makeDelayedFetchResponse(200, {}, 5 * 1000)) + + this.fetchStub.callThrough(); + + this.afterRecorderLoaded.call(this, function () { + // current replay stops, a new one starts a bit after + mixpanel.recordertest.stop_session_recording(); + + same(this.fetchStub.getCalls().length, 1, 'flushed events after stopping recording'); + var urlParams = validateAndGetUrlParams(this.fetchStub.getCall(0)); + same(urlParams.get('seq'), '0', 'sends first sequence'); + var replayId1 = urlParams.get('replay_id'); + + // start recording again while the first replay's request is in flight + mixpanel.recordertest.start_session_recording(); + simulateMouseClick(document.body); + stop(); + + untilDone(_.bind(function (done) { + this.clock.tick(10 * 1000); + var fetchCall1 = this.fetchStub.getCall(1); + if (fetchCall1) { + urlParams = validateAndGetUrlParams(this.fetchStub.getCall(1)); + same(urlParams.get('seq'), '0', 'new replay uses the first sequence'); + var replayId2 = urlParams.get('replay_id'); + ok(replayId1 !== replayId2, 'replay id is different after reset'); + mixpanel.recordertest.stop_session_recording(); + done(); + } + }, this)); + }); + }); } }, 10); }; From c19e42b6dcc04de151c1b1488dbfb2180f0e572d Mon Sep 17 00:00:00 2001 From: Jakub Grzegorzewski Date: Thu, 15 Aug 2024 15:14:38 +0000 Subject: [PATCH 06/21] extra safety, use real start time in tests --- src/recorder/index.js | 7 ++++++- tests/test.js | 8 +++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/recorder/index.js b/src/recorder/index.js index e0ce29ad..10cb2ca8 100644 --- a/src/recorder/index.js +++ b/src/recorder/index.js @@ -208,7 +208,12 @@ MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da var replayId = this.replayId; // each rrweb event has a timestamp - leverage those to get time properties var batchStartTime = data[0].timestamp; - if (this.seqNo === 0) { + if (this.seqNo === 0 || !this.replayStartTime) { + // extra safety net so that we don't send a null replay start time + if (this.seqNo !== 0) { + this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.'); + } + this.replayStartTime = batchStartTime; } var replayLengthMs = data[numEvents - 1].timestamp - this.replayStartTime; diff --git a/tests/test.js b/tests/test.js index de432b45..4b3a3e30 100644 --- a/tests/test.js +++ b/tests/test.js @@ -5273,8 +5273,8 @@ module('recorder', { setup: function () { this.token = rand_name(); - - this.clock = sinon.useFakeTimers(new Date().getTime()); + this.startTime = 1723733423402; + this.clock = sinon.useFakeTimers(this.startTime); this.randomStub = sinon.stub(Math, 'random'); this.fetchStub = sinon.stub(window, 'fetch'); @@ -5689,7 +5689,7 @@ }); - asyncTest('handles race condition where the recording resets while a request is in flight', 12, function () { + asyncTest('handles race condition where the recording resets while a request is in flight', 14, function () { this.randomStub.returns(0.02); this.initMixpanelRecorder({record_sessions_percent: 10}); this.assertRecorderScript(true); @@ -5709,6 +5709,7 @@ same(this.fetchStub.getCalls().length, 1, 'flushed events after stopping recording'); var urlParams = validateAndGetUrlParams(this.fetchStub.getCall(0)); same(urlParams.get('seq'), '0', 'sends first sequence'); + same(urlParams.get('replay_start_time'), (this.startTime / 1000).toString(), 'sends the right start time'); var replayId1 = urlParams.get('replay_id'); // start recording again while the first replay's request is in flight @@ -5722,6 +5723,7 @@ if (fetchCall1) { urlParams = validateAndGetUrlParams(this.fetchStub.getCall(1)); same(urlParams.get('seq'), '0', 'new replay uses the first sequence'); + same(urlParams.get('replay_start_time'), (this.startTime / 1000).toString(), 'sends the right start time'); var replayId2 = urlParams.get('replay_id'); ok(replayId1 !== replayId2, 'replay id is different after reset'); mixpanel.recordertest.stop_session_recording(); From 28b2523753dbb292948008b46322fabcf04daf26 Mon Sep 17 00:00:00 2001 From: Jakub Grzegorzewski Date: Thu, 15 Aug 2024 21:12:21 +0000 Subject: [PATCH 07/21] make delay required, clarify comment --- tests/test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test.js b/tests/test.js index 4b3a3e30..37bad3b7 100644 --- a/tests/test.js +++ b/tests/test.js @@ -5266,7 +5266,7 @@ return new Promise(function(resolve) { setTimeout(function() { resolve(makeFakeFetchResponse(status, body)); - }, delay || 0); + }, delay); }); } @@ -5670,7 +5670,7 @@ var replayId1 = urlParams.get('replay_id'); this.clock.tick(16 * 60 * 1000); - // simulate a mutation event to make sure it doesn't make a request + // simulate a mutation event to ensure we don't try sending it until there's a user event document.body.appendChild(document.createElement('div')); this.clock.tick(16 * 60 * 1000); From f268b0d83f0f08da4107af4eab1eb226fad84d8a Mon Sep 17 00:00:00 2001 From: Jakub Grzegorzewski Date: Thu, 15 Aug 2024 23:23:34 +0000 Subject: [PATCH 08/21] retry / queue requests when offline --- src/recorder/index.js | 2 +- src/request-batcher.js | 9 +++-- src/utils.js | 29 +++++++++------ tests/test.js | 67 ++++++++++++++++++++++++++++++++++- tests/unit/request-batcher.js | 29 +++++++++++++++ 5 files changed, 122 insertions(+), 14 deletions(-) diff --git a/src/recorder/index.js b/src/recorder/index.js index 21125054..dfed3cdc 100644 --- a/src/recorder/index.js +++ b/src/recorder/index.js @@ -197,7 +197,7 @@ MixpanelRecorder.prototype._sendRequest = function(reqParams, reqBody, callback) callback({error: error}); }); }).catch(function (error) { - callback({error: error}); + callback({error: error, httpStatusCode: 0}); }); }; diff --git a/src/request-batcher.js b/src/request-batcher.js index afe4a6b7..d5af2f7e 100644 --- a/src/request-batcher.js +++ b/src/request-batcher.js @@ -1,6 +1,6 @@ import Config from './config'; import { RequestQueue } from './request-queue'; -import { console_with_prefix, _ } from './utils'; // eslint-disable-line camelcase +import { console_with_prefix, isOnline, _ } from './utils'; // eslint-disable-line camelcase // maximum interval between request retries after exponential backoff var MAX_RETRY_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes @@ -198,7 +198,12 @@ RequestBatcher.prototype.flush = function(options) { this.flush(); } else if ( _.isObject(res) && - (res.httpStatusCode >= 500 || res.httpStatusCode === 429 || res.error === 'timeout') + ( + res.httpStatusCode >= 500 + || res.httpStatusCode === 429 + || res.httpStatusCode <= 0 && !isOnline() + || res.error === 'timeout' + ) ) { // network or API error, or 429 Too Many Requests, retry var retryMS = this.flushInterval * 2; diff --git a/src/utils.js b/src/utils.js index af6a76db..5cc47d98 100644 --- a/src/utils.js +++ b/src/utils.js @@ -8,7 +8,7 @@ if (typeof(window) === 'undefined') { hostname: '' }; win = { - navigator: { userAgent: '' }, + navigator: { userAgent: '', onLine: true }, document: { location: loc, referrer: '' @@ -1702,6 +1702,14 @@ var extract_domain = function(hostname) { return matches ? matches[0] : ''; }; +/** + * Check whether we have network connection. default to true for browsers that don't support navigator.onLine (IE) + * @returns {boolean} + */ +var isOnline = function() { + return win.navigator.onLine === undefined || win.navigator.onLine; +}; + var JSONStringify = null, JSONParse = null; if (typeof JSON !== 'undefined') { JSONStringify = JSON.stringify; @@ -1724,18 +1732,19 @@ _['info']['browserVersion'] = _.info.browserVersion; _['info']['properties'] = _.info.properties; export { - MAX_RECORDING_MS, _, - userAgent, - console, - win as window, - document, - navigator, cheap_guid, console_with_prefix, + console, + document, extract_domain, - localStorageSupported, - JSONStringify, JSONParse, - slice + JSONStringify, + isOnline, + localStorageSupported, + MAX_RECORDING_MS, + navigator, + slice, + userAgent, + win as window }; diff --git a/tests/test.js b/tests/test.js index 195b76c4..f0aab233 100644 --- a/tests/test.js +++ b/tests/test.js @@ -3941,6 +3941,24 @@ this.clock.tick(10000); same(stored_requests.length, 2, "both events should still be in localStorage"); }); + + test('requests are not cleared from localStorage when offline', 3, function() { + var onlineStub = sinon.stub(window.navigator, 'onLine').value(false); + + mixpanel.batchtest.track('storagetest 1'); + mixpanel.batchtest.track('storagetest 2'); + stored_requests = JSON.parse(localStorage.getItem(LOCALSTORAGE_EVENTS_KEY)); + same(stored_requests.length, 2, "both events should be in localStorage"); + + this.clock.tick(5000); + this.requests[0].respond(0, {}, ''); + + stored_requests = JSON.parse(localStorage.getItem(LOCALSTORAGE_EVENTS_KEY)); + same(stored_requests.length, 2, "both events should still be in localStorage"); + this.clock.tick(10000); + same(stored_requests.length, 2, "both events should still be in localStorage"); + onlineStub.restore(); + }); test('orphaned data in localStorage gets sent on init', 6, function() { clearLibInstance(mixpanel.batchtest); @@ -5543,7 +5561,7 @@ }, this)); }); }); - + asyncTest('retries record request after a 500', 17, function () { this.randomStub.returns(0.02); this.initMixpanelRecorder({record_sessions_percent: 10}); @@ -5580,6 +5598,53 @@ }); }); + asyncTest('retries record requests when offline', 7, function () { + var onlineStub = sinon.stub(window.navigator, 'onLine').value(false); + // pretend we can't compress so we can compare the events in the fetch request + var compressionStreamStub = sinon.stub(window, 'CompressionStream').value(undefined); + + this.randomStub.returns(0.02); + this.initMixpanelRecorder({record_sessions_percent: 10}); + this.assertRecorderScript(true); + + this.responseBlobStub = sinon.stub(window.Response.prototype, 'blob'); + this.responseBlobStub.returns(fakePromiseWrap(new Blob())); + this.fetchStub.onCall(0) + .returns(new Promise(function (_resolve, reject) { + // simulate offline + reject(new TypeError('Failed to fetch')); + })) + .onCall(1) + .returns(makeFakeFetchResponse(200)) + + this.afterRecorderLoaded.call(this, function () { + simulateMouseClick(document.body); + this.clock.tick(10 * 1000) + same(this.fetchStub.getCalls().length, 1, 'one batch fetch request made every ten seconds'); + + var urlParams = validateAndGetUrlParams(this.fetchStub.getCall(0)); + same(urlParams.get("seq"), "0", "first sequence fails because we're offline"); + var fetchBody = this.fetchStub.getCall(0).args[1].body; + + this.clock.tick(20 * 1000); + + stop() + untilDone(_.bind(function (done) { + var fetchCall1 = this.fetchStub.getCall(1); + if (fetchCall1) { + urlParams = validateAndGetUrlParams(fetchCall1); + same(urlParams.get("seq"), "0", "first sequence is retried with exponential backoff"); + same(fetchBody, fetchCall1.args[1].body, 'fetch body should be the same as the first request'); + } + onlineStub.restore(); + compressionStreamStub.restore(); + mixpanel.recordertest.stop_session_recording(); + + done(); + }, this)) + }); + }); + asyncTest('halves batch size and retries record request after a 413', 25, function () { this.randomStub.returns(0.02); this.initMixpanelRecorder({record_sessions_percent: 10}); diff --git a/tests/unit/request-batcher.js b/tests/unit/request-batcher.js index 77e02e64..77b562f3 100644 --- a/tests/unit/request-batcher.js +++ b/tests/unit/request-batcher.js @@ -2,6 +2,7 @@ import chai, { expect } from 'chai'; import localStorage from 'localStorage'; import sinon from 'sinon'; import sinonChai from 'sinon-chai'; +import { window } from '../../src/utils'; chai.use(sinonChai); @@ -332,6 +333,34 @@ describe(`RequestBatcher`, function() { ]); }); + it(`retries ERR_INTERNET_DISCONNECTED and continues queueing`, function() { + var isOnlineStub = sinon.stub(window.navigator, `onLine`).value(false); + batcher.flush(); + batcher.enqueue({ev: `queued event 1`}); + batcher.enqueue({ev: `queued event 2`}); + + // fail a couple times + clock.tick(DEFAULT_FLUSH_INTERVAL); + expect(batcher.sendRequest).to.have.been.calledOnce; + sendResponse(0); + clock.tick(DEFAULT_FLUSH_INTERVAL * 2); + expect(batcher.sendRequest).to.have.been.calledTwice; + sendResponse(0); + + batcher.enqueue({ev: `queued event 3`}); + + clock.tick(DEFAULT_FLUSH_INTERVAL * 4); + expect(batcher.sendRequest).to.have.callCount(3); + + // should include all events in current retry + expect(batcher.sendRequest.args[2][0]).to.deep.equal([ + {ev: `queued event 1`}, + {ev: `queued event 2`}, + {ev: `queued event 3`}, + ]); + isOnlineStub.restore(); + }); + it(`does not retry 400s / successful API rejections`, function() { batcher.enqueue({ev: `queued event 1`}); batcher.enqueue({ev: `queued event 2`}); From 6976cd0228235a4dff7ee33ea1e769948b3ce86f Mon Sep 17 00:00:00 2001 From: Jakub Grzegorzewski Date: Thu, 15 Aug 2024 18:50:16 -0500 Subject: [PATCH 09/21] Update src/request-batcher.js Co-authored-by: teddddd --- src/request-batcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/request-batcher.js b/src/request-batcher.js index d5af2f7e..40cd88fb 100644 --- a/src/request-batcher.js +++ b/src/request-batcher.js @@ -201,7 +201,7 @@ RequestBatcher.prototype.flush = function(options) { ( res.httpStatusCode >= 500 || res.httpStatusCode === 429 - || res.httpStatusCode <= 0 && !isOnline() + || (res.httpStatusCode <= 0 && !isOnline()) || res.error === 'timeout' ) ) { From 0fb0fd1ace3233fb371323a0a09cad343d972644 Mon Sep 17 00:00:00 2001 From: Jakub Grzegorzewski Date: Thu, 15 Aug 2024 18:50:36 -0500 Subject: [PATCH 10/21] Update tests/test.js Co-authored-by: teddddd --- tests/test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test.js b/tests/test.js index f0aab233..43200949 100644 --- a/tests/test.js +++ b/tests/test.js @@ -5561,7 +5561,6 @@ }, this)); }); }); - asyncTest('retries record request after a 500', 17, function () { this.randomStub.returns(0.02); this.initMixpanelRecorder({record_sessions_percent: 10}); From 69b90346b160590168105ccc85e3a7bdfb7c9cba Mon Sep 17 00:00:00 2001 From: Jakub Grzegorzewski Date: Fri, 16 Aug 2024 02:58:29 +0000 Subject: [PATCH 11/21] make onLine closure friendly --- src/utils.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utils.js b/src/utils.js index 5cc47d98..73427123 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1707,7 +1707,8 @@ var extract_domain = function(hostname) { * @returns {boolean} */ var isOnline = function() { - return win.navigator.onLine === undefined || win.navigator.onLine; + var onLine = win.navigator['onLine']; + return _.isUndefined(onLine) || onLine; }; var JSONStringify = null, JSONParse = null; From f983c412fe29b161412878e7be507c3a22e1eadb Mon Sep 17 00:00:00 2001 From: Yalcin Kaya <101181349+aliyalcinkaya@users.noreply.github.com> Date: Sat, 17 Aug 2024 08:26:47 +1000 Subject: [PATCH 12/21] Update utils.js 1. Added new UTM tags that are suppoted by GA4 utm_id, utm_source_platform, utm_campaign_id, utm_creative_format, utm_marketing_tactic 2. Added Snapchat click ID sscid --- src/utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils.js b/src/utils.js index af6a76db..85087d33 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1419,8 +1419,8 @@ _.dom_query = (function() { }; })(); -var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; -var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid']; +var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform','utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic',]; +var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid', 'sccid']; _.info = { campaignParams: function(default_value) { From 93cf372e17072181b8e2c836c2c104b56c294e26 Mon Sep 17 00:00:00 2001 From: Jakub Grzegorzewski Date: Mon, 19 Aug 2024 13:35:07 -0500 Subject: [PATCH 13/21] Update tests/test.js Co-authored-by: teddddd --- tests/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test.js b/tests/test.js index 43200949..f54e6e5e 100644 --- a/tests/test.js +++ b/tests/test.js @@ -3947,7 +3947,7 @@ mixpanel.batchtest.track('storagetest 1'); mixpanel.batchtest.track('storagetest 2'); - stored_requests = JSON.parse(localStorage.getItem(LOCALSTORAGE_EVENTS_KEY)); + var stored_requests = JSON.parse(localStorage.getItem(LOCALSTORAGE_EVENTS_KEY)); same(stored_requests.length, 2, "both events should be in localStorage"); this.clock.tick(5000); From 231138a0691db7a10477fb6d67375a5263521193 Mon Sep 17 00:00:00 2001 From: Jakub Grzegorzewski Date: Mon, 19 Aug 2024 13:35:13 -0500 Subject: [PATCH 14/21] Update tests/test.js Co-authored-by: teddddd --- tests/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test.js b/tests/test.js index f54e6e5e..0c731768 100644 --- a/tests/test.js +++ b/tests/test.js @@ -5627,7 +5627,7 @@ this.clock.tick(20 * 1000); - stop() + stop(); untilDone(_.bind(function (done) { var fetchCall1 = this.fetchStub.getCall(1); if (fetchCall1) { From 37e95ccb766f1d8cfc7a48a1e4b0e3ced51525d6 Mon Sep 17 00:00:00 2001 From: Jakub Grzegorzewski Date: Mon, 19 Aug 2024 13:35:20 -0500 Subject: [PATCH 15/21] Update tests/unit/request-batcher.js Co-authored-by: teddddd --- tests/unit/request-batcher.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/request-batcher.js b/tests/unit/request-batcher.js index 77b562f3..50c90456 100644 --- a/tests/unit/request-batcher.js +++ b/tests/unit/request-batcher.js @@ -2,6 +2,7 @@ import chai, { expect } from 'chai'; import localStorage from 'localStorage'; import sinon from 'sinon'; import sinonChai from 'sinon-chai'; + import { window } from '../../src/utils'; chai.use(sinonChai); From f0bf937e1605684a75d2748c5a9f51c227e52a3d Mon Sep 17 00:00:00 2001 From: teddddd Date: Tue, 20 Aug 2024 17:55:49 +0000 Subject: [PATCH 16/21] a-z --- src/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.js b/src/utils.js index cdfad3a7..3fe01d67 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1420,7 +1420,7 @@ _.dom_query = (function() { })(); var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform','utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic',]; -var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid', 'sccid']; +var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'sccid', 'ttclid', 'twclid', 'wbraid']; _.info = { campaignParams: function(default_value) { From 162223e1d705e799832046bc9816750d0875d114 Mon Sep 17 00:00:00 2001 From: teddddd Date: Tue, 20 Aug 2024 18:04:27 +0000 Subject: [PATCH 17/21] fix getQueryParam bracket-escaping --- src/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.js b/src/utils.js index 3fe01d67..52ba8f0b 100644 --- a/src/utils.js +++ b/src/utils.js @@ -962,7 +962,7 @@ _.HTTPBuildQuery = function(formdata, arg_separator) { _.getQueryParam = function(url, param) { // Expects a raw URL - param = param.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); + param = param.replace(/[[]/g, '\\[').replace(/[\]]/g, '\\]'); var regexS = '[\\?&]' + param + '=([^&#]*)', regex = new RegExp(regexS), results = regex.exec(url); From 304e596dd8d8f31bc89ac05aa13d489b0e9697b6 Mon Sep 17 00:00:00 2001 From: Carlos Trevino <35301701+carlosdanieltt@users.noreply.github.com> Date: Wed, 21 Aug 2024 17:25:12 +0000 Subject: [PATCH 18/21] Fixed test for minimum recording duration --- src/recorder/index.js | 2 +- src/utils.js | 2 +- tests/test.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/recorder/index.js b/src/recorder/index.js index 2025bdb0..4f2f9a92 100644 --- a/src/recorder/index.js +++ b/src/recorder/index.js @@ -87,7 +87,7 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { this.recEvents = []; this.seqNo = 0; - this.replayStartTime = null; + this.replayStartTime = new Date().getTime(); this.replayId = _.UUID(); diff --git a/src/utils.js b/src/utils.js index fdb70365..2c7fe178 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1421,7 +1421,7 @@ _.dom_query = (function() { }; })(); -var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform','utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic',]; +var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform','utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic']; var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'sccid', 'ttclid', 'twclid', 'wbraid']; _.info = { diff --git a/tests/test.js b/tests/test.js index 184e85d3..ae5e1fc8 100644 --- a/tests/test.js +++ b/tests/test.js @@ -5714,7 +5714,7 @@ asyncTest('respects minimum session length setting', function () { this.randomStub.returns(0.02); - this.initMixpanelRecorder({record_sessions_percent: 10, record_min_ms: 5000}); + this.initMixpanelRecorder({record_sessions_percent: 10, record_min_ms: 8000}); this.assertRecorderScript(true) this.afterRecorderLoaded.call(this, function () { From 567315502f2a0562a1897ece600624981a9499c3 Mon Sep 17 00:00:00 2001 From: Jakub Grzegorzewski Date: Wed, 21 Aug 2024 18:30:43 +0000 Subject: [PATCH 19/21] fix race condition test for bundled version --- tests/test.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tests/test.js b/tests/test.js index ae5e1fc8..57c74b22 100644 --- a/tests/test.js +++ b/tests/test.js @@ -5780,6 +5780,7 @@ asyncTest('handles race condition where the recording resets while a request is in flight', 14, function () { this.randomStub.returns(0.02); + this.initMixpanelRecorder({record_sessions_percent: 10}); this.assertRecorderScript(true); this.randomStub.restore(); // restore the random stub after script is loaded for batcher uuid dedupe @@ -5798,7 +5799,13 @@ same(this.fetchStub.getCalls().length, 1, 'flushed events after stopping recording'); var urlParams = validateAndGetUrlParams(this.fetchStub.getCall(0)); same(urlParams.get('seq'), '0', 'sends first sequence'); - same(urlParams.get('replay_start_time'), (this.startTime / 1000).toString(), 'sends the right start time'); + + if (!IS_RECORDER_BUNDLED) { + same(urlParams.get('replay_start_time'), (this.startTime / 1000).toString(), 'sends the right start time'); + } else { + ok(true, 'cannot test replay_start_time when recorder is bundled, rrweb stores a reference to Date.now at the global level so stubs / fake timers will not work.'); + } + var replayId1 = urlParams.get('replay_id'); // start recording again while the first replay's request is in flight @@ -5812,7 +5819,13 @@ if (fetchCall1) { urlParams = validateAndGetUrlParams(this.fetchStub.getCall(1)); same(urlParams.get('seq'), '0', 'new replay uses the first sequence'); - same(urlParams.get('replay_start_time'), (this.startTime / 1000).toString(), 'sends the right start time'); + + if (!IS_RECORDER_BUNDLED) { + same(urlParams.get('replay_start_time'), (this.startTime / 1000).toString(), 'sends the right start time'); + } else { + ok(true, 'cannot test replay_start_time when recorder is bundled, rrweb stores a reference to Date.now at the global level so stubs / fake timers will not work.'); + } + var replayId2 = urlParams.get('replay_id'); ok(replayId1 !== replayId2, 'replay id is different after reset'); mixpanel.recordertest.stop_session_recording(); From 5bf4d47e025f1a189ee4440954366fdc4ecd7949 Mon Sep 17 00:00:00 2001 From: Carlos Trevino <35301701+carlosdanieltt@users.noreply.github.com> Date: Wed, 21 Aug 2024 21:04:57 +0000 Subject: [PATCH 20/21] Build release branch --- dist/mixpanel-core.cjs.js | 27 +++- dist/mixpanel-recorder.js | 74 ++++++--- dist/mixpanel-recorder.min.js | 18 +-- dist/mixpanel-with-async-recorder.cjs.js | 27 +++- dist/mixpanel.amd.js | 75 ++++++--- dist/mixpanel.cjs.js | 75 ++++++--- dist/mixpanel.globals.js | 27 +++- dist/mixpanel.min.js | 195 ++++++++++++----------- dist/mixpanel.module.js | 75 ++++++--- dist/mixpanel.umd.js | 75 ++++++--- examples/commonjs-browserify/bundle.js | 75 ++++++--- examples/es2015-babelify/bundle.js | 88 ++++++---- examples/umd-webpack/bundle.js | 75 ++++++--- src/config.js | 2 +- 14 files changed, 623 insertions(+), 285 deletions(-) diff --git a/dist/mixpanel-core.cjs.js b/dist/mixpanel-core.cjs.js index 48dd54d1..a6889da2 100644 --- a/dist/mixpanel-core.cjs.js +++ b/dist/mixpanel-core.cjs.js @@ -2,7 +2,7 @@ var Config = { DEBUG: false, - LIB_VERSION: '2.55.0' + LIB_VERSION: '2.55.1-rc1' }; /* eslint camelcase: "off", eqeqeq: "off" */ @@ -14,7 +14,7 @@ if (typeof(window) === 'undefined') { hostname: '' }; win = { - navigator: { userAgent: '' }, + navigator: { userAgent: '', onLine: true }, document: { location: loc, referrer: '' @@ -968,7 +968,7 @@ _.HTTPBuildQuery = function(formdata, arg_separator) { _.getQueryParam = function(url, param) { // Expects a raw URL - param = param.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); + param = param.replace(/[[]/g, '\\[').replace(/[\]]/g, '\\]'); var regexS = '[\\?&]' + param + '=([^&#]*)', regex = new RegExp(regexS), results = regex.exec(url); @@ -1425,8 +1425,8 @@ _.dom_query = (function() { }; })(); -var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; -var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid']; +var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform','utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic']; +var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'sccid', 'ttclid', 'twclid', 'wbraid']; _.info = { campaignParams: function(default_value) { @@ -1708,6 +1708,15 @@ var extract_domain = function(hostname) { return matches ? matches[0] : ''; }; +/** + * Check whether we have network connection. default to true for browsers that don't support navigator.onLine (IE) + * @returns {boolean} + */ +var isOnline = function() { + var onLine = win.navigator['onLine']; + return _.isUndefined(onLine) || onLine; +}; + var JSONStringify = null, JSONParse = null; if (typeof JSON !== 'undefined') { JSONStringify = JSON.stringify; @@ -2523,7 +2532,12 @@ RequestBatcher.prototype.flush = function(options) { this.flush(); } else if ( _.isObject(res) && - (res.httpStatusCode >= 500 || res.httpStatusCode === 429 || res.error === 'timeout') + ( + res.httpStatusCode >= 500 + || res.httpStatusCode === 429 + || (res.httpStatusCode <= 0 && !isOnline()) + || res.error === 'timeout' + ) ) { // network or API error, or 429 Too Many Requests, retry var retryMS = this.flushInterval * 2; @@ -4247,6 +4261,7 @@ var DEFAULT_CONFIG = { 'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'), 'record_mask_text_selector': '*', 'record_max_ms': MAX_RECORDING_MS, + 'record_min_ms': 0, 'record_sessions_percent': 0, 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js' }; diff --git a/dist/mixpanel-recorder.js b/dist/mixpanel-recorder.js index f3e1a48c..27002b12 100644 --- a/dist/mixpanel-recorder.js +++ b/dist/mixpanel-recorder.js @@ -4510,7 +4510,7 @@ var Config = { DEBUG: false, - LIB_VERSION: '2.55.0' + LIB_VERSION: '2.55.1-rc1' }; /* eslint camelcase: "off", eqeqeq: "off" */ @@ -4522,7 +4522,7 @@ hostname: '' }; win = { - navigator: { userAgent: '' }, + navigator: { userAgent: '', onLine: true }, document: { location: loc, referrer: '' @@ -4536,6 +4536,8 @@ // Maximum allowed session recording length var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours + // Maximum allowed value for minimum session recording length + var MAX_VALUE_FOR_MIN_RECORDING_MS = 8 * 1000; // 8 seconds /* * Saved references to long variable names, so that closure compiler can @@ -5447,7 +5449,7 @@ _.getQueryParam = function(url, param) { // Expects a raw URL - param = param.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); + param = param.replace(/[[]/g, '\\[').replace(/[\]]/g, '\\]'); var regexS = '[\\?&]' + param + '=([^&#]*)', regex = new RegExp(regexS), results = regex.exec(url); @@ -5904,8 +5906,8 @@ }; })(); - var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; - var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid']; + var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform','utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic']; + var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'sccid', 'ttclid', 'twclid', 'wbraid']; _.info = { campaignParams: function(default_value) { @@ -6187,6 +6189,15 @@ return matches ? matches[0] : ''; }; + /** + * Check whether we have network connection. default to true for browsers that don't support navigator.onLine (IE) + * @returns {boolean} + */ + var isOnline = function() { + var onLine = win.navigator['onLine']; + return _.isUndefined(onLine) || onLine; + }; + var JSONStringify = null, JSONParse = null; if (typeof JSON !== 'undefined') { JSONStringify = JSON.stringify; @@ -7018,7 +7029,12 @@ this.flush(); } else if ( _.isObject(res) && - (res.httpStatusCode >= 500 || res.httpStatusCode === 429 || res.error === 'timeout') + ( + res.httpStatusCode >= 500 + || res.httpStatusCode === 429 + || (res.httpStatusCode <= 0 && !isOnline()) + || res.error === 'timeout' + ) ) { // network or API error, or 429 Too Many Requests, retry var retryMS = this.flushInterval * 2; @@ -7169,6 +7185,7 @@ this.maxTimeoutId = null; this.recordMaxMs = MAX_RECORDING_MS; + this.recordMinMs = 0; this._initBatcher(); }; @@ -7200,16 +7217,24 @@ logger.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.'); } + this.recordMinMs = this.get_config('record_min_ms'); + if (this.recordMinMs > MAX_VALUE_FOR_MIN_RECORDING_MS) { + this.recordMinMs = MAX_VALUE_FOR_MIN_RECORDING_MS; + logger.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.'); + } + this.recEvents = []; this.seqNo = 0; - this.replayStartTime = null; + this.replayStartTime = new Date().getTime(); this.replayId = _.UUID(); - if (shouldStopBatcher) { - // this is the case when we're starting recording after a reset + if (shouldStopBatcher || this.recordMinMs > 0) { + // the primary case for shouldStopBatcher is when we're starting recording after a reset // and don't want to send anything over the network until there's // actual user activity + // this also applies if the minimum recording length has not been hit yet + // so that we don't send data until we know the recording will be long enough this.batcher.stop(); } else { this.batcher.start(); @@ -7223,11 +7248,16 @@ }, this), this.get_config('record_idle_timeout_ms')); }, this); + var blockSelector = this.get_config('record_block_selector'); + if (blockSelector === '' || blockSelector === null) { + blockSelector = undefined; + } + this._stopRecording = record({ 'emit': _.bind(function (ev) { this.batcher.enqueue(ev); if (isUserEvent(ev)) { - if (this.batcher.stopped) { + if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) { // start flushing again after user activity this.batcher.start(); } @@ -7235,7 +7265,7 @@ } }, this), 'blockClass': this.get_config('record_block_class'), - 'blockSelector': this.get_config('record_block_selector'), + 'blockSelector': blockSelector, 'collectFonts': this.get_config('record_collect_fonts'), 'inlineImages': this.get_config('record_inline_images'), 'maskAllInputs': true, @@ -7289,14 +7319,14 @@ } }; - MixpanelRecorder.prototype._sendRequest = function(reqParams, reqBody, callback) { + MixpanelRecorder.prototype._sendRequest = function(currentReplayId, reqParams, reqBody, callback) { var onSuccess = _.bind(function (response, responseBody) { // Increment sequence counter only if the request was successful to guarantee ordering. // RequestBatcher will always flush the next batch after the previous one succeeds. - if (response.status === 200) { + // extra check to see if the replay ID has changed so that we don't increment the seqNo on the wrong replay + if (response.status === 200 && this.replayId === currentReplayId) { this.seqNo++; } - callback({ status: 0, httpStatusCode: response.status, @@ -7319,7 +7349,7 @@ callback({error: error}); }); }).catch(function (error) { - callback({error: error}); + callback({error: error, httpStatusCode: 0}); }); }; @@ -7327,9 +7357,15 @@ const numEvents = data.length; if (numEvents > 0) { + var replayId = this.replayId; // each rrweb event has a timestamp - leverage those to get time properties var batchStartTime = data[0].timestamp; - if (this.seqNo === 0) { + if (this.seqNo === 0 || !this.replayStartTime) { + // extra safety net so that we don't send a null replay start time + if (this.seqNo !== 0) { + this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.'); + } + this.replayStartTime = batchStartTime; } var replayLengthMs = data[numEvents - 1].timestamp - this.replayStartTime; @@ -7338,7 +7374,7 @@ 'distinct_id': String(this._mixpanel.get_distinct_id()), 'seq': this.seqNo, 'batch_start_time': batchStartTime / 1000, - 'replay_id': this.replayId, + 'replay_id': replayId, 'replay_length_ms': replayLengthMs, 'replay_start_time': this.replayStartTime / 1000 }; @@ -7361,11 +7397,11 @@ .blob() .then(_.bind(function(compressedBlob) { reqParams['format'] = 'gzip'; - this._sendRequest(reqParams, compressedBlob, callback); + this._sendRequest(replayId, reqParams, compressedBlob, callback); }, this)); } else { reqParams['format'] = 'body'; - this._sendRequest(reqParams, eventsJson, callback); + this._sendRequest(replayId, reqParams, eventsJson, callback); } } }); diff --git a/dist/mixpanel-recorder.min.js b/dist/mixpanel-recorder.min.js index ea2c33e1..a81d65df 100644 --- a/dist/mixpanel-recorder.min.js +++ b/dist/mixpanel-recorder.min.js @@ -1,6 +1,6 @@ -(function(){"use strict";var A;(function(e){e[e.Document=0]="Document",e[e.DocumentType=1]="DocumentType",e[e.Element=2]="Element",e[e.Text=3]="Text",e[e.CDATA=4]="CDATA",e[e.Comment=5]="Comment"})(A||(A={}));function Sr(e){return e.nodeType===e.ELEMENT_NODE}function be(e){const t=e?.host;return t?.shadowRoot===e}function we(e){return Object.prototype.toString.call(e)==="[object ShadowRoot]"}function br(e){return e.includes(" background-clip: text;")&&!e.includes(" -webkit-background-clip: text;")&&(e=e.replace(" background-clip: text;"," -webkit-background-clip: text; background-clip: text;")),e}function wr(e){const{cssText:t}=e;if(t.split('"').length<3)return t;const r=["@import",`url(${JSON.stringify(e.href)})`];return e.layerName===""?r.push("layer"):e.layerName&&r.push(`layer(${e.layerName})`),e.supportsText&&r.push(`supports(${e.supportsText})`),e.media.length&&r.push(e.media.mediaText),r.join(" ")+";"}function Te(e){try{const t=e.rules||e.cssRules;return t?br(Array.from(t,St).join("")):null}catch{return null}}function St(e){let t;if(Mr(e))try{t=Te(e.styleSheet)||wr(e)}catch{}else if(Cr(e)&&e.selectorText.includes(":"))return Ir(e.cssText);return t||e.cssText}function Ir(e){const t=/(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;return e.replace(t,"$1\\$2")}function Mr(e){return"styleSheet"in e}function Cr(e){return"selectorText"in e}class bt{constructor(){this.idNodeMap=new Map,this.nodeMetaMap=new WeakMap}getId(t){var r;if(!t)return-1;const n=(r=this.getMeta(t))===null||r===void 0?void 0:r.id;return n??-1}getNode(t){return this.idNodeMap.get(t)||null}getIds(){return Array.from(this.idNodeMap.keys())}getMeta(t){return this.nodeMetaMap.get(t)||null}removeNodeFromMap(t){const r=this.getId(t);this.idNodeMap.delete(r),t.childNodes&&t.childNodes.forEach(n=>this.removeNodeFromMap(n))}has(t){return this.idNodeMap.has(t)}hasNode(t){return this.nodeMetaMap.has(t)}add(t,r){const n=r.id;this.idNodeMap.set(n,t),this.nodeMetaMap.set(t,r)}replace(t,r){const n=this.getNode(t);if(n){const i=this.nodeMetaMap.get(n);i&&this.nodeMetaMap.set(r,i)}this.idNodeMap.set(t,r)}reset(){this.idNodeMap=new Map,this.nodeMetaMap=new WeakMap}}function _r(){return new bt}function tt({element:e,maskInputOptions:t,tagName:r,type:n,value:i,maskInputFn:o}){let a=i||"";const l=n&&ie(n);return(t[r.toLowerCase()]||l&&t[l])&&(o?a=o(a,e):a="*".repeat(a.length)),a}function ie(e){return e.toLowerCase()}const wt="__rrweb_original__";function Or(e){const t=e.getContext("2d");if(!t)return!0;const r=50;for(let n=0;ns!==0))return!1}return!0}function rt(e){const t=e.type;return e.hasAttribute("data-rr-is-password")?"password":t?ie(t):null}function It(e,t){var r;let n;try{n=new URL(e,t??window.location.href)}catch{return null}const i=/\.([0-9a-z]+)(?:$)/i,o=n.pathname.match(i);return(r=o?.[1])!==null&&r!==void 0?r:null}let Er=1;const kr=new RegExp("[^a-z0-9-_:]"),Ie=-2;function Mt(){return Er++}function xr(e){if(e instanceof HTMLFormElement)return"form";const t=ie(e.tagName);return kr.test(t)?"div":t}function Rr(e){let t="";return e.indexOf("//")>-1?t=e.split("/").slice(0,3).join("/"):t=e.split("/")[0],t=t.split("?")[0],t}let fe,Ct;const Tr=/url\((?:(')([^']*)'|(")(.*?)"|([^)]*))\)/gm,Dr=/^(?:[a-z+]+:)?\/\//i,Nr=/^www\..*/i,Ar=/^(data:)([^,]*),(.*)/i;function De(e,t){return(e||"").replace(Tr,(r,n,i,o,a,l)=>{const s=i||a||l,c=n||o||"";if(!s)return r;if(Dr.test(s)||Nr.test(s))return`url(${c}${s}${c})`;if(Ar.test(s))return`url(${c}${s}${c})`;if(s[0]==="/")return`url(${c}${Rr(t)+s}${c})`;const u=t.split("/"),f=s.split("/");u.pop();for(const m of f)m!=="."&&(m===".."?u.pop():u.push(m));return`url(${c}${u.join("/")}${c})`})}const Lr=/^[^ \t\n\r\u000c]+/,Fr=/^[, \t\n\r\u000c]+/;function Pr(e,t){if(t.trim()==="")return t;let r=0;function n(o){let a;const l=o.exec(t.substring(r));return l?(a=l[0],r+=a.length,a):""}const i=[];for(;n(Fr),!(r>=t.length);){let o=n(Lr);if(o.slice(-1)===",")o=he(e,o.substring(0,o.length-1)),i.push(o);else{let a="";o=he(e,o);let l=!1;for(;;){const s=t.charAt(r);if(s===""){i.push((o+a).trim());break}else if(l)s===")"&&(l=!1);else if(s===","){r+=1,i.push((o+a).trim());break}else s==="("&&(l=!0);a+=s,r+=1}}}return i.join(", ")}function he(e,t){if(!t||t.trim()==="")return t;const r=e.createElement("a");return r.href=t,r.href}function Br(e){return!!(e.tagName==="svg"||e.ownerSVGElement)}function nt(){const e=document.createElement("a");return e.href="",e.href}function _t(e,t,r,n){return n&&(r==="src"||r==="href"&&!(t==="use"&&n[0]==="#")||r==="xlink:href"&&n[0]!=="#"||r==="background"&&(t==="table"||t==="td"||t==="th")?he(e,n):r==="srcset"?Pr(e,n):r==="style"?De(n,nt()):t==="object"&&r==="data"?he(e,n):n)}function Ot(e,t,r){return(e==="video"||e==="audio")&&t==="autoplay"}function Wr(e,t,r){try{if(typeof t=="string"){if(e.classList.contains(t))return!0}else for(let n=e.classList.length;n--;){const i=e.classList[n];if(t.test(i))return!0}if(r)return e.matches(r)}catch{}return!1}function Ne(e,t,r){if(!e)return!1;if(e.nodeType!==e.ELEMENT_NODE)return r?Ne(e.parentNode,t,r):!1;for(let n=e.classList.length;n--;){const i=e.classList[n];if(t.test(i))return!0}return r?Ne(e.parentNode,t,r):!1}function Et(e,t,r,n){try{const i=e.nodeType===e.ELEMENT_NODE?e:e.parentElement;if(i===null)return!1;if(typeof t=="string"){if(n){if(i.closest(`.${t}`))return!0}else if(i.classList.contains(t))return!0}else if(Ne(i,t,n))return!0;if(r){if(n){if(i.closest(r))return!0}else if(i.matches(r))return!0}}catch{}return!1}function Ur(e,t,r){const n=e.contentWindow;if(!n)return;let i=!1,o;try{o=n.document.readyState}catch{return}if(o!=="complete"){const l=setTimeout(()=>{i||(t(),i=!0)},r);e.addEventListener("load",()=>{clearTimeout(l),i=!0,t()});return}const a="about:blank";if(n.location.href!==a||e.src===a||e.src==="")return setTimeout(t,0),e.addEventListener("load",t);e.addEventListener("load",t)}function zr(e,t,r){let n=!1,i;try{i=e.sheet}catch{return}if(i)return;const o=setTimeout(()=>{n||(t(),n=!0)},r);e.addEventListener("load",()=>{clearTimeout(o),n=!0,t()})}function Hr(e,t){const{doc:r,mirror:n,blockClass:i,blockSelector:o,needsMask:a,inlineStylesheet:l,maskInputOptions:s={},maskTextFn:c,maskInputFn:u,dataURLOptions:f={},inlineImages:m,recordCanvas:h,keepIframeSrcFn:g,newlyAddedElement:p=!1}=t,y=$r(r,n);switch(e.nodeType){case e.DOCUMENT_NODE:return e.compatMode!=="CSS1Compat"?{type:A.Document,childNodes:[],compatMode:e.compatMode}:{type:A.Document,childNodes:[]};case e.DOCUMENT_TYPE_NODE:return{type:A.DocumentType,name:e.name,publicId:e.publicId,systemId:e.systemId,rootId:y};case e.ELEMENT_NODE:return jr(e,{doc:r,blockClass:i,blockSelector:o,inlineStylesheet:l,maskInputOptions:s,maskInputFn:u,dataURLOptions:f,inlineImages:m,recordCanvas:h,keepIframeSrcFn:g,newlyAddedElement:p,rootId:y});case e.TEXT_NODE:return qr(e,{needsMask:a,maskTextFn:c,rootId:y});case e.CDATA_SECTION_NODE:return{type:A.CDATA,textContent:"",rootId:y};case e.COMMENT_NODE:return{type:A.Comment,textContent:e.textContent||"",rootId:y};default:return!1}}function $r(e,t){if(!t.hasNode(e))return;const r=t.getId(e);return r===1?void 0:r}function qr(e,t){var r;const{needsMask:n,maskTextFn:i,rootId:o}=t,a=e.parentNode&&e.parentNode.tagName;let l=e.textContent;const s=a==="STYLE"?!0:void 0,c=a==="SCRIPT"?!0:void 0;if(s&&l){try{e.nextSibling||e.previousSibling||!((r=e.parentNode.sheet)===null||r===void 0)&&r.cssRules&&(l=Te(e.parentNode.sheet))}catch(u){console.warn(`Cannot get CSS styles from text's parentNode. Error: ${u}`,e)}l=De(l,nt())}return c&&(l="SCRIPT_PLACEHOLDER"),!s&&!c&&l&&n&&(l=i?i(l,e.parentElement):l.replace(/[\S]/g,"*")),{type:A.Text,textContent:l||"",isStyle:s,rootId:o}}function jr(e,t){const{doc:r,blockClass:n,blockSelector:i,inlineStylesheet:o,maskInputOptions:a={},maskInputFn:l,dataURLOptions:s={},inlineImages:c,recordCanvas:u,keepIframeSrcFn:f,newlyAddedElement:m=!1,rootId:h}=t,g=Wr(e,n,i),p=xr(e);let y={};const w=e.attributes.length;for(let v=0;vI.href===e.href);let b=null;v&&(b=Te(v)),b&&(delete y.rel,delete y.href,y._cssText=De(b,v.href))}if(p==="style"&&e.sheet&&!(e.innerText||e.textContent||"").trim().length){const v=Te(e.sheet);v&&(y._cssText=De(v,nt()))}if(p==="input"||p==="textarea"||p==="select"){const v=e.value,b=e.checked;y.type!=="radio"&&y.type!=="checkbox"&&y.type!=="submit"&&y.type!=="button"&&v?y.value=tt({element:e,type:rt(e),tagName:p,value:v,maskInputOptions:a,maskInputFn:l}):b&&(y.checked=b)}if(p==="option"&&(e.selected&&!a.select?y.selected=!0:delete y.selected),p==="canvas"&&u){if(e.__context==="2d")Or(e)||(y.rr_dataURL=e.toDataURL(s.type,s.quality));else if(!("__context"in e)){const v=e.toDataURL(s.type,s.quality),b=document.createElement("canvas");b.width=e.width,b.height=e.height;const I=b.toDataURL(s.type,s.quality);v!==I&&(y.rr_dataURL=v)}}if(p==="img"&&c){fe||(fe=r.createElement("canvas"),Ct=fe.getContext("2d"));const v=e,b=v.crossOrigin;v.crossOrigin="anonymous";const I=()=>{v.removeEventListener("load",I);try{fe.width=v.naturalWidth,fe.height=v.naturalHeight,Ct.drawImage(v,0,0),y.rr_dataURL=fe.toDataURL(s.type,s.quality)}catch(B){console.warn(`Cannot inline img src=${v.currentSrc}! Error: ${B}`)}b?y.crossOrigin=b:v.removeAttribute("crossorigin")};v.complete&&v.naturalWidth!==0?I():v.addEventListener("load",I)}if(p==="audio"||p==="video"){const v=y;v.rr_mediaState=e.paused?"paused":"played",v.rr_mediaCurrentTime=e.currentTime,v.rr_mediaPlaybackRate=e.playbackRate,v.rr_mediaMuted=e.muted,v.rr_mediaLoop=e.loop,v.rr_mediaVolume=e.volume}if(m||(e.scrollLeft&&(y.rr_scrollLeft=e.scrollLeft),e.scrollTop&&(y.rr_scrollTop=e.scrollTop)),g){const{width:v,height:b}=e.getBoundingClientRect();y={class:y.class,rr_width:`${v}px`,rr_height:`${b}px`}}p==="iframe"&&!f(y.src)&&(e.contentDocument||(y.rr_src=y.src),delete y.src);let S;try{customElements.get(p)&&(S=!0)}catch{}return{type:A.Element,tagName:p,attributes:y,childNodes:[],isSVG:Br(e)||void 0,needBlock:g,rootId:h,isCustom:S}}function k(e){return e==null?"":e.toLowerCase()}function Gr(e,t){if(t.comment&&e.type===A.Comment)return!0;if(e.type===A.Element){if(t.script&&(e.tagName==="script"||e.tagName==="link"&&(e.attributes.rel==="preload"||e.attributes.rel==="modulepreload")&&e.attributes.as==="script"||e.tagName==="link"&&e.attributes.rel==="prefetch"&&typeof e.attributes.href=="string"&&It(e.attributes.href)==="js"))return!0;if(t.headFavicon&&(e.tagName==="link"&&e.attributes.rel==="shortcut icon"||e.tagName==="meta"&&(k(e.attributes.name).match(/^msapplication-tile(image|color)$/)||k(e.attributes.name)==="application-name"||k(e.attributes.rel)==="icon"||k(e.attributes.rel)==="apple-touch-icon"||k(e.attributes.rel)==="shortcut icon")))return!0;if(e.tagName==="meta"){if(t.headMetaDescKeywords&&k(e.attributes.name).match(/^description|keywords$/))return!0;if(t.headMetaSocial&&(k(e.attributes.property).match(/^(og|twitter|fb):/)||k(e.attributes.name).match(/^(og|twitter):/)||k(e.attributes.name)==="pinterest"))return!0;if(t.headMetaRobots&&(k(e.attributes.name)==="robots"||k(e.attributes.name)==="googlebot"||k(e.attributes.name)==="bingbot"))return!0;if(t.headMetaHttpEquiv&&e.attributes["http-equiv"]!==void 0)return!0;if(t.headMetaAuthorship&&(k(e.attributes.name)==="author"||k(e.attributes.name)==="generator"||k(e.attributes.name)==="framework"||k(e.attributes.name)==="publisher"||k(e.attributes.name)==="progid"||k(e.attributes.property).match(/^article:/)||k(e.attributes.property).match(/^product:/)))return!0;if(t.headMetaVerification&&(k(e.attributes.name)==="google-site-verification"||k(e.attributes.name)==="yandex-verification"||k(e.attributes.name)==="csrf-token"||k(e.attributes.name)==="p:domain_verify"||k(e.attributes.name)==="verify-v1"||k(e.attributes.name)==="verification"||k(e.attributes.name)==="shopify-checkout-api-token"))return!0}}return!1}function pe(e,t){const{doc:r,mirror:n,blockClass:i,blockSelector:o,maskTextClass:a,maskTextSelector:l,skipChild:s=!1,inlineStylesheet:c=!0,maskInputOptions:u={},maskTextFn:f,maskInputFn:m,slimDOMOptions:h,dataURLOptions:g={},inlineImages:p=!1,recordCanvas:y=!1,onSerialize:w,onIframeLoad:S,iframeLoadTimeout:v=5e3,onStylesheetLoad:b,stylesheetLoadTimeout:I=5e3,keepIframeSrcFn:B=()=>!1,newlyAddedElement:F=!1}=t;let{needsMask:x}=t,{preserveWhiteSpace:R=!0}=t;!x&&e.childNodes&&(x=Et(e,a,l,x===void 0));const j=Hr(e,{doc:r,mirror:n,blockClass:i,blockSelector:o,needsMask:x,inlineStylesheet:c,maskInputOptions:u,maskTextFn:f,maskInputFn:m,dataURLOptions:g,inlineImages:p,recordCanvas:y,keepIframeSrcFn:B,newlyAddedElement:F});if(!j)return console.warn(e,"not serialized"),null;let G;n.hasNode(e)?G=n.getId(e):Gr(j,h)||!R&&j.type===A.Text&&!j.isStyle&&!j.textContent.replace(/^\s+|\s+$/gm,"").length?G=Ie:G=Mt();const E=Object.assign(j,{id:G});if(n.add(e,E),G===Ie)return null;w&&w(e);let le=!s;if(E.type===A.Element){le=le&&!E.needBlock,delete E.needBlock;const z=e.shadowRoot;z&&we(z)&&(E.isShadowHost=!0)}if((E.type===A.Document||E.type===A.Element)&&le){h.headWhitespace&&E.type===A.Element&&E.tagName==="head"&&(R=!1);const z={doc:r,mirror:n,blockClass:i,blockSelector:o,needsMask:x,maskTextClass:a,maskTextSelector:l,skipChild:s,inlineStylesheet:c,maskInputOptions:u,maskTextFn:f,maskInputFn:m,slimDOMOptions:h,dataURLOptions:g,inlineImages:p,recordCanvas:y,preserveWhiteSpace:R,onSerialize:w,onIframeLoad:S,iframeLoadTimeout:v,onStylesheetLoad:b,stylesheetLoadTimeout:I,keepIframeSrcFn:B};if(!(E.type===A.Element&&E.tagName==="textarea"&&E.attributes.value!==void 0))for(const ne of Array.from(e.childNodes)){const Z=pe(ne,z);Z&&E.childNodes.push(Z)}if(Sr(e)&&e.shadowRoot)for(const ne of Array.from(e.shadowRoot.childNodes)){const Z=pe(ne,z);Z&&(we(e.shadowRoot)&&(Z.isShadow=!0),E.childNodes.push(Z))}}return e.parentNode&&be(e.parentNode)&&we(e.parentNode)&&(E.isShadow=!0),E.type===A.Element&&E.tagName==="iframe"&&Ur(e,()=>{const z=e.contentDocument;if(z&&S){const ne=pe(z,{doc:z,mirror:n,blockClass:i,blockSelector:o,needsMask:x,maskTextClass:a,maskTextSelector:l,skipChild:!1,inlineStylesheet:c,maskInputOptions:u,maskTextFn:f,maskInputFn:m,slimDOMOptions:h,dataURLOptions:g,inlineImages:p,recordCanvas:y,preserveWhiteSpace:R,onSerialize:w,onIframeLoad:S,iframeLoadTimeout:v,onStylesheetLoad:b,stylesheetLoadTimeout:I,keepIframeSrcFn:B});ne&&S(e,ne)}},v),E.type===A.Element&&E.tagName==="link"&&typeof E.attributes.rel=="string"&&(E.attributes.rel==="stylesheet"||E.attributes.rel==="preload"&&typeof E.attributes.href=="string"&&It(E.attributes.href)==="css")&&zr(e,()=>{if(b){const z=pe(e,{doc:r,mirror:n,blockClass:i,blockSelector:o,needsMask:x,maskTextClass:a,maskTextSelector:l,skipChild:!1,inlineStylesheet:c,maskInputOptions:u,maskTextFn:f,maskInputFn:m,slimDOMOptions:h,dataURLOptions:g,inlineImages:p,recordCanvas:y,preserveWhiteSpace:R,onSerialize:w,onIframeLoad:S,iframeLoadTimeout:v,onStylesheetLoad:b,stylesheetLoadTimeout:I,keepIframeSrcFn:B});z&&b(e,z)}},I),E}function Vr(e,t){const{mirror:r=new bt,blockClass:n="rr-block",blockSelector:i=null,maskTextClass:o="rr-mask",maskTextSelector:a=null,inlineStylesheet:l=!0,inlineImages:s=!1,recordCanvas:c=!1,maskAllInputs:u=!1,maskTextFn:f,maskInputFn:m,slimDOM:h=!1,dataURLOptions:g,preserveWhiteSpace:p,onSerialize:y,onIframeLoad:w,iframeLoadTimeout:S,onStylesheetLoad:v,stylesheetLoadTimeout:b,keepIframeSrcFn:I=()=>!1}=t||{};return pe(e,{doc:e,mirror:r,blockClass:n,blockSelector:i,maskTextClass:o,maskTextSelector:a,skipChild:!1,inlineStylesheet:l,maskInputOptions:u===!0?{color:!0,date:!0,"datetime-local":!0,email:!0,month:!0,number:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0,textarea:!0,select:!0,password:!0}:u===!1?{password:!0}:u,maskTextFn:f,maskInputFn:m,slimDOMOptions:h===!0||h==="all"?{script:!0,comment:!0,headFavicon:!0,headWhitespace:!0,headMetaDescKeywords:h==="all",headMetaSocial:!0,headMetaRobots:!0,headMetaHttpEquiv:!0,headMetaAuthorship:!0,headMetaVerification:!0}:h===!1?{}:h,dataURLOptions:g,inlineImages:s,recordCanvas:c,preserveWhiteSpace:p,onSerialize:y,onIframeLoad:w,iframeLoadTimeout:S,onStylesheetLoad:v,stylesheetLoadTimeout:b,keepIframeSrcFn:I,newlyAddedElement:!1})}function W(e,t,r=document){const n={capture:!0,passive:!0};return r.addEventListener(e,t,n),()=>r.removeEventListener(e,t,n)}const me=`Please stop import mirror directly. Instead of that,\r +(function(){"use strict";var A;(function(e){e[e.Document=0]="Document",e[e.DocumentType=1]="DocumentType",e[e.Element=2]="Element",e[e.Text=3]="Text",e[e.CDATA=4]="CDATA",e[e.Comment=5]="Comment"})(A||(A={}));function br(e){return e.nodeType===e.ELEMENT_NODE}function be(e){const t=e?.host;return t?.shadowRoot===e}function we(e){return Object.prototype.toString.call(e)==="[object ShadowRoot]"}function wr(e){return e.includes(" background-clip: text;")&&!e.includes(" -webkit-background-clip: text;")&&(e=e.replace(" background-clip: text;"," -webkit-background-clip: text; background-clip: text;")),e}function Mr(e){const{cssText:t}=e;if(t.split('"').length<3)return t;const r=["@import",`url(${JSON.stringify(e.href)})`];return e.layerName===""?r.push("layer"):e.layerName&&r.push(`layer(${e.layerName})`),e.supportsText&&r.push(`supports(${e.supportsText})`),e.media.length&&r.push(e.media.mediaText),r.join(" ")+";"}function Te(e){try{const t=e.rules||e.cssRules;return t?wr(Array.from(t,bt).join("")):null}catch{return null}}function bt(e){let t;if(Cr(e))try{t=Te(e.styleSheet)||Mr(e)}catch{}else if(_r(e)&&e.selectorText.includes(":"))return Ir(e.cssText);return t||e.cssText}function Ir(e){const t=/(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;return e.replace(t,"$1\\$2")}function Cr(e){return"styleSheet"in e}function _r(e){return"selectorText"in e}class wt{constructor(){this.idNodeMap=new Map,this.nodeMetaMap=new WeakMap}getId(t){var r;if(!t)return-1;const n=(r=this.getMeta(t))===null||r===void 0?void 0:r.id;return n??-1}getNode(t){return this.idNodeMap.get(t)||null}getIds(){return Array.from(this.idNodeMap.keys())}getMeta(t){return this.nodeMetaMap.get(t)||null}removeNodeFromMap(t){const r=this.getId(t);this.idNodeMap.delete(r),t.childNodes&&t.childNodes.forEach(n=>this.removeNodeFromMap(n))}has(t){return this.idNodeMap.has(t)}hasNode(t){return this.nodeMetaMap.has(t)}add(t,r){const n=r.id;this.idNodeMap.set(n,t),this.nodeMetaMap.set(t,r)}replace(t,r){const n=this.getNode(t);if(n){const i=this.nodeMetaMap.get(n);i&&this.nodeMetaMap.set(r,i)}this.idNodeMap.set(t,r)}reset(){this.idNodeMap=new Map,this.nodeMetaMap=new WeakMap}}function Or(){return new wt}function tt({element:e,maskInputOptions:t,tagName:r,type:n,value:i,maskInputFn:o}){let a=i||"";const l=n&&ie(n);return(t[r.toLowerCase()]||l&&t[l])&&(o?a=o(a,e):a="*".repeat(a.length)),a}function ie(e){return e.toLowerCase()}const Mt="__rrweb_original__";function Er(e){const t=e.getContext("2d");if(!t)return!0;const r=50;for(let n=0;ns!==0))return!1}return!0}function rt(e){const t=e.type;return e.hasAttribute("data-rr-is-password")?"password":t?ie(t):null}function It(e,t){var r;let n;try{n=new URL(e,t??window.location.href)}catch{return null}const i=/\.([0-9a-z]+)(?:$)/i,o=n.pathname.match(i);return(r=o?.[1])!==null&&r!==void 0?r:null}let kr=1;const xr=new RegExp("[^a-z0-9-_:]"),Me=-2;function Ct(){return kr++}function Rr(e){if(e instanceof HTMLFormElement)return"form";const t=ie(e.tagName);return xr.test(t)?"div":t}function Tr(e){let t="";return e.indexOf("//")>-1?t=e.split("/").slice(0,3).join("/"):t=e.split("/")[0],t=t.split("?")[0],t}let he,_t;const Dr=/url\((?:(')([^']*)'|(")(.*?)"|([^)]*))\)/gm,Nr=/^(?:[a-z+]+:)?\/\//i,Ar=/^www\..*/i,Lr=/^(data:)([^,]*),(.*)/i;function De(e,t){return(e||"").replace(Dr,(r,n,i,o,a,l)=>{const s=i||a||l,c=n||o||"";if(!s)return r;if(Nr.test(s)||Ar.test(s))return`url(${c}${s}${c})`;if(Lr.test(s))return`url(${c}${s}${c})`;if(s[0]==="/")return`url(${c}${Tr(t)+s}${c})`;const u=t.split("/"),h=s.split("/");u.pop();for(const m of h)m!=="."&&(m===".."?u.pop():u.push(m));return`url(${c}${u.join("/")}${c})`})}const Fr=/^[^ \t\n\r\u000c]+/,Pr=/^[, \t\n\r\u000c]+/;function Br(e,t){if(t.trim()==="")return t;let r=0;function n(o){let a;const l=o.exec(t.substring(r));return l?(a=l[0],r+=a.length,a):""}const i=[];for(;n(Pr),!(r>=t.length);){let o=n(Fr);if(o.slice(-1)===",")o=pe(e,o.substring(0,o.length-1)),i.push(o);else{let a="";o=pe(e,o);let l=!1;for(;;){const s=t.charAt(r);if(s===""){i.push((o+a).trim());break}else if(l)s===")"&&(l=!1);else if(s===","){r+=1,i.push((o+a).trim());break}else s==="("&&(l=!0);a+=s,r+=1}}}return i.join(", ")}function pe(e,t){if(!t||t.trim()==="")return t;const r=e.createElement("a");return r.href=t,r.href}function Wr(e){return!!(e.tagName==="svg"||e.ownerSVGElement)}function nt(){const e=document.createElement("a");return e.href="",e.href}function Ot(e,t,r,n){return n&&(r==="src"||r==="href"&&!(t==="use"&&n[0]==="#")||r==="xlink:href"&&n[0]!=="#"||r==="background"&&(t==="table"||t==="td"||t==="th")?pe(e,n):r==="srcset"?Br(e,n):r==="style"?De(n,nt()):t==="object"&&r==="data"?pe(e,n):n)}function Et(e,t,r){return(e==="video"||e==="audio")&&t==="autoplay"}function Ur(e,t,r){try{if(typeof t=="string"){if(e.classList.contains(t))return!0}else for(let n=e.classList.length;n--;){const i=e.classList[n];if(t.test(i))return!0}if(r)return e.matches(r)}catch{}return!1}function Ne(e,t,r){if(!e)return!1;if(e.nodeType!==e.ELEMENT_NODE)return r?Ne(e.parentNode,t,r):!1;for(let n=e.classList.length;n--;){const i=e.classList[n];if(t.test(i))return!0}return r?Ne(e.parentNode,t,r):!1}function kt(e,t,r,n){try{const i=e.nodeType===e.ELEMENT_NODE?e:e.parentElement;if(i===null)return!1;if(typeof t=="string"){if(n){if(i.closest(`.${t}`))return!0}else if(i.classList.contains(t))return!0}else if(Ne(i,t,n))return!0;if(r){if(n){if(i.closest(r))return!0}else if(i.matches(r))return!0}}catch{}return!1}function zr(e,t,r){const n=e.contentWindow;if(!n)return;let i=!1,o;try{o=n.document.readyState}catch{return}if(o!=="complete"){const l=setTimeout(()=>{i||(t(),i=!0)},r);e.addEventListener("load",()=>{clearTimeout(l),i=!0,t()});return}const a="about:blank";if(n.location.href!==a||e.src===a||e.src==="")return setTimeout(t,0),e.addEventListener("load",t);e.addEventListener("load",t)}function Hr(e,t,r){let n=!1,i;try{i=e.sheet}catch{return}if(i)return;const o=setTimeout(()=>{n||(t(),n=!0)},r);e.addEventListener("load",()=>{clearTimeout(o),n=!0,t()})}function $r(e,t){const{doc:r,mirror:n,blockClass:i,blockSelector:o,needsMask:a,inlineStylesheet:l,maskInputOptions:s={},maskTextFn:c,maskInputFn:u,dataURLOptions:h={},inlineImages:m,recordCanvas:f,keepIframeSrcFn:g,newlyAddedElement:p=!1}=t,y=qr(r,n);switch(e.nodeType){case e.DOCUMENT_NODE:return e.compatMode!=="CSS1Compat"?{type:A.Document,childNodes:[],compatMode:e.compatMode}:{type:A.Document,childNodes:[]};case e.DOCUMENT_TYPE_NODE:return{type:A.DocumentType,name:e.name,publicId:e.publicId,systemId:e.systemId,rootId:y};case e.ELEMENT_NODE:return Gr(e,{doc:r,blockClass:i,blockSelector:o,inlineStylesheet:l,maskInputOptions:s,maskInputFn:u,dataURLOptions:h,inlineImages:m,recordCanvas:f,keepIframeSrcFn:g,newlyAddedElement:p,rootId:y});case e.TEXT_NODE:return jr(e,{needsMask:a,maskTextFn:c,rootId:y});case e.CDATA_SECTION_NODE:return{type:A.CDATA,textContent:"",rootId:y};case e.COMMENT_NODE:return{type:A.Comment,textContent:e.textContent||"",rootId:y};default:return!1}}function qr(e,t){if(!t.hasNode(e))return;const r=t.getId(e);return r===1?void 0:r}function jr(e,t){var r;const{needsMask:n,maskTextFn:i,rootId:o}=t,a=e.parentNode&&e.parentNode.tagName;let l=e.textContent;const s=a==="STYLE"?!0:void 0,c=a==="SCRIPT"?!0:void 0;if(s&&l){try{e.nextSibling||e.previousSibling||!((r=e.parentNode.sheet)===null||r===void 0)&&r.cssRules&&(l=Te(e.parentNode.sheet))}catch(u){console.warn(`Cannot get CSS styles from text's parentNode. Error: ${u}`,e)}l=De(l,nt())}return c&&(l="SCRIPT_PLACEHOLDER"),!s&&!c&&l&&n&&(l=i?i(l,e.parentElement):l.replace(/[\S]/g,"*")),{type:A.Text,textContent:l||"",isStyle:s,rootId:o}}function Gr(e,t){const{doc:r,blockClass:n,blockSelector:i,inlineStylesheet:o,maskInputOptions:a={},maskInputFn:l,dataURLOptions:s={},inlineImages:c,recordCanvas:u,keepIframeSrcFn:h,newlyAddedElement:m=!1,rootId:f}=t,g=Ur(e,n,i),p=Rr(e);let y={};const w=e.attributes.length;for(let v=0;vM.href===e.href);let b=null;v&&(b=Te(v)),b&&(delete y.rel,delete y.href,y._cssText=De(b,v.href))}if(p==="style"&&e.sheet&&!(e.innerText||e.textContent||"").trim().length){const v=Te(e.sheet);v&&(y._cssText=De(v,nt()))}if(p==="input"||p==="textarea"||p==="select"){const v=e.value,b=e.checked;y.type!=="radio"&&y.type!=="checkbox"&&y.type!=="submit"&&y.type!=="button"&&v?y.value=tt({element:e,type:rt(e),tagName:p,value:v,maskInputOptions:a,maskInputFn:l}):b&&(y.checked=b)}if(p==="option"&&(e.selected&&!a.select?y.selected=!0:delete y.selected),p==="canvas"&&u){if(e.__context==="2d")Er(e)||(y.rr_dataURL=e.toDataURL(s.type,s.quality));else if(!("__context"in e)){const v=e.toDataURL(s.type,s.quality),b=document.createElement("canvas");b.width=e.width,b.height=e.height;const M=b.toDataURL(s.type,s.quality);v!==M&&(y.rr_dataURL=v)}}if(p==="img"&&c){he||(he=r.createElement("canvas"),_t=he.getContext("2d"));const v=e,b=v.crossOrigin;v.crossOrigin="anonymous";const M=()=>{v.removeEventListener("load",M);try{he.width=v.naturalWidth,he.height=v.naturalHeight,_t.drawImage(v,0,0),y.rr_dataURL=he.toDataURL(s.type,s.quality)}catch(B){console.warn(`Cannot inline img src=${v.currentSrc}! Error: ${B}`)}b?y.crossOrigin=b:v.removeAttribute("crossorigin")};v.complete&&v.naturalWidth!==0?M():v.addEventListener("load",M)}if(p==="audio"||p==="video"){const v=y;v.rr_mediaState=e.paused?"paused":"played",v.rr_mediaCurrentTime=e.currentTime,v.rr_mediaPlaybackRate=e.playbackRate,v.rr_mediaMuted=e.muted,v.rr_mediaLoop=e.loop,v.rr_mediaVolume=e.volume}if(m||(e.scrollLeft&&(y.rr_scrollLeft=e.scrollLeft),e.scrollTop&&(y.rr_scrollTop=e.scrollTop)),g){const{width:v,height:b}=e.getBoundingClientRect();y={class:y.class,rr_width:`${v}px`,rr_height:`${b}px`}}p==="iframe"&&!h(y.src)&&(e.contentDocument||(y.rr_src=y.src),delete y.src);let S;try{customElements.get(p)&&(S=!0)}catch{}return{type:A.Element,tagName:p,attributes:y,childNodes:[],isSVG:Wr(e)||void 0,needBlock:g,rootId:f,isCustom:S}}function k(e){return e==null?"":e.toLowerCase()}function Vr(e,t){if(t.comment&&e.type===A.Comment)return!0;if(e.type===A.Element){if(t.script&&(e.tagName==="script"||e.tagName==="link"&&(e.attributes.rel==="preload"||e.attributes.rel==="modulepreload")&&e.attributes.as==="script"||e.tagName==="link"&&e.attributes.rel==="prefetch"&&typeof e.attributes.href=="string"&&It(e.attributes.href)==="js"))return!0;if(t.headFavicon&&(e.tagName==="link"&&e.attributes.rel==="shortcut icon"||e.tagName==="meta"&&(k(e.attributes.name).match(/^msapplication-tile(image|color)$/)||k(e.attributes.name)==="application-name"||k(e.attributes.rel)==="icon"||k(e.attributes.rel)==="apple-touch-icon"||k(e.attributes.rel)==="shortcut icon")))return!0;if(e.tagName==="meta"){if(t.headMetaDescKeywords&&k(e.attributes.name).match(/^description|keywords$/))return!0;if(t.headMetaSocial&&(k(e.attributes.property).match(/^(og|twitter|fb):/)||k(e.attributes.name).match(/^(og|twitter):/)||k(e.attributes.name)==="pinterest"))return!0;if(t.headMetaRobots&&(k(e.attributes.name)==="robots"||k(e.attributes.name)==="googlebot"||k(e.attributes.name)==="bingbot"))return!0;if(t.headMetaHttpEquiv&&e.attributes["http-equiv"]!==void 0)return!0;if(t.headMetaAuthorship&&(k(e.attributes.name)==="author"||k(e.attributes.name)==="generator"||k(e.attributes.name)==="framework"||k(e.attributes.name)==="publisher"||k(e.attributes.name)==="progid"||k(e.attributes.property).match(/^article:/)||k(e.attributes.property).match(/^product:/)))return!0;if(t.headMetaVerification&&(k(e.attributes.name)==="google-site-verification"||k(e.attributes.name)==="yandex-verification"||k(e.attributes.name)==="csrf-token"||k(e.attributes.name)==="p:domain_verify"||k(e.attributes.name)==="verify-v1"||k(e.attributes.name)==="verification"||k(e.attributes.name)==="shopify-checkout-api-token"))return!0}}return!1}function me(e,t){const{doc:r,mirror:n,blockClass:i,blockSelector:o,maskTextClass:a,maskTextSelector:l,skipChild:s=!1,inlineStylesheet:c=!0,maskInputOptions:u={},maskTextFn:h,maskInputFn:m,slimDOMOptions:f,dataURLOptions:g={},inlineImages:p=!1,recordCanvas:y=!1,onSerialize:w,onIframeLoad:S,iframeLoadTimeout:v=5e3,onStylesheetLoad:b,stylesheetLoadTimeout:M=5e3,keepIframeSrcFn:B=()=>!1,newlyAddedElement:P=!1}=t;let{needsMask:x}=t,{preserveWhiteSpace:R=!0}=t;!x&&e.childNodes&&(x=kt(e,a,l,x===void 0));const j=$r(e,{doc:r,mirror:n,blockClass:i,blockSelector:o,needsMask:x,inlineStylesheet:c,maskInputOptions:u,maskTextFn:h,maskInputFn:m,dataURLOptions:g,inlineImages:p,recordCanvas:y,keepIframeSrcFn:B,newlyAddedElement:P});if(!j)return console.warn(e,"not serialized"),null;let G;n.hasNode(e)?G=n.getId(e):Vr(j,f)||!R&&j.type===A.Text&&!j.isStyle&&!j.textContent.replace(/^\s+|\s+$/gm,"").length?G=Me:G=Ct();const E=Object.assign(j,{id:G});if(n.add(e,E),G===Me)return null;w&&w(e);let ue=!s;if(E.type===A.Element){ue=ue&&!E.needBlock,delete E.needBlock;const z=e.shadowRoot;z&&we(z)&&(E.isShadowHost=!0)}if((E.type===A.Document||E.type===A.Element)&&ue){f.headWhitespace&&E.type===A.Element&&E.tagName==="head"&&(R=!1);const z={doc:r,mirror:n,blockClass:i,blockSelector:o,needsMask:x,maskTextClass:a,maskTextSelector:l,skipChild:s,inlineStylesheet:c,maskInputOptions:u,maskTextFn:h,maskInputFn:m,slimDOMOptions:f,dataURLOptions:g,inlineImages:p,recordCanvas:y,preserveWhiteSpace:R,onSerialize:w,onIframeLoad:S,iframeLoadTimeout:v,onStylesheetLoad:b,stylesheetLoadTimeout:M,keepIframeSrcFn:B};if(!(E.type===A.Element&&E.tagName==="textarea"&&E.attributes.value!==void 0))for(const ne of Array.from(e.childNodes)){const Z=me(ne,z);Z&&E.childNodes.push(Z)}if(br(e)&&e.shadowRoot)for(const ne of Array.from(e.shadowRoot.childNodes)){const Z=me(ne,z);Z&&(we(e.shadowRoot)&&(Z.isShadow=!0),E.childNodes.push(Z))}}return e.parentNode&&be(e.parentNode)&&we(e.parentNode)&&(E.isShadow=!0),E.type===A.Element&&E.tagName==="iframe"&&zr(e,()=>{const z=e.contentDocument;if(z&&S){const ne=me(z,{doc:z,mirror:n,blockClass:i,blockSelector:o,needsMask:x,maskTextClass:a,maskTextSelector:l,skipChild:!1,inlineStylesheet:c,maskInputOptions:u,maskTextFn:h,maskInputFn:m,slimDOMOptions:f,dataURLOptions:g,inlineImages:p,recordCanvas:y,preserveWhiteSpace:R,onSerialize:w,onIframeLoad:S,iframeLoadTimeout:v,onStylesheetLoad:b,stylesheetLoadTimeout:M,keepIframeSrcFn:B});ne&&S(e,ne)}},v),E.type===A.Element&&E.tagName==="link"&&typeof E.attributes.rel=="string"&&(E.attributes.rel==="stylesheet"||E.attributes.rel==="preload"&&typeof E.attributes.href=="string"&&It(E.attributes.href)==="css")&&Hr(e,()=>{if(b){const z=me(e,{doc:r,mirror:n,blockClass:i,blockSelector:o,needsMask:x,maskTextClass:a,maskTextSelector:l,skipChild:!1,inlineStylesheet:c,maskInputOptions:u,maskTextFn:h,maskInputFn:m,slimDOMOptions:f,dataURLOptions:g,inlineImages:p,recordCanvas:y,preserveWhiteSpace:R,onSerialize:w,onIframeLoad:S,iframeLoadTimeout:v,onStylesheetLoad:b,stylesheetLoadTimeout:M,keepIframeSrcFn:B});z&&b(e,z)}},M),E}function Jr(e,t){const{mirror:r=new wt,blockClass:n="rr-block",blockSelector:i=null,maskTextClass:o="rr-mask",maskTextSelector:a=null,inlineStylesheet:l=!0,inlineImages:s=!1,recordCanvas:c=!1,maskAllInputs:u=!1,maskTextFn:h,maskInputFn:m,slimDOM:f=!1,dataURLOptions:g,preserveWhiteSpace:p,onSerialize:y,onIframeLoad:w,iframeLoadTimeout:S,onStylesheetLoad:v,stylesheetLoadTimeout:b,keepIframeSrcFn:M=()=>!1}=t||{};return me(e,{doc:e,mirror:r,blockClass:n,blockSelector:i,maskTextClass:o,maskTextSelector:a,skipChild:!1,inlineStylesheet:l,maskInputOptions:u===!0?{color:!0,date:!0,"datetime-local":!0,email:!0,month:!0,number:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0,textarea:!0,select:!0,password:!0}:u===!1?{password:!0}:u,maskTextFn:h,maskInputFn:m,slimDOMOptions:f===!0||f==="all"?{script:!0,comment:!0,headFavicon:!0,headWhitespace:!0,headMetaDescKeywords:f==="all",headMetaSocial:!0,headMetaRobots:!0,headMetaHttpEquiv:!0,headMetaAuthorship:!0,headMetaVerification:!0}:f===!1?{}:f,dataURLOptions:g,inlineImages:s,recordCanvas:c,preserveWhiteSpace:p,onSerialize:y,onIframeLoad:w,iframeLoadTimeout:S,onStylesheetLoad:v,stylesheetLoadTimeout:b,keepIframeSrcFn:M,newlyAddedElement:!1})}function W(e,t,r=document){const n={capture:!0,passive:!0};return r.addEventListener(e,t,n),()=>r.removeEventListener(e,t,n)}const ge=`Please stop import mirror directly. Instead of that,\r now you can use replayer.getMirror() to access the mirror instance of a replayer,\r -or you can use record.mirror to access the mirror instance during recording.`;let kt={map:{},getId(){return console.error(me),-1},getNode(){return console.error(me),null},removeNodeFromMap(){console.error(me)},has(){return console.error(me),!1},reset(){console.error(me)}};typeof window<"u"&&window.Proxy&&window.Reflect&&(kt=new Proxy(kt,{get(e,t,r){return t==="map"&&console.error(me),Reflect.get(e,t,r)}}));function Me(e,t,r={}){let n=null,i=0;return function(...o){const a=Date.now();!i&&r.leading===!1&&(i=a);const l=t-(a-i),s=this;l<=0||l>t?(n&&(clearTimeout(n),n=null),i=a,e.apply(s,o)):!n&&r.trailing!==!1&&(n=setTimeout(()=>{i=r.leading===!1?0:Date.now(),n=null,e.apply(s,o)},l))}}function Ae(e,t,r,n,i=window){const o=i.Object.getOwnPropertyDescriptor(e,t);return i.Object.defineProperty(e,t,n?r:{set(a){setTimeout(()=>{r.set.call(this,a)},0),o&&o.set&&o.set.call(this,a)}}),()=>Ae(e,t,o||{},!0)}function ge(e,t,r){try{if(!(t in e))return()=>{};const n=e[t],i=r(n);return typeof i=="function"&&(i.prototype=i.prototype||{},Object.defineProperties(i,{__rrweb_original__:{enumerable:!1,value:n}})),e[t]=i,()=>{e[t]=n}}catch{return()=>{}}}let Le=Date.now;/[1-9][0-9]{12}/.test(Date.now().toString())||(Le=()=>new Date().getTime());function xt(e){var t,r,n,i,o,a;const l=e.document;return{left:l.scrollingElement?l.scrollingElement.scrollLeft:e.pageXOffset!==void 0?e.pageXOffset:l?.documentElement.scrollLeft||((r=(t=l?.body)===null||t===void 0?void 0:t.parentElement)===null||r===void 0?void 0:r.scrollLeft)||((n=l?.body)===null||n===void 0?void 0:n.scrollLeft)||0,top:l.scrollingElement?l.scrollingElement.scrollTop:e.pageYOffset!==void 0?e.pageYOffset:l?.documentElement.scrollTop||((o=(i=l?.body)===null||i===void 0?void 0:i.parentElement)===null||o===void 0?void 0:o.scrollTop)||((a=l?.body)===null||a===void 0?void 0:a.scrollTop)||0}}function Rt(){return window.innerHeight||document.documentElement&&document.documentElement.clientHeight||document.body&&document.body.clientHeight}function Tt(){return window.innerWidth||document.documentElement&&document.documentElement.clientWidth||document.body&&document.body.clientWidth}function Dt(e){return e?e.nodeType===e.ELEMENT_NODE?e:e.parentElement:null}function U(e,t,r,n){if(!e)return!1;const i=Dt(e);if(!i)return!1;try{if(typeof t=="string"){if(i.classList.contains(t)||n&&i.closest("."+t)!==null)return!0}else if(Ne(i,t,n))return!0}catch{}return!!(r&&(i.matches(r)||n&&i.closest(r)!==null))}function Jr(e,t){return t.getId(e)!==-1}function it(e,t){return t.getId(e)===Ie}function Nt(e,t){if(be(e))return!1;const r=t.getId(e);return t.has(r)?e.parentNode&&e.parentNode.nodeType===e.DOCUMENT_NODE?!1:e.parentNode?Nt(e.parentNode,t):!0:!0}function ot(e){return!!e.changedTouches}function Xr(e=window){"NodeList"in e&&!e.NodeList.prototype.forEach&&(e.NodeList.prototype.forEach=Array.prototype.forEach),"DOMTokenList"in e&&!e.DOMTokenList.prototype.forEach&&(e.DOMTokenList.prototype.forEach=Array.prototype.forEach),Node.prototype.contains||(Node.prototype.contains=(...t)=>{let r=t[0];if(!(0 in t))throw new TypeError("1 argument is required");do if(this===r)return!0;while(r=r&&r.parentNode);return!1})}function At(e,t){return!!(e.nodeName==="IFRAME"&&t.getMeta(e))}function Lt(e,t){return!!(e.nodeName==="LINK"&&e.nodeType===e.ELEMENT_NODE&&e.getAttribute&&e.getAttribute("rel")==="stylesheet"&&t.getMeta(e))}function st(e){return!!e?.shadowRoot}class Kr{constructor(){this.id=1,this.styleIDMap=new WeakMap,this.idStyleMap=new Map}getId(t){var r;return(r=this.styleIDMap.get(t))!==null&&r!==void 0?r:-1}has(t){return this.styleIDMap.has(t)}add(t,r){if(this.has(t))return this.getId(t);let n;return r===void 0?n=this.id++:n=r,this.styleIDMap.set(t,n),this.idStyleMap.set(n,t),n}getStyle(t){return this.idStyleMap.get(t)||null}reset(){this.styleIDMap=new WeakMap,this.idStyleMap=new Map,this.id=1}generateId(){return this.id++}}function Ft(e){var t,r;let n=null;return((r=(t=e.getRootNode)===null||t===void 0?void 0:t.call(e))===null||r===void 0?void 0:r.nodeType)===Node.DOCUMENT_FRAGMENT_NODE&&e.getRootNode().host&&(n=e.getRootNode().host),n}function Yr(e){let t=e,r;for(;r=Ft(t);)t=r;return t}function Qr(e){const t=e.ownerDocument;if(!t)return!1;const r=Yr(e);return t.contains(r)}function Pt(e){const t=e.ownerDocument;return t?t.contains(e)||Qr(e):!1}var O=(e=>(e[e.DomContentLoaded=0]="DomContentLoaded",e[e.Load=1]="Load",e[e.FullSnapshot=2]="FullSnapshot",e[e.IncrementalSnapshot=3]="IncrementalSnapshot",e[e.Meta=4]="Meta",e[e.Custom=5]="Custom",e[e.Plugin=6]="Plugin",e))(O||{}),C=(e=>(e[e.Mutation=0]="Mutation",e[e.MouseMove=1]="MouseMove",e[e.MouseInteraction=2]="MouseInteraction",e[e.Scroll=3]="Scroll",e[e.ViewportResize=4]="ViewportResize",e[e.Input=5]="Input",e[e.TouchMove=6]="TouchMove",e[e.MediaInteraction=7]="MediaInteraction",e[e.StyleSheetRule=8]="StyleSheetRule",e[e.CanvasMutation=9]="CanvasMutation",e[e.Font=10]="Font",e[e.Log=11]="Log",e[e.Drag=12]="Drag",e[e.StyleDeclaration=13]="StyleDeclaration",e[e.Selection=14]="Selection",e[e.AdoptedStyleSheet=15]="AdoptedStyleSheet",e[e.CustomElement=16]="CustomElement",e))(C||{}),$=(e=>(e[e.MouseUp=0]="MouseUp",e[e.MouseDown=1]="MouseDown",e[e.Click=2]="Click",e[e.ContextMenu=3]="ContextMenu",e[e.DblClick=4]="DblClick",e[e.Focus=5]="Focus",e[e.Blur=6]="Blur",e[e.TouchStart=7]="TouchStart",e[e.TouchMove_Departed=8]="TouchMove_Departed",e[e.TouchEnd=9]="TouchEnd",e[e.TouchCancel=10]="TouchCancel",e))($||{}),ee=(e=>(e[e.Mouse=0]="Mouse",e[e.Pen=1]="Pen",e[e.Touch=2]="Touch",e))(ee||{}),ye=(e=>(e[e["2D"]=0]="2D",e[e.WebGL=1]="WebGL",e[e.WebGL2=2]="WebGL2",e))(ye||{});function Bt(e){return"__ln"in e}class Zr{constructor(){this.length=0,this.head=null,this.tail=null}get(t){if(t>=this.length)throw new Error("Position outside of list range");let r=this.head;for(let n=0;n`${e}@${t}`;class en{constructor(){this.frozen=!1,this.locked=!1,this.texts=[],this.attributes=[],this.attributeMap=new WeakMap,this.removes=[],this.mapRemoves=[],this.movedMap={},this.addedSet=new Set,this.movedSet=new Set,this.droppedSet=new Set,this.processMutations=t=>{t.forEach(this.processMutation),this.emit()},this.emit=()=>{if(this.frozen||this.locked)return;const t=[],r=new Set,n=new Zr,i=s=>{let c=s,u=Ie;for(;u===Ie;)c=c&&c.nextSibling,u=c&&this.mirror.getId(c);return u},o=s=>{if(!s.parentNode||!Pt(s)||s.parentNode.tagName==="TEXTAREA")return;const c=be(s.parentNode)?this.mirror.getId(Ft(s)):this.mirror.getId(s.parentNode),u=i(s);if(c===-1||u===-1)return n.addNode(s);const f=pe(s,{doc:this.doc,mirror:this.mirror,blockClass:this.blockClass,blockSelector:this.blockSelector,maskTextClass:this.maskTextClass,maskTextSelector:this.maskTextSelector,skipChild:!0,newlyAddedElement:!0,inlineStylesheet:this.inlineStylesheet,maskInputOptions:this.maskInputOptions,maskTextFn:this.maskTextFn,maskInputFn:this.maskInputFn,slimDOMOptions:this.slimDOMOptions,dataURLOptions:this.dataURLOptions,recordCanvas:this.recordCanvas,inlineImages:this.inlineImages,onSerialize:m=>{At(m,this.mirror)&&this.iframeManager.addIframe(m),Lt(m,this.mirror)&&this.stylesheetManager.trackLinkElement(m),st(s)&&this.shadowDomManager.addShadowRoot(s.shadowRoot,this.doc)},onIframeLoad:(m,h)=>{this.iframeManager.attachIframe(m,h),this.shadowDomManager.observeAttachShadow(m)},onStylesheetLoad:(m,h)=>{this.stylesheetManager.attachLinkElement(m,h)}});f&&(t.push({parentId:c,nextId:u,node:f}),r.add(f.id))};for(;this.mapRemoves.length;)this.mirror.removeNodeFromMap(this.mapRemoves.shift());for(const s of this.movedSet)Ut(this.removes,s,this.mirror)&&!this.movedSet.has(s.parentNode)||o(s);for(const s of this.addedSet)!Ht(this.droppedSet,s)&&!Ut(this.removes,s,this.mirror)||Ht(this.movedSet,s)?o(s):this.droppedSet.add(s);let a=null;for(;n.length;){let s=null;if(a){const c=this.mirror.getId(a.value.parentNode),u=i(a.value);c!==-1&&u!==-1&&(s=a)}if(!s){let c=n.tail;for(;c;){const u=c;if(c=c.previous,u){const f=this.mirror.getId(u.value.parentNode);if(i(u.value)===-1)continue;if(f!==-1){s=u;break}else{const h=u.value;if(h.parentNode&&h.parentNode.nodeType===Node.DOCUMENT_FRAGMENT_NODE){const g=h.parentNode.host;if(this.mirror.getId(g)!==-1){s=u;break}}}}}}if(!s){for(;n.head;)n.removeNode(n.head.value);break}a=s.previous,n.removeNode(s.value),o(s.value)}const l={texts:this.texts.map(s=>{const c=s.node;return c.parentNode&&c.parentNode.tagName==="TEXTAREA"&&this.genTextAreaValueMutation(c.parentNode),{id:this.mirror.getId(c),value:s.value}}).filter(s=>!r.has(s.id)).filter(s=>this.mirror.has(s.id)),attributes:this.attributes.map(s=>{const{attributes:c}=s;if(typeof c.style=="string"){const u=JSON.stringify(s.styleDiff),f=JSON.stringify(s._unchangedStyles);u.length!r.has(s.id)).filter(s=>this.mirror.has(s.id)),removes:this.removes,adds:t};!l.texts.length&&!l.attributes.length&&!l.removes.length&&!l.adds.length||(this.texts=[],this.attributes=[],this.attributeMap=new WeakMap,this.removes=[],this.addedSet=new Set,this.movedSet=new Set,this.droppedSet=new Set,this.movedMap={},this.mutationCb(l))},this.genTextAreaValueMutation=t=>{let r=this.attributeMap.get(t);r||(r={node:t,attributes:{},styleDiff:{},_unchangedStyles:{}},this.attributes.push(r),this.attributeMap.set(t,r)),r.attributes.value=Array.from(t.childNodes,n=>n.textContent||"").join("")},this.processMutation=t=>{if(!it(t.target,this.mirror))switch(t.type){case"characterData":{const r=t.target.textContent;!U(t.target,this.blockClass,this.blockSelector,!1)&&r!==t.oldValue&&this.texts.push({value:Et(t.target,this.maskTextClass,this.maskTextSelector,!0)&&r?this.maskTextFn?this.maskTextFn(r,Dt(t.target)):r.replace(/[\S]/g,"*"):r,node:t.target});break}case"attributes":{const r=t.target;let n=t.attributeName,i=t.target.getAttribute(n);if(n==="value"){const a=rt(r);i=tt({element:r,maskInputOptions:this.maskInputOptions,tagName:r.tagName,type:a,value:i,maskInputFn:this.maskInputFn})}if(U(t.target,this.blockClass,this.blockSelector,!1)||i===t.oldValue)return;let o=this.attributeMap.get(t.target);if(r.tagName==="IFRAME"&&n==="src"&&!this.keepIframeSrcFn(i))if(!r.contentDocument)n="rr_src";else return;if(o||(o={node:t.target,attributes:{},styleDiff:{},_unchangedStyles:{}},this.attributes.push(o),this.attributeMap.set(t.target,o)),n==="type"&&r.tagName==="INPUT"&&(t.oldValue||"").toLowerCase()==="password"&&r.setAttribute("data-rr-is-password","true"),!Ot(r.tagName,n)&&(o.attributes[n]=_t(this.doc,ie(r.tagName),ie(n),i),n==="style")){if(!this.unattachedDoc)try{this.unattachedDoc=document.implementation.createHTMLDocument()}catch{this.unattachedDoc=this.doc}const a=this.unattachedDoc.createElement("span");t.oldValue&&a.setAttribute("style",t.oldValue);for(const l of Array.from(r.style)){const s=r.style.getPropertyValue(l),c=r.style.getPropertyPriority(l);s!==a.style.getPropertyValue(l)||c!==a.style.getPropertyPriority(l)?c===""?o.styleDiff[l]=s:o.styleDiff[l]=[s,c]:o._unchangedStyles[l]=[s,c]}for(const l of Array.from(a.style))r.style.getPropertyValue(l)===""&&(o.styleDiff[l]=!1)}break}case"childList":{if(U(t.target,this.blockClass,this.blockSelector,!0))return;if(t.target.tagName==="TEXTAREA"){this.genTextAreaValueMutation(t.target);return}t.addedNodes.forEach(r=>this.genAdds(r,t.target)),t.removedNodes.forEach(r=>{const n=this.mirror.getId(r),i=be(t.target)?this.mirror.getId(t.target.host):this.mirror.getId(t.target);U(t.target,this.blockClass,this.blockSelector,!1)||it(r,this.mirror)||!Jr(r,this.mirror)||(this.addedSet.has(r)?(at(this.addedSet,r),this.droppedSet.add(r)):this.addedSet.has(t.target)&&n===-1||Nt(t.target,this.mirror)||(this.movedSet.has(r)&&this.movedMap[Wt(n,i)]?at(this.movedSet,r):this.removes.push({parentId:i,id:n,isShadow:be(t.target)&&we(t.target)?!0:void 0})),this.mapRemoves.push(r))});break}}},this.genAdds=(t,r)=>{if(!this.processedNodeManager.inOtherBuffer(t,this)&&!(this.addedSet.has(t)||this.movedSet.has(t))){if(this.mirror.hasNode(t)){if(it(t,this.mirror))return;this.movedSet.add(t);let n=null;r&&this.mirror.hasNode(r)&&(n=this.mirror.getId(r)),n&&n!==-1&&(this.movedMap[Wt(this.mirror.getId(t),n)]=!0)}else this.addedSet.add(t),this.droppedSet.delete(t);U(t,this.blockClass,this.blockSelector,!1)||(t.childNodes.forEach(n=>this.genAdds(n)),st(t)&&t.shadowRoot.childNodes.forEach(n=>{this.processedNodeManager.add(n,this),this.genAdds(n,t)}))}}}init(t){["mutationCb","blockClass","blockSelector","maskTextClass","maskTextSelector","inlineStylesheet","maskInputOptions","maskTextFn","maskInputFn","keepIframeSrcFn","recordCanvas","inlineImages","slimDOMOptions","dataURLOptions","doc","mirror","iframeManager","stylesheetManager","shadowDomManager","canvasManager","processedNodeManager"].forEach(r=>{this[r]=t[r]})}freeze(){this.frozen=!0,this.canvasManager.freeze()}unfreeze(){this.frozen=!1,this.canvasManager.unfreeze(),this.emit()}isFrozen(){return this.frozen}lock(){this.locked=!0,this.canvasManager.lock()}unlock(){this.locked=!1,this.canvasManager.unlock(),this.emit()}reset(){this.shadowDomManager.reset(),this.canvasManager.reset()}}function at(e,t){e.delete(t),t.childNodes.forEach(r=>at(e,r))}function Ut(e,t,r){return e.length===0?!1:zt(e,t,r)}function zt(e,t,r){const{parentNode:n}=t;if(!n)return!1;const i=r.getId(n);return e.some(o=>o.id===i)?!0:zt(e,n,r)}function Ht(e,t){return e.size===0?!1:$t(e,t)}function $t(e,t){const{parentNode:r}=t;return r?e.has(r)?!0:$t(e,r):!1}let Ce;function tn(e){Ce=e}function rn(){Ce=void 0}const _=e=>Ce?(...r)=>{try{return e(...r)}catch(n){if(Ce&&Ce(n)===!0)return;throw n}}:e,oe=[];function _e(e){try{if("composedPath"in e){const t=e.composedPath();if(t.length)return t[0]}else if("path"in e&&e.path.length)return e.path[0]}catch{}return e&&e.target}function qt(e,t){var r,n;const i=new en;oe.push(i),i.init(e);let o=window.MutationObserver||window.__rrMutationObserver;const a=(n=(r=window?.Zone)===null||r===void 0?void 0:r.__symbol__)===null||n===void 0?void 0:n.call(r,"MutationObserver");a&&window[a]&&(o=window[a]);const l=new o(_(i.processMutations.bind(i)));return l.observe(t,{attributes:!0,attributeOldValue:!0,characterData:!0,characterDataOldValue:!0,childList:!0,subtree:!0}),l}function nn({mousemoveCb:e,sampling:t,doc:r,mirror:n}){if(t.mousemove===!1)return()=>{};const i=typeof t.mousemove=="number"?t.mousemove:50,o=typeof t.mousemoveCallback=="number"?t.mousemoveCallback:500;let a=[],l;const s=Me(_(f=>{const m=Date.now()-l;e(a.map(h=>(h.timeOffset-=m,h)),f),a=[],l=null}),o),c=_(Me(_(f=>{const m=_e(f),{clientX:h,clientY:g}=ot(f)?f.changedTouches[0]:f;l||(l=Le()),a.push({x:h,y:g,id:n.getId(m),timeOffset:Le()-l}),s(typeof DragEvent<"u"&&f instanceof DragEvent?C.Drag:f instanceof MouseEvent?C.MouseMove:C.TouchMove)}),i,{trailing:!1})),u=[W("mousemove",c,r),W("touchmove",c,r),W("drag",c,r)];return _(()=>{u.forEach(f=>f())})}function on({mouseInteractionCb:e,doc:t,mirror:r,blockClass:n,blockSelector:i,sampling:o}){if(o.mouseInteraction===!1)return()=>{};const a=o.mouseInteraction===!0||o.mouseInteraction===void 0?{}:o.mouseInteraction,l=[];let s=null;const c=u=>f=>{const m=_e(f);if(U(m,n,i,!0))return;let h=null,g=u;if("pointerType"in f){switch(f.pointerType){case"mouse":h=ee.Mouse;break;case"touch":h=ee.Touch;break;case"pen":h=ee.Pen;break}h===ee.Touch?$[u]===$.MouseDown?g="TouchStart":$[u]===$.MouseUp&&(g="TouchEnd"):ee.Pen}else ot(f)&&(h=ee.Touch);h!==null?(s=h,(g.startsWith("Touch")&&h===ee.Touch||g.startsWith("Mouse")&&h===ee.Mouse)&&(h=null)):$[u]===$.Click&&(h=s,s=null);const p=ot(f)?f.changedTouches[0]:f;if(!p)return;const y=r.getId(m),{clientX:w,clientY:S}=p;_(e)(Object.assign({type:$[g],id:y,x:w,y:S},h!==null&&{pointerType:h}))};return Object.keys($).filter(u=>Number.isNaN(Number(u))&&!u.endsWith("_Departed")&&a[u]!==!1).forEach(u=>{let f=ie(u);const m=c(u);if(window.PointerEvent)switch($[u]){case $.MouseDown:case $.MouseUp:f=f.replace("mouse","pointer");break;case $.TouchStart:case $.TouchEnd:return}l.push(W(f,m,t))}),_(()=>{l.forEach(u=>u())})}function jt({scrollCb:e,doc:t,mirror:r,blockClass:n,blockSelector:i,sampling:o}){const a=_(Me(_(l=>{const s=_e(l);if(!s||U(s,n,i,!0))return;const c=r.getId(s);if(s===t&&t.defaultView){const u=xt(t.defaultView);e({id:c,x:u.left,y:u.top})}else e({id:c,x:s.scrollLeft,y:s.scrollTop})}),o.scroll||100));return W("scroll",a,t)}function sn({viewportResizeCb:e},{win:t}){let r=-1,n=-1;const i=_(Me(_(()=>{const o=Rt(),a=Tt();(r!==o||n!==a)&&(e({width:Number(a),height:Number(o)}),r=o,n=a)}),200));return W("resize",i,t)}const an=["INPUT","TEXTAREA","SELECT"],Gt=new WeakMap;function ln({inputCb:e,doc:t,mirror:r,blockClass:n,blockSelector:i,ignoreClass:o,ignoreSelector:a,maskInputOptions:l,maskInputFn:s,sampling:c,userTriggeredOnInput:u}){function f(S){let v=_e(S);const b=S.isTrusted,I=v&&v.tagName;if(v&&I==="OPTION"&&(v=v.parentElement),!v||!I||an.indexOf(I)<0||U(v,n,i,!0)||v.classList.contains(o)||a&&v.matches(a))return;let B=v.value,F=!1;const x=rt(v)||"";x==="radio"||x==="checkbox"?F=v.checked:(l[I.toLowerCase()]||l[x])&&(B=tt({element:v,maskInputOptions:l,tagName:I,type:x,value:B,maskInputFn:s})),m(v,u?{text:B,isChecked:F,userTriggered:b}:{text:B,isChecked:F});const R=v.name;x==="radio"&&R&&F&&t.querySelectorAll(`input[type="radio"][name="${R}"]`).forEach(j=>{if(j!==v){const G=j.value;m(j,u?{text:G,isChecked:!F,userTriggered:!1}:{text:G,isChecked:!F})}})}function m(S,v){const b=Gt.get(S);if(!b||b.text!==v.text||b.isChecked!==v.isChecked){Gt.set(S,v);const I=r.getId(S);_(e)(Object.assign(Object.assign({},v),{id:I}))}}const g=(c.input==="last"?["change"]:["input","change"]).map(S=>W(S,_(f),t)),p=t.defaultView;if(!p)return()=>{g.forEach(S=>S())};const y=p.Object.getOwnPropertyDescriptor(p.HTMLInputElement.prototype,"value"),w=[[p.HTMLInputElement.prototype,"value"],[p.HTMLInputElement.prototype,"checked"],[p.HTMLSelectElement.prototype,"value"],[p.HTMLTextAreaElement.prototype,"value"],[p.HTMLSelectElement.prototype,"selectedIndex"],[p.HTMLOptionElement.prototype,"selected"]];return y&&y.set&&g.push(...w.map(S=>Ae(S[0],S[1],{set(){_(f)({target:this,isTrusted:!1})}},!1,p))),_(()=>{g.forEach(S=>S())})}function Fe(e){const t=[];function r(n,i){if(Pe("CSSGroupingRule")&&n.parentRule instanceof CSSGroupingRule||Pe("CSSMediaRule")&&n.parentRule instanceof CSSMediaRule||Pe("CSSSupportsRule")&&n.parentRule instanceof CSSSupportsRule||Pe("CSSConditionRule")&&n.parentRule instanceof CSSConditionRule){const a=Array.from(n.parentRule.cssRules).indexOf(n);i.unshift(a)}else if(n.parentStyleSheet){const a=Array.from(n.parentStyleSheet.cssRules).indexOf(n);i.unshift(a)}return i}return r(e,t)}function te(e,t,r){let n,i;return e?(e.ownerNode?n=t.getId(e.ownerNode):i=r.getId(e),{styleId:i,id:n}):{}}function un({styleSheetRuleCb:e,mirror:t,stylesheetManager:r},{win:n}){if(!n.CSSStyleSheet||!n.CSSStyleSheet.prototype)return()=>{};const i=n.CSSStyleSheet.prototype.insertRule;n.CSSStyleSheet.prototype.insertRule=new Proxy(i,{apply:_((u,f,m)=>{const[h,g]=m,{id:p,styleId:y}=te(f,t,r.styleMirror);return(p&&p!==-1||y&&y!==-1)&&e({id:p,styleId:y,adds:[{rule:h,index:g}]}),u.apply(f,m)})});const o=n.CSSStyleSheet.prototype.deleteRule;n.CSSStyleSheet.prototype.deleteRule=new Proxy(o,{apply:_((u,f,m)=>{const[h]=m,{id:g,styleId:p}=te(f,t,r.styleMirror);return(g&&g!==-1||p&&p!==-1)&&e({id:g,styleId:p,removes:[{index:h}]}),u.apply(f,m)})});let a;n.CSSStyleSheet.prototype.replace&&(a=n.CSSStyleSheet.prototype.replace,n.CSSStyleSheet.prototype.replace=new Proxy(a,{apply:_((u,f,m)=>{const[h]=m,{id:g,styleId:p}=te(f,t,r.styleMirror);return(g&&g!==-1||p&&p!==-1)&&e({id:g,styleId:p,replace:h}),u.apply(f,m)})}));let l;n.CSSStyleSheet.prototype.replaceSync&&(l=n.CSSStyleSheet.prototype.replaceSync,n.CSSStyleSheet.prototype.replaceSync=new Proxy(l,{apply:_((u,f,m)=>{const[h]=m,{id:g,styleId:p}=te(f,t,r.styleMirror);return(g&&g!==-1||p&&p!==-1)&&e({id:g,styleId:p,replaceSync:h}),u.apply(f,m)})}));const s={};Be("CSSGroupingRule")?s.CSSGroupingRule=n.CSSGroupingRule:(Be("CSSMediaRule")&&(s.CSSMediaRule=n.CSSMediaRule),Be("CSSConditionRule")&&(s.CSSConditionRule=n.CSSConditionRule),Be("CSSSupportsRule")&&(s.CSSSupportsRule=n.CSSSupportsRule));const c={};return Object.entries(s).forEach(([u,f])=>{c[u]={insertRule:f.prototype.insertRule,deleteRule:f.prototype.deleteRule},f.prototype.insertRule=new Proxy(c[u].insertRule,{apply:_((m,h,g)=>{const[p,y]=g,{id:w,styleId:S}=te(h.parentStyleSheet,t,r.styleMirror);return(w&&w!==-1||S&&S!==-1)&&e({id:w,styleId:S,adds:[{rule:p,index:[...Fe(h),y||0]}]}),m.apply(h,g)})}),f.prototype.deleteRule=new Proxy(c[u].deleteRule,{apply:_((m,h,g)=>{const[p]=g,{id:y,styleId:w}=te(h.parentStyleSheet,t,r.styleMirror);return(y&&y!==-1||w&&w!==-1)&&e({id:y,styleId:w,removes:[{index:[...Fe(h),p]}]}),m.apply(h,g)})})}),_(()=>{n.CSSStyleSheet.prototype.insertRule=i,n.CSSStyleSheet.prototype.deleteRule=o,a&&(n.CSSStyleSheet.prototype.replace=a),l&&(n.CSSStyleSheet.prototype.replaceSync=l),Object.entries(s).forEach(([u,f])=>{f.prototype.insertRule=c[u].insertRule,f.prototype.deleteRule=c[u].deleteRule})})}function Vt({mirror:e,stylesheetManager:t},r){var n,i,o;let a=null;r.nodeName==="#document"?a=e.getId(r):a=e.getId(r.host);const l=r.nodeName==="#document"?(n=r.defaultView)===null||n===void 0?void 0:n.Document:(o=(i=r.ownerDocument)===null||i===void 0?void 0:i.defaultView)===null||o===void 0?void 0:o.ShadowRoot,s=l?.prototype?Object.getOwnPropertyDescriptor(l?.prototype,"adoptedStyleSheets"):void 0;return a===null||a===-1||!l||!s?()=>{}:(Object.defineProperty(r,"adoptedStyleSheets",{configurable:s.configurable,enumerable:s.enumerable,get(){var c;return(c=s.get)===null||c===void 0?void 0:c.call(this)},set(c){var u;const f=(u=s.set)===null||u===void 0?void 0:u.call(this,c);if(a!==null&&a!==-1)try{t.adoptStyleSheets(c,a)}catch{}return f}}),_(()=>{Object.defineProperty(r,"adoptedStyleSheets",{configurable:s.configurable,enumerable:s.enumerable,get:s.get,set:s.set})}))}function cn({styleDeclarationCb:e,mirror:t,ignoreCSSAttributes:r,stylesheetManager:n},{win:i}){const o=i.CSSStyleDeclaration.prototype.setProperty;i.CSSStyleDeclaration.prototype.setProperty=new Proxy(o,{apply:_((l,s,c)=>{var u;const[f,m,h]=c;if(r.has(f))return o.apply(s,[f,m,h]);const{id:g,styleId:p}=te((u=s.parentRule)===null||u===void 0?void 0:u.parentStyleSheet,t,n.styleMirror);return(g&&g!==-1||p&&p!==-1)&&e({id:g,styleId:p,set:{property:f,value:m,priority:h},index:Fe(s.parentRule)}),l.apply(s,c)})});const a=i.CSSStyleDeclaration.prototype.removeProperty;return i.CSSStyleDeclaration.prototype.removeProperty=new Proxy(a,{apply:_((l,s,c)=>{var u;const[f]=c;if(r.has(f))return a.apply(s,[f]);const{id:m,styleId:h}=te((u=s.parentRule)===null||u===void 0?void 0:u.parentStyleSheet,t,n.styleMirror);return(m&&m!==-1||h&&h!==-1)&&e({id:m,styleId:h,remove:{property:f},index:Fe(s.parentRule)}),l.apply(s,c)})}),_(()=>{i.CSSStyleDeclaration.prototype.setProperty=o,i.CSSStyleDeclaration.prototype.removeProperty=a})}function dn({mediaInteractionCb:e,blockClass:t,blockSelector:r,mirror:n,sampling:i,doc:o}){const a=_(s=>Me(_(c=>{const u=_e(c);if(!u||U(u,t,r,!0))return;const{currentTime:f,volume:m,muted:h,playbackRate:g,loop:p}=u;e({type:s,id:n.getId(u),currentTime:f,volume:m,muted:h,playbackRate:g,loop:p})}),i.media||500)),l=[W("play",a(0),o),W("pause",a(1),o),W("seeked",a(2),o),W("volumechange",a(3),o),W("ratechange",a(4),o)];return _(()=>{l.forEach(s=>s())})}function fn({fontCb:e,doc:t}){const r=t.defaultView;if(!r)return()=>{};const n=[],i=new WeakMap,o=r.FontFace;r.FontFace=function(s,c,u){const f=new o(s,c,u);return i.set(f,{family:s,buffer:typeof c!="string",descriptors:u,fontSource:typeof c=="string"?c:JSON.stringify(Array.from(new Uint8Array(c)))}),f};const a=ge(t.fonts,"add",function(l){return function(s){return setTimeout(_(()=>{const c=i.get(s);c&&(e(c),i.delete(s))}),0),l.apply(this,[s])}});return n.push(()=>{r.FontFace=o}),n.push(a),_(()=>{n.forEach(l=>l())})}function hn(e){const{doc:t,mirror:r,blockClass:n,blockSelector:i,selectionCb:o}=e;let a=!0;const l=_(()=>{const s=t.getSelection();if(!s||a&&s?.isCollapsed)return;a=s.isCollapsed||!1;const c=[],u=s.rangeCount||0;for(let f=0;f{}:ge(r.customElements,"define",function(i){return function(o,a,l){try{t({define:{name:o}})}catch{console.warn(`Custom element callback failed for ${o}`)}return i.apply(this,[o,a,l])}})}function mn(e,t){const{mutationCb:r,mousemoveCb:n,mouseInteractionCb:i,scrollCb:o,viewportResizeCb:a,inputCb:l,mediaInteractionCb:s,styleSheetRuleCb:c,styleDeclarationCb:u,canvasMutationCb:f,fontCb:m,selectionCb:h,customElementCb:g}=e;e.mutationCb=(...p)=>{t.mutation&&t.mutation(...p),r(...p)},e.mousemoveCb=(...p)=>{t.mousemove&&t.mousemove(...p),n(...p)},e.mouseInteractionCb=(...p)=>{t.mouseInteraction&&t.mouseInteraction(...p),i(...p)},e.scrollCb=(...p)=>{t.scroll&&t.scroll(...p),o(...p)},e.viewportResizeCb=(...p)=>{t.viewportResize&&t.viewportResize(...p),a(...p)},e.inputCb=(...p)=>{t.input&&t.input(...p),l(...p)},e.mediaInteractionCb=(...p)=>{t.mediaInteaction&&t.mediaInteaction(...p),s(...p)},e.styleSheetRuleCb=(...p)=>{t.styleSheetRule&&t.styleSheetRule(...p),c(...p)},e.styleDeclarationCb=(...p)=>{t.styleDeclaration&&t.styleDeclaration(...p),u(...p)},e.canvasMutationCb=(...p)=>{t.canvasMutation&&t.canvasMutation(...p),f(...p)},e.fontCb=(...p)=>{t.font&&t.font(...p),m(...p)},e.selectionCb=(...p)=>{t.selection&&t.selection(...p),h(...p)},e.customElementCb=(...p)=>{t.customElement&&t.customElement(...p),g(...p)}}function gn(e,t={}){const r=e.doc.defaultView;if(!r)return()=>{};mn(e,t);let n;e.recordDOM&&(n=qt(e,e.doc));const i=nn(e),o=on(e),a=jt(e),l=sn(e,{win:r}),s=ln(e),c=dn(e);let u=()=>{},f=()=>{},m=()=>{},h=()=>{};e.recordDOM&&(u=un(e,{win:r}),f=Vt(e,e.doc),m=cn(e,{win:r}),e.collectFonts&&(h=fn(e)));const g=hn(e),p=pn(e),y=[];for(const w of e.plugins)y.push(w.observer(w.callback,r,w.options));return _(()=>{oe.forEach(w=>w.reset()),n?.disconnect(),i(),o(),a(),l(),s(),c(),u(),f(),m(),h(),g(),p(),y.forEach(w=>w())})}function Pe(e){return typeof window[e]<"u"}function Be(e){return!!(typeof window[e]<"u"&&window[e].prototype&&"insertRule"in window[e].prototype&&"deleteRule"in window[e].prototype)}class Jt{constructor(t){this.generateIdFn=t,this.iframeIdToRemoteIdMap=new WeakMap,this.iframeRemoteIdToIdMap=new WeakMap}getId(t,r,n,i){const o=n||this.getIdToRemoteIdMap(t),a=i||this.getRemoteIdToIdMap(t);let l=o.get(r);return l||(l=this.generateIdFn(),o.set(r,l),a.set(l,r)),l}getIds(t,r){const n=this.getIdToRemoteIdMap(t),i=this.getRemoteIdToIdMap(t);return r.map(o=>this.getId(t,o,n,i))}getRemoteId(t,r,n){const i=n||this.getRemoteIdToIdMap(t);if(typeof r!="number")return r;const o=i.get(r);return o||-1}getRemoteIds(t,r){const n=this.getRemoteIdToIdMap(t);return r.map(i=>this.getRemoteId(t,i,n))}reset(t){if(!t){this.iframeIdToRemoteIdMap=new WeakMap,this.iframeRemoteIdToIdMap=new WeakMap;return}this.iframeIdToRemoteIdMap.delete(t),this.iframeRemoteIdToIdMap.delete(t)}getIdToRemoteIdMap(t){let r=this.iframeIdToRemoteIdMap.get(t);return r||(r=new Map,this.iframeIdToRemoteIdMap.set(t,r)),r}getRemoteIdToIdMap(t){let r=this.iframeRemoteIdToIdMap.get(t);return r||(r=new Map,this.iframeRemoteIdToIdMap.set(t,r)),r}}class yn{constructor(t){this.iframes=new WeakMap,this.crossOriginIframeMap=new WeakMap,this.crossOriginIframeMirror=new Jt(Mt),this.crossOriginIframeRootIdMap=new WeakMap,this.mutationCb=t.mutationCb,this.wrappedEmit=t.wrappedEmit,this.stylesheetManager=t.stylesheetManager,this.recordCrossOriginIframes=t.recordCrossOriginIframes,this.crossOriginIframeStyleMirror=new Jt(this.stylesheetManager.styleMirror.generateId.bind(this.stylesheetManager.styleMirror)),this.mirror=t.mirror,this.recordCrossOriginIframes&&window.addEventListener("message",this.handleMessage.bind(this))}addIframe(t){this.iframes.set(t,!0),t.contentWindow&&this.crossOriginIframeMap.set(t.contentWindow,t)}addLoadListener(t){this.loadListener=t}attachIframe(t,r){var n;this.mutationCb({adds:[{parentId:this.mirror.getId(t),nextId:null,node:r}],removes:[],texts:[],attributes:[],isAttachIframe:!0}),(n=this.loadListener)===null||n===void 0||n.call(this,t),t.contentDocument&&t.contentDocument.adoptedStyleSheets&&t.contentDocument.adoptedStyleSheets.length>0&&this.stylesheetManager.adoptStyleSheets(t.contentDocument.adoptedStyleSheets,this.mirror.getId(t.contentDocument))}handleMessage(t){const r=t;if(r.data.type!=="rrweb"||r.origin!==r.data.origin||!t.source)return;const i=this.crossOriginIframeMap.get(t.source);if(!i)return;const o=this.transformCrossOriginEvent(i,r.data.event);o&&this.wrappedEmit(o,r.data.isCheckout)}transformCrossOriginEvent(t,r){var n;switch(r.type){case O.FullSnapshot:{this.crossOriginIframeMirror.reset(t),this.crossOriginIframeStyleMirror.reset(t),this.replaceIdOnNode(r.data.node,t);const i=r.data.node.id;return this.crossOriginIframeRootIdMap.set(t,i),this.patchRootIdOnNode(r.data.node,i),{timestamp:r.timestamp,type:O.IncrementalSnapshot,data:{source:C.Mutation,adds:[{parentId:this.mirror.getId(t),nextId:null,node:r.data.node}],removes:[],texts:[],attributes:[],isAttachIframe:!0}}}case O.Meta:case O.Load:case O.DomContentLoaded:return!1;case O.Plugin:return r;case O.Custom:return this.replaceIds(r.data.payload,t,["id","parentId","previousId","nextId"]),r;case O.IncrementalSnapshot:switch(r.data.source){case C.Mutation:return r.data.adds.forEach(i=>{this.replaceIds(i,t,["parentId","nextId","previousId"]),this.replaceIdOnNode(i.node,t);const o=this.crossOriginIframeRootIdMap.get(t);o&&this.patchRootIdOnNode(i.node,o)}),r.data.removes.forEach(i=>{this.replaceIds(i,t,["parentId","id"])}),r.data.attributes.forEach(i=>{this.replaceIds(i,t,["id"])}),r.data.texts.forEach(i=>{this.replaceIds(i,t,["id"])}),r;case C.Drag:case C.TouchMove:case C.MouseMove:return r.data.positions.forEach(i=>{this.replaceIds(i,t,["id"])}),r;case C.ViewportResize:return!1;case C.MediaInteraction:case C.MouseInteraction:case C.Scroll:case C.CanvasMutation:case C.Input:return this.replaceIds(r.data,t,["id"]),r;case C.StyleSheetRule:case C.StyleDeclaration:return this.replaceIds(r.data,t,["id"]),this.replaceStyleIds(r.data,t,["styleId"]),r;case C.Font:return r;case C.Selection:return r.data.ranges.forEach(i=>{this.replaceIds(i,t,["start","end"])}),r;case C.AdoptedStyleSheet:return this.replaceIds(r.data,t,["id"]),this.replaceStyleIds(r.data,t,["styleIds"]),(n=r.data.styles)===null||n===void 0||n.forEach(i=>{this.replaceStyleIds(i,t,["styleId"])}),r}}return!1}replace(t,r,n,i){for(const o of i)!Array.isArray(r[o])&&typeof r[o]!="number"||(Array.isArray(r[o])?r[o]=t.getIds(n,r[o]):r[o]=t.getId(n,r[o]));return r}replaceIds(t,r,n){return this.replace(this.crossOriginIframeMirror,t,r,n)}replaceStyleIds(t,r,n){return this.replace(this.crossOriginIframeStyleMirror,t,r,n)}replaceIdOnNode(t,r){this.replaceIds(t,r,["id","rootId"]),"childNodes"in t&&t.childNodes.forEach(n=>{this.replaceIdOnNode(n,r)})}patchRootIdOnNode(t,r){t.type!==A.Document&&!t.rootId&&(t.rootId=r),"childNodes"in t&&t.childNodes.forEach(n=>{this.patchRootIdOnNode(n,r)})}}class vn{constructor(t){this.shadowDoms=new WeakSet,this.restoreHandlers=[],this.mutationCb=t.mutationCb,this.scrollCb=t.scrollCb,this.bypassOptions=t.bypassOptions,this.mirror=t.mirror,this.init()}init(){this.reset(),this.patchAttachShadow(Element,document)}addShadowRoot(t,r){if(!we(t)||this.shadowDoms.has(t))return;this.shadowDoms.add(t);const n=qt(Object.assign(Object.assign({},this.bypassOptions),{doc:r,mutationCb:this.mutationCb,mirror:this.mirror,shadowDomManager:this}),t);this.restoreHandlers.push(()=>n.disconnect()),this.restoreHandlers.push(jt(Object.assign(Object.assign({},this.bypassOptions),{scrollCb:this.scrollCb,doc:t,mirror:this.mirror}))),setTimeout(()=>{t.adoptedStyleSheets&&t.adoptedStyleSheets.length>0&&this.bypassOptions.stylesheetManager.adoptStyleSheets(t.adoptedStyleSheets,this.mirror.getId(t.host)),this.restoreHandlers.push(Vt({mirror:this.mirror,stylesheetManager:this.bypassOptions.stylesheetManager},t))},0)}observeAttachShadow(t){!t.contentWindow||!t.contentDocument||this.patchAttachShadow(t.contentWindow.Element,t.contentDocument)}patchAttachShadow(t,r){const n=this;this.restoreHandlers.push(ge(t.prototype,"attachShadow",function(i){return function(o){const a=i.call(this,o);return this.shadowRoot&&Pt(this)&&n.addShadowRoot(this.shadowRoot,r),a}}))}reset(){this.restoreHandlers.forEach(t=>{try{t()}catch{}}),this.restoreHandlers=[],this.shadowDoms=new WeakSet}}/*! ***************************************************************************** +or you can use record.mirror to access the mirror instance during recording.`;let xt={map:{},getId(){return console.error(ge),-1},getNode(){return console.error(ge),null},removeNodeFromMap(){console.error(ge)},has(){return console.error(ge),!1},reset(){console.error(ge)}};typeof window<"u"&&window.Proxy&&window.Reflect&&(xt=new Proxy(xt,{get(e,t,r){return t==="map"&&console.error(ge),Reflect.get(e,t,r)}}));function Ie(e,t,r={}){let n=null,i=0;return function(...o){const a=Date.now();!i&&r.leading===!1&&(i=a);const l=t-(a-i),s=this;l<=0||l>t?(n&&(clearTimeout(n),n=null),i=a,e.apply(s,o)):!n&&r.trailing!==!1&&(n=setTimeout(()=>{i=r.leading===!1?0:Date.now(),n=null,e.apply(s,o)},l))}}function Ae(e,t,r,n,i=window){const o=i.Object.getOwnPropertyDescriptor(e,t);return i.Object.defineProperty(e,t,n?r:{set(a){setTimeout(()=>{r.set.call(this,a)},0),o&&o.set&&o.set.call(this,a)}}),()=>Ae(e,t,o||{},!0)}function ye(e,t,r){try{if(!(t in e))return()=>{};const n=e[t],i=r(n);return typeof i=="function"&&(i.prototype=i.prototype||{},Object.defineProperties(i,{__rrweb_original__:{enumerable:!1,value:n}})),e[t]=i,()=>{e[t]=n}}catch{return()=>{}}}let Le=Date.now;/[1-9][0-9]{12}/.test(Date.now().toString())||(Le=()=>new Date().getTime());function Rt(e){var t,r,n,i,o,a;const l=e.document;return{left:l.scrollingElement?l.scrollingElement.scrollLeft:e.pageXOffset!==void 0?e.pageXOffset:l?.documentElement.scrollLeft||((r=(t=l?.body)===null||t===void 0?void 0:t.parentElement)===null||r===void 0?void 0:r.scrollLeft)||((n=l?.body)===null||n===void 0?void 0:n.scrollLeft)||0,top:l.scrollingElement?l.scrollingElement.scrollTop:e.pageYOffset!==void 0?e.pageYOffset:l?.documentElement.scrollTop||((o=(i=l?.body)===null||i===void 0?void 0:i.parentElement)===null||o===void 0?void 0:o.scrollTop)||((a=l?.body)===null||a===void 0?void 0:a.scrollTop)||0}}function Tt(){return window.innerHeight||document.documentElement&&document.documentElement.clientHeight||document.body&&document.body.clientHeight}function Dt(){return window.innerWidth||document.documentElement&&document.documentElement.clientWidth||document.body&&document.body.clientWidth}function Nt(e){return e?e.nodeType===e.ELEMENT_NODE?e:e.parentElement:null}function U(e,t,r,n){if(!e)return!1;const i=Nt(e);if(!i)return!1;try{if(typeof t=="string"){if(i.classList.contains(t)||n&&i.closest("."+t)!==null)return!0}else if(Ne(i,t,n))return!0}catch{}return!!(r&&(i.matches(r)||n&&i.closest(r)!==null))}function Xr(e,t){return t.getId(e)!==-1}function it(e,t){return t.getId(e)===Me}function At(e,t){if(be(e))return!1;const r=t.getId(e);return t.has(r)?e.parentNode&&e.parentNode.nodeType===e.DOCUMENT_NODE?!1:e.parentNode?At(e.parentNode,t):!0:!0}function ot(e){return!!e.changedTouches}function Kr(e=window){"NodeList"in e&&!e.NodeList.prototype.forEach&&(e.NodeList.prototype.forEach=Array.prototype.forEach),"DOMTokenList"in e&&!e.DOMTokenList.prototype.forEach&&(e.DOMTokenList.prototype.forEach=Array.prototype.forEach),Node.prototype.contains||(Node.prototype.contains=(...t)=>{let r=t[0];if(!(0 in t))throw new TypeError("1 argument is required");do if(this===r)return!0;while(r=r&&r.parentNode);return!1})}function Lt(e,t){return!!(e.nodeName==="IFRAME"&&t.getMeta(e))}function Ft(e,t){return!!(e.nodeName==="LINK"&&e.nodeType===e.ELEMENT_NODE&&e.getAttribute&&e.getAttribute("rel")==="stylesheet"&&t.getMeta(e))}function st(e){return!!e?.shadowRoot}class Yr{constructor(){this.id=1,this.styleIDMap=new WeakMap,this.idStyleMap=new Map}getId(t){var r;return(r=this.styleIDMap.get(t))!==null&&r!==void 0?r:-1}has(t){return this.styleIDMap.has(t)}add(t,r){if(this.has(t))return this.getId(t);let n;return r===void 0?n=this.id++:n=r,this.styleIDMap.set(t,n),this.idStyleMap.set(n,t),n}getStyle(t){return this.idStyleMap.get(t)||null}reset(){this.styleIDMap=new WeakMap,this.idStyleMap=new Map,this.id=1}generateId(){return this.id++}}function Pt(e){var t,r;let n=null;return((r=(t=e.getRootNode)===null||t===void 0?void 0:t.call(e))===null||r===void 0?void 0:r.nodeType)===Node.DOCUMENT_FRAGMENT_NODE&&e.getRootNode().host&&(n=e.getRootNode().host),n}function Qr(e){let t=e,r;for(;r=Pt(t);)t=r;return t}function Zr(e){const t=e.ownerDocument;if(!t)return!1;const r=Qr(e);return t.contains(r)}function Bt(e){const t=e.ownerDocument;return t?t.contains(e)||Zr(e):!1}var O=(e=>(e[e.DomContentLoaded=0]="DomContentLoaded",e[e.Load=1]="Load",e[e.FullSnapshot=2]="FullSnapshot",e[e.IncrementalSnapshot=3]="IncrementalSnapshot",e[e.Meta=4]="Meta",e[e.Custom=5]="Custom",e[e.Plugin=6]="Plugin",e))(O||{}),C=(e=>(e[e.Mutation=0]="Mutation",e[e.MouseMove=1]="MouseMove",e[e.MouseInteraction=2]="MouseInteraction",e[e.Scroll=3]="Scroll",e[e.ViewportResize=4]="ViewportResize",e[e.Input=5]="Input",e[e.TouchMove=6]="TouchMove",e[e.MediaInteraction=7]="MediaInteraction",e[e.StyleSheetRule=8]="StyleSheetRule",e[e.CanvasMutation=9]="CanvasMutation",e[e.Font=10]="Font",e[e.Log=11]="Log",e[e.Drag=12]="Drag",e[e.StyleDeclaration=13]="StyleDeclaration",e[e.Selection=14]="Selection",e[e.AdoptedStyleSheet=15]="AdoptedStyleSheet",e[e.CustomElement=16]="CustomElement",e))(C||{}),$=(e=>(e[e.MouseUp=0]="MouseUp",e[e.MouseDown=1]="MouseDown",e[e.Click=2]="Click",e[e.ContextMenu=3]="ContextMenu",e[e.DblClick=4]="DblClick",e[e.Focus=5]="Focus",e[e.Blur=6]="Blur",e[e.TouchStart=7]="TouchStart",e[e.TouchMove_Departed=8]="TouchMove_Departed",e[e.TouchEnd=9]="TouchEnd",e[e.TouchCancel=10]="TouchCancel",e))($||{}),ee=(e=>(e[e.Mouse=0]="Mouse",e[e.Pen=1]="Pen",e[e.Touch=2]="Touch",e))(ee||{}),ve=(e=>(e[e["2D"]=0]="2D",e[e.WebGL=1]="WebGL",e[e.WebGL2=2]="WebGL2",e))(ve||{});function Wt(e){return"__ln"in e}class en{constructor(){this.length=0,this.head=null,this.tail=null}get(t){if(t>=this.length)throw new Error("Position outside of list range");let r=this.head;for(let n=0;n`${e}@${t}`;class tn{constructor(){this.frozen=!1,this.locked=!1,this.texts=[],this.attributes=[],this.attributeMap=new WeakMap,this.removes=[],this.mapRemoves=[],this.movedMap={},this.addedSet=new Set,this.movedSet=new Set,this.droppedSet=new Set,this.processMutations=t=>{t.forEach(this.processMutation),this.emit()},this.emit=()=>{if(this.frozen||this.locked)return;const t=[],r=new Set,n=new en,i=s=>{let c=s,u=Me;for(;u===Me;)c=c&&c.nextSibling,u=c&&this.mirror.getId(c);return u},o=s=>{if(!s.parentNode||!Bt(s)||s.parentNode.tagName==="TEXTAREA")return;const c=be(s.parentNode)?this.mirror.getId(Pt(s)):this.mirror.getId(s.parentNode),u=i(s);if(c===-1||u===-1)return n.addNode(s);const h=me(s,{doc:this.doc,mirror:this.mirror,blockClass:this.blockClass,blockSelector:this.blockSelector,maskTextClass:this.maskTextClass,maskTextSelector:this.maskTextSelector,skipChild:!0,newlyAddedElement:!0,inlineStylesheet:this.inlineStylesheet,maskInputOptions:this.maskInputOptions,maskTextFn:this.maskTextFn,maskInputFn:this.maskInputFn,slimDOMOptions:this.slimDOMOptions,dataURLOptions:this.dataURLOptions,recordCanvas:this.recordCanvas,inlineImages:this.inlineImages,onSerialize:m=>{Lt(m,this.mirror)&&this.iframeManager.addIframe(m),Ft(m,this.mirror)&&this.stylesheetManager.trackLinkElement(m),st(s)&&this.shadowDomManager.addShadowRoot(s.shadowRoot,this.doc)},onIframeLoad:(m,f)=>{this.iframeManager.attachIframe(m,f),this.shadowDomManager.observeAttachShadow(m)},onStylesheetLoad:(m,f)=>{this.stylesheetManager.attachLinkElement(m,f)}});h&&(t.push({parentId:c,nextId:u,node:h}),r.add(h.id))};for(;this.mapRemoves.length;)this.mirror.removeNodeFromMap(this.mapRemoves.shift());for(const s of this.movedSet)zt(this.removes,s,this.mirror)&&!this.movedSet.has(s.parentNode)||o(s);for(const s of this.addedSet)!$t(this.droppedSet,s)&&!zt(this.removes,s,this.mirror)||$t(this.movedSet,s)?o(s):this.droppedSet.add(s);let a=null;for(;n.length;){let s=null;if(a){const c=this.mirror.getId(a.value.parentNode),u=i(a.value);c!==-1&&u!==-1&&(s=a)}if(!s){let c=n.tail;for(;c;){const u=c;if(c=c.previous,u){const h=this.mirror.getId(u.value.parentNode);if(i(u.value)===-1)continue;if(h!==-1){s=u;break}else{const f=u.value;if(f.parentNode&&f.parentNode.nodeType===Node.DOCUMENT_FRAGMENT_NODE){const g=f.parentNode.host;if(this.mirror.getId(g)!==-1){s=u;break}}}}}}if(!s){for(;n.head;)n.removeNode(n.head.value);break}a=s.previous,n.removeNode(s.value),o(s.value)}const l={texts:this.texts.map(s=>{const c=s.node;return c.parentNode&&c.parentNode.tagName==="TEXTAREA"&&this.genTextAreaValueMutation(c.parentNode),{id:this.mirror.getId(c),value:s.value}}).filter(s=>!r.has(s.id)).filter(s=>this.mirror.has(s.id)),attributes:this.attributes.map(s=>{const{attributes:c}=s;if(typeof c.style=="string"){const u=JSON.stringify(s.styleDiff),h=JSON.stringify(s._unchangedStyles);u.length!r.has(s.id)).filter(s=>this.mirror.has(s.id)),removes:this.removes,adds:t};!l.texts.length&&!l.attributes.length&&!l.removes.length&&!l.adds.length||(this.texts=[],this.attributes=[],this.attributeMap=new WeakMap,this.removes=[],this.addedSet=new Set,this.movedSet=new Set,this.droppedSet=new Set,this.movedMap={},this.mutationCb(l))},this.genTextAreaValueMutation=t=>{let r=this.attributeMap.get(t);r||(r={node:t,attributes:{},styleDiff:{},_unchangedStyles:{}},this.attributes.push(r),this.attributeMap.set(t,r)),r.attributes.value=Array.from(t.childNodes,n=>n.textContent||"").join("")},this.processMutation=t=>{if(!it(t.target,this.mirror))switch(t.type){case"characterData":{const r=t.target.textContent;!U(t.target,this.blockClass,this.blockSelector,!1)&&r!==t.oldValue&&this.texts.push({value:kt(t.target,this.maskTextClass,this.maskTextSelector,!0)&&r?this.maskTextFn?this.maskTextFn(r,Nt(t.target)):r.replace(/[\S]/g,"*"):r,node:t.target});break}case"attributes":{const r=t.target;let n=t.attributeName,i=t.target.getAttribute(n);if(n==="value"){const a=rt(r);i=tt({element:r,maskInputOptions:this.maskInputOptions,tagName:r.tagName,type:a,value:i,maskInputFn:this.maskInputFn})}if(U(t.target,this.blockClass,this.blockSelector,!1)||i===t.oldValue)return;let o=this.attributeMap.get(t.target);if(r.tagName==="IFRAME"&&n==="src"&&!this.keepIframeSrcFn(i))if(!r.contentDocument)n="rr_src";else return;if(o||(o={node:t.target,attributes:{},styleDiff:{},_unchangedStyles:{}},this.attributes.push(o),this.attributeMap.set(t.target,o)),n==="type"&&r.tagName==="INPUT"&&(t.oldValue||"").toLowerCase()==="password"&&r.setAttribute("data-rr-is-password","true"),!Et(r.tagName,n)&&(o.attributes[n]=Ot(this.doc,ie(r.tagName),ie(n),i),n==="style")){if(!this.unattachedDoc)try{this.unattachedDoc=document.implementation.createHTMLDocument()}catch{this.unattachedDoc=this.doc}const a=this.unattachedDoc.createElement("span");t.oldValue&&a.setAttribute("style",t.oldValue);for(const l of Array.from(r.style)){const s=r.style.getPropertyValue(l),c=r.style.getPropertyPriority(l);s!==a.style.getPropertyValue(l)||c!==a.style.getPropertyPriority(l)?c===""?o.styleDiff[l]=s:o.styleDiff[l]=[s,c]:o._unchangedStyles[l]=[s,c]}for(const l of Array.from(a.style))r.style.getPropertyValue(l)===""&&(o.styleDiff[l]=!1)}break}case"childList":{if(U(t.target,this.blockClass,this.blockSelector,!0))return;if(t.target.tagName==="TEXTAREA"){this.genTextAreaValueMutation(t.target);return}t.addedNodes.forEach(r=>this.genAdds(r,t.target)),t.removedNodes.forEach(r=>{const n=this.mirror.getId(r),i=be(t.target)?this.mirror.getId(t.target.host):this.mirror.getId(t.target);U(t.target,this.blockClass,this.blockSelector,!1)||it(r,this.mirror)||!Xr(r,this.mirror)||(this.addedSet.has(r)?(at(this.addedSet,r),this.droppedSet.add(r)):this.addedSet.has(t.target)&&n===-1||At(t.target,this.mirror)||(this.movedSet.has(r)&&this.movedMap[Ut(n,i)]?at(this.movedSet,r):this.removes.push({parentId:i,id:n,isShadow:be(t.target)&&we(t.target)?!0:void 0})),this.mapRemoves.push(r))});break}}},this.genAdds=(t,r)=>{if(!this.processedNodeManager.inOtherBuffer(t,this)&&!(this.addedSet.has(t)||this.movedSet.has(t))){if(this.mirror.hasNode(t)){if(it(t,this.mirror))return;this.movedSet.add(t);let n=null;r&&this.mirror.hasNode(r)&&(n=this.mirror.getId(r)),n&&n!==-1&&(this.movedMap[Ut(this.mirror.getId(t),n)]=!0)}else this.addedSet.add(t),this.droppedSet.delete(t);U(t,this.blockClass,this.blockSelector,!1)||(t.childNodes.forEach(n=>this.genAdds(n)),st(t)&&t.shadowRoot.childNodes.forEach(n=>{this.processedNodeManager.add(n,this),this.genAdds(n,t)}))}}}init(t){["mutationCb","blockClass","blockSelector","maskTextClass","maskTextSelector","inlineStylesheet","maskInputOptions","maskTextFn","maskInputFn","keepIframeSrcFn","recordCanvas","inlineImages","slimDOMOptions","dataURLOptions","doc","mirror","iframeManager","stylesheetManager","shadowDomManager","canvasManager","processedNodeManager"].forEach(r=>{this[r]=t[r]})}freeze(){this.frozen=!0,this.canvasManager.freeze()}unfreeze(){this.frozen=!1,this.canvasManager.unfreeze(),this.emit()}isFrozen(){return this.frozen}lock(){this.locked=!0,this.canvasManager.lock()}unlock(){this.locked=!1,this.canvasManager.unlock(),this.emit()}reset(){this.shadowDomManager.reset(),this.canvasManager.reset()}}function at(e,t){e.delete(t),t.childNodes.forEach(r=>at(e,r))}function zt(e,t,r){return e.length===0?!1:Ht(e,t,r)}function Ht(e,t,r){const{parentNode:n}=t;if(!n)return!1;const i=r.getId(n);return e.some(o=>o.id===i)?!0:Ht(e,n,r)}function $t(e,t){return e.size===0?!1:qt(e,t)}function qt(e,t){const{parentNode:r}=t;return r?e.has(r)?!0:qt(e,r):!1}let Ce;function rn(e){Ce=e}function nn(){Ce=void 0}const _=e=>Ce?(...r)=>{try{return e(...r)}catch(n){if(Ce&&Ce(n)===!0)return;throw n}}:e,oe=[];function _e(e){try{if("composedPath"in e){const t=e.composedPath();if(t.length)return t[0]}else if("path"in e&&e.path.length)return e.path[0]}catch{}return e&&e.target}function jt(e,t){var r,n;const i=new tn;oe.push(i),i.init(e);let o=window.MutationObserver||window.__rrMutationObserver;const a=(n=(r=window?.Zone)===null||r===void 0?void 0:r.__symbol__)===null||n===void 0?void 0:n.call(r,"MutationObserver");a&&window[a]&&(o=window[a]);const l=new o(_(i.processMutations.bind(i)));return l.observe(t,{attributes:!0,attributeOldValue:!0,characterData:!0,characterDataOldValue:!0,childList:!0,subtree:!0}),l}function on({mousemoveCb:e,sampling:t,doc:r,mirror:n}){if(t.mousemove===!1)return()=>{};const i=typeof t.mousemove=="number"?t.mousemove:50,o=typeof t.mousemoveCallback=="number"?t.mousemoveCallback:500;let a=[],l;const s=Ie(_(h=>{const m=Date.now()-l;e(a.map(f=>(f.timeOffset-=m,f)),h),a=[],l=null}),o),c=_(Ie(_(h=>{const m=_e(h),{clientX:f,clientY:g}=ot(h)?h.changedTouches[0]:h;l||(l=Le()),a.push({x:f,y:g,id:n.getId(m),timeOffset:Le()-l}),s(typeof DragEvent<"u"&&h instanceof DragEvent?C.Drag:h instanceof MouseEvent?C.MouseMove:C.TouchMove)}),i,{trailing:!1})),u=[W("mousemove",c,r),W("touchmove",c,r),W("drag",c,r)];return _(()=>{u.forEach(h=>h())})}function sn({mouseInteractionCb:e,doc:t,mirror:r,blockClass:n,blockSelector:i,sampling:o}){if(o.mouseInteraction===!1)return()=>{};const a=o.mouseInteraction===!0||o.mouseInteraction===void 0?{}:o.mouseInteraction,l=[];let s=null;const c=u=>h=>{const m=_e(h);if(U(m,n,i,!0))return;let f=null,g=u;if("pointerType"in h){switch(h.pointerType){case"mouse":f=ee.Mouse;break;case"touch":f=ee.Touch;break;case"pen":f=ee.Pen;break}f===ee.Touch?$[u]===$.MouseDown?g="TouchStart":$[u]===$.MouseUp&&(g="TouchEnd"):ee.Pen}else ot(h)&&(f=ee.Touch);f!==null?(s=f,(g.startsWith("Touch")&&f===ee.Touch||g.startsWith("Mouse")&&f===ee.Mouse)&&(f=null)):$[u]===$.Click&&(f=s,s=null);const p=ot(h)?h.changedTouches[0]:h;if(!p)return;const y=r.getId(m),{clientX:w,clientY:S}=p;_(e)(Object.assign({type:$[g],id:y,x:w,y:S},f!==null&&{pointerType:f}))};return Object.keys($).filter(u=>Number.isNaN(Number(u))&&!u.endsWith("_Departed")&&a[u]!==!1).forEach(u=>{let h=ie(u);const m=c(u);if(window.PointerEvent)switch($[u]){case $.MouseDown:case $.MouseUp:h=h.replace("mouse","pointer");break;case $.TouchStart:case $.TouchEnd:return}l.push(W(h,m,t))}),_(()=>{l.forEach(u=>u())})}function Gt({scrollCb:e,doc:t,mirror:r,blockClass:n,blockSelector:i,sampling:o}){const a=_(Ie(_(l=>{const s=_e(l);if(!s||U(s,n,i,!0))return;const c=r.getId(s);if(s===t&&t.defaultView){const u=Rt(t.defaultView);e({id:c,x:u.left,y:u.top})}else e({id:c,x:s.scrollLeft,y:s.scrollTop})}),o.scroll||100));return W("scroll",a,t)}function an({viewportResizeCb:e},{win:t}){let r=-1,n=-1;const i=_(Ie(_(()=>{const o=Tt(),a=Dt();(r!==o||n!==a)&&(e({width:Number(a),height:Number(o)}),r=o,n=a)}),200));return W("resize",i,t)}const ln=["INPUT","TEXTAREA","SELECT"],Vt=new WeakMap;function un({inputCb:e,doc:t,mirror:r,blockClass:n,blockSelector:i,ignoreClass:o,ignoreSelector:a,maskInputOptions:l,maskInputFn:s,sampling:c,userTriggeredOnInput:u}){function h(S){let v=_e(S);const b=S.isTrusted,M=v&&v.tagName;if(v&&M==="OPTION"&&(v=v.parentElement),!v||!M||ln.indexOf(M)<0||U(v,n,i,!0)||v.classList.contains(o)||a&&v.matches(a))return;let B=v.value,P=!1;const x=rt(v)||"";x==="radio"||x==="checkbox"?P=v.checked:(l[M.toLowerCase()]||l[x])&&(B=tt({element:v,maskInputOptions:l,tagName:M,type:x,value:B,maskInputFn:s})),m(v,u?{text:B,isChecked:P,userTriggered:b}:{text:B,isChecked:P});const R=v.name;x==="radio"&&R&&P&&t.querySelectorAll(`input[type="radio"][name="${R}"]`).forEach(j=>{if(j!==v){const G=j.value;m(j,u?{text:G,isChecked:!P,userTriggered:!1}:{text:G,isChecked:!P})}})}function m(S,v){const b=Vt.get(S);if(!b||b.text!==v.text||b.isChecked!==v.isChecked){Vt.set(S,v);const M=r.getId(S);_(e)(Object.assign(Object.assign({},v),{id:M}))}}const g=(c.input==="last"?["change"]:["input","change"]).map(S=>W(S,_(h),t)),p=t.defaultView;if(!p)return()=>{g.forEach(S=>S())};const y=p.Object.getOwnPropertyDescriptor(p.HTMLInputElement.prototype,"value"),w=[[p.HTMLInputElement.prototype,"value"],[p.HTMLInputElement.prototype,"checked"],[p.HTMLSelectElement.prototype,"value"],[p.HTMLTextAreaElement.prototype,"value"],[p.HTMLSelectElement.prototype,"selectedIndex"],[p.HTMLOptionElement.prototype,"selected"]];return y&&y.set&&g.push(...w.map(S=>Ae(S[0],S[1],{set(){_(h)({target:this,isTrusted:!1})}},!1,p))),_(()=>{g.forEach(S=>S())})}function Fe(e){const t=[];function r(n,i){if(Pe("CSSGroupingRule")&&n.parentRule instanceof CSSGroupingRule||Pe("CSSMediaRule")&&n.parentRule instanceof CSSMediaRule||Pe("CSSSupportsRule")&&n.parentRule instanceof CSSSupportsRule||Pe("CSSConditionRule")&&n.parentRule instanceof CSSConditionRule){const a=Array.from(n.parentRule.cssRules).indexOf(n);i.unshift(a)}else if(n.parentStyleSheet){const a=Array.from(n.parentStyleSheet.cssRules).indexOf(n);i.unshift(a)}return i}return r(e,t)}function te(e,t,r){let n,i;return e?(e.ownerNode?n=t.getId(e.ownerNode):i=r.getId(e),{styleId:i,id:n}):{}}function cn({styleSheetRuleCb:e,mirror:t,stylesheetManager:r},{win:n}){if(!n.CSSStyleSheet||!n.CSSStyleSheet.prototype)return()=>{};const i=n.CSSStyleSheet.prototype.insertRule;n.CSSStyleSheet.prototype.insertRule=new Proxy(i,{apply:_((u,h,m)=>{const[f,g]=m,{id:p,styleId:y}=te(h,t,r.styleMirror);return(p&&p!==-1||y&&y!==-1)&&e({id:p,styleId:y,adds:[{rule:f,index:g}]}),u.apply(h,m)})});const o=n.CSSStyleSheet.prototype.deleteRule;n.CSSStyleSheet.prototype.deleteRule=new Proxy(o,{apply:_((u,h,m)=>{const[f]=m,{id:g,styleId:p}=te(h,t,r.styleMirror);return(g&&g!==-1||p&&p!==-1)&&e({id:g,styleId:p,removes:[{index:f}]}),u.apply(h,m)})});let a;n.CSSStyleSheet.prototype.replace&&(a=n.CSSStyleSheet.prototype.replace,n.CSSStyleSheet.prototype.replace=new Proxy(a,{apply:_((u,h,m)=>{const[f]=m,{id:g,styleId:p}=te(h,t,r.styleMirror);return(g&&g!==-1||p&&p!==-1)&&e({id:g,styleId:p,replace:f}),u.apply(h,m)})}));let l;n.CSSStyleSheet.prototype.replaceSync&&(l=n.CSSStyleSheet.prototype.replaceSync,n.CSSStyleSheet.prototype.replaceSync=new Proxy(l,{apply:_((u,h,m)=>{const[f]=m,{id:g,styleId:p}=te(h,t,r.styleMirror);return(g&&g!==-1||p&&p!==-1)&&e({id:g,styleId:p,replaceSync:f}),u.apply(h,m)})}));const s={};Be("CSSGroupingRule")?s.CSSGroupingRule=n.CSSGroupingRule:(Be("CSSMediaRule")&&(s.CSSMediaRule=n.CSSMediaRule),Be("CSSConditionRule")&&(s.CSSConditionRule=n.CSSConditionRule),Be("CSSSupportsRule")&&(s.CSSSupportsRule=n.CSSSupportsRule));const c={};return Object.entries(s).forEach(([u,h])=>{c[u]={insertRule:h.prototype.insertRule,deleteRule:h.prototype.deleteRule},h.prototype.insertRule=new Proxy(c[u].insertRule,{apply:_((m,f,g)=>{const[p,y]=g,{id:w,styleId:S}=te(f.parentStyleSheet,t,r.styleMirror);return(w&&w!==-1||S&&S!==-1)&&e({id:w,styleId:S,adds:[{rule:p,index:[...Fe(f),y||0]}]}),m.apply(f,g)})}),h.prototype.deleteRule=new Proxy(c[u].deleteRule,{apply:_((m,f,g)=>{const[p]=g,{id:y,styleId:w}=te(f.parentStyleSheet,t,r.styleMirror);return(y&&y!==-1||w&&w!==-1)&&e({id:y,styleId:w,removes:[{index:[...Fe(f),p]}]}),m.apply(f,g)})})}),_(()=>{n.CSSStyleSheet.prototype.insertRule=i,n.CSSStyleSheet.prototype.deleteRule=o,a&&(n.CSSStyleSheet.prototype.replace=a),l&&(n.CSSStyleSheet.prototype.replaceSync=l),Object.entries(s).forEach(([u,h])=>{h.prototype.insertRule=c[u].insertRule,h.prototype.deleteRule=c[u].deleteRule})})}function Jt({mirror:e,stylesheetManager:t},r){var n,i,o;let a=null;r.nodeName==="#document"?a=e.getId(r):a=e.getId(r.host);const l=r.nodeName==="#document"?(n=r.defaultView)===null||n===void 0?void 0:n.Document:(o=(i=r.ownerDocument)===null||i===void 0?void 0:i.defaultView)===null||o===void 0?void 0:o.ShadowRoot,s=l?.prototype?Object.getOwnPropertyDescriptor(l?.prototype,"adoptedStyleSheets"):void 0;return a===null||a===-1||!l||!s?()=>{}:(Object.defineProperty(r,"adoptedStyleSheets",{configurable:s.configurable,enumerable:s.enumerable,get(){var c;return(c=s.get)===null||c===void 0?void 0:c.call(this)},set(c){var u;const h=(u=s.set)===null||u===void 0?void 0:u.call(this,c);if(a!==null&&a!==-1)try{t.adoptStyleSheets(c,a)}catch{}return h}}),_(()=>{Object.defineProperty(r,"adoptedStyleSheets",{configurable:s.configurable,enumerable:s.enumerable,get:s.get,set:s.set})}))}function dn({styleDeclarationCb:e,mirror:t,ignoreCSSAttributes:r,stylesheetManager:n},{win:i}){const o=i.CSSStyleDeclaration.prototype.setProperty;i.CSSStyleDeclaration.prototype.setProperty=new Proxy(o,{apply:_((l,s,c)=>{var u;const[h,m,f]=c;if(r.has(h))return o.apply(s,[h,m,f]);const{id:g,styleId:p}=te((u=s.parentRule)===null||u===void 0?void 0:u.parentStyleSheet,t,n.styleMirror);return(g&&g!==-1||p&&p!==-1)&&e({id:g,styleId:p,set:{property:h,value:m,priority:f},index:Fe(s.parentRule)}),l.apply(s,c)})});const a=i.CSSStyleDeclaration.prototype.removeProperty;return i.CSSStyleDeclaration.prototype.removeProperty=new Proxy(a,{apply:_((l,s,c)=>{var u;const[h]=c;if(r.has(h))return a.apply(s,[h]);const{id:m,styleId:f}=te((u=s.parentRule)===null||u===void 0?void 0:u.parentStyleSheet,t,n.styleMirror);return(m&&m!==-1||f&&f!==-1)&&e({id:m,styleId:f,remove:{property:h},index:Fe(s.parentRule)}),l.apply(s,c)})}),_(()=>{i.CSSStyleDeclaration.prototype.setProperty=o,i.CSSStyleDeclaration.prototype.removeProperty=a})}function fn({mediaInteractionCb:e,blockClass:t,blockSelector:r,mirror:n,sampling:i,doc:o}){const a=_(s=>Ie(_(c=>{const u=_e(c);if(!u||U(u,t,r,!0))return;const{currentTime:h,volume:m,muted:f,playbackRate:g,loop:p}=u;e({type:s,id:n.getId(u),currentTime:h,volume:m,muted:f,playbackRate:g,loop:p})}),i.media||500)),l=[W("play",a(0),o),W("pause",a(1),o),W("seeked",a(2),o),W("volumechange",a(3),o),W("ratechange",a(4),o)];return _(()=>{l.forEach(s=>s())})}function hn({fontCb:e,doc:t}){const r=t.defaultView;if(!r)return()=>{};const n=[],i=new WeakMap,o=r.FontFace;r.FontFace=function(s,c,u){const h=new o(s,c,u);return i.set(h,{family:s,buffer:typeof c!="string",descriptors:u,fontSource:typeof c=="string"?c:JSON.stringify(Array.from(new Uint8Array(c)))}),h};const a=ye(t.fonts,"add",function(l){return function(s){return setTimeout(_(()=>{const c=i.get(s);c&&(e(c),i.delete(s))}),0),l.apply(this,[s])}});return n.push(()=>{r.FontFace=o}),n.push(a),_(()=>{n.forEach(l=>l())})}function pn(e){const{doc:t,mirror:r,blockClass:n,blockSelector:i,selectionCb:o}=e;let a=!0;const l=_(()=>{const s=t.getSelection();if(!s||a&&s?.isCollapsed)return;a=s.isCollapsed||!1;const c=[],u=s.rangeCount||0;for(let h=0;h{}:ye(r.customElements,"define",function(i){return function(o,a,l){try{t({define:{name:o}})}catch{console.warn(`Custom element callback failed for ${o}`)}return i.apply(this,[o,a,l])}})}function gn(e,t){const{mutationCb:r,mousemoveCb:n,mouseInteractionCb:i,scrollCb:o,viewportResizeCb:a,inputCb:l,mediaInteractionCb:s,styleSheetRuleCb:c,styleDeclarationCb:u,canvasMutationCb:h,fontCb:m,selectionCb:f,customElementCb:g}=e;e.mutationCb=(...p)=>{t.mutation&&t.mutation(...p),r(...p)},e.mousemoveCb=(...p)=>{t.mousemove&&t.mousemove(...p),n(...p)},e.mouseInteractionCb=(...p)=>{t.mouseInteraction&&t.mouseInteraction(...p),i(...p)},e.scrollCb=(...p)=>{t.scroll&&t.scroll(...p),o(...p)},e.viewportResizeCb=(...p)=>{t.viewportResize&&t.viewportResize(...p),a(...p)},e.inputCb=(...p)=>{t.input&&t.input(...p),l(...p)},e.mediaInteractionCb=(...p)=>{t.mediaInteaction&&t.mediaInteaction(...p),s(...p)},e.styleSheetRuleCb=(...p)=>{t.styleSheetRule&&t.styleSheetRule(...p),c(...p)},e.styleDeclarationCb=(...p)=>{t.styleDeclaration&&t.styleDeclaration(...p),u(...p)},e.canvasMutationCb=(...p)=>{t.canvasMutation&&t.canvasMutation(...p),h(...p)},e.fontCb=(...p)=>{t.font&&t.font(...p),m(...p)},e.selectionCb=(...p)=>{t.selection&&t.selection(...p),f(...p)},e.customElementCb=(...p)=>{t.customElement&&t.customElement(...p),g(...p)}}function yn(e,t={}){const r=e.doc.defaultView;if(!r)return()=>{};gn(e,t);let n;e.recordDOM&&(n=jt(e,e.doc));const i=on(e),o=sn(e),a=Gt(e),l=an(e,{win:r}),s=un(e),c=fn(e);let u=()=>{},h=()=>{},m=()=>{},f=()=>{};e.recordDOM&&(u=cn(e,{win:r}),h=Jt(e,e.doc),m=dn(e,{win:r}),e.collectFonts&&(f=hn(e)));const g=pn(e),p=mn(e),y=[];for(const w of e.plugins)y.push(w.observer(w.callback,r,w.options));return _(()=>{oe.forEach(w=>w.reset()),n?.disconnect(),i(),o(),a(),l(),s(),c(),u(),h(),m(),f(),g(),p(),y.forEach(w=>w())})}function Pe(e){return typeof window[e]<"u"}function Be(e){return!!(typeof window[e]<"u"&&window[e].prototype&&"insertRule"in window[e].prototype&&"deleteRule"in window[e].prototype)}class Xt{constructor(t){this.generateIdFn=t,this.iframeIdToRemoteIdMap=new WeakMap,this.iframeRemoteIdToIdMap=new WeakMap}getId(t,r,n,i){const o=n||this.getIdToRemoteIdMap(t),a=i||this.getRemoteIdToIdMap(t);let l=o.get(r);return l||(l=this.generateIdFn(),o.set(r,l),a.set(l,r)),l}getIds(t,r){const n=this.getIdToRemoteIdMap(t),i=this.getRemoteIdToIdMap(t);return r.map(o=>this.getId(t,o,n,i))}getRemoteId(t,r,n){const i=n||this.getRemoteIdToIdMap(t);if(typeof r!="number")return r;const o=i.get(r);return o||-1}getRemoteIds(t,r){const n=this.getRemoteIdToIdMap(t);return r.map(i=>this.getRemoteId(t,i,n))}reset(t){if(!t){this.iframeIdToRemoteIdMap=new WeakMap,this.iframeRemoteIdToIdMap=new WeakMap;return}this.iframeIdToRemoteIdMap.delete(t),this.iframeRemoteIdToIdMap.delete(t)}getIdToRemoteIdMap(t){let r=this.iframeIdToRemoteIdMap.get(t);return r||(r=new Map,this.iframeIdToRemoteIdMap.set(t,r)),r}getRemoteIdToIdMap(t){let r=this.iframeRemoteIdToIdMap.get(t);return r||(r=new Map,this.iframeRemoteIdToIdMap.set(t,r)),r}}class vn{constructor(t){this.iframes=new WeakMap,this.crossOriginIframeMap=new WeakMap,this.crossOriginIframeMirror=new Xt(Ct),this.crossOriginIframeRootIdMap=new WeakMap,this.mutationCb=t.mutationCb,this.wrappedEmit=t.wrappedEmit,this.stylesheetManager=t.stylesheetManager,this.recordCrossOriginIframes=t.recordCrossOriginIframes,this.crossOriginIframeStyleMirror=new Xt(this.stylesheetManager.styleMirror.generateId.bind(this.stylesheetManager.styleMirror)),this.mirror=t.mirror,this.recordCrossOriginIframes&&window.addEventListener("message",this.handleMessage.bind(this))}addIframe(t){this.iframes.set(t,!0),t.contentWindow&&this.crossOriginIframeMap.set(t.contentWindow,t)}addLoadListener(t){this.loadListener=t}attachIframe(t,r){var n;this.mutationCb({adds:[{parentId:this.mirror.getId(t),nextId:null,node:r}],removes:[],texts:[],attributes:[],isAttachIframe:!0}),(n=this.loadListener)===null||n===void 0||n.call(this,t),t.contentDocument&&t.contentDocument.adoptedStyleSheets&&t.contentDocument.adoptedStyleSheets.length>0&&this.stylesheetManager.adoptStyleSheets(t.contentDocument.adoptedStyleSheets,this.mirror.getId(t.contentDocument))}handleMessage(t){const r=t;if(r.data.type!=="rrweb"||r.origin!==r.data.origin||!t.source)return;const i=this.crossOriginIframeMap.get(t.source);if(!i)return;const o=this.transformCrossOriginEvent(i,r.data.event);o&&this.wrappedEmit(o,r.data.isCheckout)}transformCrossOriginEvent(t,r){var n;switch(r.type){case O.FullSnapshot:{this.crossOriginIframeMirror.reset(t),this.crossOriginIframeStyleMirror.reset(t),this.replaceIdOnNode(r.data.node,t);const i=r.data.node.id;return this.crossOriginIframeRootIdMap.set(t,i),this.patchRootIdOnNode(r.data.node,i),{timestamp:r.timestamp,type:O.IncrementalSnapshot,data:{source:C.Mutation,adds:[{parentId:this.mirror.getId(t),nextId:null,node:r.data.node}],removes:[],texts:[],attributes:[],isAttachIframe:!0}}}case O.Meta:case O.Load:case O.DomContentLoaded:return!1;case O.Plugin:return r;case O.Custom:return this.replaceIds(r.data.payload,t,["id","parentId","previousId","nextId"]),r;case O.IncrementalSnapshot:switch(r.data.source){case C.Mutation:return r.data.adds.forEach(i=>{this.replaceIds(i,t,["parentId","nextId","previousId"]),this.replaceIdOnNode(i.node,t);const o=this.crossOriginIframeRootIdMap.get(t);o&&this.patchRootIdOnNode(i.node,o)}),r.data.removes.forEach(i=>{this.replaceIds(i,t,["parentId","id"])}),r.data.attributes.forEach(i=>{this.replaceIds(i,t,["id"])}),r.data.texts.forEach(i=>{this.replaceIds(i,t,["id"])}),r;case C.Drag:case C.TouchMove:case C.MouseMove:return r.data.positions.forEach(i=>{this.replaceIds(i,t,["id"])}),r;case C.ViewportResize:return!1;case C.MediaInteraction:case C.MouseInteraction:case C.Scroll:case C.CanvasMutation:case C.Input:return this.replaceIds(r.data,t,["id"]),r;case C.StyleSheetRule:case C.StyleDeclaration:return this.replaceIds(r.data,t,["id"]),this.replaceStyleIds(r.data,t,["styleId"]),r;case C.Font:return r;case C.Selection:return r.data.ranges.forEach(i=>{this.replaceIds(i,t,["start","end"])}),r;case C.AdoptedStyleSheet:return this.replaceIds(r.data,t,["id"]),this.replaceStyleIds(r.data,t,["styleIds"]),(n=r.data.styles)===null||n===void 0||n.forEach(i=>{this.replaceStyleIds(i,t,["styleId"])}),r}}return!1}replace(t,r,n,i){for(const o of i)!Array.isArray(r[o])&&typeof r[o]!="number"||(Array.isArray(r[o])?r[o]=t.getIds(n,r[o]):r[o]=t.getId(n,r[o]));return r}replaceIds(t,r,n){return this.replace(this.crossOriginIframeMirror,t,r,n)}replaceStyleIds(t,r,n){return this.replace(this.crossOriginIframeStyleMirror,t,r,n)}replaceIdOnNode(t,r){this.replaceIds(t,r,["id","rootId"]),"childNodes"in t&&t.childNodes.forEach(n=>{this.replaceIdOnNode(n,r)})}patchRootIdOnNode(t,r){t.type!==A.Document&&!t.rootId&&(t.rootId=r),"childNodes"in t&&t.childNodes.forEach(n=>{this.patchRootIdOnNode(n,r)})}}class Sn{constructor(t){this.shadowDoms=new WeakSet,this.restoreHandlers=[],this.mutationCb=t.mutationCb,this.scrollCb=t.scrollCb,this.bypassOptions=t.bypassOptions,this.mirror=t.mirror,this.init()}init(){this.reset(),this.patchAttachShadow(Element,document)}addShadowRoot(t,r){if(!we(t)||this.shadowDoms.has(t))return;this.shadowDoms.add(t);const n=jt(Object.assign(Object.assign({},this.bypassOptions),{doc:r,mutationCb:this.mutationCb,mirror:this.mirror,shadowDomManager:this}),t);this.restoreHandlers.push(()=>n.disconnect()),this.restoreHandlers.push(Gt(Object.assign(Object.assign({},this.bypassOptions),{scrollCb:this.scrollCb,doc:t,mirror:this.mirror}))),setTimeout(()=>{t.adoptedStyleSheets&&t.adoptedStyleSheets.length>0&&this.bypassOptions.stylesheetManager.adoptStyleSheets(t.adoptedStyleSheets,this.mirror.getId(t.host)),this.restoreHandlers.push(Jt({mirror:this.mirror,stylesheetManager:this.bypassOptions.stylesheetManager},t))},0)}observeAttachShadow(t){!t.contentWindow||!t.contentDocument||this.patchAttachShadow(t.contentWindow.Element,t.contentDocument)}patchAttachShadow(t,r){const n=this;this.restoreHandlers.push(ye(t.prototype,"attachShadow",function(i){return function(o){const a=i.call(this,o);return this.shadowRoot&&Bt(this)&&n.addShadowRoot(this.shadowRoot,r),a}}))}reset(){this.restoreHandlers.forEach(t=>{try{t()}catch{}}),this.restoreHandlers=[],this.shadowDoms=new WeakSet}}/*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any @@ -13,10 +13,10 @@ or you can use record.mirror to access the mirror instance during recording.`;le LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ***************************************************************************** */function Sn(e,t){var r={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var i=0,n=Object.getOwnPropertySymbols(e);i"u"?[]:new Uint8Array(256),We=0;We>2],i+=ve[(t[r]&3)<<4|t[r+1]>>4],i+=ve[(t[r+1]&15)<<2|t[r+2]>>6],i+=ve[t[r+2]&63];return n%3===2?i=i.substring(0,i.length-1)+"=":n%3===1&&(i=i.substring(0,i.length-2)+"=="),i};const Xt=new Map;function Mn(e,t){let r=Xt.get(e);return r||(r=new Map,Xt.set(e,r)),r.has(t)||r.set(t,[]),r.get(t)}const Kt=(e,t,r)=>{if(!e||!(Qt(e,t)||typeof e=="object"))return;const n=e.constructor.name,i=Mn(r,n);let o=i.indexOf(e);return o===-1&&(o=i.length,i.push(e)),o};function Ue(e,t,r){if(e instanceof Array)return e.map(n=>Ue(n,t,r));if(e===null)return e;if(e instanceof Float32Array||e instanceof Float64Array||e instanceof Int32Array||e instanceof Uint32Array||e instanceof Uint8Array||e instanceof Uint16Array||e instanceof Int16Array||e instanceof Int8Array||e instanceof Uint8ClampedArray)return{rr_type:e.constructor.name,args:[Object.values(e)]};if(e instanceof ArrayBuffer){const n=e.constructor.name,i=In(e);return{rr_type:n,base64:i}}else{if(e instanceof DataView)return{rr_type:e.constructor.name,args:[Ue(e.buffer,t,r),e.byteOffset,e.byteLength]};if(e instanceof HTMLImageElement){const n=e.constructor.name,{src:i}=e;return{rr_type:n,src:i}}else if(e instanceof HTMLCanvasElement){const n="HTMLImageElement",i=e.toDataURL();return{rr_type:n,src:i}}else{if(e instanceof ImageData)return{rr_type:e.constructor.name,args:[Ue(e.data,t,r),e.width,e.height]};if(Qt(e,t)||typeof e=="object"){const n=e.constructor.name,i=Kt(e,t,r);return{rr_type:n,index:i}}}}return e}const Yt=(e,t,r)=>e.map(n=>Ue(n,t,r)),Qt=(e,t)=>!!["WebGLActiveInfo","WebGLBuffer","WebGLFramebuffer","WebGLProgram","WebGLRenderbuffer","WebGLShader","WebGLShaderPrecisionFormat","WebGLTexture","WebGLUniformLocation","WebGLVertexArrayObject","WebGLVertexArrayObjectOES"].filter(i=>typeof t[i]=="function").find(i=>e instanceof t[i]);function Cn(e,t,r,n){const i=[],o=Object.getOwnPropertyNames(t.CanvasRenderingContext2D.prototype);for(const a of o)try{if(typeof t.CanvasRenderingContext2D.prototype[a]!="function")continue;const l=ge(t.CanvasRenderingContext2D.prototype,a,function(s){return function(...c){return U(this.canvas,r,n,!0)||setTimeout(()=>{const u=Yt(c,t,this);e(this.canvas,{type:ye["2D"],property:a,args:u})},0),s.apply(this,c)}});i.push(l)}catch{const s=Ae(t.CanvasRenderingContext2D.prototype,a,{set(c){e(this.canvas,{type:ye["2D"],property:a,args:[c],setter:!0})}});i.push(s)}return()=>{i.forEach(a=>a())}}function _n(e){return e==="experimental-webgl"?"webgl":e}function Zt(e,t,r,n){const i=[];try{const o=ge(e.HTMLCanvasElement.prototype,"getContext",function(a){return function(l,...s){if(!U(this,t,r,!0)){const c=_n(l);if("__context"in this||(this.__context=c),n&&["webgl","webgl2"].includes(c))if(s[0]&&typeof s[0]=="object"){const u=s[0];u.preserveDrawingBuffer||(u.preserveDrawingBuffer=!0)}else s.splice(0,1,{preserveDrawingBuffer:!0})}return a.apply(this,[l,...s])}});i.push(o)}catch{console.error("failed to patch HTMLCanvasElement.prototype.getContext")}return()=>{i.forEach(o=>o())}}function er(e,t,r,n,i,o,a){const l=[],s=Object.getOwnPropertyNames(e);for(const c of s)if(!["isContextLost","canvas","drawingBufferWidth","drawingBufferHeight"].includes(c))try{if(typeof e[c]!="function")continue;const u=ge(e,c,function(f){return function(...m){const h=f.apply(this,m);if(Kt(h,a,this),"tagName"in this.canvas&&!U(this.canvas,n,i,!0)){const g=Yt(m,a,this),p={type:t,property:c,args:g};r(this.canvas,p)}return h}});l.push(u)}catch{const f=Ae(e,c,{set(m){r(this.canvas,{type:t,property:c,args:[m],setter:!0})}});l.push(f)}return l}function On(e,t,r,n,i){const o=[];return o.push(...er(t.WebGLRenderingContext.prototype,ye.WebGL,e,r,n,i,t)),typeof t.WebGL2RenderingContext<"u"&&o.push(...er(t.WebGL2RenderingContext.prototype,ye.WebGL2,e,r,n,i,t)),()=>{o.forEach(a=>a())}}function En(e,t){var r=t===void 0?null:t,n=e.toString(),i=n.split(` + ***************************************************************************** */function bn(e,t){var r={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var i=0,n=Object.getOwnPropertySymbols(e);i"u"?[]:new Uint8Array(256),We=0;We>2],i+=Se[(t[r]&3)<<4|t[r+1]>>4],i+=Se[(t[r+1]&15)<<2|t[r+2]>>6],i+=Se[t[r+2]&63];return n%3===2?i=i.substring(0,i.length-1)+"=":n%3===1&&(i=i.substring(0,i.length-2)+"=="),i};const Kt=new Map;function Cn(e,t){let r=Kt.get(e);return r||(r=new Map,Kt.set(e,r)),r.has(t)||r.set(t,[]),r.get(t)}const Yt=(e,t,r)=>{if(!e||!(Zt(e,t)||typeof e=="object"))return;const n=e.constructor.name,i=Cn(r,n);let o=i.indexOf(e);return o===-1&&(o=i.length,i.push(e)),o};function Ue(e,t,r){if(e instanceof Array)return e.map(n=>Ue(n,t,r));if(e===null)return e;if(e instanceof Float32Array||e instanceof Float64Array||e instanceof Int32Array||e instanceof Uint32Array||e instanceof Uint8Array||e instanceof Uint16Array||e instanceof Int16Array||e instanceof Int8Array||e instanceof Uint8ClampedArray)return{rr_type:e.constructor.name,args:[Object.values(e)]};if(e instanceof ArrayBuffer){const n=e.constructor.name,i=In(e);return{rr_type:n,base64:i}}else{if(e instanceof DataView)return{rr_type:e.constructor.name,args:[Ue(e.buffer,t,r),e.byteOffset,e.byteLength]};if(e instanceof HTMLImageElement){const n=e.constructor.name,{src:i}=e;return{rr_type:n,src:i}}else if(e instanceof HTMLCanvasElement){const n="HTMLImageElement",i=e.toDataURL();return{rr_type:n,src:i}}else{if(e instanceof ImageData)return{rr_type:e.constructor.name,args:[Ue(e.data,t,r),e.width,e.height]};if(Zt(e,t)||typeof e=="object"){const n=e.constructor.name,i=Yt(e,t,r);return{rr_type:n,index:i}}}}return e}const Qt=(e,t,r)=>e.map(n=>Ue(n,t,r)),Zt=(e,t)=>!!["WebGLActiveInfo","WebGLBuffer","WebGLFramebuffer","WebGLProgram","WebGLRenderbuffer","WebGLShader","WebGLShaderPrecisionFormat","WebGLTexture","WebGLUniformLocation","WebGLVertexArrayObject","WebGLVertexArrayObjectOES"].filter(i=>typeof t[i]=="function").find(i=>e instanceof t[i]);function _n(e,t,r,n){const i=[],o=Object.getOwnPropertyNames(t.CanvasRenderingContext2D.prototype);for(const a of o)try{if(typeof t.CanvasRenderingContext2D.prototype[a]!="function")continue;const l=ye(t.CanvasRenderingContext2D.prototype,a,function(s){return function(...c){return U(this.canvas,r,n,!0)||setTimeout(()=>{const u=Qt(c,t,this);e(this.canvas,{type:ve["2D"],property:a,args:u})},0),s.apply(this,c)}});i.push(l)}catch{const s=Ae(t.CanvasRenderingContext2D.prototype,a,{set(c){e(this.canvas,{type:ve["2D"],property:a,args:[c],setter:!0})}});i.push(s)}return()=>{i.forEach(a=>a())}}function On(e){return e==="experimental-webgl"?"webgl":e}function er(e,t,r,n){const i=[];try{const o=ye(e.HTMLCanvasElement.prototype,"getContext",function(a){return function(l,...s){if(!U(this,t,r,!0)){const c=On(l);if("__context"in this||(this.__context=c),n&&["webgl","webgl2"].includes(c))if(s[0]&&typeof s[0]=="object"){const u=s[0];u.preserveDrawingBuffer||(u.preserveDrawingBuffer=!0)}else s.splice(0,1,{preserveDrawingBuffer:!0})}return a.apply(this,[l,...s])}});i.push(o)}catch{console.error("failed to patch HTMLCanvasElement.prototype.getContext")}return()=>{i.forEach(o=>o())}}function tr(e,t,r,n,i,o,a){const l=[],s=Object.getOwnPropertyNames(e);for(const c of s)if(!["isContextLost","canvas","drawingBufferWidth","drawingBufferHeight"].includes(c))try{if(typeof e[c]!="function")continue;const u=ye(e,c,function(h){return function(...m){const f=h.apply(this,m);if(Yt(f,a,this),"tagName"in this.canvas&&!U(this.canvas,n,i,!0)){const g=Qt(m,a,this),p={type:t,property:c,args:g};r(this.canvas,p)}return f}});l.push(u)}catch{const h=Ae(e,c,{set(m){r(this.canvas,{type:t,property:c,args:[m],setter:!0})}});l.push(h)}return l}function En(e,t,r,n,i){const o=[];return o.push(...tr(t.WebGLRenderingContext.prototype,ve.WebGL,e,r,n,i,t)),typeof t.WebGL2RenderingContext<"u"&&o.push(...tr(t.WebGL2RenderingContext.prototype,ve.WebGL2,e,r,n,i,t)),()=>{o.forEach(a=>a())}}function kn(e,t){var r=t===void 0?null:t,n=e.toString(),i=n.split(` `);i.pop(),i.shift();for(var o=i[0].search(/\S/),a=/(['"])__worker_loader_strict__(['"])/g,l=0,s=i.length;l"u"?[]:new Uint8Array(256),n=0;n>2],h+=t[(u[f]&3)<<4|u[f+1]>>4],h+=t[(u[f+1]&15)<<2|u[f+2]>>6],h+=t[u[f+2]&63];return m%3===2?h=h.substring(0,h.length-1)+"=":m%3===1&&(h=h.substring(0,h.length-2)+"=="),h};const o=new Map,a=new Map;function l(c,u,f){return e(this,void 0,void 0,function*(){const m=`${c}-${u}`;if("OffscreenCanvas"in globalThis){if(a.has(m))return a.get(m);const h=new OffscreenCanvas(c,u);h.getContext("2d");const p=yield(yield h.convertToBlob(f)).arrayBuffer(),y=i(p);return a.set(m,y),y}else return""})}const s=self;s.onmessage=function(c){return e(this,void 0,void 0,function*(){if("OffscreenCanvas"in globalThis){const{id:u,bitmap:f,width:m,height:h,dataURLOptions:g}=c.data,p=l(m,h,g),y=new OffscreenCanvas(m,h);y.getContext("2d").drawImage(f,0,0),f.close();const S=yield y.convertToBlob(g),v=S.type,b=yield S.arrayBuffer(),I=i(b);if(!o.has(u)&&(yield p)===I)return o.set(u,I),s.postMessage({id:u});if(o.get(u)===I)return s.postMessage({id:u});s.postMessage({id:u,type:v,base64:I,width:m,height:h}),o.set(u,I)}else return s.postMessage({id:c.data.id})})}})()},null);class Tn{reset(){this.pendingCanvasMutations.clear(),this.resetObservers&&this.resetObservers()}freeze(){this.frozen=!0}unfreeze(){this.frozen=!1}lock(){this.locked=!0}unlock(){this.locked=!1}constructor(t){this.pendingCanvasMutations=new Map,this.rafStamps={latestId:0,invokeId:null},this.frozen=!1,this.locked=!1,this.processMutation=(s,c)=>{(this.rafStamps.invokeId&&this.rafStamps.latestId!==this.rafStamps.invokeId||!this.rafStamps.invokeId)&&(this.rafStamps.invokeId=this.rafStamps.latestId),this.pendingCanvasMutations.has(s)||this.pendingCanvasMutations.set(s,[]),this.pendingCanvasMutations.get(s).push(c)};const{sampling:r="all",win:n,blockClass:i,blockSelector:o,recordCanvas:a,dataURLOptions:l}=t;this.mutationCb=t.mutationCb,this.mirror=t.mirror,a&&r==="all"&&this.initCanvasMutationObserver(n,i,o),a&&typeof r=="number"&&this.initCanvasFPSObserver(r,n,i,o,{dataURLOptions:l})}initCanvasFPSObserver(t,r,n,i,o){const a=Zt(r,n,i,!0),l=new Map,s=new Rn;s.onmessage=g=>{const{id:p}=g.data;if(l.set(p,!1),!("base64"in g.data))return;const{base64:y,type:w,width:S,height:v}=g.data;this.mutationCb({id:p,type:ye["2D"],commands:[{property:"clearRect",args:[0,0,S,v]},{property:"drawImage",args:[{rr_type:"ImageBitmap",args:[{rr_type:"Blob",data:[{rr_type:"ArrayBuffer",base64:y}],type:w}]},0,0]}]})};const c=1e3/t;let u=0,f;const m=()=>{const g=[];return r.document.querySelectorAll("canvas").forEach(p=>{U(p,n,i,!0)||g.push(p)}),g},h=g=>{if(u&&g-ubn(this,void 0,void 0,function*(){var y;const w=this.mirror.getId(p);if(l.get(w)||p.width===0||p.height===0)return;if(l.set(w,!0),["webgl","webgl2"].includes(p.__context)){const v=p.getContext(p.__context);((y=v?.getContextAttributes())===null||y===void 0?void 0:y.preserveDrawingBuffer)===!1&&v.clear(v.COLOR_BUFFER_BIT)}const S=yield createImageBitmap(p);s.postMessage({id:w,bitmap:S,width:p.width,height:p.height,dataURLOptions:o.dataURLOptions},[S])})),f=requestAnimationFrame(h)};f=requestAnimationFrame(h),this.resetObservers=()=>{a(),cancelAnimationFrame(f)}}initCanvasMutationObserver(t,r,n){this.startRAFTimestamping(),this.startPendingCanvasMutationFlusher();const i=Zt(t,r,n,!1),o=Cn(this.processMutation.bind(this),t,r,n),a=On(this.processMutation.bind(this),t,r,n,this.mirror);this.resetObservers=()=>{i(),o(),a()}}startPendingCanvasMutationFlusher(){requestAnimationFrame(()=>this.flushPendingCanvasMutations())}startRAFTimestamping(){const t=r=>{this.rafStamps.latestId=r,requestAnimationFrame(t)};requestAnimationFrame(t)}flushPendingCanvasMutations(){this.pendingCanvasMutations.forEach((t,r)=>{const n=this.mirror.getId(r);this.flushPendingCanvasMutationFor(r,n)}),requestAnimationFrame(()=>this.flushPendingCanvasMutations())}flushPendingCanvasMutationFor(t,r){if(this.frozen||this.locked)return;const n=this.pendingCanvasMutations.get(t);if(!n||r===-1)return;const i=n.map(a=>Sn(a,["type"])),{type:o}=n[0];this.mutationCb({id:r,type:o,commands:i}),this.pendingCanvasMutations.delete(t)}}class Dn{constructor(t){this.trackedLinkElements=new WeakSet,this.styleMirror=new Kr,this.mutationCb=t.mutationCb,this.adoptedStyleSheetCb=t.adoptedStyleSheetCb}attachLinkElement(t,r){"_cssText"in r.attributes&&this.mutationCb({adds:[],removes:[],texts:[],attributes:[{id:r.id,attributes:r.attributes}]}),this.trackLinkElement(t)}trackLinkElement(t){this.trackedLinkElements.has(t)||(this.trackedLinkElements.add(t),this.trackStylesheetInLinkElement(t))}adoptStyleSheets(t,r){if(t.length===0)return;const n={id:r,styleIds:[]},i=[];for(const o of t){let a;this.styleMirror.has(o)?a=this.styleMirror.getId(o):(a=this.styleMirror.add(o),i.push({styleId:a,rules:Array.from(o.rules||CSSRule,(l,s)=>({rule:St(l),index:s}))})),n.styleIds.push(a)}i.length>0&&(n.styles=i),this.adoptedStyleSheetCb(n)}reset(){this.styleMirror.reset(),this.trackedLinkElements=new WeakSet}trackStylesheetInLinkElement(t){}}class Nn{constructor(){this.nodeMap=new WeakMap,this.loop=!0,this.periodicallyClear()}periodicallyClear(){requestAnimationFrame(()=>{this.clear(),this.loop&&this.periodicallyClear()})}inOtherBuffer(t,r){const n=this.nodeMap.get(t);return n&&Array.from(n).some(i=>i!==r)}add(t,r){this.nodeMap.set(t,(this.nodeMap.get(t)||new Set).add(r))}clear(){this.nodeMap=new WeakMap}destroy(){this.loop=!1}}function L(e){return Object.assign(Object.assign({},e),{timestamp:Le()})}let N,ze,lt,He=!1;const V=_r();function Oe(e={}){const{emit:t,checkoutEveryNms:r,checkoutEveryNth:n,blockClass:i="rr-block",blockSelector:o=null,ignoreClass:a="rr-ignore",ignoreSelector:l=null,maskTextClass:s="rr-mask",maskTextSelector:c=null,inlineStylesheet:u=!0,maskAllInputs:f,maskInputOptions:m,slimDOMOptions:h,maskInputFn:g,maskTextFn:p,hooks:y,packFn:w,sampling:S={},dataURLOptions:v={},mousemoveWait:b,recordDOM:I=!0,recordCanvas:B=!1,recordCrossOriginIframes:F=!1,recordAfter:x=e.recordAfter==="DOMContentLoaded"?e.recordAfter:"load",userTriggeredOnInput:R=!1,collectFonts:j=!1,inlineImages:G=!1,plugins:E,keepIframeSrcFn:le=()=>!1,ignoreCSSAttributes:z=new Set([]),errorHandler:ne}=e;tn(ne);const Z=F?window.parent===window:!0;let Qe=!1;if(!Z)try{window.parent.document&&(Qe=!1)}catch{Qe=!0}if(Z&&!t)throw new Error("emit function is required");b!==void 0&&S.mousemove===void 0&&(S.mousemove=b),V.reset();const pt=f===!0?{color:!0,date:!0,"datetime-local":!0,email:!0,month:!0,number:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0,textarea:!0,select:!0,password:!0}:m!==void 0?m:{password:!0},mt=h===!0||h==="all"?{script:!0,comment:!0,headFavicon:!0,headWhitespace:!0,headMetaSocial:!0,headMetaRobots:!0,headMetaHttpEquiv:!0,headMetaVerification:!0,headMetaAuthorship:h==="all",headMetaDescKeywords:h==="all"}:h||{};Xr();let mr,gt=0;const gr=M=>{for(const K of E||[])K.eventProcessor&&(M=K.eventProcessor(M));return w&&!Qe&&(M=w(M)),M};N=(M,K)=>{var D;if(!((D=oe[0])===null||D===void 0)&&D.isFrozen()&&M.type!==O.FullSnapshot&&!(M.type===O.IncrementalSnapshot&&M.data.source===C.Mutation)&&oe.forEach(H=>H.unfreeze()),Z)t?.(gr(M),K);else if(Qe){const H={type:"rrweb",event:gr(M),origin:window.location.origin,isCheckout:K};window.parent.postMessage(H,"*")}if(M.type===O.FullSnapshot)mr=M,gt=0;else if(M.type===O.IncrementalSnapshot){if(M.data.source===C.Mutation&&M.data.isAttachIframe)return;gt++;const H=n&>>=n,de=r&&M.timestamp-mr.timestamp>r;(H||de)&&ze(!0)}};const Ze=M=>{N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Mutation},M)}))},yr=M=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Scroll},M)})),vr=M=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.CanvasMutation},M)})),ei=M=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.AdoptedStyleSheet},M)})),ue=new Dn({mutationCb:Ze,adoptedStyleSheetCb:ei}),ce=new yn({mirror:V,mutationCb:Ze,stylesheetManager:ue,recordCrossOriginIframes:F,wrappedEmit:N});for(const M of E||[])M.getMirror&&M.getMirror({nodeMirror:V,crossOriginIframeMirror:ce.crossOriginIframeMirror,crossOriginIframeStyleMirror:ce.crossOriginIframeStyleMirror});const yt=new Nn;lt=new Tn({recordCanvas:B,mutationCb:vr,win:window,blockClass:i,blockSelector:o,mirror:V,sampling:S.canvas,dataURLOptions:v});const et=new vn({mutationCb:Ze,scrollCb:yr,bypassOptions:{blockClass:i,blockSelector:o,maskTextClass:s,maskTextSelector:c,inlineStylesheet:u,maskInputOptions:pt,dataURLOptions:v,maskTextFn:p,maskInputFn:g,recordCanvas:B,inlineImages:G,sampling:S,slimDOMOptions:mt,iframeManager:ce,stylesheetManager:ue,canvasManager:lt,keepIframeSrcFn:le,processedNodeManager:yt},mirror:V});ze=(M=!1)=>{if(!I)return;N(L({type:O.Meta,data:{href:window.location.href,width:Tt(),height:Rt()}}),M),ue.reset(),et.init(),oe.forEach(D=>D.lock());const K=Vr(document,{mirror:V,blockClass:i,blockSelector:o,maskTextClass:s,maskTextSelector:c,inlineStylesheet:u,maskAllInputs:pt,maskTextFn:p,slimDOM:mt,dataURLOptions:v,recordCanvas:B,inlineImages:G,onSerialize:D=>{At(D,V)&&ce.addIframe(D),Lt(D,V)&&ue.trackLinkElement(D),st(D)&&et.addShadowRoot(D.shadowRoot,document)},onIframeLoad:(D,H)=>{ce.attachIframe(D,H),et.observeAttachShadow(D)},onStylesheetLoad:(D,H)=>{ue.attachLinkElement(D,H)},keepIframeSrcFn:le});if(!K)return console.warn("Failed to snapshot the document");N(L({type:O.FullSnapshot,data:{node:K,initialOffset:xt(window)}}),M),oe.forEach(D=>D.unlock()),document.adoptedStyleSheets&&document.adoptedStyleSheets.length>0&&ue.adoptStyleSheets(document.adoptedStyleSheets,V.getId(document))};try{const M=[],K=H=>{var de;return _(gn)({mutationCb:Ze,mousemoveCb:(T,vt)=>N(L({type:O.IncrementalSnapshot,data:{source:vt,positions:T}})),mouseInteractionCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.MouseInteraction},T)})),scrollCb:yr,viewportResizeCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.ViewportResize},T)})),inputCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Input},T)})),mediaInteractionCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.MediaInteraction},T)})),styleSheetRuleCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.StyleSheetRule},T)})),styleDeclarationCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.StyleDeclaration},T)})),canvasMutationCb:vr,fontCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Font},T)})),selectionCb:T=>{N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Selection},T)}))},customElementCb:T=>{N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.CustomElement},T)}))},blockClass:i,ignoreClass:a,ignoreSelector:l,maskTextClass:s,maskTextSelector:c,maskInputOptions:pt,inlineStylesheet:u,sampling:S,recordDOM:I,recordCanvas:B,inlineImages:G,userTriggeredOnInput:R,collectFonts:j,doc:H,maskInputFn:g,maskTextFn:p,keepIframeSrcFn:le,blockSelector:o,slimDOMOptions:mt,dataURLOptions:v,mirror:V,iframeManager:ce,stylesheetManager:ue,shadowDomManager:et,processedNodeManager:yt,canvasManager:lt,ignoreCSSAttributes:z,plugins:((de=E?.filter(T=>T.observer))===null||de===void 0?void 0:de.map(T=>({observer:T.observer,options:T.options,callback:vt=>N(L({type:O.Plugin,data:{plugin:T.name,payload:vt}}))})))||[]},y)};ce.addLoadListener(H=>{try{M.push(K(H.contentDocument))}catch(de){console.warn(de)}});const D=()=>{ze(),M.push(K(document)),He=!0};return document.readyState==="interactive"||document.readyState==="complete"?D():(M.push(W("DOMContentLoaded",()=>{N(L({type:O.DomContentLoaded,data:{}})),x==="DOMContentLoaded"&&D()})),M.push(W("load",()=>{N(L({type:O.Load,data:{}})),x==="load"&&D()},window))),()=>{M.forEach(H=>H()),yt.destroy(),He=!1,rn()}}catch(M){console.warn(M)}}Oe.addCustomEvent=(e,t)=>{if(!He)throw new Error("please add custom event after start recording");N(L({type:O.Custom,data:{tag:e,payload:t}}))},Oe.freezePage=()=>{oe.forEach(e=>e.freeze())},Oe.takeFullSnapshot=e=>{if(!He)throw new Error("please take full snapshot after start recording");ze(e)},Oe.mirror=V;var tr=(e=>(e[e.DomContentLoaded=0]="DomContentLoaded",e[e.Load=1]="Load",e[e.FullSnapshot=2]="FullSnapshot",e[e.IncrementalSnapshot=3]="IncrementalSnapshot",e[e.Meta=4]="Meta",e[e.Custom=5]="Custom",e[e.Plugin=6]="Plugin",e))(tr||{}),Y=(e=>(e[e.Mutation=0]="Mutation",e[e.MouseMove=1]="MouseMove",e[e.MouseInteraction=2]="MouseInteraction",e[e.Scroll=3]="Scroll",e[e.ViewportResize=4]="ViewportResize",e[e.Input=5]="Input",e[e.TouchMove=6]="TouchMove",e[e.MediaInteraction=7]="MediaInteraction",e[e.StyleSheetRule=8]="StyleSheetRule",e[e.CanvasMutation=9]="CanvasMutation",e[e.Font=10]="Font",e[e.Log=11]="Log",e[e.Drag=12]="Drag",e[e.StyleDeclaration=13]="StyleDeclaration",e[e.Selection=14]="Selection",e[e.AdoptedStyleSheet=15]="AdoptedStyleSheet",e[e.CustomElement=16]="CustomElement",e))(Y||{}),rr={DEBUG:!1,LIB_VERSION:"2.55.0"},P;if(typeof window>"u"){var nr={hostname:""};P={navigator:{userAgent:""},document:{location:nr,referrer:""},screen:{width:0,height:0},location:nr}}else P=window;var $e=24*60*60*1e3,qe=Array.prototype,An=Function.prototype,ir=Object.prototype,se=qe.slice,Ee=ir.toString,je=ir.hasOwnProperty,ke=P.console,xe=P.navigator,q=P.document,Ge=P.opera,Ve=P.screen,ae=xe.userAgent,ut=An.bind,or=qe.forEach,sr=qe.indexOf,ar=qe.map,Ln=Array.isArray,ct={},d={trim:function(e){return e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")}},J={log:function(){},warn:function(){},error:function(){},critical:function(){if(!d.isUndefined(ke)&&ke){var e=["Mixpanel error:"].concat(d.toArray(arguments));try{ke.error.apply(ke,e)}catch{d.each(e,function(r){ke.error(r)})}}}},dt=function(e,t){return function(){return arguments[0]="["+t+"] "+arguments[0],e.apply(J,arguments)}},Je=function(e){return{log:dt(J.log,e),error:dt(J.error,e),critical:dt(J.critical,e)}};d.bind=function(e,t){var r,n;if(ut&&e.bind===ut)return ut.apply(e,se.call(arguments,1));if(!d.isFunction(e))throw new TypeError;return r=se.call(arguments,2),n=function(){if(!(this instanceof n))return e.apply(t,r.concat(se.call(arguments)));var i={};i.prototype=e.prototype;var o=new i;i.prototype=null;var a=e.apply(o,r.concat(se.call(arguments)));return Object(a)===a?a:o},n},d.each=function(e,t,r){if(e!=null){if(or&&e.forEach===or)e.forEach(t,r);else if(e.length===+e.length){for(var n=0,i=e.length;n0&&(t[n]=r)}),t},d.truncate=function(e,t){var r;return typeof e=="string"?r=e.slice(0,t):d.isArray(e)?(r=[],d.each(e,function(n){r.push(d.truncate(n,t))})):d.isObject(e)?(r={},d.each(e,function(n,i){r[i]=d.truncate(n,t)})):r=e,r},d.JSONEncode=function(){return function(e){var t=e,r=function(i){var o=/[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,a={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};return o.lastIndex=0,o.test(i)?'"'+i.replace(o,function(l){var s=a[l];return typeof s=="string"?s:"\\u"+("0000"+l.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+i+'"'},n=function(i,o){var a="",l=" ",s=0,c="",u="",f=0,m=a,h=[],g=o[i];switch(g&&typeof g=="object"&&typeof g.toJSON=="function"&&(g=g.toJSON(i)),typeof g){case"string":return r(g);case"number":return isFinite(g)?String(g):"null";case"boolean":case"null":return String(g);case"object":if(!g)return"null";if(a+=l,h=[],Ee.apply(g)==="[object Array]"){for(f=g.length,s=0;s"u"?[]:new Uint8Array(256),n=0;n>2],f+=t[(u[h]&3)<<4|u[h+1]>>4],f+=t[(u[h+1]&15)<<2|u[h+2]>>6],f+=t[u[h+2]&63];return m%3===2?f=f.substring(0,f.length-1)+"=":m%3===1&&(f=f.substring(0,f.length-2)+"=="),f};const o=new Map,a=new Map;function l(c,u,h){return e(this,void 0,void 0,function*(){const m=`${c}-${u}`;if("OffscreenCanvas"in globalThis){if(a.has(m))return a.get(m);const f=new OffscreenCanvas(c,u);f.getContext("2d");const p=yield(yield f.convertToBlob(h)).arrayBuffer(),y=i(p);return a.set(m,y),y}else return""})}const s=self;s.onmessage=function(c){return e(this,void 0,void 0,function*(){if("OffscreenCanvas"in globalThis){const{id:u,bitmap:h,width:m,height:f,dataURLOptions:g}=c.data,p=l(m,f,g),y=new OffscreenCanvas(m,f);y.getContext("2d").drawImage(h,0,0),h.close();const S=yield y.convertToBlob(g),v=S.type,b=yield S.arrayBuffer(),M=i(b);if(!o.has(u)&&(yield p)===M)return o.set(u,M),s.postMessage({id:u});if(o.get(u)===M)return s.postMessage({id:u});s.postMessage({id:u,type:v,base64:M,width:m,height:f}),o.set(u,M)}else return s.postMessage({id:c.data.id})})}})()},null);class Dn{reset(){this.pendingCanvasMutations.clear(),this.resetObservers&&this.resetObservers()}freeze(){this.frozen=!0}unfreeze(){this.frozen=!1}lock(){this.locked=!0}unlock(){this.locked=!1}constructor(t){this.pendingCanvasMutations=new Map,this.rafStamps={latestId:0,invokeId:null},this.frozen=!1,this.locked=!1,this.processMutation=(s,c)=>{(this.rafStamps.invokeId&&this.rafStamps.latestId!==this.rafStamps.invokeId||!this.rafStamps.invokeId)&&(this.rafStamps.invokeId=this.rafStamps.latestId),this.pendingCanvasMutations.has(s)||this.pendingCanvasMutations.set(s,[]),this.pendingCanvasMutations.get(s).push(c)};const{sampling:r="all",win:n,blockClass:i,blockSelector:o,recordCanvas:a,dataURLOptions:l}=t;this.mutationCb=t.mutationCb,this.mirror=t.mirror,a&&r==="all"&&this.initCanvasMutationObserver(n,i,o),a&&typeof r=="number"&&this.initCanvasFPSObserver(r,n,i,o,{dataURLOptions:l})}initCanvasFPSObserver(t,r,n,i,o){const a=er(r,n,i,!0),l=new Map,s=new Tn;s.onmessage=g=>{const{id:p}=g.data;if(l.set(p,!1),!("base64"in g.data))return;const{base64:y,type:w,width:S,height:v}=g.data;this.mutationCb({id:p,type:ve["2D"],commands:[{property:"clearRect",args:[0,0,S,v]},{property:"drawImage",args:[{rr_type:"ImageBitmap",args:[{rr_type:"Blob",data:[{rr_type:"ArrayBuffer",base64:y}],type:w}]},0,0]}]})};const c=1e3/t;let u=0,h;const m=()=>{const g=[];return r.document.querySelectorAll("canvas").forEach(p=>{U(p,n,i,!0)||g.push(p)}),g},f=g=>{if(u&&g-uwn(this,void 0,void 0,function*(){var y;const w=this.mirror.getId(p);if(l.get(w)||p.width===0||p.height===0)return;if(l.set(w,!0),["webgl","webgl2"].includes(p.__context)){const v=p.getContext(p.__context);((y=v?.getContextAttributes())===null||y===void 0?void 0:y.preserveDrawingBuffer)===!1&&v.clear(v.COLOR_BUFFER_BIT)}const S=yield createImageBitmap(p);s.postMessage({id:w,bitmap:S,width:p.width,height:p.height,dataURLOptions:o.dataURLOptions},[S])})),h=requestAnimationFrame(f)};h=requestAnimationFrame(f),this.resetObservers=()=>{a(),cancelAnimationFrame(h)}}initCanvasMutationObserver(t,r,n){this.startRAFTimestamping(),this.startPendingCanvasMutationFlusher();const i=er(t,r,n,!1),o=_n(this.processMutation.bind(this),t,r,n),a=En(this.processMutation.bind(this),t,r,n,this.mirror);this.resetObservers=()=>{i(),o(),a()}}startPendingCanvasMutationFlusher(){requestAnimationFrame(()=>this.flushPendingCanvasMutations())}startRAFTimestamping(){const t=r=>{this.rafStamps.latestId=r,requestAnimationFrame(t)};requestAnimationFrame(t)}flushPendingCanvasMutations(){this.pendingCanvasMutations.forEach((t,r)=>{const n=this.mirror.getId(r);this.flushPendingCanvasMutationFor(r,n)}),requestAnimationFrame(()=>this.flushPendingCanvasMutations())}flushPendingCanvasMutationFor(t,r){if(this.frozen||this.locked)return;const n=this.pendingCanvasMutations.get(t);if(!n||r===-1)return;const i=n.map(a=>bn(a,["type"])),{type:o}=n[0];this.mutationCb({id:r,type:o,commands:i}),this.pendingCanvasMutations.delete(t)}}class Nn{constructor(t){this.trackedLinkElements=new WeakSet,this.styleMirror=new Yr,this.mutationCb=t.mutationCb,this.adoptedStyleSheetCb=t.adoptedStyleSheetCb}attachLinkElement(t,r){"_cssText"in r.attributes&&this.mutationCb({adds:[],removes:[],texts:[],attributes:[{id:r.id,attributes:r.attributes}]}),this.trackLinkElement(t)}trackLinkElement(t){this.trackedLinkElements.has(t)||(this.trackedLinkElements.add(t),this.trackStylesheetInLinkElement(t))}adoptStyleSheets(t,r){if(t.length===0)return;const n={id:r,styleIds:[]},i=[];for(const o of t){let a;this.styleMirror.has(o)?a=this.styleMirror.getId(o):(a=this.styleMirror.add(o),i.push({styleId:a,rules:Array.from(o.rules||CSSRule,(l,s)=>({rule:bt(l),index:s}))})),n.styleIds.push(a)}i.length>0&&(n.styles=i),this.adoptedStyleSheetCb(n)}reset(){this.styleMirror.reset(),this.trackedLinkElements=new WeakSet}trackStylesheetInLinkElement(t){}}class An{constructor(){this.nodeMap=new WeakMap,this.loop=!0,this.periodicallyClear()}periodicallyClear(){requestAnimationFrame(()=>{this.clear(),this.loop&&this.periodicallyClear()})}inOtherBuffer(t,r){const n=this.nodeMap.get(t);return n&&Array.from(n).some(i=>i!==r)}add(t,r){this.nodeMap.set(t,(this.nodeMap.get(t)||new Set).add(r))}clear(){this.nodeMap=new WeakMap}destroy(){this.loop=!1}}function L(e){return Object.assign(Object.assign({},e),{timestamp:Le()})}let N,ze,lt,He=!1;const V=Or();function Oe(e={}){const{emit:t,checkoutEveryNms:r,checkoutEveryNth:n,blockClass:i="rr-block",blockSelector:o=null,ignoreClass:a="rr-ignore",ignoreSelector:l=null,maskTextClass:s="rr-mask",maskTextSelector:c=null,inlineStylesheet:u=!0,maskAllInputs:h,maskInputOptions:m,slimDOMOptions:f,maskInputFn:g,maskTextFn:p,hooks:y,packFn:w,sampling:S={},dataURLOptions:v={},mousemoveWait:b,recordDOM:M=!0,recordCanvas:B=!1,recordCrossOriginIframes:P=!1,recordAfter:x=e.recordAfter==="DOMContentLoaded"?e.recordAfter:"load",userTriggeredOnInput:R=!1,collectFonts:j=!1,inlineImages:G=!1,plugins:E,keepIframeSrcFn:ue=()=>!1,ignoreCSSAttributes:z=new Set([]),errorHandler:ne}=e;rn(ne);const Z=P?window.parent===window:!0;let Qe=!1;if(!Z)try{window.parent.document&&(Qe=!1)}catch{Qe=!0}if(Z&&!t)throw new Error("emit function is required");b!==void 0&&S.mousemove===void 0&&(S.mousemove=b),V.reset();const mt=h===!0?{color:!0,date:!0,"datetime-local":!0,email:!0,month:!0,number:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0,textarea:!0,select:!0,password:!0}:m!==void 0?m:{password:!0},gt=f===!0||f==="all"?{script:!0,comment:!0,headFavicon:!0,headWhitespace:!0,headMetaSocial:!0,headMetaRobots:!0,headMetaHttpEquiv:!0,headMetaVerification:!0,headMetaAuthorship:f==="all",headMetaDescKeywords:f==="all"}:f||{};Kr();let gr,yt=0;const yr=I=>{for(const K of E||[])K.eventProcessor&&(I=K.eventProcessor(I));return w&&!Qe&&(I=w(I)),I};N=(I,K)=>{var D;if(!((D=oe[0])===null||D===void 0)&&D.isFrozen()&&I.type!==O.FullSnapshot&&!(I.type===O.IncrementalSnapshot&&I.data.source===C.Mutation)&&oe.forEach(H=>H.unfreeze()),Z)t?.(yr(I),K);else if(Qe){const H={type:"rrweb",event:yr(I),origin:window.location.origin,isCheckout:K};window.parent.postMessage(H,"*")}if(I.type===O.FullSnapshot)gr=I,yt=0;else if(I.type===O.IncrementalSnapshot){if(I.data.source===C.Mutation&&I.data.isAttachIframe)return;yt++;const H=n&&yt>=n,fe=r&&I.timestamp-gr.timestamp>r;(H||fe)&&ze(!0)}};const Ze=I=>{N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Mutation},I)}))},vr=I=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Scroll},I)})),Sr=I=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.CanvasMutation},I)})),ri=I=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.AdoptedStyleSheet},I)})),ce=new Nn({mutationCb:Ze,adoptedStyleSheetCb:ri}),de=new vn({mirror:V,mutationCb:Ze,stylesheetManager:ce,recordCrossOriginIframes:P,wrappedEmit:N});for(const I of E||[])I.getMirror&&I.getMirror({nodeMirror:V,crossOriginIframeMirror:de.crossOriginIframeMirror,crossOriginIframeStyleMirror:de.crossOriginIframeStyleMirror});const vt=new An;lt=new Dn({recordCanvas:B,mutationCb:Sr,win:window,blockClass:i,blockSelector:o,mirror:V,sampling:S.canvas,dataURLOptions:v});const et=new Sn({mutationCb:Ze,scrollCb:vr,bypassOptions:{blockClass:i,blockSelector:o,maskTextClass:s,maskTextSelector:c,inlineStylesheet:u,maskInputOptions:mt,dataURLOptions:v,maskTextFn:p,maskInputFn:g,recordCanvas:B,inlineImages:G,sampling:S,slimDOMOptions:gt,iframeManager:de,stylesheetManager:ce,canvasManager:lt,keepIframeSrcFn:ue,processedNodeManager:vt},mirror:V});ze=(I=!1)=>{if(!M)return;N(L({type:O.Meta,data:{href:window.location.href,width:Dt(),height:Tt()}}),I),ce.reset(),et.init(),oe.forEach(D=>D.lock());const K=Jr(document,{mirror:V,blockClass:i,blockSelector:o,maskTextClass:s,maskTextSelector:c,inlineStylesheet:u,maskAllInputs:mt,maskTextFn:p,slimDOM:gt,dataURLOptions:v,recordCanvas:B,inlineImages:G,onSerialize:D=>{Lt(D,V)&&de.addIframe(D),Ft(D,V)&&ce.trackLinkElement(D),st(D)&&et.addShadowRoot(D.shadowRoot,document)},onIframeLoad:(D,H)=>{de.attachIframe(D,H),et.observeAttachShadow(D)},onStylesheetLoad:(D,H)=>{ce.attachLinkElement(D,H)},keepIframeSrcFn:ue});if(!K)return console.warn("Failed to snapshot the document");N(L({type:O.FullSnapshot,data:{node:K,initialOffset:Rt(window)}}),I),oe.forEach(D=>D.unlock()),document.adoptedStyleSheets&&document.adoptedStyleSheets.length>0&&ce.adoptStyleSheets(document.adoptedStyleSheets,V.getId(document))};try{const I=[],K=H=>{var fe;return _(yn)({mutationCb:Ze,mousemoveCb:(T,St)=>N(L({type:O.IncrementalSnapshot,data:{source:St,positions:T}})),mouseInteractionCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.MouseInteraction},T)})),scrollCb:vr,viewportResizeCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.ViewportResize},T)})),inputCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Input},T)})),mediaInteractionCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.MediaInteraction},T)})),styleSheetRuleCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.StyleSheetRule},T)})),styleDeclarationCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.StyleDeclaration},T)})),canvasMutationCb:Sr,fontCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Font},T)})),selectionCb:T=>{N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Selection},T)}))},customElementCb:T=>{N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.CustomElement},T)}))},blockClass:i,ignoreClass:a,ignoreSelector:l,maskTextClass:s,maskTextSelector:c,maskInputOptions:mt,inlineStylesheet:u,sampling:S,recordDOM:M,recordCanvas:B,inlineImages:G,userTriggeredOnInput:R,collectFonts:j,doc:H,maskInputFn:g,maskTextFn:p,keepIframeSrcFn:ue,blockSelector:o,slimDOMOptions:gt,dataURLOptions:v,mirror:V,iframeManager:de,stylesheetManager:ce,shadowDomManager:et,processedNodeManager:vt,canvasManager:lt,ignoreCSSAttributes:z,plugins:((fe=E?.filter(T=>T.observer))===null||fe===void 0?void 0:fe.map(T=>({observer:T.observer,options:T.options,callback:St=>N(L({type:O.Plugin,data:{plugin:T.name,payload:St}}))})))||[]},y)};de.addLoadListener(H=>{try{I.push(K(H.contentDocument))}catch(fe){console.warn(fe)}});const D=()=>{ze(),I.push(K(document)),He=!0};return document.readyState==="interactive"||document.readyState==="complete"?D():(I.push(W("DOMContentLoaded",()=>{N(L({type:O.DomContentLoaded,data:{}})),x==="DOMContentLoaded"&&D()})),I.push(W("load",()=>{N(L({type:O.Load,data:{}})),x==="load"&&D()},window))),()=>{I.forEach(H=>H()),vt.destroy(),He=!1,nn()}}catch(I){console.warn(I)}}Oe.addCustomEvent=(e,t)=>{if(!He)throw new Error("please add custom event after start recording");N(L({type:O.Custom,data:{tag:e,payload:t}}))},Oe.freezePage=()=>{oe.forEach(e=>e.freeze())},Oe.takeFullSnapshot=e=>{if(!He)throw new Error("please take full snapshot after start recording");ze(e)},Oe.mirror=V;var rr=(e=>(e[e.DomContentLoaded=0]="DomContentLoaded",e[e.Load=1]="Load",e[e.FullSnapshot=2]="FullSnapshot",e[e.IncrementalSnapshot=3]="IncrementalSnapshot",e[e.Meta=4]="Meta",e[e.Custom=5]="Custom",e[e.Plugin=6]="Plugin",e))(rr||{}),Y=(e=>(e[e.Mutation=0]="Mutation",e[e.MouseMove=1]="MouseMove",e[e.MouseInteraction=2]="MouseInteraction",e[e.Scroll=3]="Scroll",e[e.ViewportResize=4]="ViewportResize",e[e.Input=5]="Input",e[e.TouchMove=6]="TouchMove",e[e.MediaInteraction=7]="MediaInteraction",e[e.StyleSheetRule=8]="StyleSheetRule",e[e.CanvasMutation=9]="CanvasMutation",e[e.Font=10]="Font",e[e.Log=11]="Log",e[e.Drag=12]="Drag",e[e.StyleDeclaration=13]="StyleDeclaration",e[e.Selection=14]="Selection",e[e.AdoptedStyleSheet=15]="AdoptedStyleSheet",e[e.CustomElement=16]="CustomElement",e))(Y||{}),nr={DEBUG:!1,LIB_VERSION:"2.55.1-rc1"},F;if(typeof window>"u"){var ir={hostname:""};F={navigator:{userAgent:"",onLine:!0},document:{location:ir,referrer:""},screen:{width:0,height:0},location:ir}}else F=window;var $e=24*60*60*1e3,ut=8*1e3,qe=Array.prototype,Ln=Function.prototype,or=Object.prototype,se=qe.slice,Ee=or.toString,je=or.hasOwnProperty,ke=F.console,xe=F.navigator,q=F.document,Ge=F.opera,Ve=F.screen,ae=xe.userAgent,ct=Ln.bind,sr=qe.forEach,ar=qe.indexOf,lr=qe.map,Fn=Array.isArray,dt={},d={trim:function(e){return e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")}},J={log:function(){},warn:function(){},error:function(){},critical:function(){if(!d.isUndefined(ke)&&ke){var e=["Mixpanel error:"].concat(d.toArray(arguments));try{ke.error.apply(ke,e)}catch{d.each(e,function(r){ke.error(r)})}}}},ft=function(e,t){return function(){return arguments[0]="["+t+"] "+arguments[0],e.apply(J,arguments)}},Je=function(e){return{log:ft(J.log,e),error:ft(J.error,e),critical:ft(J.critical,e)}};d.bind=function(e,t){var r,n;if(ct&&e.bind===ct)return ct.apply(e,se.call(arguments,1));if(!d.isFunction(e))throw new TypeError;return r=se.call(arguments,2),n=function(){if(!(this instanceof n))return e.apply(t,r.concat(se.call(arguments)));var i={};i.prototype=e.prototype;var o=new i;i.prototype=null;var a=e.apply(o,r.concat(se.call(arguments)));return Object(a)===a?a:o},n},d.each=function(e,t,r){if(e!=null){if(sr&&e.forEach===sr)e.forEach(t,r);else if(e.length===+e.length){for(var n=0,i=e.length;n0&&(t[n]=r)}),t},d.truncate=function(e,t){var r;return typeof e=="string"?r=e.slice(0,t):d.isArray(e)?(r=[],d.each(e,function(n){r.push(d.truncate(n,t))})):d.isObject(e)?(r={},d.each(e,function(n,i){r[i]=d.truncate(n,t)})):r=e,r},d.JSONEncode=function(){return function(e){var t=e,r=function(i){var o=/[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,a={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};return o.lastIndex=0,o.test(i)?'"'+i.replace(o,function(l){var s=a[l];return typeof s=="string"?s:"\\u"+("0000"+l.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+i+'"'},n=function(i,o){var a="",l=" ",s=0,c="",u="",h=0,m=a,f=[],g=o[i];switch(g&&typeof g=="object"&&typeof g.toJSON=="function"&&(g=g.toJSON(i)),typeof g){case"string":return r(g);case"number":return isFinite(g)?String(g):"null";case"boolean":case"null":return String(g);case"object":if(!g)return"null";if(a+=l,f=[],Ee.apply(g)==="[object Array]"){for(h=g.length,s=0;s="0"&&t<="9";)g+=t,o();if(t===".")for(g+=".";o()&&t>="0"&&t<="9";)g+=t;if(t==="e"||t==="E")for(g+=t,o(),(t==="-"||t==="+")&&(g+=t,o());t>="0"&&t<="9";)g+=t,o();if(h=+g,!isFinite(h))i("Bad number");else return h},l=function(){var h,g,p="",y;if(t==='"')for(;o();){if(t==='"')return o(),p;if(t==="\\")if(o(),t==="u"){for(y=0,g=0;g<4&&(h=parseInt(o(),16),!!isFinite(h));g+=1)y=y*16+h;p+=String.fromCharCode(y)}else if(typeof r[t]=="string")p+=r[t];else break;else p+=t}i("Bad string")},s=function(){for(;t&&t<=" ";)o()},c=function(){switch(t){case"t":return o("t"),o("r"),o("u"),o("e"),!0;case"f":return o("f"),o("a"),o("l"),o("s"),o("e"),!1;case"n":return o("n"),o("u"),o("l"),o("l"),null}i('Unexpected "'+t+'"')},u,f=function(){var h=[];if(t==="["){if(o("["),s(),t==="]")return o("]"),h;for(;t;){if(h.push(u()),s(),t==="]")return o("]"),h;o(","),s()}}i("Bad array")},m=function(){var h,g={};if(t==="{"){if(o("{"),s(),t==="}")return o("}"),g;for(;t;){if(h=l(),s(),o(":"),Object.hasOwnProperty.call(g,h)&&i('Duplicate key "'+h+'"'),g[h]=u(),s(),t==="}")return o("}"),g;o(","),s()}}i("Bad object")};return u=function(){switch(s(),t){case"{":return m();case"[":return f();case'"':return l();case"-":return a();default:return t>="0"&&t<="9"?a():c()}},function(h){var g;return n=h,e=0,t=" ",g=u(),s(),t&&i("Syntax error"),g}}(),d.base64Encode=function(e){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",r,n,i,o,a,l,s,c,u=0,f=0,m="",h=[];if(!e)return e;e=d.utf8Encode(e);do r=e.charCodeAt(u++),n=e.charCodeAt(u++),i=e.charCodeAt(u++),c=r<<16|n<<8|i,o=c>>18&63,a=c>>12&63,l=c>>6&63,s=c&63,h[f++]=t.charAt(o)+t.charAt(a)+t.charAt(l)+t.charAt(s);while(u="0"&&t<="9";)g+=t,o();if(t===".")for(g+=".";o()&&t>="0"&&t<="9";)g+=t;if(t==="e"||t==="E")for(g+=t,o(),(t==="-"||t==="+")&&(g+=t,o());t>="0"&&t<="9";)g+=t,o();if(f=+g,!isFinite(f))i("Bad number");else return f},l=function(){var f,g,p="",y;if(t==='"')for(;o();){if(t==='"')return o(),p;if(t==="\\")if(o(),t==="u"){for(y=0,g=0;g<4&&(f=parseInt(o(),16),!!isFinite(f));g+=1)y=y*16+f;p+=String.fromCharCode(y)}else if(typeof r[t]=="string")p+=r[t];else break;else p+=t}i("Bad string")},s=function(){for(;t&&t<=" ";)o()},c=function(){switch(t){case"t":return o("t"),o("r"),o("u"),o("e"),!0;case"f":return o("f"),o("a"),o("l"),o("s"),o("e"),!1;case"n":return o("n"),o("u"),o("l"),o("l"),null}i('Unexpected "'+t+'"')},u,h=function(){var f=[];if(t==="["){if(o("["),s(),t==="]")return o("]"),f;for(;t;){if(f.push(u()),s(),t==="]")return o("]"),f;o(","),s()}}i("Bad array")},m=function(){var f,g={};if(t==="{"){if(o("{"),s(),t==="}")return o("}"),g;for(;t;){if(f=l(),s(),o(":"),Object.hasOwnProperty.call(g,f)&&i('Duplicate key "'+f+'"'),g[f]=u(),s(),t==="}")return o("}"),g;o(","),s()}}i("Bad object")};return u=function(){switch(s(),t){case"{":return m();case"[":return h();case'"':return l();case"-":return a();default:return t>="0"&&t<="9"?a():c()}},function(f){var g;return n=f,e=0,t=" ",g=u(),s(),t&&i("Syntax error"),g}}(),d.base64Encode=function(e){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",r,n,i,o,a,l,s,c,u=0,h=0,m="",f=[];if(!e)return e;e=d.utf8Encode(e);do r=e.charCodeAt(u++),n=e.charCodeAt(u++),i=e.charCodeAt(u++),c=r<<16|n<<8|i,o=c>>18&63,a=c>>12&63,l=c>>6&63,s=c&63,f[h++]=t.charAt(o)+t.charAt(a)+t.charAt(l)+t.charAt(s);while(u127&&a<2048?l=String.fromCharCode(a>>6|192,a&63|128):l=String.fromCharCode(a>>12|224,a>>6&63|128,a&63|128),l!==null&&(n>r&&(t+=e.substring(r,n)),t+=l,r=n=o+1)}return n>r&&(t+=e.substring(r,e.length)),t},d.UUID=function(){var e=function(){var n=1*new Date,i;if(P.performance&&P.performance.now)i=P.performance.now();else for(i=0;n==1*new Date;)i++;return n.toString(16)+Math.floor(i).toString(16)},t=function(){return Math.random().toString(16).replace(".","")},r=function(){var n=ae,i,o,a=[],l=0;function s(c,u){var f,m=0;for(f=0;f=4&&(l=s(l,a),a=[]);return a.length>0&&(l=s(l,a)),l.toString(16)};return function(){var n=(Ve.height*Ve.width).toString(16);return e()+"-"+t()+"-"+r()+"-"+n+"-"+e()}}();var lr=["ahrefsbot","ahrefssiteaudit","baiduspider","bingbot","bingpreview","chrome-lighthouse","facebookexternal","petalbot","pinterest","screaming frog","yahoo! slurp","yandexbot","adsbot-google","apis-google","duplexweb-google","feedfetcher-google","google favicon","google web preview","google-read-aloud","googlebot","googleweblight","mediapartners-google","storebot-google"];d.isBlockedUA=function(e){var t;for(e=e.toLowerCase(),t=0;t=0}function n(i){if(!q.getElementsByTagName)return[];var o=i.split(" "),a,l,s,c,u,f,m,h,g,p,y=[q];for(f=0;f-1){l=a.split("#"),s=l[0];var w=l[1],S=q.getElementById(w);if(!S||s&&S.nodeName.toLowerCase()!=s)return[];y=[S];continue}if(a.indexOf(".")>-1){l=a.split("."),s=l[0];var v=l[1];for(s||(s="*"),c=[],u=0,m=0;m-1};break;default:x=function(R){return R.getAttribute(I)}}for(y=[],p=0,m=0;m=3?t[2]:""},currentUrl:function(){return P.location.href},properties:function(e){return typeof e!="object"&&(e={}),d.extend(d.strip_empty_properties({$os:d.info.os(),$browser:d.info.browser(ae,xe.vendor,Ge),$referrer:q.referrer,$referring_domain:d.info.referringDomain(q.referrer),$device:d.info.device(ae)}),{$current_url:d.info.currentUrl(),$browser_version:d.info.browserVersion(ae,xe.vendor,Ge),$screen_height:Ve.height,$screen_width:Ve.width,mp_lib:"web",$lib_version:rr.LIB_VERSION,$insert_id:ht(),time:d.timestamp()/1e3},d.strip_empty_properties(e))},people_properties:function(){return d.extend(d.strip_empty_properties({$os:d.info.os(),$browser:d.info.browser(ae,xe.vendor,Ge)}),{$browser_version:d.info.browserVersion(ae,xe.vendor,Ge)})},mpPageViewProperties:function(){return d.strip_empty_properties({current_page_title:q.title,current_domain:P.location.hostname,current_url_path:P.location.pathname,current_url_protocol:P.location.protocol,current_url_search:P.location.search})}};var ht=function(e){var t=Math.random().toString(36).substring(2,10)+Math.random().toString(36).substring(2,10);return e?t.substring(0,e):t},Wn=/[a-z0-9][a-z0-9-]*\.[a-z]+$/i,Un=/[a-z0-9][a-z0-9-]+\.[a-z.]{2,6}$/i,ur=function(e){var t=Un,r=e.split("."),n=r[r.length-1];(n.length>4||n==="com"||n==="org")&&(t=Wn);var i=e.match(t);return i?i[0]:""},Ke=null,Ye=null;typeof JSON<"u"&&(Ke=JSON.stringify,Ye=JSON.parse),Ke=Ke||d.JSONEncode,Ye=Ye||d.JSONDecode,d.toArray=d.toArray,d.isObject=d.isObject,d.JSONEncode=d.JSONEncode,d.JSONDecode=d.JSONDecode,d.isBlockedUA=d.isBlockedUA,d.isEmptyObject=d.isEmptyObject,d.info=d.info,d.info.device=d.info.device,d.info.browser=d.info.browser,d.info.browserVersion=d.info.browserVersion,d.info.properties=d.info.properties;var zn="__mp_opt_in_out_";function Hn(e,t){if(Vn(t))return J.warn('This browser has "Do Not Track" enabled. This will prevent the Mixpanel SDK from sending any data. To ignore the "Do Not Track" browser setting, initialize the Mixpanel instance with the config "ignore_dnt: true"'),!0;var r=Gn(e,t)==="0";return r&&J.warn("You are opted out of Mixpanel tracking. This will prevent the Mixpanel SDK from sending any data."),r}function $n(e){return Jn(e,function(t){return this.get_config(t)})}function qn(e){return e=e||{},e.persistenceType==="localStorage"?d.localStorage:d.cookie}function jn(e,t){return t=t||{},(t.persistencePrefix||zn)+e}function Gn(e,t){return qn(t).get(jn(e,t))}function Vn(e){if(e&&e.ignoreDnt)return!1;var t=e&&e.window||P,r=t.navigator||{},n=!1;return d.each([r.doNotTrack,r.msDoNotTrack,t.doNotTrack],function(i){d.includes([!0,1,"1","yes"],i)&&(n=!0)}),n}function Jn(e,t){return function(){var r=!1;try{var n=t.call(this,"token"),i=t.call(this,"ignore_dnt"),o=t.call(this,"opt_out_tracking_persistence_type"),a=t.call(this,"opt_out_tracking_cookie_prefix"),l=t.call(this,"window");n&&(r=Hn(n,{ignoreDnt:i,persistenceType:o,persistencePrefix:a,window:l}))}catch(c){J.error("Unexpected error when checking tracking opt-out status: "+c)}if(!r)return e.apply(this,arguments);var s=arguments[arguments.length-1];typeof s=="function"&&s(0)}}var Xn=Je("lock"),cr=function(e,t){t=t||{},this.storageKey=e,this.storage=t.storage||window.localStorage,this.pollIntervalMS=t.pollIntervalMS||100,this.timeoutMS=t.timeoutMS||2e3};cr.prototype.withLock=function(e,t,r){!r&&typeof t!="function"&&(r=t,t=null);var n=r||new Date().getTime()+"|"+Math.random(),i=new Date().getTime(),o=this.storageKey,a=this.pollIntervalMS,l=this.timeoutMS,s=this.storage,c=o+":X",u=o+":Y",f=o+":Z",m=function(S){t&&t(S)},h=function(S){if(new Date().getTime()-i>l){Xn.error("Timeout waiting for mutex on "+o+"; clearing lock. ["+n+"]"),s.removeItem(f),s.removeItem(u),y();return}setTimeout(function(){try{S()}catch(v){m(v)}},a*(Math.random()+.1))},g=function(S,v){S()?v():h(function(){g(S,v)})},p=function(){var S=s.getItem(u);if(S&&S!==n)return!1;if(s.setItem(u,n),s.getItem(u)===n)return!0;if(!Xe(s,!0))throw new Error("localStorage support dropped while acquiring lock");return!1},y=function(){s.setItem(c,n),g(p,function(){if(s.getItem(c)===n){w();return}h(function(){if(s.getItem(u)!==n){y();return}g(function(){return!s.getItem(f)},w)})})},w=function(){s.setItem(f,"1");try{e()}finally{s.removeItem(f),s.getItem(u)===n&&s.removeItem(u),s.getItem(c)===n&&s.removeItem(c)}};try{if(Xe(s,!0))y();else throw new Error("localStorage support check failed")}catch(S){m(S)}};var dr=Je("batch"),re=function(e,t){t=t||{},this.storageKey=e,this.storage=t.storage||window.localStorage,this.reportError=t.errorReporter||d.bind(dr.error,dr),this.lock=new cr(e,{storage:this.storage}),this.usePersistence=t.usePersistence,this.pid=t.pid||null,this.memQueue=[]};re.prototype.enqueue=function(e,t,r){var n={id:ht(),flushAfter:new Date().getTime()+t*2,payload:e};this.usePersistence?this.lock.withLock(d.bind(function(){var o;try{var a=this.readFromStorage();a.push(n),o=this.saveToStorage(a),o&&this.memQueue.push(n)}catch{this.reportError("Error enqueueing item",e),o=!1}r&&r(o)},this),d.bind(function(o){this.reportError("Error acquiring storage lock",o),r&&r(!1)},this),this.pid):(this.memQueue.push(n),r&&r(!0))},re.prototype.fillBatch=function(e){var t=this.memQueue.slice(0,e);if(this.usePersistence&&t.lengtho.flushAfter&&!n[o.id]&&(o.orphaned=!0,t.push(o),t.length>=e))break}}}return t};var fr=function(e,t){var r=[];return d.each(e,function(n){n.id&&!t[n.id]&&r.push(n)}),r};re.prototype.removeItemsByID=function(e,t){var r={};if(d.each(e,function(i){r[i]=!0}),this.memQueue=fr(this.memQueue,r),!this.usePersistence)t&&t(!0);else{var n=d.bind(function(){var i;try{var o=this.readFromStorage();if(o=fr(o,r),i=this.saveToStorage(o),i){o=this.readFromStorage();for(var a=0;a5&&(this.reportError("[dupe] item ID sent too many times, not sending",{item:u,batchSize:i.length,timesSent:this.itemIdsSentSuccessfully[h]}),m=!1):this.reportError("[dupe] found item with no ID",{item:u}),m&&a.push(f)}l[u.id]=f},this),a.length<1){this.resetFlush();return}this.requestInProgress=!0;var s=d.bind(function(u){this.requestInProgress=!1;try{var f=!1;if(e.unloading)this.queue.updatePayloads(l);else if(d.isObject(u)&&u.error==="timeout"&&new Date().getTime()-r>=t)this.reportError("Network timeout; retrying"),this.flush();else if(d.isObject(u)&&(u.httpStatusCode>=500||u.httpStatusCode===429||u.error==="timeout")){var m=this.flushInterval*2;u.retryAfter&&(m=parseInt(u.retryAfter,10)*1e3||m),m=Math.min(Kn,m),this.reportError("Error; retry in "+m+" ms"),this.scheduleFlush(m)}else if(d.isObject(u)&&u.httpStatusCode===413)if(i.length>1){var h=Math.max(1,Math.floor(n/2));this.batchSize=Math.min(this.batchSize,h,i.length-1),this.reportError("413 response; reducing batch size to "+this.batchSize),this.resetFlush()}else this.reportError("Single-event request too large; dropping",i),this.resetBatchSize(),f=!0;else f=!0;f&&(this.queue.removeItemsByID(d.map(i,function(g){return g.id}),d.bind(function(g){g?(this.consecutiveRemovalFailures=0,this.flushOnlyOnInterval&&!o?this.resetFlush():this.flush()):(this.reportError("Failed to remove items from queue"),++this.consecutiveRemovalFailures>5?(this.reportError("Too many queue failures; disabling batching system."),this.stopAllBatching()):this.resetFlush())},this)),d.each(i,d.bind(function(g){var p=g.id;p?(this.itemIdsSentSuccessfully[p]=this.itemIdsSentSuccessfully[p]||0,this.itemIdsSentSuccessfully[p]++,this.itemIdsSentSuccessfully[p]>5&&this.reportError("[dupe] item ID sent too many times",{item:g,batchSize:i.length,timesSent:this.itemIdsSentSuccessfully[p]})):this.reportError("[dupe] found item with no ID while removing",{item:g})},this)))}catch(g){this.reportError("Error handling API response",g),this.resetFlush()}},this),c={method:"POST",verbose:!0,ignore_json_errors:!0,timeout_ms:t};e.unloading&&(c.transport="sendBeacon"),Re.log("MIXPANEL REQUEST:",a),this.sendRequest(a,c,s)}catch(u){this.reportError("Error flushing request queue",u),this.resetFlush()}},Q.prototype.reportError=function(e,t){if(Re.error.apply(Re.error,arguments),this.errorReporter)try{t instanceof Error||(t=new Error(e)),this.errorReporter(e,t)}catch(r){Re.error(r)}};var Se=Je("recorder"),pr=P.CompressionStream,Yn={batch_size:1e3,batch_flush_interval_ms:10*1e3,batch_request_timeout_ms:90*1e3,batch_autostart:!0},Qn=new Set([Y.MouseMove,Y.MouseInteraction,Y.Scroll,Y.ViewportResize,Y.Input,Y.TouchMove,Y.MediaInteraction,Y.Drag,Y.Selection]);function Zn(e){return e.type===tr.IncrementalSnapshot&&Qn.has(e.data.source)}var X=function(e){this._mixpanel=e,this._stopRecording=null,this.recEvents=[],this.seqNo=0,this.replayId=null,this.replayStartTime=null,this.sendBatchId=null,this.idleTimeoutId=null,this.maxTimeoutId=null,this.recordMaxMs=$e,this._initBatcher()};X.prototype._initBatcher=function(){this.batcher=new Q("__mprec",{libConfig:Yn,sendRequestFunc:d.bind(this.flushEventsWithOptOut,this),errorReporter:d.bind(this.reportError,this),flushOnlyOnInterval:!0,usePersistence:!1})},X.prototype.get_config=function(e){return this._mixpanel.get_config(e)},X.prototype.startRecording=function(e){if(this._stopRecording!==null){Se.log("Recording already in progress, skipping startRecording.");return}this.recordMaxMs=this.get_config("record_max_ms"),this.recordMaxMs>$e&&(this.recordMaxMs=$e,Se.critical("record_max_ms cannot be greater than "+$e+"ms. Capping value.")),this.recEvents=[],this.seqNo=0,this.replayStartTime=null,this.replayId=d.UUID(),e?this.batcher.stop():this.batcher.start();var t=d.bind(function(){clearTimeout(this.idleTimeoutId),this.idleTimeoutId=setTimeout(d.bind(function(){Se.log("Idle timeout reached, restarting recording."),this.resetRecording()},this),this.get_config("record_idle_timeout_ms"))},this);this._stopRecording=Oe({emit:d.bind(function(r){this.batcher.enqueue(r),Zn(r)&&(this.batcher.stopped&&this.batcher.start(),t())},this),blockClass:this.get_config("record_block_class"),blockSelector:this.get_config("record_block_selector"),collectFonts:this.get_config("record_collect_fonts"),inlineImages:this.get_config("record_inline_images"),maskAllInputs:!0,maskTextClass:this.get_config("record_mask_text_class"),maskTextSelector:this.get_config("record_mask_text_selector")}),t(),this.maxTimeoutId=setTimeout(d.bind(this.resetRecording,this),this.recordMaxMs)},X.prototype.resetRecording=function(){this.stopRecording(),this.startRecording(!0)},X.prototype.stopRecording=function(){this._stopRecording!==null&&(this._stopRecording(),this._stopRecording=null),this.batcher.stopped?this.batcher.clear():(this.batcher.flush(),this.batcher.stop()),this.replayId=null,clearTimeout(this.idleTimeoutId),clearTimeout(this.maxTimeoutId)},X.prototype.flushEventsWithOptOut=function(e,t,r){this._flushEvents(e,t,r,d.bind(this._onOptOut,this))},X.prototype._onOptOut=function(e){e===0&&(this.recEvents=[],this.stopRecording())},X.prototype._sendRequest=function(e,t,r){var n=d.bind(function(i,o){i.status===200&&this.seqNo++,r({status:0,httpStatusCode:i.status,responseBody:o,retryAfter:i.headers.get("Retry-After")})},this);P.fetch(this.get_config("api_host")+"/"+this.get_config("api_routes").record+"?"+new URLSearchParams(e),{method:"POST",headers:{Authorization:"Basic "+btoa(this.get_config("token")+":"),"Content-Type":"application/octet-stream"},body:t}).then(function(i){i.json().then(function(o){n(i,o)}).catch(function(o){r({error:o})})}).catch(function(i){r({error:i})})},X.prototype._flushEvents=$n(function(e,t,r){const n=e.length;if(n>0){var i=e[0].timestamp;this.seqNo===0&&(this.replayStartTime=i);var o=e[n-1].timestamp-this.replayStartTime,a={distinct_id:String(this._mixpanel.get_distinct_id()),seq:this.seqNo,batch_start_time:i/1e3,replay_id:this.replayId,replay_length_ms:o,replay_start_time:this.replayStartTime/1e3},l=d.JSONEncode(e),s=this._mixpanel.get_property("$device_id");s&&(a.$device_id=s);var c=this._mixpanel.get_property("$user_id");if(c&&(a.$user_id=c),pr){var u=new Blob([l],{type:"application/json"}).stream(),f=u.pipeThrough(new pr("gzip"));new Response(f).blob().then(d.bind(function(m){a.format="gzip",this._sendRequest(a,m,r)},this))}else a.format="body",this._sendRequest(a,l,r)}}),X.prototype.reportError=function(e,t){Se.error.apply(Se.error,arguments);try{!t&&!(e instanceof Error)&&(e=new Error(e)),this.get_config("error_reporter")(e,t)}catch(r){Se.error(r)}},P.__mp_recorder=X})(); +`);var t="",r,n,i=0,o;for(r=n=0,i=e.length,o=0;o127&&a<2048?l=String.fromCharCode(a>>6|192,a&63|128):l=String.fromCharCode(a>>12|224,a>>6&63|128,a&63|128),l!==null&&(n>r&&(t+=e.substring(r,n)),t+=l,r=n=o+1)}return n>r&&(t+=e.substring(r,e.length)),t},d.UUID=function(){var e=function(){var n=1*new Date,i;if(F.performance&&F.performance.now)i=F.performance.now();else for(i=0;n==1*new Date;)i++;return n.toString(16)+Math.floor(i).toString(16)},t=function(){return Math.random().toString(16).replace(".","")},r=function(){var n=ae,i,o,a=[],l=0;function s(c,u){var h,m=0;for(h=0;h=4&&(l=s(l,a),a=[]);return a.length>0&&(l=s(l,a)),l.toString(16)};return function(){var n=(Ve.height*Ve.width).toString(16);return e()+"-"+t()+"-"+r()+"-"+n+"-"+e()}}();var ur=["ahrefsbot","ahrefssiteaudit","baiduspider","bingbot","bingpreview","chrome-lighthouse","facebookexternal","petalbot","pinterest","screaming frog","yahoo! slurp","yandexbot","adsbot-google","apis-google","duplexweb-google","feedfetcher-google","google favicon","google web preview","google-read-aloud","googlebot","googleweblight","mediapartners-google","storebot-google"];d.isBlockedUA=function(e){var t;for(e=e.toLowerCase(),t=0;t=0}function n(i){if(!q.getElementsByTagName)return[];var o=i.split(" "),a,l,s,c,u,h,m,f,g,p,y=[q];for(h=0;h-1){l=a.split("#"),s=l[0];var w=l[1],S=q.getElementById(w);if(!S||s&&S.nodeName.toLowerCase()!=s)return[];y=[S];continue}if(a.indexOf(".")>-1){l=a.split("."),s=l[0];var v=l[1];for(s||(s="*"),c=[],u=0,m=0;m-1};break;default:x=function(R){return R.getAttribute(M)}}for(y=[],p=0,m=0;m=3?t[2]:""},currentUrl:function(){return F.location.href},properties:function(e){return typeof e!="object"&&(e={}),d.extend(d.strip_empty_properties({$os:d.info.os(),$browser:d.info.browser(ae,xe.vendor,Ge),$referrer:q.referrer,$referring_domain:d.info.referringDomain(q.referrer),$device:d.info.device(ae)}),{$current_url:d.info.currentUrl(),$browser_version:d.info.browserVersion(ae,xe.vendor,Ge),$screen_height:Ve.height,$screen_width:Ve.width,mp_lib:"web",$lib_version:nr.LIB_VERSION,$insert_id:pt(),time:d.timestamp()/1e3},d.strip_empty_properties(e))},people_properties:function(){return d.extend(d.strip_empty_properties({$os:d.info.os(),$browser:d.info.browser(ae,xe.vendor,Ge)}),{$browser_version:d.info.browserVersion(ae,xe.vendor,Ge)})},mpPageViewProperties:function(){return d.strip_empty_properties({current_page_title:q.title,current_domain:F.location.hostname,current_url_path:F.location.pathname,current_url_protocol:F.location.protocol,current_url_search:F.location.search})}};var pt=function(e){var t=Math.random().toString(36).substring(2,10)+Math.random().toString(36).substring(2,10);return e?t.substring(0,e):t},Un=/[a-z0-9][a-z0-9-]*\.[a-z]+$/i,zn=/[a-z0-9][a-z0-9-]+\.[a-z.]{2,6}$/i,cr=function(e){var t=zn,r=e.split("."),n=r[r.length-1];(n.length>4||n==="com"||n==="org")&&(t=Un);var i=e.match(t);return i?i[0]:""},Hn=function(){var e=F.navigator.onLine;return d.isUndefined(e)||e},Ke=null,Ye=null;typeof JSON<"u"&&(Ke=JSON.stringify,Ye=JSON.parse),Ke=Ke||d.JSONEncode,Ye=Ye||d.JSONDecode,d.toArray=d.toArray,d.isObject=d.isObject,d.JSONEncode=d.JSONEncode,d.JSONDecode=d.JSONDecode,d.isBlockedUA=d.isBlockedUA,d.isEmptyObject=d.isEmptyObject,d.info=d.info,d.info.device=d.info.device,d.info.browser=d.info.browser,d.info.browserVersion=d.info.browserVersion,d.info.properties=d.info.properties;var $n="__mp_opt_in_out_";function qn(e,t){if(Xn(t))return J.warn('This browser has "Do Not Track" enabled. This will prevent the Mixpanel SDK from sending any data. To ignore the "Do Not Track" browser setting, initialize the Mixpanel instance with the config "ignore_dnt: true"'),!0;var r=Jn(e,t)==="0";return r&&J.warn("You are opted out of Mixpanel tracking. This will prevent the Mixpanel SDK from sending any data."),r}function jn(e){return Kn(e,function(t){return this.get_config(t)})}function Gn(e){return e=e||{},e.persistenceType==="localStorage"?d.localStorage:d.cookie}function Vn(e,t){return t=t||{},(t.persistencePrefix||$n)+e}function Jn(e,t){return Gn(t).get(Vn(e,t))}function Xn(e){if(e&&e.ignoreDnt)return!1;var t=e&&e.window||F,r=t.navigator||{},n=!1;return d.each([r.doNotTrack,r.msDoNotTrack,t.doNotTrack],function(i){d.includes([!0,1,"1","yes"],i)&&(n=!0)}),n}function Kn(e,t){return function(){var r=!1;try{var n=t.call(this,"token"),i=t.call(this,"ignore_dnt"),o=t.call(this,"opt_out_tracking_persistence_type"),a=t.call(this,"opt_out_tracking_cookie_prefix"),l=t.call(this,"window");n&&(r=qn(n,{ignoreDnt:i,persistenceType:o,persistencePrefix:a,window:l}))}catch(c){J.error("Unexpected error when checking tracking opt-out status: "+c)}if(!r)return e.apply(this,arguments);var s=arguments[arguments.length-1];typeof s=="function"&&s(0)}}var Yn=Je("lock"),dr=function(e,t){t=t||{},this.storageKey=e,this.storage=t.storage||window.localStorage,this.pollIntervalMS=t.pollIntervalMS||100,this.timeoutMS=t.timeoutMS||2e3};dr.prototype.withLock=function(e,t,r){!r&&typeof t!="function"&&(r=t,t=null);var n=r||new Date().getTime()+"|"+Math.random(),i=new Date().getTime(),o=this.storageKey,a=this.pollIntervalMS,l=this.timeoutMS,s=this.storage,c=o+":X",u=o+":Y",h=o+":Z",m=function(S){t&&t(S)},f=function(S){if(new Date().getTime()-i>l){Yn.error("Timeout waiting for mutex on "+o+"; clearing lock. ["+n+"]"),s.removeItem(h),s.removeItem(u),y();return}setTimeout(function(){try{S()}catch(v){m(v)}},a*(Math.random()+.1))},g=function(S,v){S()?v():f(function(){g(S,v)})},p=function(){var S=s.getItem(u);if(S&&S!==n)return!1;if(s.setItem(u,n),s.getItem(u)===n)return!0;if(!Xe(s,!0))throw new Error("localStorage support dropped while acquiring lock");return!1},y=function(){s.setItem(c,n),g(p,function(){if(s.getItem(c)===n){w();return}f(function(){if(s.getItem(u)!==n){y();return}g(function(){return!s.getItem(h)},w)})})},w=function(){s.setItem(h,"1");try{e()}finally{s.removeItem(h),s.getItem(u)===n&&s.removeItem(u),s.getItem(c)===n&&s.removeItem(c)}};try{if(Xe(s,!0))y();else throw new Error("localStorage support check failed")}catch(S){m(S)}};var fr=Je("batch"),re=function(e,t){t=t||{},this.storageKey=e,this.storage=t.storage||window.localStorage,this.reportError=t.errorReporter||d.bind(fr.error,fr),this.lock=new dr(e,{storage:this.storage}),this.usePersistence=t.usePersistence,this.pid=t.pid||null,this.memQueue=[]};re.prototype.enqueue=function(e,t,r){var n={id:pt(),flushAfter:new Date().getTime()+t*2,payload:e};this.usePersistence?this.lock.withLock(d.bind(function(){var o;try{var a=this.readFromStorage();a.push(n),o=this.saveToStorage(a),o&&this.memQueue.push(n)}catch{this.reportError("Error enqueueing item",e),o=!1}r&&r(o)},this),d.bind(function(o){this.reportError("Error acquiring storage lock",o),r&&r(!1)},this),this.pid):(this.memQueue.push(n),r&&r(!0))},re.prototype.fillBatch=function(e){var t=this.memQueue.slice(0,e);if(this.usePersistence&&t.lengtho.flushAfter&&!n[o.id]&&(o.orphaned=!0,t.push(o),t.length>=e))break}}}return t};var hr=function(e,t){var r=[];return d.each(e,function(n){n.id&&!t[n.id]&&r.push(n)}),r};re.prototype.removeItemsByID=function(e,t){var r={};if(d.each(e,function(i){r[i]=!0}),this.memQueue=hr(this.memQueue,r),!this.usePersistence)t&&t(!0);else{var n=d.bind(function(){var i;try{var o=this.readFromStorage();if(o=hr(o,r),i=this.saveToStorage(o),i){o=this.readFromStorage();for(var a=0;a5&&(this.reportError("[dupe] item ID sent too many times, not sending",{item:u,batchSize:i.length,timesSent:this.itemIdsSentSuccessfully[f]}),m=!1):this.reportError("[dupe] found item with no ID",{item:u}),m&&a.push(h)}l[u.id]=h},this),a.length<1){this.resetFlush();return}this.requestInProgress=!0;var s=d.bind(function(u){this.requestInProgress=!1;try{var h=!1;if(e.unloading)this.queue.updatePayloads(l);else if(d.isObject(u)&&u.error==="timeout"&&new Date().getTime()-r>=t)this.reportError("Network timeout; retrying"),this.flush();else if(d.isObject(u)&&(u.httpStatusCode>=500||u.httpStatusCode===429||u.httpStatusCode<=0&&!Hn()||u.error==="timeout")){var m=this.flushInterval*2;u.retryAfter&&(m=parseInt(u.retryAfter,10)*1e3||m),m=Math.min(Qn,m),this.reportError("Error; retry in "+m+" ms"),this.scheduleFlush(m)}else if(d.isObject(u)&&u.httpStatusCode===413)if(i.length>1){var f=Math.max(1,Math.floor(n/2));this.batchSize=Math.min(this.batchSize,f,i.length-1),this.reportError("413 response; reducing batch size to "+this.batchSize),this.resetFlush()}else this.reportError("Single-event request too large; dropping",i),this.resetBatchSize(),h=!0;else h=!0;h&&(this.queue.removeItemsByID(d.map(i,function(g){return g.id}),d.bind(function(g){g?(this.consecutiveRemovalFailures=0,this.flushOnlyOnInterval&&!o?this.resetFlush():this.flush()):(this.reportError("Failed to remove items from queue"),++this.consecutiveRemovalFailures>5?(this.reportError("Too many queue failures; disabling batching system."),this.stopAllBatching()):this.resetFlush())},this)),d.each(i,d.bind(function(g){var p=g.id;p?(this.itemIdsSentSuccessfully[p]=this.itemIdsSentSuccessfully[p]||0,this.itemIdsSentSuccessfully[p]++,this.itemIdsSentSuccessfully[p]>5&&this.reportError("[dupe] item ID sent too many times",{item:g,batchSize:i.length,timesSent:this.itemIdsSentSuccessfully[p]})):this.reportError("[dupe] found item with no ID while removing",{item:g})},this)))}catch(g){this.reportError("Error handling API response",g),this.resetFlush()}},this),c={method:"POST",verbose:!0,ignore_json_errors:!0,timeout_ms:t};e.unloading&&(c.transport="sendBeacon"),Re.log("MIXPANEL REQUEST:",a),this.sendRequest(a,c,s)}catch(u){this.reportError("Error flushing request queue",u),this.resetFlush()}},Q.prototype.reportError=function(e,t){if(Re.error.apply(Re.error,arguments),this.errorReporter)try{t instanceof Error||(t=new Error(e)),this.errorReporter(e,t)}catch(r){Re.error(r)}};var le=Je("recorder"),mr=F.CompressionStream,Zn={batch_size:1e3,batch_flush_interval_ms:10*1e3,batch_request_timeout_ms:90*1e3,batch_autostart:!0},ei=new Set([Y.MouseMove,Y.MouseInteraction,Y.Scroll,Y.ViewportResize,Y.Input,Y.TouchMove,Y.MediaInteraction,Y.Drag,Y.Selection]);function ti(e){return e.type===rr.IncrementalSnapshot&&ei.has(e.data.source)}var X=function(e){this._mixpanel=e,this._stopRecording=null,this.recEvents=[],this.seqNo=0,this.replayId=null,this.replayStartTime=null,this.sendBatchId=null,this.idleTimeoutId=null,this.maxTimeoutId=null,this.recordMaxMs=$e,this.recordMinMs=0,this._initBatcher()};X.prototype._initBatcher=function(){this.batcher=new Q("__mprec",{libConfig:Zn,sendRequestFunc:d.bind(this.flushEventsWithOptOut,this),errorReporter:d.bind(this.reportError,this),flushOnlyOnInterval:!0,usePersistence:!1})},X.prototype.get_config=function(e){return this._mixpanel.get_config(e)},X.prototype.startRecording=function(e){if(this._stopRecording!==null){le.log("Recording already in progress, skipping startRecording.");return}this.recordMaxMs=this.get_config("record_max_ms"),this.recordMaxMs>$e&&(this.recordMaxMs=$e,le.critical("record_max_ms cannot be greater than "+$e+"ms. Capping value.")),this.recordMinMs=this.get_config("record_min_ms"),this.recordMinMs>ut&&(this.recordMinMs=ut,le.critical("record_min_ms cannot be greater than "+ut+"ms. Capping value.")),this.recEvents=[],this.seqNo=0,this.replayStartTime=new Date().getTime(),this.replayId=d.UUID(),e||this.recordMinMs>0?this.batcher.stop():this.batcher.start();var t=d.bind(function(){clearTimeout(this.idleTimeoutId),this.idleTimeoutId=setTimeout(d.bind(function(){le.log("Idle timeout reached, restarting recording."),this.resetRecording()},this),this.get_config("record_idle_timeout_ms"))},this),r=this.get_config("record_block_selector");(r===""||r===null)&&(r=void 0),this._stopRecording=Oe({emit:d.bind(function(n){this.batcher.enqueue(n),ti(n)&&(this.batcher.stopped&&new Date().getTime()-this.replayStartTime>=this.recordMinMs&&this.batcher.start(),t())},this),blockClass:this.get_config("record_block_class"),blockSelector:r,collectFonts:this.get_config("record_collect_fonts"),inlineImages:this.get_config("record_inline_images"),maskAllInputs:!0,maskTextClass:this.get_config("record_mask_text_class"),maskTextSelector:this.get_config("record_mask_text_selector")}),t(),this.maxTimeoutId=setTimeout(d.bind(this.resetRecording,this),this.recordMaxMs)},X.prototype.resetRecording=function(){this.stopRecording(),this.startRecording(!0)},X.prototype.stopRecording=function(){this._stopRecording!==null&&(this._stopRecording(),this._stopRecording=null),this.batcher.stopped?this.batcher.clear():(this.batcher.flush(),this.batcher.stop()),this.replayId=null,clearTimeout(this.idleTimeoutId),clearTimeout(this.maxTimeoutId)},X.prototype.flushEventsWithOptOut=function(e,t,r){this._flushEvents(e,t,r,d.bind(this._onOptOut,this))},X.prototype._onOptOut=function(e){e===0&&(this.recEvents=[],this.stopRecording())},X.prototype._sendRequest=function(e,t,r,n){var i=d.bind(function(o,a){o.status===200&&this.replayId===e&&this.seqNo++,n({status:0,httpStatusCode:o.status,responseBody:a,retryAfter:o.headers.get("Retry-After")})},this);F.fetch(this.get_config("api_host")+"/"+this.get_config("api_routes").record+"?"+new URLSearchParams(t),{method:"POST",headers:{Authorization:"Basic "+btoa(this.get_config("token")+":"),"Content-Type":"application/octet-stream"},body:r}).then(function(o){o.json().then(function(a){i(o,a)}).catch(function(a){n({error:a})})}).catch(function(o){n({error:o,httpStatusCode:0})})},X.prototype._flushEvents=jn(function(e,t,r){const n=e.length;if(n>0){var i=this.replayId,o=e[0].timestamp;(this.seqNo===0||!this.replayStartTime)&&(this.seqNo!==0&&this.reportError("Replay start time not set but seqNo is not 0. Using current batch start time as a fallback."),this.replayStartTime=o);var a=e[n-1].timestamp-this.replayStartTime,l={distinct_id:String(this._mixpanel.get_distinct_id()),seq:this.seqNo,batch_start_time:o/1e3,replay_id:i,replay_length_ms:a,replay_start_time:this.replayStartTime/1e3},s=d.JSONEncode(e),c=this._mixpanel.get_property("$device_id");c&&(l.$device_id=c);var u=this._mixpanel.get_property("$user_id");if(u&&(l.$user_id=u),mr){var h=new Blob([s],{type:"application/json"}).stream(),m=h.pipeThrough(new mr("gzip"));new Response(m).blob().then(d.bind(function(f){l.format="gzip",this._sendRequest(i,l,f,r)},this))}else l.format="body",this._sendRequest(i,l,s,r)}}),X.prototype.reportError=function(e,t){le.error.apply(le.error,arguments);try{!t&&!(e instanceof Error)&&(e=new Error(e)),this.get_config("error_reporter")(e,t)}catch(r){le.error(r)}},F.__mp_recorder=X})(); diff --git a/dist/mixpanel-with-async-recorder.cjs.js b/dist/mixpanel-with-async-recorder.cjs.js index 18560421..2e0b62ec 100644 --- a/dist/mixpanel-with-async-recorder.cjs.js +++ b/dist/mixpanel-with-async-recorder.cjs.js @@ -2,7 +2,7 @@ var Config = { DEBUG: false, - LIB_VERSION: '2.55.0' + LIB_VERSION: '2.55.1-rc1' }; /* eslint camelcase: "off", eqeqeq: "off" */ @@ -14,7 +14,7 @@ if (typeof(window) === 'undefined') { hostname: '' }; win = { - navigator: { userAgent: '' }, + navigator: { userAgent: '', onLine: true }, document: { location: loc, referrer: '' @@ -968,7 +968,7 @@ _.HTTPBuildQuery = function(formdata, arg_separator) { _.getQueryParam = function(url, param) { // Expects a raw URL - param = param.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); + param = param.replace(/[[]/g, '\\[').replace(/[\]]/g, '\\]'); var regexS = '[\\?&]' + param + '=([^&#]*)', regex = new RegExp(regexS), results = regex.exec(url); @@ -1425,8 +1425,8 @@ _.dom_query = (function() { }; })(); -var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; -var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid']; +var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform','utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic']; +var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'sccid', 'ttclid', 'twclid', 'wbraid']; _.info = { campaignParams: function(default_value) { @@ -1708,6 +1708,15 @@ var extract_domain = function(hostname) { return matches ? matches[0] : ''; }; +/** + * Check whether we have network connection. default to true for browsers that don't support navigator.onLine (IE) + * @returns {boolean} + */ +var isOnline = function() { + var onLine = win.navigator['onLine']; + return _.isUndefined(onLine) || onLine; +}; + var JSONStringify = null, JSONParse = null; if (typeof JSON !== 'undefined') { JSONStringify = JSON.stringify; @@ -2523,7 +2532,12 @@ RequestBatcher.prototype.flush = function(options) { this.flush(); } else if ( _.isObject(res) && - (res.httpStatusCode >= 500 || res.httpStatusCode === 429 || res.error === 'timeout') + ( + res.httpStatusCode >= 500 + || res.httpStatusCode === 429 + || (res.httpStatusCode <= 0 && !isOnline()) + || res.error === 'timeout' + ) ) { // network or API error, or 429 Too Many Requests, retry var retryMS = this.flushInterval * 2; @@ -4247,6 +4261,7 @@ var DEFAULT_CONFIG = { 'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'), 'record_mask_text_selector': '*', 'record_max_ms': MAX_RECORDING_MS, + 'record_min_ms': 0, 'record_sessions_percent': 0, 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js' }; diff --git a/dist/mixpanel.amd.js b/dist/mixpanel.amd.js index 4619c3ab..693c8f38 100644 --- a/dist/mixpanel.amd.js +++ b/dist/mixpanel.amd.js @@ -4509,7 +4509,7 @@ define((function () { 'use strict'; var Config = { DEBUG: false, - LIB_VERSION: '2.55.0' + LIB_VERSION: '2.55.1-rc1' }; /* eslint camelcase: "off", eqeqeq: "off" */ @@ -4521,7 +4521,7 @@ define((function () { 'use strict'; hostname: '' }; win = { - navigator: { userAgent: '' }, + navigator: { userAgent: '', onLine: true }, document: { location: loc, referrer: '' @@ -4535,6 +4535,8 @@ define((function () { 'use strict'; // Maximum allowed session recording length var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours + // Maximum allowed value for minimum session recording length + var MAX_VALUE_FOR_MIN_RECORDING_MS = 8 * 1000; // 8 seconds /* * Saved references to long variable names, so that closure compiler can @@ -5475,7 +5477,7 @@ define((function () { 'use strict'; _.getQueryParam = function(url, param) { // Expects a raw URL - param = param.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); + param = param.replace(/[[]/g, '\\[').replace(/[\]]/g, '\\]'); var regexS = '[\\?&]' + param + '=([^&#]*)', regex = new RegExp(regexS), results = regex.exec(url); @@ -5932,8 +5934,8 @@ define((function () { 'use strict'; }; })(); - var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; - var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid']; + var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform','utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic']; + var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'sccid', 'ttclid', 'twclid', 'wbraid']; _.info = { campaignParams: function(default_value) { @@ -6215,6 +6217,15 @@ define((function () { 'use strict'; return matches ? matches[0] : ''; }; + /** + * Check whether we have network connection. default to true for browsers that don't support navigator.onLine (IE) + * @returns {boolean} + */ + var isOnline = function() { + var onLine = win.navigator['onLine']; + return _.isUndefined(onLine) || onLine; + }; + var JSONStringify = null, JSONParse = null; if (typeof JSON !== 'undefined') { JSONStringify = JSON.stringify; @@ -7178,7 +7189,12 @@ define((function () { 'use strict'; this.flush(); } else if ( _.isObject(res) && - (res.httpStatusCode >= 500 || res.httpStatusCode === 429 || res.error === 'timeout') + ( + res.httpStatusCode >= 500 + || res.httpStatusCode === 429 + || (res.httpStatusCode <= 0 && !isOnline()) + || res.error === 'timeout' + ) ) { // network or API error, or 429 Too Many Requests, retry var retryMS = this.flushInterval * 2; @@ -7329,6 +7345,7 @@ define((function () { 'use strict'; this.maxTimeoutId = null; this.recordMaxMs = MAX_RECORDING_MS; + this.recordMinMs = 0; this._initBatcher(); }; @@ -7360,16 +7377,24 @@ define((function () { 'use strict'; logger.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.'); } + this.recordMinMs = this.get_config('record_min_ms'); + if (this.recordMinMs > MAX_VALUE_FOR_MIN_RECORDING_MS) { + this.recordMinMs = MAX_VALUE_FOR_MIN_RECORDING_MS; + logger.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.'); + } + this.recEvents = []; this.seqNo = 0; - this.replayStartTime = null; + this.replayStartTime = new Date().getTime(); this.replayId = _.UUID(); - if (shouldStopBatcher) { - // this is the case when we're starting recording after a reset + if (shouldStopBatcher || this.recordMinMs > 0) { + // the primary case for shouldStopBatcher is when we're starting recording after a reset // and don't want to send anything over the network until there's // actual user activity + // this also applies if the minimum recording length has not been hit yet + // so that we don't send data until we know the recording will be long enough this.batcher.stop(); } else { this.batcher.start(); @@ -7383,11 +7408,16 @@ define((function () { 'use strict'; }, this), this.get_config('record_idle_timeout_ms')); }, this); + var blockSelector = this.get_config('record_block_selector'); + if (blockSelector === '' || blockSelector === null) { + blockSelector = undefined; + } + this._stopRecording = record({ 'emit': _.bind(function (ev) { this.batcher.enqueue(ev); if (isUserEvent(ev)) { - if (this.batcher.stopped) { + if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) { // start flushing again after user activity this.batcher.start(); } @@ -7395,7 +7425,7 @@ define((function () { 'use strict'; } }, this), 'blockClass': this.get_config('record_block_class'), - 'blockSelector': this.get_config('record_block_selector'), + 'blockSelector': blockSelector, 'collectFonts': this.get_config('record_collect_fonts'), 'inlineImages': this.get_config('record_inline_images'), 'maskAllInputs': true, @@ -7449,14 +7479,14 @@ define((function () { 'use strict'; } }; - MixpanelRecorder.prototype._sendRequest = function(reqParams, reqBody, callback) { + MixpanelRecorder.prototype._sendRequest = function(currentReplayId, reqParams, reqBody, callback) { var onSuccess = _.bind(function (response, responseBody) { // Increment sequence counter only if the request was successful to guarantee ordering. // RequestBatcher will always flush the next batch after the previous one succeeds. - if (response.status === 200) { + // extra check to see if the replay ID has changed so that we don't increment the seqNo on the wrong replay + if (response.status === 200 && this.replayId === currentReplayId) { this.seqNo++; } - callback({ status: 0, httpStatusCode: response.status, @@ -7479,7 +7509,7 @@ define((function () { 'use strict'; callback({error: error}); }); }).catch(function (error) { - callback({error: error}); + callback({error: error, httpStatusCode: 0}); }); }; @@ -7487,9 +7517,15 @@ define((function () { 'use strict'; const numEvents = data.length; if (numEvents > 0) { + var replayId = this.replayId; // each rrweb event has a timestamp - leverage those to get time properties var batchStartTime = data[0].timestamp; - if (this.seqNo === 0) { + if (this.seqNo === 0 || !this.replayStartTime) { + // extra safety net so that we don't send a null replay start time + if (this.seqNo !== 0) { + this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.'); + } + this.replayStartTime = batchStartTime; } var replayLengthMs = data[numEvents - 1].timestamp - this.replayStartTime; @@ -7498,7 +7534,7 @@ define((function () { 'use strict'; 'distinct_id': String(this._mixpanel.get_distinct_id()), 'seq': this.seqNo, 'batch_start_time': batchStartTime / 1000, - 'replay_id': this.replayId, + 'replay_id': replayId, 'replay_length_ms': replayLengthMs, 'replay_start_time': this.replayStartTime / 1000 }; @@ -7521,11 +7557,11 @@ define((function () { 'use strict'; .blob() .then(_.bind(function(compressedBlob) { reqParams['format'] = 'gzip'; - this._sendRequest(reqParams, compressedBlob, callback); + this._sendRequest(replayId, reqParams, compressedBlob, callback); }, this)); } else { reqParams['format'] = 'body'; - this._sendRequest(reqParams, eventsJson, callback); + this._sendRequest(replayId, reqParams, eventsJson, callback); } } }); @@ -9013,6 +9049,7 @@ define((function () { 'use strict'; 'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'), 'record_mask_text_selector': '*', 'record_max_ms': MAX_RECORDING_MS, + 'record_min_ms': 0, 'record_sessions_percent': 0, 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js' }; diff --git a/dist/mixpanel.cjs.js b/dist/mixpanel.cjs.js index 1bfc0ca1..76cee8c6 100644 --- a/dist/mixpanel.cjs.js +++ b/dist/mixpanel.cjs.js @@ -4509,7 +4509,7 @@ var IncrementalSource = /* @__PURE__ */ ((IncrementalSource2) => { var Config = { DEBUG: false, - LIB_VERSION: '2.55.0' + LIB_VERSION: '2.55.1-rc1' }; /* eslint camelcase: "off", eqeqeq: "off" */ @@ -4521,7 +4521,7 @@ if (typeof(window) === 'undefined') { hostname: '' }; win = { - navigator: { userAgent: '' }, + navigator: { userAgent: '', onLine: true }, document: { location: loc, referrer: '' @@ -4535,6 +4535,8 @@ if (typeof(window) === 'undefined') { // Maximum allowed session recording length var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours +// Maximum allowed value for minimum session recording length +var MAX_VALUE_FOR_MIN_RECORDING_MS = 8 * 1000; // 8 seconds /* * Saved references to long variable names, so that closure compiler can @@ -5475,7 +5477,7 @@ _.HTTPBuildQuery = function(formdata, arg_separator) { _.getQueryParam = function(url, param) { // Expects a raw URL - param = param.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); + param = param.replace(/[[]/g, '\\[').replace(/[\]]/g, '\\]'); var regexS = '[\\?&]' + param + '=([^&#]*)', regex = new RegExp(regexS), results = regex.exec(url); @@ -5932,8 +5934,8 @@ _.dom_query = (function() { }; })(); -var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; -var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid']; +var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform','utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic']; +var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'sccid', 'ttclid', 'twclid', 'wbraid']; _.info = { campaignParams: function(default_value) { @@ -6215,6 +6217,15 @@ var extract_domain = function(hostname) { return matches ? matches[0] : ''; }; +/** + * Check whether we have network connection. default to true for browsers that don't support navigator.onLine (IE) + * @returns {boolean} + */ +var isOnline = function() { + var onLine = win.navigator['onLine']; + return _.isUndefined(onLine) || onLine; +}; + var JSONStringify = null, JSONParse = null; if (typeof JSON !== 'undefined') { JSONStringify = JSON.stringify; @@ -7178,7 +7189,12 @@ RequestBatcher.prototype.flush = function(options) { this.flush(); } else if ( _.isObject(res) && - (res.httpStatusCode >= 500 || res.httpStatusCode === 429 || res.error === 'timeout') + ( + res.httpStatusCode >= 500 + || res.httpStatusCode === 429 + || (res.httpStatusCode <= 0 && !isOnline()) + || res.error === 'timeout' + ) ) { // network or API error, or 429 Too Many Requests, retry var retryMS = this.flushInterval * 2; @@ -7329,6 +7345,7 @@ var MixpanelRecorder = function(mixpanelInstance) { this.maxTimeoutId = null; this.recordMaxMs = MAX_RECORDING_MS; + this.recordMinMs = 0; this._initBatcher(); }; @@ -7360,16 +7377,24 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { logger.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.'); } + this.recordMinMs = this.get_config('record_min_ms'); + if (this.recordMinMs > MAX_VALUE_FOR_MIN_RECORDING_MS) { + this.recordMinMs = MAX_VALUE_FOR_MIN_RECORDING_MS; + logger.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.'); + } + this.recEvents = []; this.seqNo = 0; - this.replayStartTime = null; + this.replayStartTime = new Date().getTime(); this.replayId = _.UUID(); - if (shouldStopBatcher) { - // this is the case when we're starting recording after a reset + if (shouldStopBatcher || this.recordMinMs > 0) { + // the primary case for shouldStopBatcher is when we're starting recording after a reset // and don't want to send anything over the network until there's // actual user activity + // this also applies if the minimum recording length has not been hit yet + // so that we don't send data until we know the recording will be long enough this.batcher.stop(); } else { this.batcher.start(); @@ -7383,11 +7408,16 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { }, this), this.get_config('record_idle_timeout_ms')); }, this); + var blockSelector = this.get_config('record_block_selector'); + if (blockSelector === '' || blockSelector === null) { + blockSelector = undefined; + } + this._stopRecording = record({ 'emit': _.bind(function (ev) { this.batcher.enqueue(ev); if (isUserEvent(ev)) { - if (this.batcher.stopped) { + if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) { // start flushing again after user activity this.batcher.start(); } @@ -7395,7 +7425,7 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { } }, this), 'blockClass': this.get_config('record_block_class'), - 'blockSelector': this.get_config('record_block_selector'), + 'blockSelector': blockSelector, 'collectFonts': this.get_config('record_collect_fonts'), 'inlineImages': this.get_config('record_inline_images'), 'maskAllInputs': true, @@ -7449,14 +7479,14 @@ MixpanelRecorder.prototype._onOptOut = function (code) { } }; -MixpanelRecorder.prototype._sendRequest = function(reqParams, reqBody, callback) { +MixpanelRecorder.prototype._sendRequest = function(currentReplayId, reqParams, reqBody, callback) { var onSuccess = _.bind(function (response, responseBody) { // Increment sequence counter only if the request was successful to guarantee ordering. // RequestBatcher will always flush the next batch after the previous one succeeds. - if (response.status === 200) { + // extra check to see if the replay ID has changed so that we don't increment the seqNo on the wrong replay + if (response.status === 200 && this.replayId === currentReplayId) { this.seqNo++; } - callback({ status: 0, httpStatusCode: response.status, @@ -7479,7 +7509,7 @@ MixpanelRecorder.prototype._sendRequest = function(reqParams, reqBody, callback) callback({error: error}); }); }).catch(function (error) { - callback({error: error}); + callback({error: error, httpStatusCode: 0}); }); }; @@ -7487,9 +7517,15 @@ MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da const numEvents = data.length; if (numEvents > 0) { + var replayId = this.replayId; // each rrweb event has a timestamp - leverage those to get time properties var batchStartTime = data[0].timestamp; - if (this.seqNo === 0) { + if (this.seqNo === 0 || !this.replayStartTime) { + // extra safety net so that we don't send a null replay start time + if (this.seqNo !== 0) { + this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.'); + } + this.replayStartTime = batchStartTime; } var replayLengthMs = data[numEvents - 1].timestamp - this.replayStartTime; @@ -7498,7 +7534,7 @@ MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da 'distinct_id': String(this._mixpanel.get_distinct_id()), 'seq': this.seqNo, 'batch_start_time': batchStartTime / 1000, - 'replay_id': this.replayId, + 'replay_id': replayId, 'replay_length_ms': replayLengthMs, 'replay_start_time': this.replayStartTime / 1000 }; @@ -7521,11 +7557,11 @@ MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da .blob() .then(_.bind(function(compressedBlob) { reqParams['format'] = 'gzip'; - this._sendRequest(reqParams, compressedBlob, callback); + this._sendRequest(replayId, reqParams, compressedBlob, callback); }, this)); } else { reqParams['format'] = 'body'; - this._sendRequest(reqParams, eventsJson, callback); + this._sendRequest(replayId, reqParams, eventsJson, callback); } } }); @@ -9013,6 +9049,7 @@ var DEFAULT_CONFIG = { 'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'), 'record_mask_text_selector': '*', 'record_max_ms': MAX_RECORDING_MS, + 'record_min_ms': 0, 'record_sessions_percent': 0, 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js' }; diff --git a/dist/mixpanel.globals.js b/dist/mixpanel.globals.js index 169818d4..1fd35749 100644 --- a/dist/mixpanel.globals.js +++ b/dist/mixpanel.globals.js @@ -3,7 +3,7 @@ var Config = { DEBUG: false, - LIB_VERSION: '2.55.0' + LIB_VERSION: '2.55.1-rc1' }; /* eslint camelcase: "off", eqeqeq: "off" */ @@ -15,7 +15,7 @@ hostname: '' }; win = { - navigator: { userAgent: '' }, + navigator: { userAgent: '', onLine: true }, document: { location: loc, referrer: '' @@ -969,7 +969,7 @@ _.getQueryParam = function(url, param) { // Expects a raw URL - param = param.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); + param = param.replace(/[[]/g, '\\[').replace(/[\]]/g, '\\]'); var regexS = '[\\?&]' + param + '=([^&#]*)', regex = new RegExp(regexS), results = regex.exec(url); @@ -1426,8 +1426,8 @@ }; })(); - var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; - var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid']; + var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform','utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic']; + var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'sccid', 'ttclid', 'twclid', 'wbraid']; _.info = { campaignParams: function(default_value) { @@ -1709,6 +1709,15 @@ return matches ? matches[0] : ''; }; + /** + * Check whether we have network connection. default to true for browsers that don't support navigator.onLine (IE) + * @returns {boolean} + */ + var isOnline = function() { + var onLine = win.navigator['onLine']; + return _.isUndefined(onLine) || onLine; + }; + var JSONStringify = null, JSONParse = null; if (typeof JSON !== 'undefined') { JSONStringify = JSON.stringify; @@ -2524,7 +2533,12 @@ this.flush(); } else if ( _.isObject(res) && - (res.httpStatusCode >= 500 || res.httpStatusCode === 429 || res.error === 'timeout') + ( + res.httpStatusCode >= 500 + || res.httpStatusCode === 429 + || (res.httpStatusCode <= 0 && !isOnline()) + || res.error === 'timeout' + ) ) { // network or API error, or 429 Too Many Requests, retry var retryMS = this.flushInterval * 2; @@ -4248,6 +4262,7 @@ 'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'), 'record_mask_text_selector': '*', 'record_max_ms': MAX_RECORDING_MS, + 'record_min_ms': 0, 'record_sessions_percent': 0, 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js' }; diff --git a/dist/mixpanel.min.js b/dist/mixpanel.min.js index d49ab84e..30bce548 100644 --- a/dist/mixpanel.min.js +++ b/dist/mixpanel.min.js @@ -1,112 +1,113 @@ (function() { var l=void 0,m=!0,r=null,D=!1; -(function(){function Ba(){function a(){if(!a.Gc)la=a.Gc=m,ma=D,c.a(F,function(a){a.tc()})}function b(){try{v.documentElement.doScroll("left")}catch(d){setTimeout(b,1);return}a()}if(v.addEventListener)"complete"===v.readyState?a():v.addEventListener("DOMContentLoaded",a,D);else if(v.attachEvent){v.attachEvent("onreadystatechange",a);var d=D;try{d=o.frameElement===r}catch(f){}v.documentElement.doScroll&&d&&b()}c.Vb(o,"load",a,m)}function Ca(){x.init=function(a,b,d){if(d)return x[d]||(x[d]=F[d]=S(a, -b,d),x[d].la()),x[d];d=x;if(F.mixpanel)d=F.mixpanel;else if(a)d=S(a,b,"mixpanel"),d.la(),F.mixpanel=d;x=d;1===ca&&(o.mixpanel=x);Da()}}function Da(){c.a(F,function(a,b){"mixpanel"!==b&&(x[b]=a)});x._=c}function da(a){a=c.e(a)?a:c.g(a)?{}:{days:a};return c.extend({},Ea,a)}function S(a,b,d){var f,h="mixpanel"===d?x:x[d];if(h&&0===ca)f=h;else{if(h&&!c.isArray(h)){n.error("You have already initialized "+d);return}f=new e}f.lb={};f.Y(a,b,d);f.people=new j;f.people.Y(f);if(!f.c("skip_first_touch_marketing")){var a= -c.info.Z(r),g={},t=D;c.a(a,function(a,b){(g["initial_"+b]=a)&&(t=m)});t&&f.people.O(g)}J=J||f.c("debug");!c.g(h)&&c.isArray(h)&&(f.Aa.call(f.people,h.people),f.Aa(h));return f}function e(){}function P(){}function Fa(a){return a}function na(a){throw Error(a+" not available in this build.");}function q(a){this.props={};this.Dd=D;this.name=a.persistence_name?"mp_"+a.persistence_name:"mp_"+a.token+"_mixpanel";var b=a.persistence;if("cookie"!==b&&"localStorage"!==b)n.B("Unknown persistence type "+b+"; falling back to cookie"), -b=a.persistence="cookie";this.j="localStorage"===b&&c.localStorage.ta()?c.localStorage:c.cookie;this.load();this.nc(a);this.zd();this.save()}function j(){}function u(){}function C(a,b){this.K=b.K;this.ca=new G(a,{K:c.bind(this.h,this),j:b.j,z:b.z});this.C=b.C;this.bd=b.cd;this.ma=b.ma;this.md=b.nd;this.G=this.C.batch_size;this.qa=this.C.batch_flush_interval_ms;this.fa=!this.C.batch_autostart;this.Ja=0;this.I={};this.Db=b.Db||D}function oa(a,b){var d=[];c.a(a,function(a){var c=a.id;if(c in b){if(c= -b[c],c!==r)a.payload=c,d.push(a)}else d.push(a)});return d}function pa(a,b){var d=[];c.a(a,function(a){a.id&&!b[a.id]&&d.push(a)});return d}function G(a,b){b=b||{};this.P=a;this.j=b.j||window.localStorage;this.h=b.K||c.bind(qa.error,qa);this.Ya=new ra(a,{j:this.j});this.z=b.z;this.va=b.va||r;this.D=[]}function ra(a,b){b=b||{};this.P=a;this.j=b.j||window.localStorage;this.Tb=b.Tb||100;this.hc=b.hc||2E3}function T(){this.Qb="submit"}function M(){this.Qb="click"}function E(){}function sa(a){var b=Ga, -d=a.split("."),d=d[d.length-1];if(4a?"0"+a:a}return a.getUTCFullYear()+"-"+b(a.getUTCMonth()+1)+"-"+b(a.getUTCDate())+"T"+b(a.getUTCHours())+":"+b(a.getUTCMinutes())+":"+b(a.getUTCSeconds())};c.ga=function(a){var b= -{};c.a(a,function(a,f){c.Xa(a)&&0=i;)h()}function d(){var a,b,d="",c;if('"'===i)for(;h();){if('"'===i)return h(),d;if("\\"===i)if(h(),"u"===i){for(b=c=0;4>b;b+=1){a=parseInt(h(),16);if(!isFinite(a))break;c=16*c+a}d+=String.fromCharCode(c)}else if("string"===typeof k[i])d+=k[i];else break;else d+=i}g("Bad string")}function c(){var a;a="";"-"===i&&(a="-",h("-"));for(;"0"<=i&&"9">=i;)a+=i,h();if("."===i)for(a+=".";h()&&"0"<=i&&"9">=i;)a+=i;if("e"===i||"E"===i){a+=i;h();if("-"===i||"+"===i)a+=i,h();for(;"0"<=i&&"9">=i;)a+=i,h()}a= -+a;if(isFinite(a))return a;g("Bad number")}function h(a){a&&a!==i&&g("Expected '"+a+"' instead of '"+i+"'");i=p.charAt(e);e+=1;return i}function g(a){a=new SyntaxError(a);a.Cd=e;a.text=p;throw a;}var e,i,k={'"':'"',"\\":"\\","/":"/",b:"\u0008",f:"\u000c",n:"\n",r:"\r",t:"\t"},p,s;s=function(){b();switch(i){case "{":var e;a:{var t,k={};if("{"===i){h("{");b();if("}"===i){h("}");e=k;break a}for(;i;){t=d();b();h(":");Object.hasOwnProperty.call(k,t)&&g('Duplicate key "'+t+'"');k[t]=s();b();if("}"===i){h("}"); -e=k;break a}h(",");b()}}g("Bad object")}return e;case "[":a:{e=[];if("["===i){h("[");b();if("]"===i){h("]");t=e;break a}for(;i;){e.push(s());b();if("]"===i){h("]");t=e;break a}h(",");b()}}g("Bad array")}return t;case '"':return d();case "-":return c();default:return"0"<=i&&"9">=i?c():a()}};return function(a){p=a;e=0;i=" ";a=s();b();i&&g("Syntax error");return a}}();c.Bc=function(a){var b,d,f,h,g=0,e=0,i="",i=[];if(!a)return a;a=c.Ad(a);do b=a.charCodeAt(g++),d=a.charCodeAt(g++),f=a.charCodeAt(g++), -h=b<<16|d<<8|f,b=h>>18&63,d=h>>12&63,f=h>>6&63,h&=63,i[e++]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(b)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(d)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(f)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(h);while(ge?c++:i=127e?String.fromCharCode(e>>6|192,e&63|128):String.fromCharCode(e>>12|224,e>>6&63|128,e&63|128);i!==r&&(c>d&&(b+=a.substring(d,c)),b+=i,d=c=g+1)}c>d&&(b+=a.substring(d,a.length));return b};c.jb=function(){function a(){function a(b,c){var d,f=0;for(d=0;da?"0"+a:a}return a.getUTCFullYear()+"-"+b(a.getUTCMonth()+1)+"-"+b(a.getUTCDate())+ +"T"+b(a.getUTCHours())+":"+b(a.getUTCMinutes())+":"+b(a.getUTCSeconds())};c.ga=function(a){var b={};c.a(a,function(a,f){c.Xa(a)&&0=i;)h()}function d(){var a,b,d="",c;if('"'===i)for(;h();){if('"'===i)return h(),d;if("\\"===i)if(h(),"u"===i){for(b=c=0;4>b;b+=1){a=parseInt(h(),16);if(!isFinite(a))break;c=16*c+a}d+=String.fromCharCode(c)}else if("string"===typeof k[i])d+=k[i];else break;else d+=i}g("Bad string")}function c(){var a;a="";"-"===i&&(a="-",h("-"));for(;"0"<=i&&"9">=i;)a+=i,h();if("."===i)for(a+= +".";h()&&"0"<=i&&"9">=i;)a+=i;if("e"===i||"E"===i){a+=i;h();if("-"===i||"+"===i)a+=i,h();for(;"0"<=i&&"9">=i;)a+=i,h()}a=+a;if(isFinite(a))return a;g("Bad number")}function h(a){a&&a!==i&&g("Expected '"+a+"' instead of '"+i+"'");i=p.charAt(e);e+=1;return i}function g(a){a=new SyntaxError(a);a.Cd=e;a.text=p;throw a;}var e,i,k={'"':'"',"\\":"\\","/":"/",b:"\u0008",f:"\u000c",n:"\n",r:"\r",t:"\t"},p,s;s=function(){b();switch(i){case "{":var e;a:{var t,k={};if("{"===i){h("{");b();if("}"===i){h("}");e= +k;break a}for(;i;){t=d();b();h(":");Object.hasOwnProperty.call(k,t)&&g('Duplicate key "'+t+'"');k[t]=s();b();if("}"===i){h("}");e=k;break a}h(",");b()}}g("Bad object")}return e;case "[":a:{e=[];if("["===i){h("[");b();if("]"===i){h("]");t=e;break a}for(;i;){e.push(s());b();if("]"===i){h("]");t=e;break a}h(",");b()}}g("Bad array")}return t;case '"':return d();case "-":return c();default:return"0"<=i&&"9">=i?c():a()}};return function(a){p=a;e=0;i=" ";a=s();b();i&&g("Syntax error");return a}}();c.Bc= +function(a){var b,d,f,h,g=0,e=0,i="",i=[];if(!a)return a;a=c.Ad(a);do b=a.charCodeAt(g++),d=a.charCodeAt(g++),f=a.charCodeAt(g++),h=b<<16|d<<8|f,b=h>>18&63,d=h>>12&63,f=h>>6&63,h&=63,i[e++]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(b)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(d)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(f)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(h); +while(ge?c++:i=127e?String.fromCharCode(e>>6|192,e&63|128):String.fromCharCode(e>>12|224,e>>6&63|128,e&63|128);i!==r&&(c>d&&(b+=a.substring(d,c)),b+=i,d=c=g+1)}c>d&&(b+=a.substring(d,a.length));return b};c.jb=function(){function a(){function a(b, +c){var d,f=0;for(d=0;dB?(Ra.error("Timeout waiting for mutex on "+s+"; clearing lock. ["+k+"]"),j.removeItem(n),j.removeItem(q),h()):setTimeout(function(){try{a()}catch(c){b&&b(c)}},w*(Math.random()+0.1))}!c&&"function"!==typeof b&&(c=b,b=r);var k=c|| -(new Date).getTime()+"|"+Math.random(),p=(new Date).getTime(),s=this.P,w=this.Tb,B=this.hc,j=this.j,o=s+":X",q=s+":Y",n=s+":Z";try{if(U(j,m))h();else throw Error("localStorage support check failed");}catch(v){b&&b(v)}};var qa=ga("batch");G.prototype.Na=function(a,b,d){var f={id:ea(),flushAfter:(new Date).getTime()+2*b,payload:a};this.z?this.Ya.ib(c.bind(function(){var b;try{var c=this.ea();c.push(f);(b=this.ab(c))&&this.D.push(f)}catch(e){this.h("Error enqueueing item",a),b=D}d&&d(b)},this),c.bind(function(a){this.h("Error acquiring storage lock", -a);d&&d(D)},this),this.va):(this.D.push(f),d&&d(m))};G.prototype.Hc=function(a){var b=this.D.slice(0,a);if(this.z&&b.lengthg.flushAfter&&!f[g.id]&&(g.Uc=m,b.push(g),b.length>=a))break}}}return b};G.prototype.Wc=function(a,b){var d={};c.a(a,function(a){d[a]=m});this.D=pa(this.D,d);if(this.z){var f=c.bind(function(){var b;try{var c=this.ea(),c=pa(c,d);if(b=this.ab(c))for(var c= -this.ea(),f=0;ft.length)this.N();else{this.Xb=m;var k=c.bind(function(k){this.Xb=D;try{var t=D;if(a.lc)this.ca.yd(i);else if(c.e(k)&&"timeout"===k.error&&(new Date).getTime()-d>=b)this.h("Network timeout; retrying"),this.flush();else if(c.e(k)&&(500<=k.Sa||429===k.Sa||"timeout"===k.error)){var j=2*this.qa;k.Zb&&(j=1E3*parseInt(k.Zb,10)||j);j=Math.min(6E5,j);this.h("Error; retry in "+j+" ms"); -this.$b(j)}else if(c.e(k)&&413===k.Sa)if(1B?(Sa.error("Timeout waiting for mutex on "+s+"; clearing lock. ["+k+"]"),j.removeItem(o),j.removeItem(q),h()):setTimeout(function(){try{a()}catch(c){b&&b(c)}},w*(Math.random()+0.1))}!c&&"function"!==typeof b&&(c=b,b=r);var k=c|| +(new Date).getTime()+"|"+Math.random(),p=(new Date).getTime(),s=this.P,w=this.Tb,B=this.hc,j=this.j,n=s+":X",q=s+":Y",o=s+":Z";try{if(U(j,m))h();else throw Error("localStorage support check failed");}catch(v){b&&b(v)}};var qa=ga("batch");G.prototype.Oa=function(a,b,d){var f={id:ea(),flushAfter:(new Date).getTime()+2*b,payload:a};this.z?this.Ya.ib(c.bind(function(){var b;try{var c=this.ea();c.push(f);(b=this.ab(c))&&this.D.push(f)}catch(e){this.h("Error enqueueing item",a),b=D}d&&d(b)},this),c.bind(function(a){this.h("Error acquiring storage lock", +a);d&&d(D)},this),this.wa):(this.D.push(f),d&&d(m))};G.prototype.Hc=function(a){var b=this.D.slice(0,a);if(this.z&&b.lengthg.flushAfter&&!f[g.id]&&(g.Uc=m,b.push(g),b.length>=a))break}}}return b};G.prototype.Wc=function(a,b){var d={};c.a(a,function(a){d[a]=m});this.D=pa(this.D,d);if(this.z){var f=c.bind(function(){var b;try{var c=this.ea(),c=pa(c,d);if(b=this.ab(c))for(var c= +this.ea(),f=0;ft.length)this.N();else{this.Xb=m;var k=c.bind(function(k){this.Xb=D;try{var t=D;if(a.lc)this.ca.yd(i);else if(c.g(k)&&"timeout"===k.error&&(new Date).getTime()-d>=b)this.h("Network timeout; retrying"),this.flush();else if(c.g(k)&&(500<=k.sa||429===k.sa||0>=k.sa&&!Ga()||"timeout"===k.error)){var j=2*this.qa;k.Zb&&(j=1E3*parseInt(k.Zb,10)||j);j=Math.min(6E5,j);this.h("Error; retry in "+ +j+" ms");this.$b(j)}else if(c.g(k)&&413===k.sa)if(1=n.timeout?"timeout":"Bad HTTP status: "+n.status+" "+n.statusText,p.l(a),f&&(k?f({status:0,Sa:n.status,error:a,Zb:(n.responseHeaders|| -{})["Retry-After"]}):f(0))};n.send(j)}catch(y){p.l(y),e=D}else j=v.createElement("script"),j.type="text/javascript",j.async=m,j.defer=m,j.src=a,u=v.getElementsByTagName("script")[0],u.parentNode.insertBefore(j,u);return e};e.prototype.Aa=function(a){function b(a,b){c.a(a,function(a){if(c.isArray(a[0])){var d=b;c.a(a,function(a){d=d[a[0]].apply(d,a.slice(1))})}else this[a[0]].apply(this,a.slice(1))},b)}var d,e=[],h=[],g=[];c.a(a,function(a){a&&(d=a[0],c.isArray(d)?g.push(a):"function"===typeof a?a.call(this): -c.isArray(a)&&"alias"===d?e.push(a):c.isArray(a)&&-1!==d.indexOf("track")&&"function"===typeof this[d]?g.push(a):h.push(a))},this);b(e,this);b(h,this);b(g,this)};e.prototype.sb=function(){return!!this.u.L};e.prototype.Eb=function(){var a="__mpq_"+this.c("token"),b=this.c("api_routes");return this.kb=this.kb||{L:{type:"events",H:"/"+b.track,da:a+"_ev"},$a:{type:"people",H:"/"+b.engage,da:a+"_pp"},Ra:{type:"groups",H:"/"+b.groups,da:a+"_gr"}}};e.prototype.Nc=function(){if(!this.sb()){var a=c.bind(function(a){return new C(a.da, -{C:this.config,K:this.c("error_reporter"),cd:c.bind(function(b,c,e){this.k(this.c("api_host")+a.H,this.mb(b),c,this.ob(e,b))},this),ma:c.bind(function(b){return this.qb("before_send_"+a.type,b)},this),nd:c.bind(this.cb,this),z:m})},this),b=this.Eb();this.u={L:a(b.L),$a:a(b.$a),Ra:a(b.Ra)}}this.c("batch_autostart")&&this.bb()};e.prototype.bb=function(){this.rc=m;if(this.sb())this.U=m,c.a(this.u,function(a){a.start()})};e.prototype.cb=function(){this.U=D;c.a(this.u,function(a){a.stop();a.clear()})}; -e.prototype.push=function(a){this.Aa([a])};e.prototype.disable=function(a){"undefined"===typeof a?this.V.Ec=m:this.xa=this.xa.concat(a)};e.prototype.mb=function(a){a=c.ia(a);"base64"===this.c("api_payload_format")&&(a=c.Bc(a));return{data:a}};e.prototype.Fa=function(a,b){var d=c.truncate(a.data,255),e=a.H,h=a.Ha,g=a.ld,j=a.dd||{},b=b||P,i=m,k=c.bind(function(){j.fc||(d=this.qb("before_send_"+a.type,d));return d?(n.log("MIXPANEL REQUEST:"),n.log(d),this.k(e,this.mb(d),j,this.ob(b,d))):r},this);this.U&& -!g?h.Na(d,function(a){a?b(1,d):k()}):i=k();return i&&d};e.prototype.o=K(function(a,b,d,e){!e&&"function"===typeof d&&(e=d,d=r);var d=d||{},h=d.transport;if(h)d.gb=h;h=d.send_immediately;"function"!==typeof e&&(e=P);if(c.g(a))this.l("No event name provided to mixpanel.track");else if(this.nb(a))e(0);else{b=c.extend({},b);b.token=this.c("token");var g=this.persistence.Xc(a);c.g(g)||(b.$duration=parseFloat((((new Date).getTime()-g)/1E3).toFixed(3)));this.rb();g=this.c("track_marketing")?c.info.Rc(): -{};b=c.extend({},c.info.ba({mp_loader:this.c("mp_loader")}),g,this.persistence.ba(),this.R,this.Fb(),b);g=this.c("property_blacklist");c.isArray(g)?c.a(g,function(a){delete b[a]}):this.l("Invalid value for property_blacklist config: "+g);return this.Fa({type:"events",data:{event:a,properties:b},H:this.c("api_host")+"/"+this.c("api_routes").track,Ha:this.u.L,ld:h,dd:d},e)}});e.prototype.jd=K(function(a,b,d){c.isArray(b)||(b=[b]);var e={};e[a]=b;this.m(e);return this.people.set(a,b,d)});e.prototype.yc= +record_block_selector:"img, video",record_collect_fonts:D,record_idle_timeout_ms:18E5,record_inline_images:D,record_mask_text_class:/^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$/,record_mask_text_selector:"*",record_max_ms:864E5,record_min_ms:0,record_sessions_percent:0,recorder_src:"https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js"},la=D;e.prototype.Va=function(a,b,d){if(c.e(d))this.l("You must name your new library: init(token, config, name)");else if("mixpanel"===d)this.l("You must initialize the main mixpanel object right after you include the Mixpanel js snippet"); +else return a=S(a,b,d),x[d]=a,a.la(),a};e.prototype.Y=function(a,b,d){b=b||{};this.__loaded=m;this.config={};var f={};"api_payload_format"in b||(b.api_host||Aa.api_host).match(/\.mixpanel\.com/)&&(f.api_payload_format="json");this.cc(c.extend({},Aa,f,b,{name:d,token:a,callback_fn:("mixpanel"===d?d:"mixpanel."+d)+"._jsc"}));this._jsc=P;this.za=[];this.Aa=[];this.ya=[];this.V={disable_all_events:D,identify_called:D};this.u={};if(this.U=this.c("batch_requests"))if(!c.localStorage.ua(m)||!O)this.U=D, +o.log("Turning off Mixpanel request-queueing; needs XHR and localStorage support"),c.a(this.Eb(),function(a){o.log("Clearing batch queue "+a.da);c.localStorage.remove(a.da)});else if(this.Nc(),ba&&n.addEventListener){var e=c.bind(function(){this.u.L.fa||this.u.L.flush({lc:m})},this);n.addEventListener("pagehide",function(a){a.persisted&&e()});n.addEventListener("visibilitychange",function(){"hidden"===v.visibilityState&&e()})}this.persistence=this.cookie=new q(this.config);this.R={};this.wc();a=c.jb(); +this.M()||this.w({distinct_id:"$device:"+a,$device_id:a},"");(a=this.c("track_pageview"))&&this.xc(a);0=o.timeout?"timeout":"Bad HTTP status: "+o.status+" "+o.statusText,p.l(a),f&&(k?f({status:0,sa:o.status,error:a,Zb:(o.responseHeaders|| +{})["Retry-After"]}):f(0))};o.send(j)}catch(y){p.l(y),e=D}else j=v.createElement("script"),j.type="text/javascript",j.async=m,j.defer=m,j.src=a,u=v.getElementsByTagName("script")[0],u.parentNode.insertBefore(j,u);return e};e.prototype.Ba=function(a){function b(a,b){c.a(a,function(a){if(c.isArray(a[0])){var d=b;c.a(a,function(a){d=d[a[0]].apply(d,a.slice(1))})}else this[a[0]].apply(this,a.slice(1))},b)}var d,e=[],h=[],g=[];c.a(a,function(a){a&&(d=a[0],c.isArray(d)?g.push(a):"function"===typeof a?a.call(this): +c.isArray(a)&&"alias"===d?e.push(a):c.isArray(a)&&-1!==d.indexOf("track")&&"function"===typeof this[d]?g.push(a):h.push(a))},this);b(e,this);b(h,this);b(g,this)};e.prototype.sb=function(){return!!this.u.L};e.prototype.Eb=function(){var a="__mpq_"+this.c("token"),b=this.c("api_routes");return this.kb=this.kb||{L:{type:"events",H:"/"+b.track,da:a+"_ev"},$a:{type:"people",H:"/"+b.engage,da:a+"_pp"},Sa:{type:"groups",H:"/"+b.groups,da:a+"_gr"}}};e.prototype.Nc=function(){if(!this.sb()){var a=c.bind(function(a){return new C(a.da, +{C:this.config,K:this.c("error_reporter"),cd:c.bind(function(b,c,e){this.k(this.c("api_host")+a.H,this.mb(b),c,this.ob(e,b))},this),ma:c.bind(function(b){return this.qb("before_send_"+a.type,b)},this),nd:c.bind(this.cb,this),z:m})},this),b=this.Eb();this.u={L:a(b.L),$a:a(b.$a),Sa:a(b.Sa)}}this.c("batch_autostart")&&this.bb()};e.prototype.bb=function(){this.rc=m;if(this.sb())this.U=m,c.a(this.u,function(a){a.start()})};e.prototype.cb=function(){this.U=D;c.a(this.u,function(a){a.stop();a.clear()})}; +e.prototype.push=function(a){this.Ba([a])};e.prototype.disable=function(a){"undefined"===typeof a?this.V.Ec=m:this.ya=this.ya.concat(a)};e.prototype.mb=function(a){a=c.ia(a);"base64"===this.c("api_payload_format")&&(a=c.Bc(a));return{data:a}};e.prototype.Ga=function(a,b){var d=c.truncate(a.data,255),e=a.H,h=a.Ia,g=a.ld,j=a.dd||{},b=b||P,i=m,k=c.bind(function(){j.fc||(d=this.qb("before_send_"+a.type,d));return d?(o.log("MIXPANEL REQUEST:"),o.log(d),this.k(e,this.mb(d),j,this.ob(b,d))):r},this);this.U&& +!g?h.Oa(d,function(a){a?b(1,d):k()}):i=k();return i&&d};e.prototype.o=K(function(a,b,d,e){!e&&"function"===typeof d&&(e=d,d=r);var d=d||{},h=d.transport;if(h)d.gb=h;h=d.send_immediately;"function"!==typeof e&&(e=P);if(c.e(a))this.l("No event name provided to mixpanel.track");else if(this.nb(a))e(0);else{b=c.extend({},b);b.token=this.c("token");var g=this.persistence.Xc(a);c.e(g)||(b.$duration=parseFloat((((new Date).getTime()-g)/1E3).toFixed(3)));this.rb();g=this.c("track_marketing")?c.info.Rc(): +{};b=c.extend({},c.info.ba({mp_loader:this.c("mp_loader")}),g,this.persistence.ba(),this.R,this.Fb(),b);g=this.c("property_blacklist");c.isArray(g)?c.a(g,function(a){delete b[a]}):this.l("Invalid value for property_blacklist config: "+g);return this.Ga({type:"events",data:{event:a,properties:b},H:this.c("api_host")+"/"+this.c("api_routes").track,Ia:this.u.L,ld:h,dd:d},e)}});e.prototype.jd=K(function(a,b,d){c.isArray(b)||(b=[b]);var e={};e[a]=b;this.m(e);return this.people.set(a,b,d)});e.prototype.yc= K(function(a,b,c){var e=this.s(a),h={};e===l?(h[a]=[b],this.m(h)):-1===e.indexOf(b)&&(e.push(b),h[a]=e,this.m(h));return this.people.ha(a,b,c)});e.prototype.Yc=K(function(a,b,c){var e=this.s(a);if(e!==l){var h=e.indexOf(b);-1(x.__SV||0)?n.B("Version mismatch; please ensure you're using the latest version of the Mixpanel code snippet."):(c.a(x._i,function(a){a&&c.isArray(a)&&(F[a[a.length-1]]=S.apply(this,a))}),Ca(),x.init(),c.a(F,function(a){a.la()}),Ba())})(function(a,b){var c=document.createElement("script");c.type="text/javascript";c.async=m;c.onload=b;c.src=a;document.head.appendChild(c)})})(); +q.prototype.get_cross_subdomain=q.prototype.Jc;q.prototype.clear=q.prototype.clear;var F={};(function(a){na=a;ca=1;x=n.mixpanel;c.e(x)?o.B('"mixpanel" object not initialized. Ensure you are using the latest version of the Mixpanel JS Library along with the snippet we provide.'):x.__loaded||x.config&&x.persistence?o.B("The Mixpanel library has already been downloaded at least once. Ensure that the Mixpanel code snippet only appears once on the page (and is not double-loaded by a tag manager) in order to avoid errors."): +1.1>(x.__SV||0)?o.B("Version mismatch; please ensure you're using the latest version of the Mixpanel code snippet."):(c.a(x._i,function(a){a&&c.isArray(a)&&(F[a[a.length-1]]=S.apply(this,a))}),Ca(),x.init(),c.a(F,function(a){a.la()}),Ba())})(function(a,b){var c=document.createElement("script");c.type="text/javascript";c.async=m;c.onload=b;c.src=a;document.head.appendChild(c)})})(); })(); diff --git a/dist/mixpanel.module.js b/dist/mixpanel.module.js index 7826bcdb..8effb719 100644 --- a/dist/mixpanel.module.js +++ b/dist/mixpanel.module.js @@ -4507,7 +4507,7 @@ var IncrementalSource = /* @__PURE__ */ ((IncrementalSource2) => { var Config = { DEBUG: false, - LIB_VERSION: '2.55.0' + LIB_VERSION: '2.55.1-rc1' }; /* eslint camelcase: "off", eqeqeq: "off" */ @@ -4519,7 +4519,7 @@ if (typeof(window) === 'undefined') { hostname: '' }; win = { - navigator: { userAgent: '' }, + navigator: { userAgent: '', onLine: true }, document: { location: loc, referrer: '' @@ -4533,6 +4533,8 @@ if (typeof(window) === 'undefined') { // Maximum allowed session recording length var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours +// Maximum allowed value for minimum session recording length +var MAX_VALUE_FOR_MIN_RECORDING_MS = 8 * 1000; // 8 seconds /* * Saved references to long variable names, so that closure compiler can @@ -5473,7 +5475,7 @@ _.HTTPBuildQuery = function(formdata, arg_separator) { _.getQueryParam = function(url, param) { // Expects a raw URL - param = param.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); + param = param.replace(/[[]/g, '\\[').replace(/[\]]/g, '\\]'); var regexS = '[\\?&]' + param + '=([^&#]*)', regex = new RegExp(regexS), results = regex.exec(url); @@ -5930,8 +5932,8 @@ _.dom_query = (function() { }; })(); -var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; -var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid']; +var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform','utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic']; +var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'sccid', 'ttclid', 'twclid', 'wbraid']; _.info = { campaignParams: function(default_value) { @@ -6213,6 +6215,15 @@ var extract_domain = function(hostname) { return matches ? matches[0] : ''; }; +/** + * Check whether we have network connection. default to true for browsers that don't support navigator.onLine (IE) + * @returns {boolean} + */ +var isOnline = function() { + var onLine = win.navigator['onLine']; + return _.isUndefined(onLine) || onLine; +}; + var JSONStringify = null, JSONParse = null; if (typeof JSON !== 'undefined') { JSONStringify = JSON.stringify; @@ -7176,7 +7187,12 @@ RequestBatcher.prototype.flush = function(options) { this.flush(); } else if ( _.isObject(res) && - (res.httpStatusCode >= 500 || res.httpStatusCode === 429 || res.error === 'timeout') + ( + res.httpStatusCode >= 500 + || res.httpStatusCode === 429 + || (res.httpStatusCode <= 0 && !isOnline()) + || res.error === 'timeout' + ) ) { // network or API error, or 429 Too Many Requests, retry var retryMS = this.flushInterval * 2; @@ -7327,6 +7343,7 @@ var MixpanelRecorder = function(mixpanelInstance) { this.maxTimeoutId = null; this.recordMaxMs = MAX_RECORDING_MS; + this.recordMinMs = 0; this._initBatcher(); }; @@ -7358,16 +7375,24 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { logger.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.'); } + this.recordMinMs = this.get_config('record_min_ms'); + if (this.recordMinMs > MAX_VALUE_FOR_MIN_RECORDING_MS) { + this.recordMinMs = MAX_VALUE_FOR_MIN_RECORDING_MS; + logger.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.'); + } + this.recEvents = []; this.seqNo = 0; - this.replayStartTime = null; + this.replayStartTime = new Date().getTime(); this.replayId = _.UUID(); - if (shouldStopBatcher) { - // this is the case when we're starting recording after a reset + if (shouldStopBatcher || this.recordMinMs > 0) { + // the primary case for shouldStopBatcher is when we're starting recording after a reset // and don't want to send anything over the network until there's // actual user activity + // this also applies if the minimum recording length has not been hit yet + // so that we don't send data until we know the recording will be long enough this.batcher.stop(); } else { this.batcher.start(); @@ -7381,11 +7406,16 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { }, this), this.get_config('record_idle_timeout_ms')); }, this); + var blockSelector = this.get_config('record_block_selector'); + if (blockSelector === '' || blockSelector === null) { + blockSelector = undefined; + } + this._stopRecording = record({ 'emit': _.bind(function (ev) { this.batcher.enqueue(ev); if (isUserEvent(ev)) { - if (this.batcher.stopped) { + if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) { // start flushing again after user activity this.batcher.start(); } @@ -7393,7 +7423,7 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { } }, this), 'blockClass': this.get_config('record_block_class'), - 'blockSelector': this.get_config('record_block_selector'), + 'blockSelector': blockSelector, 'collectFonts': this.get_config('record_collect_fonts'), 'inlineImages': this.get_config('record_inline_images'), 'maskAllInputs': true, @@ -7447,14 +7477,14 @@ MixpanelRecorder.prototype._onOptOut = function (code) { } }; -MixpanelRecorder.prototype._sendRequest = function(reqParams, reqBody, callback) { +MixpanelRecorder.prototype._sendRequest = function(currentReplayId, reqParams, reqBody, callback) { var onSuccess = _.bind(function (response, responseBody) { // Increment sequence counter only if the request was successful to guarantee ordering. // RequestBatcher will always flush the next batch after the previous one succeeds. - if (response.status === 200) { + // extra check to see if the replay ID has changed so that we don't increment the seqNo on the wrong replay + if (response.status === 200 && this.replayId === currentReplayId) { this.seqNo++; } - callback({ status: 0, httpStatusCode: response.status, @@ -7477,7 +7507,7 @@ MixpanelRecorder.prototype._sendRequest = function(reqParams, reqBody, callback) callback({error: error}); }); }).catch(function (error) { - callback({error: error}); + callback({error: error, httpStatusCode: 0}); }); }; @@ -7485,9 +7515,15 @@ MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da const numEvents = data.length; if (numEvents > 0) { + var replayId = this.replayId; // each rrweb event has a timestamp - leverage those to get time properties var batchStartTime = data[0].timestamp; - if (this.seqNo === 0) { + if (this.seqNo === 0 || !this.replayStartTime) { + // extra safety net so that we don't send a null replay start time + if (this.seqNo !== 0) { + this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.'); + } + this.replayStartTime = batchStartTime; } var replayLengthMs = data[numEvents - 1].timestamp - this.replayStartTime; @@ -7496,7 +7532,7 @@ MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da 'distinct_id': String(this._mixpanel.get_distinct_id()), 'seq': this.seqNo, 'batch_start_time': batchStartTime / 1000, - 'replay_id': this.replayId, + 'replay_id': replayId, 'replay_length_ms': replayLengthMs, 'replay_start_time': this.replayStartTime / 1000 }; @@ -7519,11 +7555,11 @@ MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da .blob() .then(_.bind(function(compressedBlob) { reqParams['format'] = 'gzip'; - this._sendRequest(reqParams, compressedBlob, callback); + this._sendRequest(replayId, reqParams, compressedBlob, callback); }, this)); } else { reqParams['format'] = 'body'; - this._sendRequest(reqParams, eventsJson, callback); + this._sendRequest(replayId, reqParams, eventsJson, callback); } } }); @@ -9011,6 +9047,7 @@ var DEFAULT_CONFIG = { 'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'), 'record_mask_text_selector': '*', 'record_max_ms': MAX_RECORDING_MS, + 'record_min_ms': 0, 'record_sessions_percent': 0, 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js' }; diff --git a/dist/mixpanel.umd.js b/dist/mixpanel.umd.js index de10f216..3dd00cc5 100644 --- a/dist/mixpanel.umd.js +++ b/dist/mixpanel.umd.js @@ -4513,7 +4513,7 @@ var Config = { DEBUG: false, - LIB_VERSION: '2.55.0' + LIB_VERSION: '2.55.1-rc1' }; /* eslint camelcase: "off", eqeqeq: "off" */ @@ -4525,7 +4525,7 @@ hostname: '' }; win = { - navigator: { userAgent: '' }, + navigator: { userAgent: '', onLine: true }, document: { location: loc, referrer: '' @@ -4539,6 +4539,8 @@ // Maximum allowed session recording length var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours + // Maximum allowed value for minimum session recording length + var MAX_VALUE_FOR_MIN_RECORDING_MS = 8 * 1000; // 8 seconds /* * Saved references to long variable names, so that closure compiler can @@ -5479,7 +5481,7 @@ _.getQueryParam = function(url, param) { // Expects a raw URL - param = param.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); + param = param.replace(/[[]/g, '\\[').replace(/[\]]/g, '\\]'); var regexS = '[\\?&]' + param + '=([^&#]*)', regex = new RegExp(regexS), results = regex.exec(url); @@ -5936,8 +5938,8 @@ }; })(); - var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; - var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid']; + var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform','utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic']; + var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'sccid', 'ttclid', 'twclid', 'wbraid']; _.info = { campaignParams: function(default_value) { @@ -6219,6 +6221,15 @@ return matches ? matches[0] : ''; }; + /** + * Check whether we have network connection. default to true for browsers that don't support navigator.onLine (IE) + * @returns {boolean} + */ + var isOnline = function() { + var onLine = win.navigator['onLine']; + return _.isUndefined(onLine) || onLine; + }; + var JSONStringify = null, JSONParse = null; if (typeof JSON !== 'undefined') { JSONStringify = JSON.stringify; @@ -7182,7 +7193,12 @@ this.flush(); } else if ( _.isObject(res) && - (res.httpStatusCode >= 500 || res.httpStatusCode === 429 || res.error === 'timeout') + ( + res.httpStatusCode >= 500 + || res.httpStatusCode === 429 + || (res.httpStatusCode <= 0 && !isOnline()) + || res.error === 'timeout' + ) ) { // network or API error, or 429 Too Many Requests, retry var retryMS = this.flushInterval * 2; @@ -7333,6 +7349,7 @@ this.maxTimeoutId = null; this.recordMaxMs = MAX_RECORDING_MS; + this.recordMinMs = 0; this._initBatcher(); }; @@ -7364,16 +7381,24 @@ logger.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.'); } + this.recordMinMs = this.get_config('record_min_ms'); + if (this.recordMinMs > MAX_VALUE_FOR_MIN_RECORDING_MS) { + this.recordMinMs = MAX_VALUE_FOR_MIN_RECORDING_MS; + logger.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.'); + } + this.recEvents = []; this.seqNo = 0; - this.replayStartTime = null; + this.replayStartTime = new Date().getTime(); this.replayId = _.UUID(); - if (shouldStopBatcher) { - // this is the case when we're starting recording after a reset + if (shouldStopBatcher || this.recordMinMs > 0) { + // the primary case for shouldStopBatcher is when we're starting recording after a reset // and don't want to send anything over the network until there's // actual user activity + // this also applies if the minimum recording length has not been hit yet + // so that we don't send data until we know the recording will be long enough this.batcher.stop(); } else { this.batcher.start(); @@ -7387,11 +7412,16 @@ }, this), this.get_config('record_idle_timeout_ms')); }, this); + var blockSelector = this.get_config('record_block_selector'); + if (blockSelector === '' || blockSelector === null) { + blockSelector = undefined; + } + this._stopRecording = record({ 'emit': _.bind(function (ev) { this.batcher.enqueue(ev); if (isUserEvent(ev)) { - if (this.batcher.stopped) { + if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) { // start flushing again after user activity this.batcher.start(); } @@ -7399,7 +7429,7 @@ } }, this), 'blockClass': this.get_config('record_block_class'), - 'blockSelector': this.get_config('record_block_selector'), + 'blockSelector': blockSelector, 'collectFonts': this.get_config('record_collect_fonts'), 'inlineImages': this.get_config('record_inline_images'), 'maskAllInputs': true, @@ -7453,14 +7483,14 @@ } }; - MixpanelRecorder.prototype._sendRequest = function(reqParams, reqBody, callback) { + MixpanelRecorder.prototype._sendRequest = function(currentReplayId, reqParams, reqBody, callback) { var onSuccess = _.bind(function (response, responseBody) { // Increment sequence counter only if the request was successful to guarantee ordering. // RequestBatcher will always flush the next batch after the previous one succeeds. - if (response.status === 200) { + // extra check to see if the replay ID has changed so that we don't increment the seqNo on the wrong replay + if (response.status === 200 && this.replayId === currentReplayId) { this.seqNo++; } - callback({ status: 0, httpStatusCode: response.status, @@ -7483,7 +7513,7 @@ callback({error: error}); }); }).catch(function (error) { - callback({error: error}); + callback({error: error, httpStatusCode: 0}); }); }; @@ -7491,9 +7521,15 @@ const numEvents = data.length; if (numEvents > 0) { + var replayId = this.replayId; // each rrweb event has a timestamp - leverage those to get time properties var batchStartTime = data[0].timestamp; - if (this.seqNo === 0) { + if (this.seqNo === 0 || !this.replayStartTime) { + // extra safety net so that we don't send a null replay start time + if (this.seqNo !== 0) { + this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.'); + } + this.replayStartTime = batchStartTime; } var replayLengthMs = data[numEvents - 1].timestamp - this.replayStartTime; @@ -7502,7 +7538,7 @@ 'distinct_id': String(this._mixpanel.get_distinct_id()), 'seq': this.seqNo, 'batch_start_time': batchStartTime / 1000, - 'replay_id': this.replayId, + 'replay_id': replayId, 'replay_length_ms': replayLengthMs, 'replay_start_time': this.replayStartTime / 1000 }; @@ -7525,11 +7561,11 @@ .blob() .then(_.bind(function(compressedBlob) { reqParams['format'] = 'gzip'; - this._sendRequest(reqParams, compressedBlob, callback); + this._sendRequest(replayId, reqParams, compressedBlob, callback); }, this)); } else { reqParams['format'] = 'body'; - this._sendRequest(reqParams, eventsJson, callback); + this._sendRequest(replayId, reqParams, eventsJson, callback); } } }); @@ -9017,6 +9053,7 @@ 'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'), 'record_mask_text_selector': '*', 'record_max_ms': MAX_RECORDING_MS, + 'record_min_ms': 0, 'record_sessions_percent': 0, 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js' }; diff --git a/examples/commonjs-browserify/bundle.js b/examples/commonjs-browserify/bundle.js index 1ded6a34..527dd581 100644 --- a/examples/commonjs-browserify/bundle.js +++ b/examples/commonjs-browserify/bundle.js @@ -4510,7 +4510,7 @@ var IncrementalSource = /* @__PURE__ */ ((IncrementalSource2) => { var Config = { DEBUG: false, - LIB_VERSION: '2.55.0' + LIB_VERSION: '2.55.1-rc1' }; /* eslint camelcase: "off", eqeqeq: "off" */ @@ -4522,7 +4522,7 @@ if (typeof(window) === 'undefined') { hostname: '' }; win = { - navigator: { userAgent: '' }, + navigator: { userAgent: '', onLine: true }, document: { location: loc, referrer: '' @@ -4536,6 +4536,8 @@ if (typeof(window) === 'undefined') { // Maximum allowed session recording length var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours +// Maximum allowed value for minimum session recording length +var MAX_VALUE_FOR_MIN_RECORDING_MS = 8 * 1000; // 8 seconds /* * Saved references to long variable names, so that closure compiler can @@ -5476,7 +5478,7 @@ _.HTTPBuildQuery = function(formdata, arg_separator) { _.getQueryParam = function(url, param) { // Expects a raw URL - param = param.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); + param = param.replace(/[[]/g, '\\[').replace(/[\]]/g, '\\]'); var regexS = '[\\?&]' + param + '=([^&#]*)', regex = new RegExp(regexS), results = regex.exec(url); @@ -5933,8 +5935,8 @@ _.dom_query = (function() { }; })(); -var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; -var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid']; +var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform','utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic']; +var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'sccid', 'ttclid', 'twclid', 'wbraid']; _.info = { campaignParams: function(default_value) { @@ -6216,6 +6218,15 @@ var extract_domain = function(hostname) { return matches ? matches[0] : ''; }; +/** + * Check whether we have network connection. default to true for browsers that don't support navigator.onLine (IE) + * @returns {boolean} + */ +var isOnline = function() { + var onLine = win.navigator['onLine']; + return _.isUndefined(onLine) || onLine; +}; + var JSONStringify = null, JSONParse = null; if (typeof JSON !== 'undefined') { JSONStringify = JSON.stringify; @@ -7179,7 +7190,12 @@ RequestBatcher.prototype.flush = function(options) { this.flush(); } else if ( _.isObject(res) && - (res.httpStatusCode >= 500 || res.httpStatusCode === 429 || res.error === 'timeout') + ( + res.httpStatusCode >= 500 + || res.httpStatusCode === 429 + || (res.httpStatusCode <= 0 && !isOnline()) + || res.error === 'timeout' + ) ) { // network or API error, or 429 Too Many Requests, retry var retryMS = this.flushInterval * 2; @@ -7330,6 +7346,7 @@ var MixpanelRecorder = function(mixpanelInstance) { this.maxTimeoutId = null; this.recordMaxMs = MAX_RECORDING_MS; + this.recordMinMs = 0; this._initBatcher(); }; @@ -7361,16 +7378,24 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { logger.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.'); } + this.recordMinMs = this.get_config('record_min_ms'); + if (this.recordMinMs > MAX_VALUE_FOR_MIN_RECORDING_MS) { + this.recordMinMs = MAX_VALUE_FOR_MIN_RECORDING_MS; + logger.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.'); + } + this.recEvents = []; this.seqNo = 0; - this.replayStartTime = null; + this.replayStartTime = new Date().getTime(); this.replayId = _.UUID(); - if (shouldStopBatcher) { - // this is the case when we're starting recording after a reset + if (shouldStopBatcher || this.recordMinMs > 0) { + // the primary case for shouldStopBatcher is when we're starting recording after a reset // and don't want to send anything over the network until there's // actual user activity + // this also applies if the minimum recording length has not been hit yet + // so that we don't send data until we know the recording will be long enough this.batcher.stop(); } else { this.batcher.start(); @@ -7384,11 +7409,16 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { }, this), this.get_config('record_idle_timeout_ms')); }, this); + var blockSelector = this.get_config('record_block_selector'); + if (blockSelector === '' || blockSelector === null) { + blockSelector = undefined; + } + this._stopRecording = record({ 'emit': _.bind(function (ev) { this.batcher.enqueue(ev); if (isUserEvent(ev)) { - if (this.batcher.stopped) { + if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) { // start flushing again after user activity this.batcher.start(); } @@ -7396,7 +7426,7 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { } }, this), 'blockClass': this.get_config('record_block_class'), - 'blockSelector': this.get_config('record_block_selector'), + 'blockSelector': blockSelector, 'collectFonts': this.get_config('record_collect_fonts'), 'inlineImages': this.get_config('record_inline_images'), 'maskAllInputs': true, @@ -7450,14 +7480,14 @@ MixpanelRecorder.prototype._onOptOut = function (code) { } }; -MixpanelRecorder.prototype._sendRequest = function(reqParams, reqBody, callback) { +MixpanelRecorder.prototype._sendRequest = function(currentReplayId, reqParams, reqBody, callback) { var onSuccess = _.bind(function (response, responseBody) { // Increment sequence counter only if the request was successful to guarantee ordering. // RequestBatcher will always flush the next batch after the previous one succeeds. - if (response.status === 200) { + // extra check to see if the replay ID has changed so that we don't increment the seqNo on the wrong replay + if (response.status === 200 && this.replayId === currentReplayId) { this.seqNo++; } - callback({ status: 0, httpStatusCode: response.status, @@ -7480,7 +7510,7 @@ MixpanelRecorder.prototype._sendRequest = function(reqParams, reqBody, callback) callback({error: error}); }); }).catch(function (error) { - callback({error: error}); + callback({error: error, httpStatusCode: 0}); }); }; @@ -7488,9 +7518,15 @@ MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da const numEvents = data.length; if (numEvents > 0) { + var replayId = this.replayId; // each rrweb event has a timestamp - leverage those to get time properties var batchStartTime = data[0].timestamp; - if (this.seqNo === 0) { + if (this.seqNo === 0 || !this.replayStartTime) { + // extra safety net so that we don't send a null replay start time + if (this.seqNo !== 0) { + this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.'); + } + this.replayStartTime = batchStartTime; } var replayLengthMs = data[numEvents - 1].timestamp - this.replayStartTime; @@ -7499,7 +7535,7 @@ MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da 'distinct_id': String(this._mixpanel.get_distinct_id()), 'seq': this.seqNo, 'batch_start_time': batchStartTime / 1000, - 'replay_id': this.replayId, + 'replay_id': replayId, 'replay_length_ms': replayLengthMs, 'replay_start_time': this.replayStartTime / 1000 }; @@ -7522,11 +7558,11 @@ MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da .blob() .then(_.bind(function(compressedBlob) { reqParams['format'] = 'gzip'; - this._sendRequest(reqParams, compressedBlob, callback); + this._sendRequest(replayId, reqParams, compressedBlob, callback); }, this)); } else { reqParams['format'] = 'body'; - this._sendRequest(reqParams, eventsJson, callback); + this._sendRequest(replayId, reqParams, eventsJson, callback); } } }); @@ -9014,6 +9050,7 @@ var DEFAULT_CONFIG = { 'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'), 'record_mask_text_selector': '*', 'record_max_ms': MAX_RECORDING_MS, + 'record_min_ms': 0, 'record_sessions_percent': 0, 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js' }; diff --git a/examples/es2015-babelify/bundle.js b/examples/es2015-babelify/bundle.js index 49dc73bb..5da3d177 100644 --- a/examples/es2015-babelify/bundle.js +++ b/examples/es2015-babelify/bundle.js @@ -10982,7 +10982,7 @@ Object.defineProperty(exports, '__esModule', { }); var Config = { DEBUG: false, - LIB_VERSION: '2.55.0' + LIB_VERSION: '2.55.1-rc1' }; exports['default'] = Config; @@ -11682,6 +11682,7 @@ var DEFAULT_CONFIG = { 'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'), 'record_mask_text_selector': '*', 'record_max_ms': _utils.MAX_RECORDING_MS, + 'record_min_ms': 0, 'record_sessions_percent': 0, 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js' }; @@ -14943,6 +14944,7 @@ var MixpanelRecorder = function MixpanelRecorder(mixpanelInstance) { this.maxTimeoutId = null; this.recordMaxMs = _utils.MAX_RECORDING_MS; + this.recordMinMs = 0; this._initBatcher(); }; @@ -14973,16 +14975,24 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { logger.critical('record_max_ms cannot be greater than ' + _utils.MAX_RECORDING_MS + 'ms. Capping value.'); } + this.recordMinMs = this.get_config('record_min_ms'); + if (this.recordMinMs > _utils.MAX_VALUE_FOR_MIN_RECORDING_MS) { + this.recordMinMs = _utils.MAX_VALUE_FOR_MIN_RECORDING_MS; + logger.critical('record_min_ms cannot be greater than ' + _utils.MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.'); + } + this.recEvents = []; this.seqNo = 0; - this.replayStartTime = null; + this.replayStartTime = new Date().getTime(); this.replayId = _utils._.UUID(); - if (shouldStopBatcher) { - // this is the case when we're starting recording after a reset + if (shouldStopBatcher || this.recordMinMs > 0) { + // the primary case for shouldStopBatcher is when we're starting recording after a reset // and don't want to send anything over the network until there's // actual user activity + // this also applies if the minimum recording length has not been hit yet + // so that we don't send data until we know the recording will be long enough this.batcher.stop(); } else { this.batcher.start(); @@ -14996,11 +15006,16 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { }, this), this.get_config('record_idle_timeout_ms')); }, this); + var blockSelector = this.get_config('record_block_selector'); + if (blockSelector === '' || blockSelector === null) { + blockSelector = undefined; + } + this._stopRecording = (0, _rrweb.record)({ 'emit': _utils._.bind(function (ev) { this.batcher.enqueue(ev); if (isUserEvent(ev)) { - if (this.batcher.stopped) { + if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) { // start flushing again after user activity this.batcher.start(); } @@ -15008,7 +15023,7 @@ MixpanelRecorder.prototype.startRecording = function (shouldStopBatcher) { } }, this), 'blockClass': this.get_config('record_block_class'), - 'blockSelector': this.get_config('record_block_selector'), + 'blockSelector': blockSelector, 'collectFonts': this.get_config('record_collect_fonts'), 'inlineImages': this.get_config('record_inline_images'), 'maskAllInputs': true, @@ -15062,14 +15077,14 @@ MixpanelRecorder.prototype._onOptOut = function (code) { } }; -MixpanelRecorder.prototype._sendRequest = function (reqParams, reqBody, callback) { +MixpanelRecorder.prototype._sendRequest = function (currentReplayId, reqParams, reqBody, callback) { var onSuccess = _utils._.bind(function (response, responseBody) { // Increment sequence counter only if the request was successful to guarantee ordering. // RequestBatcher will always flush the next batch after the previous one succeeds. - if (response.status === 200) { + // extra check to see if the replay ID has changed so that we don't increment the seqNo on the wrong replay + if (response.status === 200 && this.replayId === currentReplayId) { this.seqNo++; } - callback({ status: 0, httpStatusCode: response.status, @@ -15092,7 +15107,7 @@ MixpanelRecorder.prototype._sendRequest = function (reqParams, reqBody, callback callback({ error: error }); }); })['catch'](function (error) { - callback({ error: error }); + callback({ error: error, httpStatusCode: 0 }); }); }; @@ -15100,9 +15115,15 @@ MixpanelRecorder.prototype._flushEvents = (0, _gdprUtils.addOptOutCheckMixpanelL var numEvents = data.length; if (numEvents > 0) { + var replayId = this.replayId; // each rrweb event has a timestamp - leverage those to get time properties var batchStartTime = data[0].timestamp; - if (this.seqNo === 0) { + if (this.seqNo === 0 || !this.replayStartTime) { + // extra safety net so that we don't send a null replay start time + if (this.seqNo !== 0) { + this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.'); + } + this.replayStartTime = batchStartTime; } var replayLengthMs = data[numEvents - 1].timestamp - this.replayStartTime; @@ -15111,7 +15132,7 @@ MixpanelRecorder.prototype._flushEvents = (0, _gdprUtils.addOptOutCheckMixpanelL 'distinct_id': String(this._mixpanel.get_distinct_id()), 'seq': this.seqNo, 'batch_start_time': batchStartTime / 1000, - 'replay_id': this.replayId, + 'replay_id': replayId, 'replay_length_ms': replayLengthMs, 'replay_start_time': this.replayStartTime / 1000 }; @@ -15132,11 +15153,11 @@ MixpanelRecorder.prototype._flushEvents = (0, _gdprUtils.addOptOutCheckMixpanelL var gzipStream = jsonStream.pipeThrough(new CompressionStream('gzip')); new Response(gzipStream).blob().then(_utils._.bind(function (compressedBlob) { reqParams['format'] = 'gzip'; - this._sendRequest(reqParams, compressedBlob, callback); + this._sendRequest(replayId, reqParams, compressedBlob, callback); }, this)); } else { reqParams['format'] = 'body'; - this._sendRequest(reqParams, eventsJson, callback); + this._sendRequest(replayId, reqParams, eventsJson, callback); } } }); @@ -15361,7 +15382,7 @@ RequestBatcher.prototype.flush = function (options) { } else if (_utils._.isObject(res) && res.error === 'timeout' && new Date().getTime() - startTime >= timeoutMS) { this.reportError('Network timeout; retrying'); this.flush(); - } else if (_utils._.isObject(res) && (res.httpStatusCode >= 500 || res.httpStatusCode === 429 || res.error === 'timeout')) { + } else if (_utils._.isObject(res) && (res.httpStatusCode >= 500 || res.httpStatusCode === 429 || res.httpStatusCode <= 0 && !(0, _utils.isOnline)() || res.error === 'timeout')) { // network or API error, or 429 Too Many Requests, retry var retryMS = this.flushInterval * 2; if (res.retryAfter) { @@ -15968,7 +15989,7 @@ if (typeof window === 'undefined') { hostname: '' }; exports.window = win = { - navigator: { userAgent: '' }, + navigator: { userAgent: '', onLine: true }, document: { location: loc, referrer: '' @@ -15982,6 +16003,8 @@ if (typeof window === 'undefined') { // Maximum allowed session recording length var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours +// Maximum allowed value for minimum session recording length +var MAX_VALUE_FOR_MIN_RECORDING_MS = 8 * 1000; // 8 seconds /* * Saved references to long variable names, so that closure compiler can @@ -16900,7 +16923,7 @@ _.HTTPBuildQuery = function (formdata, arg_separator) { _.getQueryParam = function (url, param) { // Expects a raw URL - param = param.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); + param = param.replace(/[[]/g, '\\[').replace(/[\]]/g, '\\]'); var regexS = '[\\?&]' + param + '=([^&#]*)', regex = new RegExp(regexS), results = regex.exec(url); @@ -17356,8 +17379,8 @@ _.dom_query = (function () { }; })(); -var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; -var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid']; +var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform', 'utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic']; +var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'sccid', 'ttclid', 'twclid', 'wbraid']; _.info = { campaignParams: function campaignParams(default_value) { @@ -17639,6 +17662,15 @@ var extract_domain = function extract_domain(hostname) { return matches ? matches[0] : ''; }; +/** + * Check whether we have network connection. default to true for browsers that don't support navigator.onLine (IE) + * @returns {boolean} + */ +var isOnline = function isOnline() { + var onLine = win.navigator['onLine']; + return _.isUndefined(onLine) || onLine; +}; + var JSONStringify = null, JSONParse = null; if (typeof JSON !== 'undefined') { @@ -17661,19 +17693,21 @@ _['info']['browser'] = _.info.browser; _['info']['browserVersion'] = _.info.browserVersion; _['info']['properties'] = _.info.properties; -exports.MAX_RECORDING_MS = MAX_RECORDING_MS; exports._ = _; -exports.userAgent = userAgent; -exports.console = console; -exports.window = win; -exports.document = document; -exports.navigator = navigator; exports.cheap_guid = cheap_guid; exports.console_with_prefix = console_with_prefix; +exports.console = console; +exports.document = document; exports.extract_domain = extract_domain; -exports.localStorageSupported = localStorageSupported; -exports.JSONStringify = JSONStringify; exports.JSONParse = JSONParse; +exports.JSONStringify = JSONStringify; +exports.isOnline = isOnline; +exports.localStorageSupported = localStorageSupported; +exports.MAX_RECORDING_MS = MAX_RECORDING_MS; +exports.MAX_VALUE_FOR_MIN_RECORDING_MS = MAX_VALUE_FOR_MIN_RECORDING_MS; +exports.navigator = navigator; exports.slice = slice; +exports.userAgent = userAgent; +exports.window = win; },{"./config":5}]},{},[1]); diff --git a/examples/umd-webpack/bundle.js b/examples/umd-webpack/bundle.js index 97556c5f..7c2b1ae2 100644 --- a/examples/umd-webpack/bundle.js +++ b/examples/umd-webpack/bundle.js @@ -4576,7 +4576,7 @@ var Config = { DEBUG: false, - LIB_VERSION: '2.55.0' + LIB_VERSION: '2.55.1-rc1' }; /* eslint camelcase: "off", eqeqeq: "off" */ @@ -4588,7 +4588,7 @@ hostname: '' }; win = { - navigator: { userAgent: '' }, + navigator: { userAgent: '', onLine: true }, document: { location: loc, referrer: '' @@ -4602,6 +4602,8 @@ // Maximum allowed session recording length var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours + // Maximum allowed value for minimum session recording length + var MAX_VALUE_FOR_MIN_RECORDING_MS = 8 * 1000; // 8 seconds /* * Saved references to long variable names, so that closure compiler can @@ -5542,7 +5544,7 @@ _.getQueryParam = function(url, param) { // Expects a raw URL - param = param.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); + param = param.replace(/[[]/g, '\\[').replace(/[\]]/g, '\\]'); var regexS = '[\\?&]' + param + '=([^&#]*)', regex = new RegExp(regexS), results = regex.exec(url); @@ -5999,8 +6001,8 @@ }; })(); - var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; - var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid']; + var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_id', 'utm_source_platform','utm_campaign_id', 'utm_creative_format', 'utm_marketing_tactic']; + var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'sccid', 'ttclid', 'twclid', 'wbraid']; _.info = { campaignParams: function(default_value) { @@ -6282,6 +6284,15 @@ return matches ? matches[0] : ''; }; + /** + * Check whether we have network connection. default to true for browsers that don't support navigator.onLine (IE) + * @returns {boolean} + */ + var isOnline = function() { + var onLine = win.navigator['onLine']; + return _.isUndefined(onLine) || onLine; + }; + var JSONStringify = null, JSONParse = null; if (typeof JSON !== 'undefined') { JSONStringify = JSON.stringify; @@ -7245,7 +7256,12 @@ this.flush(); } else if ( _.isObject(res) && - (res.httpStatusCode >= 500 || res.httpStatusCode === 429 || res.error === 'timeout') + ( + res.httpStatusCode >= 500 + || res.httpStatusCode === 429 + || (res.httpStatusCode <= 0 && !isOnline()) + || res.error === 'timeout' + ) ) { // network or API error, or 429 Too Many Requests, retry var retryMS = this.flushInterval * 2; @@ -7396,6 +7412,7 @@ this.maxTimeoutId = null; this.recordMaxMs = MAX_RECORDING_MS; + this.recordMinMs = 0; this._initBatcher(); }; @@ -7427,16 +7444,24 @@ logger.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.'); } + this.recordMinMs = this.get_config('record_min_ms'); + if (this.recordMinMs > MAX_VALUE_FOR_MIN_RECORDING_MS) { + this.recordMinMs = MAX_VALUE_FOR_MIN_RECORDING_MS; + logger.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.'); + } + this.recEvents = []; this.seqNo = 0; - this.replayStartTime = null; + this.replayStartTime = new Date().getTime(); this.replayId = _.UUID(); - if (shouldStopBatcher) { - // this is the case when we're starting recording after a reset + if (shouldStopBatcher || this.recordMinMs > 0) { + // the primary case for shouldStopBatcher is when we're starting recording after a reset // and don't want to send anything over the network until there's // actual user activity + // this also applies if the minimum recording length has not been hit yet + // so that we don't send data until we know the recording will be long enough this.batcher.stop(); } else { this.batcher.start(); @@ -7450,11 +7475,16 @@ }, this), this.get_config('record_idle_timeout_ms')); }, this); + var blockSelector = this.get_config('record_block_selector'); + if (blockSelector === '' || blockSelector === null) { + blockSelector = undefined; + } + this._stopRecording = record({ 'emit': _.bind(function (ev) { this.batcher.enqueue(ev); if (isUserEvent(ev)) { - if (this.batcher.stopped) { + if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) { // start flushing again after user activity this.batcher.start(); } @@ -7462,7 +7492,7 @@ } }, this), 'blockClass': this.get_config('record_block_class'), - 'blockSelector': this.get_config('record_block_selector'), + 'blockSelector': blockSelector, 'collectFonts': this.get_config('record_collect_fonts'), 'inlineImages': this.get_config('record_inline_images'), 'maskAllInputs': true, @@ -7516,14 +7546,14 @@ } }; - MixpanelRecorder.prototype._sendRequest = function(reqParams, reqBody, callback) { + MixpanelRecorder.prototype._sendRequest = function(currentReplayId, reqParams, reqBody, callback) { var onSuccess = _.bind(function (response, responseBody) { // Increment sequence counter only if the request was successful to guarantee ordering. // RequestBatcher will always flush the next batch after the previous one succeeds. - if (response.status === 200) { + // extra check to see if the replay ID has changed so that we don't increment the seqNo on the wrong replay + if (response.status === 200 && this.replayId === currentReplayId) { this.seqNo++; } - callback({ status: 0, httpStatusCode: response.status, @@ -7546,7 +7576,7 @@ callback({error: error}); }); }).catch(function (error) { - callback({error: error}); + callback({error: error, httpStatusCode: 0}); }); }; @@ -7554,9 +7584,15 @@ const numEvents = data.length; if (numEvents > 0) { + var replayId = this.replayId; // each rrweb event has a timestamp - leverage those to get time properties var batchStartTime = data[0].timestamp; - if (this.seqNo === 0) { + if (this.seqNo === 0 || !this.replayStartTime) { + // extra safety net so that we don't send a null replay start time + if (this.seqNo !== 0) { + this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.'); + } + this.replayStartTime = batchStartTime; } var replayLengthMs = data[numEvents - 1].timestamp - this.replayStartTime; @@ -7565,7 +7601,7 @@ 'distinct_id': String(this._mixpanel.get_distinct_id()), 'seq': this.seqNo, 'batch_start_time': batchStartTime / 1000, - 'replay_id': this.replayId, + 'replay_id': replayId, 'replay_length_ms': replayLengthMs, 'replay_start_time': this.replayStartTime / 1000 }; @@ -7588,11 +7624,11 @@ .blob() .then(_.bind(function(compressedBlob) { reqParams['format'] = 'gzip'; - this._sendRequest(reqParams, compressedBlob, callback); + this._sendRequest(replayId, reqParams, compressedBlob, callback); }, this)); } else { reqParams['format'] = 'body'; - this._sendRequest(reqParams, eventsJson, callback); + this._sendRequest(replayId, reqParams, eventsJson, callback); } } }); @@ -9080,6 +9116,7 @@ 'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'), 'record_mask_text_selector': '*', 'record_max_ms': MAX_RECORDING_MS, + 'record_min_ms': 0, 'record_sessions_percent': 0, 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js' }; diff --git a/src/config.js b/src/config.js index 4d9887ad..24810d2c 100644 --- a/src/config.js +++ b/src/config.js @@ -1,6 +1,6 @@ var Config = { DEBUG: false, - LIB_VERSION: '2.55.0' + LIB_VERSION: '2.55.1-rc1' }; export default Config; From cb938d7876ac41491438fbe48bde7a3ea2e9fc2f Mon Sep 17 00:00:00 2001 From: Carlos Trevino <35301701+carlosdanieltt@users.noreply.github.com> Date: Tue, 27 Aug 2024 17:43:49 +0000 Subject: [PATCH 21/21] Build 2.55.1 --- CHANGELOG.md | 4 ++++ dist/mixpanel-core.cjs.js | 2 +- dist/mixpanel-recorder.js | 2 +- dist/mixpanel-recorder.min.js | 2 +- dist/mixpanel-with-async-recorder.cjs.js | 2 +- dist/mixpanel.amd.js | 2 +- dist/mixpanel.cjs.js | 2 +- dist/mixpanel.globals.js | 2 +- dist/mixpanel.min.js | 4 ++-- dist/mixpanel.module.js | 2 +- dist/mixpanel.umd.js | 2 +- examples/commonjs-browserify/bundle.js | 2 +- examples/es2015-babelify/bundle.js | 2 +- examples/umd-webpack/bundle.js | 2 +- src/config.js | 2 +- 15 files changed, 19 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13e9150a..7482ac57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +**2.55.1** (27 Aug 2024) +- Adds a minimum recording length option for session recording +- Fixes and improvements for session recording batcher to support offline queueing and retry + **2.55.0** (2 Aug 2024) - Added new build to support native JavaScript modules diff --git a/dist/mixpanel-core.cjs.js b/dist/mixpanel-core.cjs.js index a6889da2..e0d99c30 100644 --- a/dist/mixpanel-core.cjs.js +++ b/dist/mixpanel-core.cjs.js @@ -2,7 +2,7 @@ var Config = { DEBUG: false, - LIB_VERSION: '2.55.1-rc1' + LIB_VERSION: '2.55.1' }; /* eslint camelcase: "off", eqeqeq: "off" */ diff --git a/dist/mixpanel-recorder.js b/dist/mixpanel-recorder.js index 27002b12..6c34bf47 100644 --- a/dist/mixpanel-recorder.js +++ b/dist/mixpanel-recorder.js @@ -4510,7 +4510,7 @@ var Config = { DEBUG: false, - LIB_VERSION: '2.55.1-rc1' + LIB_VERSION: '2.55.1' }; /* eslint camelcase: "off", eqeqeq: "off" */ diff --git a/dist/mixpanel-recorder.min.js b/dist/mixpanel-recorder.min.js index a81d65df..0197d859 100644 --- a/dist/mixpanel-recorder.min.js +++ b/dist/mixpanel-recorder.min.js @@ -29,7 +29,7 @@ or you can use record.mirror to access the mirror instance during recording.`;le LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ***************************************************************************** */function e(c,u,h,m){function f(g){return g instanceof h?g:new h(function(p){p(g)})}return new(h||(h=Promise))(function(g,p){function y(v){try{S(m.next(v))}catch(b){p(b)}}function w(v){try{S(m.throw(v))}catch(b){p(b)}}function S(v){v.done?g(v.value):f(v.value).then(y,w)}S((m=m.apply(c,u||[])).next())})}for(var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",r=typeof Uint8Array>"u"?[]:new Uint8Array(256),n=0;n>2],f+=t[(u[h]&3)<<4|u[h+1]>>4],f+=t[(u[h+1]&15)<<2|u[h+2]>>6],f+=t[u[h+2]&63];return m%3===2?f=f.substring(0,f.length-1)+"=":m%3===1&&(f=f.substring(0,f.length-2)+"=="),f};const o=new Map,a=new Map;function l(c,u,h){return e(this,void 0,void 0,function*(){const m=`${c}-${u}`;if("OffscreenCanvas"in globalThis){if(a.has(m))return a.get(m);const f=new OffscreenCanvas(c,u);f.getContext("2d");const p=yield(yield f.convertToBlob(h)).arrayBuffer(),y=i(p);return a.set(m,y),y}else return""})}const s=self;s.onmessage=function(c){return e(this,void 0,void 0,function*(){if("OffscreenCanvas"in globalThis){const{id:u,bitmap:h,width:m,height:f,dataURLOptions:g}=c.data,p=l(m,f,g),y=new OffscreenCanvas(m,f);y.getContext("2d").drawImage(h,0,0),h.close();const S=yield y.convertToBlob(g),v=S.type,b=yield S.arrayBuffer(),M=i(b);if(!o.has(u)&&(yield p)===M)return o.set(u,M),s.postMessage({id:u});if(o.get(u)===M)return s.postMessage({id:u});s.postMessage({id:u,type:v,base64:M,width:m,height:f}),o.set(u,M)}else return s.postMessage({id:c.data.id})})}})()},null);class Dn{reset(){this.pendingCanvasMutations.clear(),this.resetObservers&&this.resetObservers()}freeze(){this.frozen=!0}unfreeze(){this.frozen=!1}lock(){this.locked=!0}unlock(){this.locked=!1}constructor(t){this.pendingCanvasMutations=new Map,this.rafStamps={latestId:0,invokeId:null},this.frozen=!1,this.locked=!1,this.processMutation=(s,c)=>{(this.rafStamps.invokeId&&this.rafStamps.latestId!==this.rafStamps.invokeId||!this.rafStamps.invokeId)&&(this.rafStamps.invokeId=this.rafStamps.latestId),this.pendingCanvasMutations.has(s)||this.pendingCanvasMutations.set(s,[]),this.pendingCanvasMutations.get(s).push(c)};const{sampling:r="all",win:n,blockClass:i,blockSelector:o,recordCanvas:a,dataURLOptions:l}=t;this.mutationCb=t.mutationCb,this.mirror=t.mirror,a&&r==="all"&&this.initCanvasMutationObserver(n,i,o),a&&typeof r=="number"&&this.initCanvasFPSObserver(r,n,i,o,{dataURLOptions:l})}initCanvasFPSObserver(t,r,n,i,o){const a=er(r,n,i,!0),l=new Map,s=new Tn;s.onmessage=g=>{const{id:p}=g.data;if(l.set(p,!1),!("base64"in g.data))return;const{base64:y,type:w,width:S,height:v}=g.data;this.mutationCb({id:p,type:ve["2D"],commands:[{property:"clearRect",args:[0,0,S,v]},{property:"drawImage",args:[{rr_type:"ImageBitmap",args:[{rr_type:"Blob",data:[{rr_type:"ArrayBuffer",base64:y}],type:w}]},0,0]}]})};const c=1e3/t;let u=0,h;const m=()=>{const g=[];return r.document.querySelectorAll("canvas").forEach(p=>{U(p,n,i,!0)||g.push(p)}),g},f=g=>{if(u&&g-uwn(this,void 0,void 0,function*(){var y;const w=this.mirror.getId(p);if(l.get(w)||p.width===0||p.height===0)return;if(l.set(w,!0),["webgl","webgl2"].includes(p.__context)){const v=p.getContext(p.__context);((y=v?.getContextAttributes())===null||y===void 0?void 0:y.preserveDrawingBuffer)===!1&&v.clear(v.COLOR_BUFFER_BIT)}const S=yield createImageBitmap(p);s.postMessage({id:w,bitmap:S,width:p.width,height:p.height,dataURLOptions:o.dataURLOptions},[S])})),h=requestAnimationFrame(f)};h=requestAnimationFrame(f),this.resetObservers=()=>{a(),cancelAnimationFrame(h)}}initCanvasMutationObserver(t,r,n){this.startRAFTimestamping(),this.startPendingCanvasMutationFlusher();const i=er(t,r,n,!1),o=_n(this.processMutation.bind(this),t,r,n),a=En(this.processMutation.bind(this),t,r,n,this.mirror);this.resetObservers=()=>{i(),o(),a()}}startPendingCanvasMutationFlusher(){requestAnimationFrame(()=>this.flushPendingCanvasMutations())}startRAFTimestamping(){const t=r=>{this.rafStamps.latestId=r,requestAnimationFrame(t)};requestAnimationFrame(t)}flushPendingCanvasMutations(){this.pendingCanvasMutations.forEach((t,r)=>{const n=this.mirror.getId(r);this.flushPendingCanvasMutationFor(r,n)}),requestAnimationFrame(()=>this.flushPendingCanvasMutations())}flushPendingCanvasMutationFor(t,r){if(this.frozen||this.locked)return;const n=this.pendingCanvasMutations.get(t);if(!n||r===-1)return;const i=n.map(a=>bn(a,["type"])),{type:o}=n[0];this.mutationCb({id:r,type:o,commands:i}),this.pendingCanvasMutations.delete(t)}}class Nn{constructor(t){this.trackedLinkElements=new WeakSet,this.styleMirror=new Yr,this.mutationCb=t.mutationCb,this.adoptedStyleSheetCb=t.adoptedStyleSheetCb}attachLinkElement(t,r){"_cssText"in r.attributes&&this.mutationCb({adds:[],removes:[],texts:[],attributes:[{id:r.id,attributes:r.attributes}]}),this.trackLinkElement(t)}trackLinkElement(t){this.trackedLinkElements.has(t)||(this.trackedLinkElements.add(t),this.trackStylesheetInLinkElement(t))}adoptStyleSheets(t,r){if(t.length===0)return;const n={id:r,styleIds:[]},i=[];for(const o of t){let a;this.styleMirror.has(o)?a=this.styleMirror.getId(o):(a=this.styleMirror.add(o),i.push({styleId:a,rules:Array.from(o.rules||CSSRule,(l,s)=>({rule:bt(l),index:s}))})),n.styleIds.push(a)}i.length>0&&(n.styles=i),this.adoptedStyleSheetCb(n)}reset(){this.styleMirror.reset(),this.trackedLinkElements=new WeakSet}trackStylesheetInLinkElement(t){}}class An{constructor(){this.nodeMap=new WeakMap,this.loop=!0,this.periodicallyClear()}periodicallyClear(){requestAnimationFrame(()=>{this.clear(),this.loop&&this.periodicallyClear()})}inOtherBuffer(t,r){const n=this.nodeMap.get(t);return n&&Array.from(n).some(i=>i!==r)}add(t,r){this.nodeMap.set(t,(this.nodeMap.get(t)||new Set).add(r))}clear(){this.nodeMap=new WeakMap}destroy(){this.loop=!1}}function L(e){return Object.assign(Object.assign({},e),{timestamp:Le()})}let N,ze,lt,He=!1;const V=Or();function Oe(e={}){const{emit:t,checkoutEveryNms:r,checkoutEveryNth:n,blockClass:i="rr-block",blockSelector:o=null,ignoreClass:a="rr-ignore",ignoreSelector:l=null,maskTextClass:s="rr-mask",maskTextSelector:c=null,inlineStylesheet:u=!0,maskAllInputs:h,maskInputOptions:m,slimDOMOptions:f,maskInputFn:g,maskTextFn:p,hooks:y,packFn:w,sampling:S={},dataURLOptions:v={},mousemoveWait:b,recordDOM:M=!0,recordCanvas:B=!1,recordCrossOriginIframes:P=!1,recordAfter:x=e.recordAfter==="DOMContentLoaded"?e.recordAfter:"load",userTriggeredOnInput:R=!1,collectFonts:j=!1,inlineImages:G=!1,plugins:E,keepIframeSrcFn:ue=()=>!1,ignoreCSSAttributes:z=new Set([]),errorHandler:ne}=e;rn(ne);const Z=P?window.parent===window:!0;let Qe=!1;if(!Z)try{window.parent.document&&(Qe=!1)}catch{Qe=!0}if(Z&&!t)throw new Error("emit function is required");b!==void 0&&S.mousemove===void 0&&(S.mousemove=b),V.reset();const mt=h===!0?{color:!0,date:!0,"datetime-local":!0,email:!0,month:!0,number:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0,textarea:!0,select:!0,password:!0}:m!==void 0?m:{password:!0},gt=f===!0||f==="all"?{script:!0,comment:!0,headFavicon:!0,headWhitespace:!0,headMetaSocial:!0,headMetaRobots:!0,headMetaHttpEquiv:!0,headMetaVerification:!0,headMetaAuthorship:f==="all",headMetaDescKeywords:f==="all"}:f||{};Kr();let gr,yt=0;const yr=I=>{for(const K of E||[])K.eventProcessor&&(I=K.eventProcessor(I));return w&&!Qe&&(I=w(I)),I};N=(I,K)=>{var D;if(!((D=oe[0])===null||D===void 0)&&D.isFrozen()&&I.type!==O.FullSnapshot&&!(I.type===O.IncrementalSnapshot&&I.data.source===C.Mutation)&&oe.forEach(H=>H.unfreeze()),Z)t?.(yr(I),K);else if(Qe){const H={type:"rrweb",event:yr(I),origin:window.location.origin,isCheckout:K};window.parent.postMessage(H,"*")}if(I.type===O.FullSnapshot)gr=I,yt=0;else if(I.type===O.IncrementalSnapshot){if(I.data.source===C.Mutation&&I.data.isAttachIframe)return;yt++;const H=n&&yt>=n,fe=r&&I.timestamp-gr.timestamp>r;(H||fe)&&ze(!0)}};const Ze=I=>{N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Mutation},I)}))},vr=I=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Scroll},I)})),Sr=I=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.CanvasMutation},I)})),ri=I=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.AdoptedStyleSheet},I)})),ce=new Nn({mutationCb:Ze,adoptedStyleSheetCb:ri}),de=new vn({mirror:V,mutationCb:Ze,stylesheetManager:ce,recordCrossOriginIframes:P,wrappedEmit:N});for(const I of E||[])I.getMirror&&I.getMirror({nodeMirror:V,crossOriginIframeMirror:de.crossOriginIframeMirror,crossOriginIframeStyleMirror:de.crossOriginIframeStyleMirror});const vt=new An;lt=new Dn({recordCanvas:B,mutationCb:Sr,win:window,blockClass:i,blockSelector:o,mirror:V,sampling:S.canvas,dataURLOptions:v});const et=new Sn({mutationCb:Ze,scrollCb:vr,bypassOptions:{blockClass:i,blockSelector:o,maskTextClass:s,maskTextSelector:c,inlineStylesheet:u,maskInputOptions:mt,dataURLOptions:v,maskTextFn:p,maskInputFn:g,recordCanvas:B,inlineImages:G,sampling:S,slimDOMOptions:gt,iframeManager:de,stylesheetManager:ce,canvasManager:lt,keepIframeSrcFn:ue,processedNodeManager:vt},mirror:V});ze=(I=!1)=>{if(!M)return;N(L({type:O.Meta,data:{href:window.location.href,width:Dt(),height:Tt()}}),I),ce.reset(),et.init(),oe.forEach(D=>D.lock());const K=Jr(document,{mirror:V,blockClass:i,blockSelector:o,maskTextClass:s,maskTextSelector:c,inlineStylesheet:u,maskAllInputs:mt,maskTextFn:p,slimDOM:gt,dataURLOptions:v,recordCanvas:B,inlineImages:G,onSerialize:D=>{Lt(D,V)&&de.addIframe(D),Ft(D,V)&&ce.trackLinkElement(D),st(D)&&et.addShadowRoot(D.shadowRoot,document)},onIframeLoad:(D,H)=>{de.attachIframe(D,H),et.observeAttachShadow(D)},onStylesheetLoad:(D,H)=>{ce.attachLinkElement(D,H)},keepIframeSrcFn:ue});if(!K)return console.warn("Failed to snapshot the document");N(L({type:O.FullSnapshot,data:{node:K,initialOffset:Rt(window)}}),I),oe.forEach(D=>D.unlock()),document.adoptedStyleSheets&&document.adoptedStyleSheets.length>0&&ce.adoptStyleSheets(document.adoptedStyleSheets,V.getId(document))};try{const I=[],K=H=>{var fe;return _(yn)({mutationCb:Ze,mousemoveCb:(T,St)=>N(L({type:O.IncrementalSnapshot,data:{source:St,positions:T}})),mouseInteractionCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.MouseInteraction},T)})),scrollCb:vr,viewportResizeCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.ViewportResize},T)})),inputCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Input},T)})),mediaInteractionCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.MediaInteraction},T)})),styleSheetRuleCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.StyleSheetRule},T)})),styleDeclarationCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.StyleDeclaration},T)})),canvasMutationCb:Sr,fontCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Font},T)})),selectionCb:T=>{N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Selection},T)}))},customElementCb:T=>{N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.CustomElement},T)}))},blockClass:i,ignoreClass:a,ignoreSelector:l,maskTextClass:s,maskTextSelector:c,maskInputOptions:mt,inlineStylesheet:u,sampling:S,recordDOM:M,recordCanvas:B,inlineImages:G,userTriggeredOnInput:R,collectFonts:j,doc:H,maskInputFn:g,maskTextFn:p,keepIframeSrcFn:ue,blockSelector:o,slimDOMOptions:gt,dataURLOptions:v,mirror:V,iframeManager:de,stylesheetManager:ce,shadowDomManager:et,processedNodeManager:vt,canvasManager:lt,ignoreCSSAttributes:z,plugins:((fe=E?.filter(T=>T.observer))===null||fe===void 0?void 0:fe.map(T=>({observer:T.observer,options:T.options,callback:St=>N(L({type:O.Plugin,data:{plugin:T.name,payload:St}}))})))||[]},y)};de.addLoadListener(H=>{try{I.push(K(H.contentDocument))}catch(fe){console.warn(fe)}});const D=()=>{ze(),I.push(K(document)),He=!0};return document.readyState==="interactive"||document.readyState==="complete"?D():(I.push(W("DOMContentLoaded",()=>{N(L({type:O.DomContentLoaded,data:{}})),x==="DOMContentLoaded"&&D()})),I.push(W("load",()=>{N(L({type:O.Load,data:{}})),x==="load"&&D()},window))),()=>{I.forEach(H=>H()),vt.destroy(),He=!1,nn()}}catch(I){console.warn(I)}}Oe.addCustomEvent=(e,t)=>{if(!He)throw new Error("please add custom event after start recording");N(L({type:O.Custom,data:{tag:e,payload:t}}))},Oe.freezePage=()=>{oe.forEach(e=>e.freeze())},Oe.takeFullSnapshot=e=>{if(!He)throw new Error("please take full snapshot after start recording");ze(e)},Oe.mirror=V;var rr=(e=>(e[e.DomContentLoaded=0]="DomContentLoaded",e[e.Load=1]="Load",e[e.FullSnapshot=2]="FullSnapshot",e[e.IncrementalSnapshot=3]="IncrementalSnapshot",e[e.Meta=4]="Meta",e[e.Custom=5]="Custom",e[e.Plugin=6]="Plugin",e))(rr||{}),Y=(e=>(e[e.Mutation=0]="Mutation",e[e.MouseMove=1]="MouseMove",e[e.MouseInteraction=2]="MouseInteraction",e[e.Scroll=3]="Scroll",e[e.ViewportResize=4]="ViewportResize",e[e.Input=5]="Input",e[e.TouchMove=6]="TouchMove",e[e.MediaInteraction=7]="MediaInteraction",e[e.StyleSheetRule=8]="StyleSheetRule",e[e.CanvasMutation=9]="CanvasMutation",e[e.Font=10]="Font",e[e.Log=11]="Log",e[e.Drag=12]="Drag",e[e.StyleDeclaration=13]="StyleDeclaration",e[e.Selection=14]="Selection",e[e.AdoptedStyleSheet=15]="AdoptedStyleSheet",e[e.CustomElement=16]="CustomElement",e))(Y||{}),nr={DEBUG:!1,LIB_VERSION:"2.55.1-rc1"},F;if(typeof window>"u"){var ir={hostname:""};F={navigator:{userAgent:"",onLine:!0},document:{location:ir,referrer:""},screen:{width:0,height:0},location:ir}}else F=window;var $e=24*60*60*1e3,ut=8*1e3,qe=Array.prototype,Ln=Function.prototype,or=Object.prototype,se=qe.slice,Ee=or.toString,je=or.hasOwnProperty,ke=F.console,xe=F.navigator,q=F.document,Ge=F.opera,Ve=F.screen,ae=xe.userAgent,ct=Ln.bind,sr=qe.forEach,ar=qe.indexOf,lr=qe.map,Fn=Array.isArray,dt={},d={trim:function(e){return e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")}},J={log:function(){},warn:function(){},error:function(){},critical:function(){if(!d.isUndefined(ke)&&ke){var e=["Mixpanel error:"].concat(d.toArray(arguments));try{ke.error.apply(ke,e)}catch{d.each(e,function(r){ke.error(r)})}}}},ft=function(e,t){return function(){return arguments[0]="["+t+"] "+arguments[0],e.apply(J,arguments)}},Je=function(e){return{log:ft(J.log,e),error:ft(J.error,e),critical:ft(J.critical,e)}};d.bind=function(e,t){var r,n;if(ct&&e.bind===ct)return ct.apply(e,se.call(arguments,1));if(!d.isFunction(e))throw new TypeError;return r=se.call(arguments,2),n=function(){if(!(this instanceof n))return e.apply(t,r.concat(se.call(arguments)));var i={};i.prototype=e.prototype;var o=new i;i.prototype=null;var a=e.apply(o,r.concat(se.call(arguments)));return Object(a)===a?a:o},n},d.each=function(e,t,r){if(e!=null){if(sr&&e.forEach===sr)e.forEach(t,r);else if(e.length===+e.length){for(var n=0,i=e.length;n0&&(t[n]=r)}),t},d.truncate=function(e,t){var r;return typeof e=="string"?r=e.slice(0,t):d.isArray(e)?(r=[],d.each(e,function(n){r.push(d.truncate(n,t))})):d.isObject(e)?(r={},d.each(e,function(n,i){r[i]=d.truncate(n,t)})):r=e,r},d.JSONEncode=function(){return function(e){var t=e,r=function(i){var o=/[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,a={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};return o.lastIndex=0,o.test(i)?'"'+i.replace(o,function(l){var s=a[l];return typeof s=="string"?s:"\\u"+("0000"+l.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+i+'"'},n=function(i,o){var a="",l=" ",s=0,c="",u="",h=0,m=a,f=[],g=o[i];switch(g&&typeof g=="object"&&typeof g.toJSON=="function"&&(g=g.toJSON(i)),typeof g){case"string":return r(g);case"number":return isFinite(g)?String(g):"null";case"boolean":case"null":return String(g);case"object":if(!g)return"null";if(a+=l,f=[],Ee.apply(g)==="[object Array]"){for(h=g.length,s=0;s"u"?[]:new Uint8Array(256),n=0;n>2],f+=t[(u[h]&3)<<4|u[h+1]>>4],f+=t[(u[h+1]&15)<<2|u[h+2]>>6],f+=t[u[h+2]&63];return m%3===2?f=f.substring(0,f.length-1)+"=":m%3===1&&(f=f.substring(0,f.length-2)+"=="),f};const o=new Map,a=new Map;function l(c,u,h){return e(this,void 0,void 0,function*(){const m=`${c}-${u}`;if("OffscreenCanvas"in globalThis){if(a.has(m))return a.get(m);const f=new OffscreenCanvas(c,u);f.getContext("2d");const p=yield(yield f.convertToBlob(h)).arrayBuffer(),y=i(p);return a.set(m,y),y}else return""})}const s=self;s.onmessage=function(c){return e(this,void 0,void 0,function*(){if("OffscreenCanvas"in globalThis){const{id:u,bitmap:h,width:m,height:f,dataURLOptions:g}=c.data,p=l(m,f,g),y=new OffscreenCanvas(m,f);y.getContext("2d").drawImage(h,0,0),h.close();const S=yield y.convertToBlob(g),v=S.type,b=yield S.arrayBuffer(),M=i(b);if(!o.has(u)&&(yield p)===M)return o.set(u,M),s.postMessage({id:u});if(o.get(u)===M)return s.postMessage({id:u});s.postMessage({id:u,type:v,base64:M,width:m,height:f}),o.set(u,M)}else return s.postMessage({id:c.data.id})})}})()},null);class Dn{reset(){this.pendingCanvasMutations.clear(),this.resetObservers&&this.resetObservers()}freeze(){this.frozen=!0}unfreeze(){this.frozen=!1}lock(){this.locked=!0}unlock(){this.locked=!1}constructor(t){this.pendingCanvasMutations=new Map,this.rafStamps={latestId:0,invokeId:null},this.frozen=!1,this.locked=!1,this.processMutation=(s,c)=>{(this.rafStamps.invokeId&&this.rafStamps.latestId!==this.rafStamps.invokeId||!this.rafStamps.invokeId)&&(this.rafStamps.invokeId=this.rafStamps.latestId),this.pendingCanvasMutations.has(s)||this.pendingCanvasMutations.set(s,[]),this.pendingCanvasMutations.get(s).push(c)};const{sampling:r="all",win:n,blockClass:i,blockSelector:o,recordCanvas:a,dataURLOptions:l}=t;this.mutationCb=t.mutationCb,this.mirror=t.mirror,a&&r==="all"&&this.initCanvasMutationObserver(n,i,o),a&&typeof r=="number"&&this.initCanvasFPSObserver(r,n,i,o,{dataURLOptions:l})}initCanvasFPSObserver(t,r,n,i,o){const a=er(r,n,i,!0),l=new Map,s=new Tn;s.onmessage=g=>{const{id:p}=g.data;if(l.set(p,!1),!("base64"in g.data))return;const{base64:y,type:w,width:S,height:v}=g.data;this.mutationCb({id:p,type:ve["2D"],commands:[{property:"clearRect",args:[0,0,S,v]},{property:"drawImage",args:[{rr_type:"ImageBitmap",args:[{rr_type:"Blob",data:[{rr_type:"ArrayBuffer",base64:y}],type:w}]},0,0]}]})};const c=1e3/t;let u=0,h;const m=()=>{const g=[];return r.document.querySelectorAll("canvas").forEach(p=>{U(p,n,i,!0)||g.push(p)}),g},f=g=>{if(u&&g-uwn(this,void 0,void 0,function*(){var y;const w=this.mirror.getId(p);if(l.get(w)||p.width===0||p.height===0)return;if(l.set(w,!0),["webgl","webgl2"].includes(p.__context)){const v=p.getContext(p.__context);((y=v?.getContextAttributes())===null||y===void 0?void 0:y.preserveDrawingBuffer)===!1&&v.clear(v.COLOR_BUFFER_BIT)}const S=yield createImageBitmap(p);s.postMessage({id:w,bitmap:S,width:p.width,height:p.height,dataURLOptions:o.dataURLOptions},[S])})),h=requestAnimationFrame(f)};h=requestAnimationFrame(f),this.resetObservers=()=>{a(),cancelAnimationFrame(h)}}initCanvasMutationObserver(t,r,n){this.startRAFTimestamping(),this.startPendingCanvasMutationFlusher();const i=er(t,r,n,!1),o=_n(this.processMutation.bind(this),t,r,n),a=En(this.processMutation.bind(this),t,r,n,this.mirror);this.resetObservers=()=>{i(),o(),a()}}startPendingCanvasMutationFlusher(){requestAnimationFrame(()=>this.flushPendingCanvasMutations())}startRAFTimestamping(){const t=r=>{this.rafStamps.latestId=r,requestAnimationFrame(t)};requestAnimationFrame(t)}flushPendingCanvasMutations(){this.pendingCanvasMutations.forEach((t,r)=>{const n=this.mirror.getId(r);this.flushPendingCanvasMutationFor(r,n)}),requestAnimationFrame(()=>this.flushPendingCanvasMutations())}flushPendingCanvasMutationFor(t,r){if(this.frozen||this.locked)return;const n=this.pendingCanvasMutations.get(t);if(!n||r===-1)return;const i=n.map(a=>bn(a,["type"])),{type:o}=n[0];this.mutationCb({id:r,type:o,commands:i}),this.pendingCanvasMutations.delete(t)}}class Nn{constructor(t){this.trackedLinkElements=new WeakSet,this.styleMirror=new Yr,this.mutationCb=t.mutationCb,this.adoptedStyleSheetCb=t.adoptedStyleSheetCb}attachLinkElement(t,r){"_cssText"in r.attributes&&this.mutationCb({adds:[],removes:[],texts:[],attributes:[{id:r.id,attributes:r.attributes}]}),this.trackLinkElement(t)}trackLinkElement(t){this.trackedLinkElements.has(t)||(this.trackedLinkElements.add(t),this.trackStylesheetInLinkElement(t))}adoptStyleSheets(t,r){if(t.length===0)return;const n={id:r,styleIds:[]},i=[];for(const o of t){let a;this.styleMirror.has(o)?a=this.styleMirror.getId(o):(a=this.styleMirror.add(o),i.push({styleId:a,rules:Array.from(o.rules||CSSRule,(l,s)=>({rule:bt(l),index:s}))})),n.styleIds.push(a)}i.length>0&&(n.styles=i),this.adoptedStyleSheetCb(n)}reset(){this.styleMirror.reset(),this.trackedLinkElements=new WeakSet}trackStylesheetInLinkElement(t){}}class An{constructor(){this.nodeMap=new WeakMap,this.loop=!0,this.periodicallyClear()}periodicallyClear(){requestAnimationFrame(()=>{this.clear(),this.loop&&this.periodicallyClear()})}inOtherBuffer(t,r){const n=this.nodeMap.get(t);return n&&Array.from(n).some(i=>i!==r)}add(t,r){this.nodeMap.set(t,(this.nodeMap.get(t)||new Set).add(r))}clear(){this.nodeMap=new WeakMap}destroy(){this.loop=!1}}function L(e){return Object.assign(Object.assign({},e),{timestamp:Le()})}let N,ze,lt,He=!1;const V=Or();function Oe(e={}){const{emit:t,checkoutEveryNms:r,checkoutEveryNth:n,blockClass:i="rr-block",blockSelector:o=null,ignoreClass:a="rr-ignore",ignoreSelector:l=null,maskTextClass:s="rr-mask",maskTextSelector:c=null,inlineStylesheet:u=!0,maskAllInputs:h,maskInputOptions:m,slimDOMOptions:f,maskInputFn:g,maskTextFn:p,hooks:y,packFn:w,sampling:S={},dataURLOptions:v={},mousemoveWait:b,recordDOM:M=!0,recordCanvas:B=!1,recordCrossOriginIframes:P=!1,recordAfter:x=e.recordAfter==="DOMContentLoaded"?e.recordAfter:"load",userTriggeredOnInput:R=!1,collectFonts:j=!1,inlineImages:G=!1,plugins:E,keepIframeSrcFn:ue=()=>!1,ignoreCSSAttributes:z=new Set([]),errorHandler:ne}=e;rn(ne);const Z=P?window.parent===window:!0;let Qe=!1;if(!Z)try{window.parent.document&&(Qe=!1)}catch{Qe=!0}if(Z&&!t)throw new Error("emit function is required");b!==void 0&&S.mousemove===void 0&&(S.mousemove=b),V.reset();const mt=h===!0?{color:!0,date:!0,"datetime-local":!0,email:!0,month:!0,number:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0,textarea:!0,select:!0,password:!0}:m!==void 0?m:{password:!0},gt=f===!0||f==="all"?{script:!0,comment:!0,headFavicon:!0,headWhitespace:!0,headMetaSocial:!0,headMetaRobots:!0,headMetaHttpEquiv:!0,headMetaVerification:!0,headMetaAuthorship:f==="all",headMetaDescKeywords:f==="all"}:f||{};Kr();let gr,yt=0;const yr=I=>{for(const K of E||[])K.eventProcessor&&(I=K.eventProcessor(I));return w&&!Qe&&(I=w(I)),I};N=(I,K)=>{var D;if(!((D=oe[0])===null||D===void 0)&&D.isFrozen()&&I.type!==O.FullSnapshot&&!(I.type===O.IncrementalSnapshot&&I.data.source===C.Mutation)&&oe.forEach(H=>H.unfreeze()),Z)t?.(yr(I),K);else if(Qe){const H={type:"rrweb",event:yr(I),origin:window.location.origin,isCheckout:K};window.parent.postMessage(H,"*")}if(I.type===O.FullSnapshot)gr=I,yt=0;else if(I.type===O.IncrementalSnapshot){if(I.data.source===C.Mutation&&I.data.isAttachIframe)return;yt++;const H=n&&yt>=n,fe=r&&I.timestamp-gr.timestamp>r;(H||fe)&&ze(!0)}};const Ze=I=>{N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Mutation},I)}))},vr=I=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Scroll},I)})),Sr=I=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.CanvasMutation},I)})),ri=I=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.AdoptedStyleSheet},I)})),ce=new Nn({mutationCb:Ze,adoptedStyleSheetCb:ri}),de=new vn({mirror:V,mutationCb:Ze,stylesheetManager:ce,recordCrossOriginIframes:P,wrappedEmit:N});for(const I of E||[])I.getMirror&&I.getMirror({nodeMirror:V,crossOriginIframeMirror:de.crossOriginIframeMirror,crossOriginIframeStyleMirror:de.crossOriginIframeStyleMirror});const vt=new An;lt=new Dn({recordCanvas:B,mutationCb:Sr,win:window,blockClass:i,blockSelector:o,mirror:V,sampling:S.canvas,dataURLOptions:v});const et=new Sn({mutationCb:Ze,scrollCb:vr,bypassOptions:{blockClass:i,blockSelector:o,maskTextClass:s,maskTextSelector:c,inlineStylesheet:u,maskInputOptions:mt,dataURLOptions:v,maskTextFn:p,maskInputFn:g,recordCanvas:B,inlineImages:G,sampling:S,slimDOMOptions:gt,iframeManager:de,stylesheetManager:ce,canvasManager:lt,keepIframeSrcFn:ue,processedNodeManager:vt},mirror:V});ze=(I=!1)=>{if(!M)return;N(L({type:O.Meta,data:{href:window.location.href,width:Dt(),height:Tt()}}),I),ce.reset(),et.init(),oe.forEach(D=>D.lock());const K=Jr(document,{mirror:V,blockClass:i,blockSelector:o,maskTextClass:s,maskTextSelector:c,inlineStylesheet:u,maskAllInputs:mt,maskTextFn:p,slimDOM:gt,dataURLOptions:v,recordCanvas:B,inlineImages:G,onSerialize:D=>{Lt(D,V)&&de.addIframe(D),Ft(D,V)&&ce.trackLinkElement(D),st(D)&&et.addShadowRoot(D.shadowRoot,document)},onIframeLoad:(D,H)=>{de.attachIframe(D,H),et.observeAttachShadow(D)},onStylesheetLoad:(D,H)=>{ce.attachLinkElement(D,H)},keepIframeSrcFn:ue});if(!K)return console.warn("Failed to snapshot the document");N(L({type:O.FullSnapshot,data:{node:K,initialOffset:Rt(window)}}),I),oe.forEach(D=>D.unlock()),document.adoptedStyleSheets&&document.adoptedStyleSheets.length>0&&ce.adoptStyleSheets(document.adoptedStyleSheets,V.getId(document))};try{const I=[],K=H=>{var fe;return _(yn)({mutationCb:Ze,mousemoveCb:(T,St)=>N(L({type:O.IncrementalSnapshot,data:{source:St,positions:T}})),mouseInteractionCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.MouseInteraction},T)})),scrollCb:vr,viewportResizeCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.ViewportResize},T)})),inputCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Input},T)})),mediaInteractionCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.MediaInteraction},T)})),styleSheetRuleCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.StyleSheetRule},T)})),styleDeclarationCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.StyleDeclaration},T)})),canvasMutationCb:Sr,fontCb:T=>N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Font},T)})),selectionCb:T=>{N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.Selection},T)}))},customElementCb:T=>{N(L({type:O.IncrementalSnapshot,data:Object.assign({source:C.CustomElement},T)}))},blockClass:i,ignoreClass:a,ignoreSelector:l,maskTextClass:s,maskTextSelector:c,maskInputOptions:mt,inlineStylesheet:u,sampling:S,recordDOM:M,recordCanvas:B,inlineImages:G,userTriggeredOnInput:R,collectFonts:j,doc:H,maskInputFn:g,maskTextFn:p,keepIframeSrcFn:ue,blockSelector:o,slimDOMOptions:gt,dataURLOptions:v,mirror:V,iframeManager:de,stylesheetManager:ce,shadowDomManager:et,processedNodeManager:vt,canvasManager:lt,ignoreCSSAttributes:z,plugins:((fe=E?.filter(T=>T.observer))===null||fe===void 0?void 0:fe.map(T=>({observer:T.observer,options:T.options,callback:St=>N(L({type:O.Plugin,data:{plugin:T.name,payload:St}}))})))||[]},y)};de.addLoadListener(H=>{try{I.push(K(H.contentDocument))}catch(fe){console.warn(fe)}});const D=()=>{ze(),I.push(K(document)),He=!0};return document.readyState==="interactive"||document.readyState==="complete"?D():(I.push(W("DOMContentLoaded",()=>{N(L({type:O.DomContentLoaded,data:{}})),x==="DOMContentLoaded"&&D()})),I.push(W("load",()=>{N(L({type:O.Load,data:{}})),x==="load"&&D()},window))),()=>{I.forEach(H=>H()),vt.destroy(),He=!1,nn()}}catch(I){console.warn(I)}}Oe.addCustomEvent=(e,t)=>{if(!He)throw new Error("please add custom event after start recording");N(L({type:O.Custom,data:{tag:e,payload:t}}))},Oe.freezePage=()=>{oe.forEach(e=>e.freeze())},Oe.takeFullSnapshot=e=>{if(!He)throw new Error("please take full snapshot after start recording");ze(e)},Oe.mirror=V;var rr=(e=>(e[e.DomContentLoaded=0]="DomContentLoaded",e[e.Load=1]="Load",e[e.FullSnapshot=2]="FullSnapshot",e[e.IncrementalSnapshot=3]="IncrementalSnapshot",e[e.Meta=4]="Meta",e[e.Custom=5]="Custom",e[e.Plugin=6]="Plugin",e))(rr||{}),Y=(e=>(e[e.Mutation=0]="Mutation",e[e.MouseMove=1]="MouseMove",e[e.MouseInteraction=2]="MouseInteraction",e[e.Scroll=3]="Scroll",e[e.ViewportResize=4]="ViewportResize",e[e.Input=5]="Input",e[e.TouchMove=6]="TouchMove",e[e.MediaInteraction=7]="MediaInteraction",e[e.StyleSheetRule=8]="StyleSheetRule",e[e.CanvasMutation=9]="CanvasMutation",e[e.Font=10]="Font",e[e.Log=11]="Log",e[e.Drag=12]="Drag",e[e.StyleDeclaration=13]="StyleDeclaration",e[e.Selection=14]="Selection",e[e.AdoptedStyleSheet=15]="AdoptedStyleSheet",e[e.CustomElement=16]="CustomElement",e))(Y||{}),nr={DEBUG:!1,LIB_VERSION:"2.55.1"},F;if(typeof window>"u"){var ir={hostname:""};F={navigator:{userAgent:"",onLine:!0},document:{location:ir,referrer:""},screen:{width:0,height:0},location:ir}}else F=window;var $e=24*60*60*1e3,ut=8*1e3,qe=Array.prototype,Ln=Function.prototype,or=Object.prototype,se=qe.slice,Ee=or.toString,je=or.hasOwnProperty,ke=F.console,xe=F.navigator,q=F.document,Ge=F.opera,Ve=F.screen,ae=xe.userAgent,ct=Ln.bind,sr=qe.forEach,ar=qe.indexOf,lr=qe.map,Fn=Array.isArray,dt={},d={trim:function(e){return e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")}},J={log:function(){},warn:function(){},error:function(){},critical:function(){if(!d.isUndefined(ke)&&ke){var e=["Mixpanel error:"].concat(d.toArray(arguments));try{ke.error.apply(ke,e)}catch{d.each(e,function(r){ke.error(r)})}}}},ft=function(e,t){return function(){return arguments[0]="["+t+"] "+arguments[0],e.apply(J,arguments)}},Je=function(e){return{log:ft(J.log,e),error:ft(J.error,e),critical:ft(J.critical,e)}};d.bind=function(e,t){var r,n;if(ct&&e.bind===ct)return ct.apply(e,se.call(arguments,1));if(!d.isFunction(e))throw new TypeError;return r=se.call(arguments,2),n=function(){if(!(this instanceof n))return e.apply(t,r.concat(se.call(arguments)));var i={};i.prototype=e.prototype;var o=new i;i.prototype=null;var a=e.apply(o,r.concat(se.call(arguments)));return Object(a)===a?a:o},n},d.each=function(e,t,r){if(e!=null){if(sr&&e.forEach===sr)e.forEach(t,r);else if(e.length===+e.length){for(var n=0,i=e.length;n0&&(t[n]=r)}),t},d.truncate=function(e,t){var r;return typeof e=="string"?r=e.slice(0,t):d.isArray(e)?(r=[],d.each(e,function(n){r.push(d.truncate(n,t))})):d.isObject(e)?(r={},d.each(e,function(n,i){r[i]=d.truncate(n,t)})):r=e,r},d.JSONEncode=function(){return function(e){var t=e,r=function(i){var o=/[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,a={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};return o.lastIndex=0,o.test(i)?'"'+i.replace(o,function(l){var s=a[l];return typeof s=="string"?s:"\\u"+("0000"+l.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+i+'"'},n=function(i,o){var a="",l=" ",s=0,c="",u="",h=0,m=a,f=[],g=o[i];switch(g&&typeof g=="object"&&typeof g.toJSON=="function"&&(g=g.toJSON(i)),typeof g){case"string":return r(g);case"number":return isFinite(g)?String(g):"null";case"boolean":case"null":return String(g);case"object":if(!g)return"null";if(a+=l,f=[],Ee.apply(g)==="[object Array]"){for(h=g.length,s=0;s { var Config = { DEBUG: false, - LIB_VERSION: '2.55.1-rc1' + LIB_VERSION: '2.55.1' }; /* eslint camelcase: "off", eqeqeq: "off" */ diff --git a/dist/mixpanel.globals.js b/dist/mixpanel.globals.js index 1fd35749..6be0a895 100644 --- a/dist/mixpanel.globals.js +++ b/dist/mixpanel.globals.js @@ -3,7 +3,7 @@ var Config = { DEBUG: false, - LIB_VERSION: '2.55.1-rc1' + LIB_VERSION: '2.55.1' }; /* eslint camelcase: "off", eqeqeq: "off" */ diff --git a/dist/mixpanel.min.js b/dist/mixpanel.min.js index 30bce548..9c5ad1ca 100644 --- a/dist/mixpanel.min.js +++ b/dist/mixpanel.min.js @@ -40,7 +40,7 @@ a);return d},na:function(a,b,d){return d||c.i(a," OPR/")?c.i(a,"Mini")?"Opera Mi "Safari":c.i(a,"Android")?"Android Mobile":c.i(a,"Konqueror")?"Konqueror":c.i(a,"Firefox")?"Firefox":c.i(a,"MSIE")||c.i(a,"Trident/")?"Internet Explorer":c.i(a,"Gecko")?"Mozilla":""},Ja:function(a,b,d){b={"Internet Explorer Mobile":/rv:(\d+(\.\d+)?)/,"Microsoft Edge":/Edge?\/(\d+(\.\d+)?)/,Chrome:/Chrome\/(\d+(\.\d+)?)/,"Chrome iOS":/CriOS\/(\d+(\.\d+)?)/,"UC Browser":/(UCBrowser|UCWEB)\/(\d+(\.\d+)?)/,Safari:/Version\/(\d+(\.\d+)?)/,"Mobile Safari":/Version\/(\d+(\.\d+)?)/,Opera:/(Opera|OPR)\/(\d+(\.\d+)?)/, Firefox:/Firefox\/(\d+(\.\d+)?)/,"Firefox iOS":/FxiOS\/(\d+(\.\d+)?)/,Konqueror:/Konqueror:(\d+(\.\d+)?)/,BlackBerry:/BlackBerry (\d+(\.\d+)?)/,"Android Mobile":/android\s(\d+(\.\d+)?)/,"Samsung Internet":/SamsungBrowser\/(\d+(\.\d+)?)/,"Internet Explorer":/(rv:|MSIE )(\d+(\.\d+)?)/,Mozilla:/rv:(\d+(\.\d+)?)/}[c.info.na(a,b,d)];if(b===l)return r;a=a.match(b);return!a?r:parseFloat(a[a.length-2])},Pb:function(){return/Windows/i.test(z)?/Phone/.test(z)||/WPDesktop/.test(z)?"Windows Phone":"Windows": /(iPhone|iPad|iPod)/.test(z)?"iOS":/Android/.test(z)?"Android":/(BlackBerry|PlayBook|BB10)/i.test(z)?"BlackBerry":/Mac/i.test(z)?"Mac OS X":/Linux/.test(z)?"Linux":/CrOS/.test(z)?"Chrome OS":""},Cb:function(a){return/Windows Phone/i.test(a)||/WPDesktop/.test(a)?"Windows Phone":/iPad/.test(a)?"iPad":/iPod/.test(a)?"iPod Touch":/iPhone/.test(a)?"iPhone":/(BlackBerry|PlayBook|BB10)/i.test(a)?"BlackBerry":/Android/.test(a)?"Android":""},Ub:function(a){a=a.split("/");return 3<=a.length?a[2]:""},Ma:function(){return n.location.href}, -ba:function(a){"object"!==typeof a&&(a={});return c.extend(c.ga({$os:c.info.Pb(),$browser:c.info.na(z,I.vendor,Y),$referrer:v.referrer,$referring_domain:c.info.Ub(v.referrer),$device:c.info.Cb(z)}),{$current_url:c.info.Ma(),$browser_version:c.info.Ja(z,I.vendor,Y),$screen_height:Z.height,$screen_width:Z.width,mp_lib:"web",$lib_version:"2.55.1-rc1",$insert_id:ea(),time:c.timestamp()/1E3},c.ga(a))},Vc:function(){return c.extend(c.ga({$os:c.info.Pb(),$browser:c.info.na(z,I.vendor,Y)}),{$browser_version:c.info.Ja(z, +ba:function(a){"object"!==typeof a&&(a={});return c.extend(c.ga({$os:c.info.Pb(),$browser:c.info.na(z,I.vendor,Y),$referrer:v.referrer,$referring_domain:c.info.Ub(v.referrer),$device:c.info.Cb(z)}),{$current_url:c.info.Ma(),$browser_version:c.info.Ja(z,I.vendor,Y),$screen_height:Z.height,$screen_width:Z.width,mp_lib:"web",$lib_version:"2.55.1",$insert_id:ea(),time:c.timestamp()/1E3},c.ga(a))},Vc:function(){return c.extend(c.ga({$os:c.info.Pb(),$browser:c.info.na(z,I.vendor,Y)}),{$browser_version:c.info.Ja(z, I.vendor,Y)})},Sc:function(){return c.ga({current_page_title:v.title,current_domain:n.location.hostname,current_url_path:n.location.pathname,current_url_protocol:n.location.protocol,current_url_search:n.location.search})}};var Ia=/[a-z0-9][a-z0-9-]*\.[a-z]+$/i,Ha=/[a-z0-9][a-z0-9-]+\.[a-z.]{2,6}$/i,$=r,aa=r;if("undefined"!==typeof JSON)$=JSON.stringify,aa=JSON.parse;$=$||c.ia;aa=aa||c.T;c.toArray=c.Q;c.isObject=c.g;c.JSONEncode=c.ia;c.JSONDecode=c.T;c.isBlockedUA=c.Kb;c.isEmptyObject=c.ta;c.info= c.info;c.info.device=c.info.Cb;c.info.browser=c.info.na;c.info.browserVersion=c.info.Ja;c.info.properties=c.info.ba;E.prototype.pa=function(){};E.prototype.Pa=function(){};E.prototype.Ha=function(){};E.prototype.Va=function(a){this.Mb=a;return this};E.prototype.o=function(a,b,d,f){var h=this,g=c.Fc(a);if(0===g.length)o.error("The DOM query ("+a+") returned 0 elements");else return c.a(g,function(a){c.Vb(a,this.Qb,function(a){var c={},g=h.pa(d,this),e=h.Mb.c("track_links_timeout");h.Pa(a,this,c);window.setTimeout(h.jc(f, g,c,m),e);h.Mb.o(b,g,h.jc(f,g,c))})},this),m};E.prototype.jc=function(a,b,c,f){var f=f||D,h=this;return function(){if(!c.Cc)c.Cc=m,a&&a(f,b)===D||h.Ha(b,c,f)}};E.prototype.pa=function(a,b){return"function"===typeof a?a(b):c.extend({},a)};c.Jb(M,E);M.prototype.pa=function(a,b){var c=M.pd.pa.apply(this,arguments);if(b.href)c.url=b.href;return c};M.prototype.Pa=function(a,b,c){c.Nb=2===a.which||a.metaKey||a.ctrlKey||"_blank"===b.target;c.href=b.href;c.Nb||a.preventDefault()};M.prototype.Ha=function(a, @@ -51,7 +51,7 @@ a);d&&d(D)},this),this.wa):(this.D.push(f),d&&d(m))};G.prototype.Hc=function(a){ this.ea(),f=0;ft.length)this.N();else{this.Xb=m;var k=c.bind(function(k){this.Xb=D;try{var t=D;if(a.lc)this.ca.yd(i);else if(c.g(k)&&"timeout"===k.error&&(new Date).getTime()-d>=b)this.h("Network timeout; retrying"),this.flush();else if(c.g(k)&&(500<=k.sa||429===k.sa||0>=k.sa&&!Ga()||"timeout"===k.error)){var j=2*this.qa;k.Zb&&(j=1E3*parseInt(k.Zb,10)||j);j=Math.min(6E5,j);this.h("Error; retry in "+ j+" ms");this.$b(j)}else if(c.g(k)&&413===k.sa)if(1 { var Config = { DEBUG: false, - LIB_VERSION: '2.55.1-rc1' + LIB_VERSION: '2.55.1' }; /* eslint camelcase: "off", eqeqeq: "off" */ diff --git a/dist/mixpanel.umd.js b/dist/mixpanel.umd.js index 3dd00cc5..370bd479 100644 --- a/dist/mixpanel.umd.js +++ b/dist/mixpanel.umd.js @@ -4513,7 +4513,7 @@ var Config = { DEBUG: false, - LIB_VERSION: '2.55.1-rc1' + LIB_VERSION: '2.55.1' }; /* eslint camelcase: "off", eqeqeq: "off" */ diff --git a/examples/commonjs-browserify/bundle.js b/examples/commonjs-browserify/bundle.js index 527dd581..01a47fbe 100644 --- a/examples/commonjs-browserify/bundle.js +++ b/examples/commonjs-browserify/bundle.js @@ -4510,7 +4510,7 @@ var IncrementalSource = /* @__PURE__ */ ((IncrementalSource2) => { var Config = { DEBUG: false, - LIB_VERSION: '2.55.1-rc1' + LIB_VERSION: '2.55.1' }; /* eslint camelcase: "off", eqeqeq: "off" */ diff --git a/examples/es2015-babelify/bundle.js b/examples/es2015-babelify/bundle.js index 5da3d177..4341757d 100644 --- a/examples/es2015-babelify/bundle.js +++ b/examples/es2015-babelify/bundle.js @@ -10982,7 +10982,7 @@ Object.defineProperty(exports, '__esModule', { }); var Config = { DEBUG: false, - LIB_VERSION: '2.55.1-rc1' + LIB_VERSION: '2.55.1' }; exports['default'] = Config; diff --git a/examples/umd-webpack/bundle.js b/examples/umd-webpack/bundle.js index 7c2b1ae2..1dfc0d97 100644 --- a/examples/umd-webpack/bundle.js +++ b/examples/umd-webpack/bundle.js @@ -4576,7 +4576,7 @@ var Config = { DEBUG: false, - LIB_VERSION: '2.55.1-rc1' + LIB_VERSION: '2.55.1' }; /* eslint camelcase: "off", eqeqeq: "off" */ diff --git a/src/config.js b/src/config.js index 24810d2c..a98d7980 100644 --- a/src/config.js +++ b/src/config.js @@ -1,6 +1,6 @@ var Config = { DEBUG: false, - LIB_VERSION: '2.55.1-rc1' + LIB_VERSION: '2.55.1' }; export default Config;