mixpanel-browser 2.63.0 → 2.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/dist/mixpanel-core.cjs.js +276 -54
- package/dist/mixpanel-recorder.js +6 -2
- package/dist/mixpanel-recorder.min.js +1 -1
- package/dist/mixpanel-recorder.min.js.map +1 -1
- package/dist/mixpanel-with-async-recorder.cjs.js +276 -54
- package/dist/mixpanel-with-recorder.js +297 -75
- package/dist/mixpanel-with-recorder.min.js +1 -1
- package/dist/mixpanel.amd.js +297 -75
- package/dist/mixpanel.cjs.js +297 -75
- package/dist/mixpanel.globals.js +276 -54
- package/dist/mixpanel.min.js +151 -144
- package/dist/mixpanel.module.js +297 -75
- package/dist/mixpanel.umd.js +297 -75
- package/package.json +1 -1
- package/src/autocapture/index.js +4 -3
- package/src/autocapture/utils.js +7 -1
- package/src/config.js +1 -1
- package/src/flags/index.js +200 -0
- package/src/mixpanel-core.js +29 -3
- package/src/mixpanel-people.js +2 -12
- package/src/utils.js +5 -1
package/dist/mixpanel.umd.js
CHANGED
|
@@ -13948,7 +13948,7 @@
|
|
|
13948
13948
|
|
|
13949
13949
|
var Config = {
|
|
13950
13950
|
DEBUG: false,
|
|
13951
|
-
LIB_VERSION: '2.
|
|
13951
|
+
LIB_VERSION: '2.65.0'
|
|
13952
13952
|
};
|
|
13953
13953
|
|
|
13954
13954
|
/* eslint camelcase: "off", eqeqeq: "off" */
|
|
@@ -15433,6 +15433,9 @@
|
|
|
15433
15433
|
return 'Microsoft Edge';
|
|
15434
15434
|
} else if (_.includes(user_agent, 'FBIOS')) {
|
|
15435
15435
|
return 'Facebook Mobile';
|
|
15436
|
+
} else if (_.includes(user_agent, 'Whale/')) {
|
|
15437
|
+
// https://user-agents.net/browsers/whale-browser
|
|
15438
|
+
return 'Whale Browser';
|
|
15436
15439
|
} else if (_.includes(user_agent, 'Chrome')) {
|
|
15437
15440
|
return 'Chrome';
|
|
15438
15441
|
} else if (_.includes(user_agent, 'CriOS')) {
|
|
@@ -15484,7 +15487,8 @@
|
|
|
15484
15487
|
'Android Mobile': /android\s(\d+(\.\d+)?)/,
|
|
15485
15488
|
'Samsung Internet': /SamsungBrowser\/(\d+(\.\d+)?)/,
|
|
15486
15489
|
'Internet Explorer': /(rv:|MSIE )(\d+(\.\d+)?)/,
|
|
15487
|
-
'Mozilla': /rv:(\d+(\.\d+)?)
|
|
15490
|
+
'Mozilla': /rv:(\d+(\.\d+)?)/,
|
|
15491
|
+
'Whale Browser': /Whale\/(\d+(\.\d+)?)/
|
|
15488
15492
|
};
|
|
15489
15493
|
var regex = versionRegexs[browser];
|
|
15490
15494
|
if (regex === undefined) {
|
|
@@ -16107,7 +16111,7 @@
|
|
|
16107
16111
|
};
|
|
16108
16112
|
}
|
|
16109
16113
|
|
|
16110
|
-
var logger$
|
|
16114
|
+
var logger$6 = console_with_prefix('lock');
|
|
16111
16115
|
|
|
16112
16116
|
/**
|
|
16113
16117
|
* SharedLock: a mutex built on HTML5 localStorage, to ensure that only one browser
|
|
@@ -16159,7 +16163,7 @@
|
|
|
16159
16163
|
|
|
16160
16164
|
var delay = function(cb) {
|
|
16161
16165
|
if (new Date().getTime() - startTime > timeoutMS) {
|
|
16162
|
-
logger$
|
|
16166
|
+
logger$6.error('Timeout waiting for mutex on ' + key + '; clearing lock. [' + i + ']');
|
|
16163
16167
|
storage.removeItem(keyZ);
|
|
16164
16168
|
storage.removeItem(keyY);
|
|
16165
16169
|
loop();
|
|
@@ -16302,7 +16306,7 @@
|
|
|
16302
16306
|
}, this));
|
|
16303
16307
|
};
|
|
16304
16308
|
|
|
16305
|
-
var logger$
|
|
16309
|
+
var logger$5 = console_with_prefix('batch');
|
|
16306
16310
|
|
|
16307
16311
|
/**
|
|
16308
16312
|
* RequestQueue: queue for batching API requests with localStorage backup for retries.
|
|
@@ -16331,7 +16335,7 @@
|
|
|
16331
16335
|
timeoutMS: options.sharedLockTimeoutMS,
|
|
16332
16336
|
});
|
|
16333
16337
|
}
|
|
16334
|
-
this.reportError = options.errorReporter || _.bind(logger$
|
|
16338
|
+
this.reportError = options.errorReporter || _.bind(logger$5.error, logger$5);
|
|
16335
16339
|
|
|
16336
16340
|
this.pid = options.pid || null; // pass pid to test out storage lock contention scenarios
|
|
16337
16341
|
|
|
@@ -16664,7 +16668,7 @@
|
|
|
16664
16668
|
// maximum interval between request retries after exponential backoff
|
|
16665
16669
|
var MAX_RETRY_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
|
|
16666
16670
|
|
|
16667
|
-
var logger$
|
|
16671
|
+
var logger$4 = console_with_prefix('batch');
|
|
16668
16672
|
|
|
16669
16673
|
/**
|
|
16670
16674
|
* RequestBatcher: manages the queueing, flushing, retry etc of requests of one
|
|
@@ -16792,7 +16796,7 @@
|
|
|
16792
16796
|
*/
|
|
16793
16797
|
RequestBatcher.prototype.flush = function(options) {
|
|
16794
16798
|
if (this.requestInProgress) {
|
|
16795
|
-
logger$
|
|
16799
|
+
logger$4.log('Flush: Request already in progress');
|
|
16796
16800
|
return PromisePolyfill.resolve();
|
|
16797
16801
|
}
|
|
16798
16802
|
|
|
@@ -16969,7 +16973,7 @@
|
|
|
16969
16973
|
if (options.unloading) {
|
|
16970
16974
|
requestOptions.transport = 'sendBeacon';
|
|
16971
16975
|
}
|
|
16972
|
-
logger$
|
|
16976
|
+
logger$4.log('MIXPANEL REQUEST:', dataForRequest);
|
|
16973
16977
|
return this.sendRequestPromise(dataForRequest, requestOptions).then(batchSendCallback);
|
|
16974
16978
|
}, this))
|
|
16975
16979
|
.catch(_.bind(function(err) {
|
|
@@ -16982,7 +16986,7 @@
|
|
|
16982
16986
|
* Log error to global logger and optional user-defined logger.
|
|
16983
16987
|
*/
|
|
16984
16988
|
RequestBatcher.prototype.reportError = function(msg, err) {
|
|
16985
|
-
logger$
|
|
16989
|
+
logger$4.error.apply(logger$4.error, arguments);
|
|
16986
16990
|
if (this.errorReporter) {
|
|
16987
16991
|
try {
|
|
16988
16992
|
if (!(err instanceof Error)) {
|
|
@@ -16990,7 +16994,7 @@
|
|
|
16990
16994
|
}
|
|
16991
16995
|
this.errorReporter(msg, err);
|
|
16992
16996
|
} catch(err) {
|
|
16993
|
-
logger$
|
|
16997
|
+
logger$4.error(err);
|
|
16994
16998
|
}
|
|
16995
16999
|
}
|
|
16996
17000
|
};
|
|
@@ -17006,7 +17010,7 @@
|
|
|
17006
17010
|
|
|
17007
17011
|
var RECORD_ENQUEUE_THROTTLE_MS = 250;
|
|
17008
17012
|
|
|
17009
|
-
var logger$
|
|
17013
|
+
var logger$3 = console_with_prefix('recorder');
|
|
17010
17014
|
var CompressionStream = win['CompressionStream'];
|
|
17011
17015
|
|
|
17012
17016
|
var RECORDER_BATCHER_LIB_CONFIG = {
|
|
@@ -17143,14 +17147,14 @@
|
|
|
17143
17147
|
}
|
|
17144
17148
|
|
|
17145
17149
|
if (this._stopRecording !== null) {
|
|
17146
|
-
logger$
|
|
17150
|
+
logger$3.log('Recording already in progress, skipping startRecording.');
|
|
17147
17151
|
return;
|
|
17148
17152
|
}
|
|
17149
17153
|
|
|
17150
17154
|
this.recordMaxMs = this.getConfig('record_max_ms');
|
|
17151
17155
|
if (this.recordMaxMs > MAX_RECORDING_MS) {
|
|
17152
17156
|
this.recordMaxMs = MAX_RECORDING_MS;
|
|
17153
|
-
logger$
|
|
17157
|
+
logger$3.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.');
|
|
17154
17158
|
}
|
|
17155
17159
|
|
|
17156
17160
|
if (!this.maxExpires) {
|
|
@@ -17160,7 +17164,7 @@
|
|
|
17160
17164
|
this.recordMinMs = this.getConfig('record_min_ms');
|
|
17161
17165
|
if (this.recordMinMs > MAX_VALUE_FOR_MIN_RECORDING_MS) {
|
|
17162
17166
|
this.recordMinMs = MAX_VALUE_FOR_MIN_RECORDING_MS;
|
|
17163
|
-
logger$
|
|
17167
|
+
logger$3.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.');
|
|
17164
17168
|
}
|
|
17165
17169
|
|
|
17166
17170
|
if (!this.replayStartTime) {
|
|
@@ -17444,14 +17448,14 @@
|
|
|
17444
17448
|
|
|
17445
17449
|
|
|
17446
17450
|
SessionRecording.prototype.reportError = function(msg, err) {
|
|
17447
|
-
logger$
|
|
17451
|
+
logger$3.error.apply(logger$3.error, arguments);
|
|
17448
17452
|
try {
|
|
17449
17453
|
if (!err && !(msg instanceof Error)) {
|
|
17450
17454
|
msg = new Error(msg);
|
|
17451
17455
|
}
|
|
17452
17456
|
this.getConfig('error_reporter')(msg, err);
|
|
17453
17457
|
} catch(err) {
|
|
17454
|
-
logger$
|
|
17458
|
+
logger$3.error(err);
|
|
17455
17459
|
}
|
|
17456
17460
|
};
|
|
17457
17461
|
|
|
@@ -17547,7 +17551,7 @@
|
|
|
17547
17551
|
.catch(this.handleError.bind(this));
|
|
17548
17552
|
};
|
|
17549
17553
|
|
|
17550
|
-
var logger$
|
|
17554
|
+
var logger$2 = console_with_prefix('recorder');
|
|
17551
17555
|
|
|
17552
17556
|
/**
|
|
17553
17557
|
* Recorder API: bundles rrweb and and exposes methods to start and stop recordings.
|
|
@@ -17563,7 +17567,7 @@
|
|
|
17563
17567
|
*/
|
|
17564
17568
|
this.recordingRegistry = new RecordingRegistry({
|
|
17565
17569
|
mixpanelInstance: this.mixpanelInstance,
|
|
17566
|
-
errorReporter: logger$
|
|
17570
|
+
errorReporter: logger$2.error,
|
|
17567
17571
|
sharedLockStorage: sharedLockStorage
|
|
17568
17572
|
});
|
|
17569
17573
|
this._flushInactivePromise = this.recordingRegistry.flushInactiveRecordings();
|
|
@@ -17574,17 +17578,17 @@
|
|
|
17574
17578
|
MixpanelRecorder.prototype.startRecording = function(options) {
|
|
17575
17579
|
options = options || {};
|
|
17576
17580
|
if (this.activeRecording && !this.activeRecording.isRrwebStopped()) {
|
|
17577
|
-
logger$
|
|
17581
|
+
logger$2.log('Recording already in progress, skipping startRecording.');
|
|
17578
17582
|
return;
|
|
17579
17583
|
}
|
|
17580
17584
|
|
|
17581
17585
|
var onIdleTimeout = function () {
|
|
17582
|
-
logger$
|
|
17586
|
+
logger$2.log('Idle timeout reached, restarting recording.');
|
|
17583
17587
|
this.resetRecording();
|
|
17584
17588
|
}.bind(this);
|
|
17585
17589
|
|
|
17586
17590
|
var onMaxLengthReached = function () {
|
|
17587
|
-
logger$
|
|
17591
|
+
logger$2.log('Max recording length reached, stopping recording.');
|
|
17588
17592
|
this.resetRecording();
|
|
17589
17593
|
}.bind(this);
|
|
17590
17594
|
|
|
@@ -17647,7 +17651,7 @@
|
|
|
17647
17651
|
} else if (startNewIfInactive) {
|
|
17648
17652
|
return this.startRecording({shouldStopBatcher: false});
|
|
17649
17653
|
} else {
|
|
17650
|
-
logger$
|
|
17654
|
+
logger$2.log('No resumable recording found.');
|
|
17651
17655
|
return null;
|
|
17652
17656
|
}
|
|
17653
17657
|
}.bind(this));
|
|
@@ -17705,7 +17709,7 @@
|
|
|
17705
17709
|
'href', 'name', 'role', 'title', 'type'
|
|
17706
17710
|
];
|
|
17707
17711
|
|
|
17708
|
-
var logger = console_with_prefix('autocapture');
|
|
17712
|
+
var logger$1 = console_with_prefix('autocapture');
|
|
17709
17713
|
|
|
17710
17714
|
|
|
17711
17715
|
function getClasses(el) {
|
|
@@ -17791,6 +17795,7 @@
|
|
|
17791
17795
|
var blockSelectors = config.blockSelectors || [];
|
|
17792
17796
|
var captureTextContent = config.captureTextContent || false;
|
|
17793
17797
|
var captureExtraAttrs = config.captureExtraAttrs || [];
|
|
17798
|
+
var capturedForHeatMap = config.capturedForHeatMap || false;
|
|
17794
17799
|
|
|
17795
17800
|
// convert array to set every time, as the config may have changed
|
|
17796
17801
|
var blockAttrsSet = {};
|
|
@@ -17845,7 +17850,9 @@
|
|
|
17845
17850
|
'$elements': elementsJson,
|
|
17846
17851
|
'$el_attr__href': href,
|
|
17847
17852
|
'$viewportHeight': Math.max(docElement['clientHeight'], win['innerHeight'] || 0),
|
|
17848
|
-
'$viewportWidth': Math.max(docElement['clientWidth'], win['innerWidth'] || 0)
|
|
17853
|
+
'$viewportWidth': Math.max(docElement['clientWidth'], win['innerWidth'] || 0),
|
|
17854
|
+
'$pageHeight': document$1['body']['offsetHeight'] || 0,
|
|
17855
|
+
'$pageWidth': document$1['body']['offsetWidth'] || 0,
|
|
17849
17856
|
};
|
|
17850
17857
|
_.each(captureExtraAttrs, function(attr) {
|
|
17851
17858
|
if (!blockAttrsSet[attr] && target.hasAttribute(attr)) {
|
|
@@ -17869,6 +17876,9 @@
|
|
|
17869
17876
|
props['$' + prop] = ev[prop];
|
|
17870
17877
|
}
|
|
17871
17878
|
});
|
|
17879
|
+
if (capturedForHeatMap) {
|
|
17880
|
+
props['$captured_for_heatmap'] = true;
|
|
17881
|
+
}
|
|
17872
17882
|
target = guessRealClickTarget(ev);
|
|
17873
17883
|
}
|
|
17874
17884
|
// prioritize text content from "real" click target if different from original target
|
|
@@ -17963,7 +17973,7 @@
|
|
|
17963
17973
|
return false;
|
|
17964
17974
|
}
|
|
17965
17975
|
} catch (err) {
|
|
17966
|
-
logger.critical('Error while checking element in allowElementCallback', err);
|
|
17976
|
+
logger$1.critical('Error while checking element in allowElementCallback', err);
|
|
17967
17977
|
return false;
|
|
17968
17978
|
}
|
|
17969
17979
|
}
|
|
@@ -17980,7 +17990,7 @@
|
|
|
17980
17990
|
return true;
|
|
17981
17991
|
}
|
|
17982
17992
|
} catch (err) {
|
|
17983
|
-
logger.critical('Error while checking selector: ' + sel, err);
|
|
17993
|
+
logger$1.critical('Error while checking selector: ' + sel, err);
|
|
17984
17994
|
}
|
|
17985
17995
|
}
|
|
17986
17996
|
return false;
|
|
@@ -17995,7 +18005,7 @@
|
|
|
17995
18005
|
return true;
|
|
17996
18006
|
}
|
|
17997
18007
|
} catch (err) {
|
|
17998
|
-
logger.critical('Error while checking element in blockElementCallback', err);
|
|
18008
|
+
logger$1.critical('Error while checking element in blockElementCallback', err);
|
|
17999
18009
|
return true;
|
|
18000
18010
|
}
|
|
18001
18011
|
}
|
|
@@ -18009,7 +18019,7 @@
|
|
|
18009
18019
|
return true;
|
|
18010
18020
|
}
|
|
18011
18021
|
} catch (err) {
|
|
18012
|
-
logger.critical('Error while checking selector: ' + sel, err);
|
|
18022
|
+
logger$1.critical('Error while checking selector: ' + sel, err);
|
|
18013
18023
|
}
|
|
18014
18024
|
}
|
|
18015
18025
|
}
|
|
@@ -18215,22 +18225,22 @@
|
|
|
18215
18225
|
var CONFIG_TRACK_SCROLL = 'scroll';
|
|
18216
18226
|
var CONFIG_TRACK_SUBMIT = 'submit';
|
|
18217
18227
|
|
|
18218
|
-
var CONFIG_DEFAULTS = {};
|
|
18219
|
-
CONFIG_DEFAULTS[CONFIG_ALLOW_SELECTORS] = [];
|
|
18220
|
-
CONFIG_DEFAULTS[CONFIG_ALLOW_URL_REGEXES] = [];
|
|
18221
|
-
CONFIG_DEFAULTS[CONFIG_BLOCK_ATTRS] = [];
|
|
18222
|
-
CONFIG_DEFAULTS[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
|
|
18223
|
-
CONFIG_DEFAULTS[CONFIG_BLOCK_SELECTORS] = [];
|
|
18224
|
-
CONFIG_DEFAULTS[CONFIG_BLOCK_URL_REGEXES] = [];
|
|
18225
|
-
CONFIG_DEFAULTS[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
|
|
18226
|
-
CONFIG_DEFAULTS[CONFIG_CAPTURE_TEXT_CONTENT] = false;
|
|
18227
|
-
CONFIG_DEFAULTS[CONFIG_SCROLL_CAPTURE_ALL] = false;
|
|
18228
|
-
CONFIG_DEFAULTS[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
|
|
18229
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_CLICK] = true;
|
|
18230
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_INPUT] = true;
|
|
18231
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
|
|
18232
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_SCROLL] = true;
|
|
18233
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_SUBMIT] = true;
|
|
18228
|
+
var CONFIG_DEFAULTS$1 = {};
|
|
18229
|
+
CONFIG_DEFAULTS$1[CONFIG_ALLOW_SELECTORS] = [];
|
|
18230
|
+
CONFIG_DEFAULTS$1[CONFIG_ALLOW_URL_REGEXES] = [];
|
|
18231
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_ATTRS] = [];
|
|
18232
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
|
|
18233
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_SELECTORS] = [];
|
|
18234
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_URL_REGEXES] = [];
|
|
18235
|
+
CONFIG_DEFAULTS$1[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
|
|
18236
|
+
CONFIG_DEFAULTS$1[CONFIG_CAPTURE_TEXT_CONTENT] = false;
|
|
18237
|
+
CONFIG_DEFAULTS$1[CONFIG_SCROLL_CAPTURE_ALL] = false;
|
|
18238
|
+
CONFIG_DEFAULTS$1[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
|
|
18239
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_CLICK] = true;
|
|
18240
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_INPUT] = true;
|
|
18241
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
|
|
18242
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_SCROLL] = true;
|
|
18243
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_SUBMIT] = true;
|
|
18234
18244
|
|
|
18235
18245
|
var DEFAULT_PROPS = {
|
|
18236
18246
|
'$mp_autocapture': true
|
|
@@ -18251,7 +18261,7 @@
|
|
|
18251
18261
|
|
|
18252
18262
|
Autocapture.prototype.init = function() {
|
|
18253
18263
|
if (!minDOMApisSupported()) {
|
|
18254
|
-
logger.critical('Autocapture unavailable: missing required DOM APIs');
|
|
18264
|
+
logger$1.critical('Autocapture unavailable: missing required DOM APIs');
|
|
18255
18265
|
return;
|
|
18256
18266
|
}
|
|
18257
18267
|
|
|
@@ -18268,10 +18278,10 @@
|
|
|
18268
18278
|
// Autocapture is completely off
|
|
18269
18279
|
return {};
|
|
18270
18280
|
} else if (_.isObject(autocaptureConfig)) {
|
|
18271
|
-
return _.extend({}, CONFIG_DEFAULTS, autocaptureConfig);
|
|
18281
|
+
return _.extend({}, CONFIG_DEFAULTS$1, autocaptureConfig);
|
|
18272
18282
|
} else {
|
|
18273
18283
|
// Autocapture config is non-object truthy value, return default
|
|
18274
|
-
return CONFIG_DEFAULTS;
|
|
18284
|
+
return CONFIG_DEFAULTS$1;
|
|
18275
18285
|
}
|
|
18276
18286
|
};
|
|
18277
18287
|
|
|
@@ -18295,7 +18305,7 @@
|
|
|
18295
18305
|
break;
|
|
18296
18306
|
}
|
|
18297
18307
|
} catch (err) {
|
|
18298
|
-
logger.critical('Error while checking block URL regex: ' + allowRegex, err);
|
|
18308
|
+
logger$1.critical('Error while checking block URL regex: ' + allowRegex, err);
|
|
18299
18309
|
return true;
|
|
18300
18310
|
}
|
|
18301
18311
|
}
|
|
@@ -18316,7 +18326,7 @@
|
|
|
18316
18326
|
return true;
|
|
18317
18327
|
}
|
|
18318
18328
|
} catch (err) {
|
|
18319
|
-
logger.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
|
|
18329
|
+
logger$1.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
|
|
18320
18330
|
return true;
|
|
18321
18331
|
}
|
|
18322
18332
|
}
|
|
@@ -18345,7 +18355,8 @@
|
|
|
18345
18355
|
blockElementCallback: this.getConfig(CONFIG_BLOCK_ELEMENT_CALLBACK),
|
|
18346
18356
|
blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
|
|
18347
18357
|
captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
|
|
18348
|
-
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT)
|
|
18358
|
+
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT),
|
|
18359
|
+
capturedForHeatMap: mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK) && this.mp.is_recording_heatmap_data(),
|
|
18349
18360
|
});
|
|
18350
18361
|
if (props) {
|
|
18351
18362
|
_.extend(props, DEFAULT_PROPS);
|
|
@@ -18356,13 +18367,13 @@
|
|
|
18356
18367
|
Autocapture.prototype.initClickTracking = function() {
|
|
18357
18368
|
win.removeEventListener(EV_CLICK, this.listenerClick);
|
|
18358
18369
|
|
|
18359
|
-
if (!this.getConfig(CONFIG_TRACK_CLICK)) {
|
|
18370
|
+
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
|
|
18360
18371
|
return;
|
|
18361
18372
|
}
|
|
18362
|
-
logger.log('Initializing click tracking');
|
|
18373
|
+
logger$1.log('Initializing click tracking');
|
|
18363
18374
|
|
|
18364
18375
|
this.listenerClick = win.addEventListener(EV_CLICK, function(ev) {
|
|
18365
|
-
if (!this.getConfig(CONFIG_TRACK_CLICK)) {
|
|
18376
|
+
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
|
|
18366
18377
|
return;
|
|
18367
18378
|
}
|
|
18368
18379
|
this.trackDomEvent(ev, MP_EV_CLICK);
|
|
@@ -18375,7 +18386,7 @@
|
|
|
18375
18386
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
18376
18387
|
return;
|
|
18377
18388
|
}
|
|
18378
|
-
logger.log('Initializing input tracking');
|
|
18389
|
+
logger$1.log('Initializing input tracking');
|
|
18379
18390
|
|
|
18380
18391
|
this.listenerChange = win.addEventListener(EV_CHANGE, function(ev) {
|
|
18381
18392
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
@@ -18393,7 +18404,7 @@
|
|
|
18393
18404
|
if (!this.pageviewTrackingConfig()) {
|
|
18394
18405
|
return;
|
|
18395
18406
|
}
|
|
18396
|
-
logger.log('Initializing pageview tracking');
|
|
18407
|
+
logger$1.log('Initializing pageview tracking');
|
|
18397
18408
|
|
|
18398
18409
|
var previousTrackedUrl = '';
|
|
18399
18410
|
var tracked = false;
|
|
@@ -18448,7 +18459,7 @@
|
|
|
18448
18459
|
}
|
|
18449
18460
|
if (didPathChange) {
|
|
18450
18461
|
this.lastScrollCheckpoint = 0;
|
|
18451
|
-
logger.log('Path change: re-initializing scroll depth checkpoints');
|
|
18462
|
+
logger$1.log('Path change: re-initializing scroll depth checkpoints');
|
|
18452
18463
|
}
|
|
18453
18464
|
}
|
|
18454
18465
|
}.bind(this)));
|
|
@@ -18460,7 +18471,7 @@
|
|
|
18460
18471
|
if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
|
|
18461
18472
|
return;
|
|
18462
18473
|
}
|
|
18463
|
-
logger.log('Initializing scroll tracking');
|
|
18474
|
+
logger$1.log('Initializing scroll tracking');
|
|
18464
18475
|
this.lastScrollCheckpoint = 0;
|
|
18465
18476
|
|
|
18466
18477
|
this.listenerScroll = win.addEventListener(EV_SCROLLEND, safewrap(function() {
|
|
@@ -18497,7 +18508,7 @@
|
|
|
18497
18508
|
}
|
|
18498
18509
|
}
|
|
18499
18510
|
} catch (err) {
|
|
18500
|
-
logger.critical('Error while calculating scroll percentage', err);
|
|
18511
|
+
logger$1.critical('Error while calculating scroll percentage', err);
|
|
18501
18512
|
}
|
|
18502
18513
|
if (shouldTrack) {
|
|
18503
18514
|
this.mp.track(MP_EV_SCROLL, props);
|
|
@@ -18511,7 +18522,7 @@
|
|
|
18511
18522
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
18512
18523
|
return;
|
|
18513
18524
|
}
|
|
18514
|
-
logger.log('Initializing submit tracking');
|
|
18525
|
+
logger$1.log('Initializing submit tracking');
|
|
18515
18526
|
|
|
18516
18527
|
this.listenerSubmit = win.addEventListener(EV_SUBMIT, function(ev) {
|
|
18517
18528
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
@@ -18524,6 +18535,202 @@
|
|
|
18524
18535
|
// TODO integrate error_reporter from mixpanel instance
|
|
18525
18536
|
safewrapClass(Autocapture);
|
|
18526
18537
|
|
|
18538
|
+
var fetch = win['fetch'];
|
|
18539
|
+
var logger = console_with_prefix('flags');
|
|
18540
|
+
|
|
18541
|
+
var FLAGS_CONFIG_KEY = 'flags';
|
|
18542
|
+
|
|
18543
|
+
var CONFIG_CONTEXT = 'context';
|
|
18544
|
+
var CONFIG_DEFAULTS = {};
|
|
18545
|
+
CONFIG_DEFAULTS[CONFIG_CONTEXT] = {};
|
|
18546
|
+
|
|
18547
|
+
/**
|
|
18548
|
+
* FeatureFlagManager: support for Mixpanel's feature flagging product
|
|
18549
|
+
* @constructor
|
|
18550
|
+
*/
|
|
18551
|
+
var FeatureFlagManager = function(initOptions) {
|
|
18552
|
+
this.getMpConfig = initOptions.getConfigFunc;
|
|
18553
|
+
this.getDistinctId = initOptions.getDistinctIdFunc;
|
|
18554
|
+
this.track = initOptions.trackingFunc;
|
|
18555
|
+
};
|
|
18556
|
+
|
|
18557
|
+
FeatureFlagManager.prototype.init = function() {
|
|
18558
|
+
if (!minApisSupported()) {
|
|
18559
|
+
logger.critical('Feature Flags unavailable: missing minimum required APIs');
|
|
18560
|
+
return;
|
|
18561
|
+
}
|
|
18562
|
+
|
|
18563
|
+
this.flags = null;
|
|
18564
|
+
this.fetchFlags();
|
|
18565
|
+
|
|
18566
|
+
this.trackedFeatures = new Set();
|
|
18567
|
+
};
|
|
18568
|
+
|
|
18569
|
+
FeatureFlagManager.prototype.getFullConfig = function() {
|
|
18570
|
+
var ffConfig = this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
18571
|
+
if (!ffConfig) {
|
|
18572
|
+
// flags are completely off
|
|
18573
|
+
return {};
|
|
18574
|
+
} else if (_.isObject(ffConfig)) {
|
|
18575
|
+
return _.extend({}, CONFIG_DEFAULTS, ffConfig);
|
|
18576
|
+
} else {
|
|
18577
|
+
// config is non-object truthy value, return default
|
|
18578
|
+
return CONFIG_DEFAULTS;
|
|
18579
|
+
}
|
|
18580
|
+
};
|
|
18581
|
+
|
|
18582
|
+
FeatureFlagManager.prototype.getConfig = function(key) {
|
|
18583
|
+
return this.getFullConfig()[key];
|
|
18584
|
+
};
|
|
18585
|
+
|
|
18586
|
+
FeatureFlagManager.prototype.isSystemEnabled = function() {
|
|
18587
|
+
return !!this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
18588
|
+
};
|
|
18589
|
+
|
|
18590
|
+
FeatureFlagManager.prototype.areFlagsReady = function() {
|
|
18591
|
+
if (!this.isSystemEnabled()) {
|
|
18592
|
+
logger.error('Feature Flags not enabled');
|
|
18593
|
+
}
|
|
18594
|
+
return !!this.flags;
|
|
18595
|
+
};
|
|
18596
|
+
|
|
18597
|
+
FeatureFlagManager.prototype.fetchFlags = function() {
|
|
18598
|
+
if (!this.isSystemEnabled()) {
|
|
18599
|
+
return;
|
|
18600
|
+
}
|
|
18601
|
+
|
|
18602
|
+
var distinctId = this.getDistinctId();
|
|
18603
|
+
logger.log('Fetching flags for distinct ID: ' + distinctId);
|
|
18604
|
+
var reqParams = {
|
|
18605
|
+
'context': _.extend({'distinct_id': distinctId}, this.getConfig(CONFIG_CONTEXT))
|
|
18606
|
+
};
|
|
18607
|
+
this.fetchPromise = win['fetch'](this.getMpConfig('api_host') + '/' + this.getMpConfig('api_routes')['flags'], {
|
|
18608
|
+
'method': 'POST',
|
|
18609
|
+
'headers': {
|
|
18610
|
+
'Authorization': 'Basic ' + btoa(this.getMpConfig('token') + ':'),
|
|
18611
|
+
'Content-Type': 'application/octet-stream'
|
|
18612
|
+
},
|
|
18613
|
+
'body': JSON.stringify(reqParams)
|
|
18614
|
+
}).then(function(response) {
|
|
18615
|
+
return response.json().then(function(responseBody) {
|
|
18616
|
+
var responseFlags = responseBody['flags'];
|
|
18617
|
+
if (!responseFlags) {
|
|
18618
|
+
throw new Error('No flags in API response');
|
|
18619
|
+
}
|
|
18620
|
+
var flags = new Map();
|
|
18621
|
+
_.each(responseFlags, function(data, key) {
|
|
18622
|
+
flags.set(key, {
|
|
18623
|
+
'key': data['variant_key'],
|
|
18624
|
+
'value': data['variant_value']
|
|
18625
|
+
});
|
|
18626
|
+
});
|
|
18627
|
+
this.flags = flags;
|
|
18628
|
+
}.bind(this)).catch(function(error) {
|
|
18629
|
+
logger.error(error);
|
|
18630
|
+
});
|
|
18631
|
+
}.bind(this)).catch(function() {});
|
|
18632
|
+
};
|
|
18633
|
+
|
|
18634
|
+
FeatureFlagManager.prototype.getVariant = function(featureName, fallback) {
|
|
18635
|
+
if (!this.fetchPromise) {
|
|
18636
|
+
return new Promise(function(resolve) {
|
|
18637
|
+
logger.critical('Feature Flags not initialized');
|
|
18638
|
+
resolve(fallback);
|
|
18639
|
+
});
|
|
18640
|
+
}
|
|
18641
|
+
|
|
18642
|
+
return this.fetchPromise.then(function() {
|
|
18643
|
+
return this.getVariantSync(featureName, fallback);
|
|
18644
|
+
}.bind(this)).catch(function(error) {
|
|
18645
|
+
logger.error(error);
|
|
18646
|
+
return fallback;
|
|
18647
|
+
});
|
|
18648
|
+
};
|
|
18649
|
+
|
|
18650
|
+
FeatureFlagManager.prototype.getVariantSync = function(featureName, fallback) {
|
|
18651
|
+
if (!this.areFlagsReady()) {
|
|
18652
|
+
logger.log('Flags not loaded yet');
|
|
18653
|
+
return fallback;
|
|
18654
|
+
}
|
|
18655
|
+
var feature = this.flags.get(featureName);
|
|
18656
|
+
if (!feature) {
|
|
18657
|
+
logger.log('No flag found: "' + featureName + '"');
|
|
18658
|
+
return fallback;
|
|
18659
|
+
}
|
|
18660
|
+
this.trackFeatureCheck(featureName, feature);
|
|
18661
|
+
return feature;
|
|
18662
|
+
};
|
|
18663
|
+
|
|
18664
|
+
FeatureFlagManager.prototype.getVariantValue = function(featureName, fallbackValue) {
|
|
18665
|
+
return this.getVariant(featureName, {'value': fallbackValue}).then(function(feature) {
|
|
18666
|
+
return feature['value'];
|
|
18667
|
+
}).catch(function(error) {
|
|
18668
|
+
logger.error(error);
|
|
18669
|
+
return fallbackValue;
|
|
18670
|
+
});
|
|
18671
|
+
};
|
|
18672
|
+
|
|
18673
|
+
// TODO remove deprecated method
|
|
18674
|
+
FeatureFlagManager.prototype.getFeatureData = function(featureName, fallbackValue) {
|
|
18675
|
+
logger.critical('mixpanel.flags.get_feature_data() is deprecated and will be removed in a future release. Use mixpanel.flags.get_variant_value() instead.');
|
|
18676
|
+
return this.getVariantValue(featureName, fallbackValue);
|
|
18677
|
+
};
|
|
18678
|
+
|
|
18679
|
+
FeatureFlagManager.prototype.getVariantValueSync = function(featureName, fallbackValue) {
|
|
18680
|
+
return this.getVariantSync(featureName, {'value': fallbackValue})['value'];
|
|
18681
|
+
};
|
|
18682
|
+
|
|
18683
|
+
FeatureFlagManager.prototype.isEnabled = function(featureName, fallbackValue) {
|
|
18684
|
+
return this.getVariantValue(featureName).then(function() {
|
|
18685
|
+
return this.isEnabledSync(featureName, fallbackValue);
|
|
18686
|
+
}.bind(this)).catch(function(error) {
|
|
18687
|
+
logger.error(error);
|
|
18688
|
+
return fallbackValue;
|
|
18689
|
+
});
|
|
18690
|
+
};
|
|
18691
|
+
|
|
18692
|
+
FeatureFlagManager.prototype.isEnabledSync = function(featureName, fallbackValue) {
|
|
18693
|
+
fallbackValue = fallbackValue || false;
|
|
18694
|
+
var val = this.getVariantValueSync(featureName, fallbackValue);
|
|
18695
|
+
if (val !== true && val !== false) {
|
|
18696
|
+
logger.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
|
|
18697
|
+
val = fallbackValue;
|
|
18698
|
+
}
|
|
18699
|
+
return val;
|
|
18700
|
+
};
|
|
18701
|
+
|
|
18702
|
+
FeatureFlagManager.prototype.trackFeatureCheck = function(featureName, feature) {
|
|
18703
|
+
if (this.trackedFeatures.has(featureName)) {
|
|
18704
|
+
return;
|
|
18705
|
+
}
|
|
18706
|
+
this.trackedFeatures.add(featureName);
|
|
18707
|
+
this.track('$experiment_started', {
|
|
18708
|
+
'Experiment name': featureName,
|
|
18709
|
+
'Variant name': feature['key'],
|
|
18710
|
+
'$experiment_type': 'feature_flag'
|
|
18711
|
+
});
|
|
18712
|
+
};
|
|
18713
|
+
|
|
18714
|
+
function minApisSupported() {
|
|
18715
|
+
return !!fetch &&
|
|
18716
|
+
typeof Promise !== 'undefined' &&
|
|
18717
|
+
typeof Map !== 'undefined' &&
|
|
18718
|
+
typeof Set !== 'undefined';
|
|
18719
|
+
}
|
|
18720
|
+
|
|
18721
|
+
safewrapClass(FeatureFlagManager);
|
|
18722
|
+
|
|
18723
|
+
FeatureFlagManager.prototype['are_flags_ready'] = FeatureFlagManager.prototype.areFlagsReady;
|
|
18724
|
+
FeatureFlagManager.prototype['get_variant'] = FeatureFlagManager.prototype.getVariant;
|
|
18725
|
+
FeatureFlagManager.prototype['get_variant_sync'] = FeatureFlagManager.prototype.getVariantSync;
|
|
18726
|
+
FeatureFlagManager.prototype['get_variant_value'] = FeatureFlagManager.prototype.getVariantValue;
|
|
18727
|
+
FeatureFlagManager.prototype['get_variant_value_sync'] = FeatureFlagManager.prototype.getVariantValueSync;
|
|
18728
|
+
FeatureFlagManager.prototype['is_enabled'] = FeatureFlagManager.prototype.isEnabled;
|
|
18729
|
+
FeatureFlagManager.prototype['is_enabled_sync'] = FeatureFlagManager.prototype.isEnabledSync;
|
|
18730
|
+
|
|
18731
|
+
// Deprecated method
|
|
18732
|
+
FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
|
|
18733
|
+
|
|
18527
18734
|
/* eslint camelcase: "off" */
|
|
18528
18735
|
|
|
18529
18736
|
|
|
@@ -19218,18 +19425,8 @@
|
|
|
19218
19425
|
* @param {Function} [callback] If provided, the callback will be called when the server responds
|
|
19219
19426
|
* @deprecated
|
|
19220
19427
|
*/
|
|
19221
|
-
MixpanelPeople.prototype.track_charge = addOptOutCheckMixpanelPeople(function(
|
|
19222
|
-
|
|
19223
|
-
amount = parseFloat(amount);
|
|
19224
|
-
if (isNaN(amount)) {
|
|
19225
|
-
console$1.error('Invalid value passed to mixpanel.people.track_charge - must be a number');
|
|
19226
|
-
return;
|
|
19227
|
-
}
|
|
19228
|
-
}
|
|
19229
|
-
|
|
19230
|
-
return this.append('$transactions', _.extend({
|
|
19231
|
-
'$amount': amount
|
|
19232
|
-
}, properties), callback);
|
|
19428
|
+
MixpanelPeople.prototype.track_charge = addOptOutCheckMixpanelPeople(function() {
|
|
19429
|
+
console$1.error('mixpanel.people.track_charge() is deprecated and no longer has any effect.');
|
|
19233
19430
|
});
|
|
19234
19431
|
|
|
19235
19432
|
/*
|
|
@@ -19928,10 +20125,11 @@
|
|
|
19928
20125
|
}
|
|
19929
20126
|
|
|
19930
20127
|
var DEFAULT_API_ROUTES = {
|
|
19931
|
-
'track':
|
|
20128
|
+
'track': 'track/',
|
|
19932
20129
|
'engage': 'engage/',
|
|
19933
20130
|
'groups': 'groups/',
|
|
19934
|
-
'record': 'record/'
|
|
20131
|
+
'record': 'record/',
|
|
20132
|
+
'flags': 'flags/'
|
|
19935
20133
|
};
|
|
19936
20134
|
|
|
19937
20135
|
/*
|
|
@@ -19940,6 +20138,7 @@
|
|
|
19940
20138
|
var DEFAULT_CONFIG = {
|
|
19941
20139
|
'api_host': 'https://api-js.mixpanel.com',
|
|
19942
20140
|
'api_routes': DEFAULT_API_ROUTES,
|
|
20141
|
+
'api_extra_query_params': {},
|
|
19943
20142
|
'api_method': 'POST',
|
|
19944
20143
|
'api_transport': 'XHR',
|
|
19945
20144
|
'api_payload_format': PAYLOAD_TYPE_BASE64,
|
|
@@ -19949,6 +20148,7 @@
|
|
|
19949
20148
|
'cross_site_cookie': false,
|
|
19950
20149
|
'cross_subdomain_cookie': true,
|
|
19951
20150
|
'error_reporter': NOOP_FUNC,
|
|
20151
|
+
'flags': false,
|
|
19952
20152
|
'persistence': 'cookie',
|
|
19953
20153
|
'persistence_name': '',
|
|
19954
20154
|
'cookie_domain': '',
|
|
@@ -19989,6 +20189,7 @@
|
|
|
19989
20189
|
'record_block_selector': 'img, video',
|
|
19990
20190
|
'record_canvas': false,
|
|
19991
20191
|
'record_collect_fonts': false,
|
|
20192
|
+
'record_heatmap_data': false,
|
|
19992
20193
|
'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
|
|
19993
20194
|
'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'),
|
|
19994
20195
|
'record_mask_text_selector': '*',
|
|
@@ -20204,6 +20405,14 @@
|
|
|
20204
20405
|
}, '');
|
|
20205
20406
|
}
|
|
20206
20407
|
|
|
20408
|
+
this.flags = new FeatureFlagManager({
|
|
20409
|
+
getConfigFunc: _.bind(this.get_config, this),
|
|
20410
|
+
getDistinctIdFunc: _.bind(this.get_distinct_id, this),
|
|
20411
|
+
trackingFunc: _.bind(this.track, this)
|
|
20412
|
+
});
|
|
20413
|
+
this.flags.init();
|
|
20414
|
+
this['flags'] = this.flags;
|
|
20415
|
+
|
|
20207
20416
|
this.autocapture = new Autocapture(this);
|
|
20208
20417
|
this.autocapture.init();
|
|
20209
20418
|
|
|
@@ -20329,6 +20538,10 @@
|
|
|
20329
20538
|
}
|
|
20330
20539
|
};
|
|
20331
20540
|
|
|
20541
|
+
MixpanelLib.prototype.is_recording_heatmap_data = function () {
|
|
20542
|
+
return this._get_session_replay_id() && this.get_config('record_heatmap_data');
|
|
20543
|
+
};
|
|
20544
|
+
|
|
20332
20545
|
MixpanelLib.prototype.get_session_recording_properties = function () {
|
|
20333
20546
|
var props = {};
|
|
20334
20547
|
var replay_id = this._get_session_replay_id();
|
|
@@ -20513,6 +20726,8 @@
|
|
|
20513
20726
|
delete data['data'];
|
|
20514
20727
|
}
|
|
20515
20728
|
|
|
20729
|
+
_.extend(data, this.get_config('api_extra_query_params'));
|
|
20730
|
+
|
|
20516
20731
|
url += '?' + _.HTTPBuildQuery(data);
|
|
20517
20732
|
|
|
20518
20733
|
var lib = this;
|
|
@@ -21410,6 +21625,11 @@
|
|
|
21410
21625
|
'$anon_distinct_id': previous_distinct_id
|
|
21411
21626
|
}, {skip_hooks: true});
|
|
21412
21627
|
}
|
|
21628
|
+
|
|
21629
|
+
// check feature flags again if distinct id has changed
|
|
21630
|
+
if (new_distinct_id !== previous_distinct_id) {
|
|
21631
|
+
this.flags.fetchFlags();
|
|
21632
|
+
}
|
|
21413
21633
|
};
|
|
21414
21634
|
|
|
21415
21635
|
/**
|
|
@@ -21424,6 +21644,8 @@
|
|
|
21424
21644
|
'distinct_id': DEVICE_ID_PREFIX + uuid,
|
|
21425
21645
|
'$device_id': uuid
|
|
21426
21646
|
}, '');
|
|
21647
|
+
this.stop_session_recording();
|
|
21648
|
+
this._check_and_start_session_recording();
|
|
21427
21649
|
};
|
|
21428
21650
|
|
|
21429
21651
|
/**
|
|
@@ -21684,7 +21906,7 @@
|
|
|
21684
21906
|
}
|
|
21685
21907
|
Config.DEBUG = Config.DEBUG || this.get_config('debug');
|
|
21686
21908
|
|
|
21687
|
-
if ('autocapture' in config && this.autocapture) {
|
|
21909
|
+
if (('autocapture' in config || 'record_heatmap_data' in config) && this.autocapture) {
|
|
21688
21910
|
this.autocapture.init();
|
|
21689
21911
|
}
|
|
21690
21912
|
}
|