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
|
@@ -13945,7 +13945,7 @@
|
|
|
13945
13945
|
|
|
13946
13946
|
var Config = {
|
|
13947
13947
|
DEBUG: false,
|
|
13948
|
-
LIB_VERSION: '2.
|
|
13948
|
+
LIB_VERSION: '2.65.0'
|
|
13949
13949
|
};
|
|
13950
13950
|
|
|
13951
13951
|
/* eslint camelcase: "off", eqeqeq: "off" */
|
|
@@ -15430,6 +15430,9 @@
|
|
|
15430
15430
|
return 'Microsoft Edge';
|
|
15431
15431
|
} else if (_.includes(user_agent, 'FBIOS')) {
|
|
15432
15432
|
return 'Facebook Mobile';
|
|
15433
|
+
} else if (_.includes(user_agent, 'Whale/')) {
|
|
15434
|
+
// https://user-agents.net/browsers/whale-browser
|
|
15435
|
+
return 'Whale Browser';
|
|
15433
15436
|
} else if (_.includes(user_agent, 'Chrome')) {
|
|
15434
15437
|
return 'Chrome';
|
|
15435
15438
|
} else if (_.includes(user_agent, 'CriOS')) {
|
|
@@ -15481,7 +15484,8 @@
|
|
|
15481
15484
|
'Android Mobile': /android\s(\d+(\.\d+)?)/,
|
|
15482
15485
|
'Samsung Internet': /SamsungBrowser\/(\d+(\.\d+)?)/,
|
|
15483
15486
|
'Internet Explorer': /(rv:|MSIE )(\d+(\.\d+)?)/,
|
|
15484
|
-
'Mozilla': /rv:(\d+(\.\d+)?)
|
|
15487
|
+
'Mozilla': /rv:(\d+(\.\d+)?)/,
|
|
15488
|
+
'Whale Browser': /Whale\/(\d+(\.\d+)?)/
|
|
15485
15489
|
};
|
|
15486
15490
|
var regex = versionRegexs[browser];
|
|
15487
15491
|
if (regex === undefined) {
|
|
@@ -16104,7 +16108,7 @@
|
|
|
16104
16108
|
};
|
|
16105
16109
|
}
|
|
16106
16110
|
|
|
16107
|
-
var logger$
|
|
16111
|
+
var logger$6 = console_with_prefix('lock');
|
|
16108
16112
|
|
|
16109
16113
|
/**
|
|
16110
16114
|
* SharedLock: a mutex built on HTML5 localStorage, to ensure that only one browser
|
|
@@ -16156,7 +16160,7 @@
|
|
|
16156
16160
|
|
|
16157
16161
|
var delay = function(cb) {
|
|
16158
16162
|
if (new Date().getTime() - startTime > timeoutMS) {
|
|
16159
|
-
logger$
|
|
16163
|
+
logger$6.error('Timeout waiting for mutex on ' + key + '; clearing lock. [' + i + ']');
|
|
16160
16164
|
storage.removeItem(keyZ);
|
|
16161
16165
|
storage.removeItem(keyY);
|
|
16162
16166
|
loop();
|
|
@@ -16299,7 +16303,7 @@
|
|
|
16299
16303
|
}, this));
|
|
16300
16304
|
};
|
|
16301
16305
|
|
|
16302
|
-
var logger$
|
|
16306
|
+
var logger$5 = console_with_prefix('batch');
|
|
16303
16307
|
|
|
16304
16308
|
/**
|
|
16305
16309
|
* RequestQueue: queue for batching API requests with localStorage backup for retries.
|
|
@@ -16328,7 +16332,7 @@
|
|
|
16328
16332
|
timeoutMS: options.sharedLockTimeoutMS,
|
|
16329
16333
|
});
|
|
16330
16334
|
}
|
|
16331
|
-
this.reportError = options.errorReporter || _.bind(logger$
|
|
16335
|
+
this.reportError = options.errorReporter || _.bind(logger$5.error, logger$5);
|
|
16332
16336
|
|
|
16333
16337
|
this.pid = options.pid || null; // pass pid to test out storage lock contention scenarios
|
|
16334
16338
|
|
|
@@ -16661,7 +16665,7 @@
|
|
|
16661
16665
|
// maximum interval between request retries after exponential backoff
|
|
16662
16666
|
var MAX_RETRY_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
|
|
16663
16667
|
|
|
16664
|
-
var logger$
|
|
16668
|
+
var logger$4 = console_with_prefix('batch');
|
|
16665
16669
|
|
|
16666
16670
|
/**
|
|
16667
16671
|
* RequestBatcher: manages the queueing, flushing, retry etc of requests of one
|
|
@@ -16789,7 +16793,7 @@
|
|
|
16789
16793
|
*/
|
|
16790
16794
|
RequestBatcher.prototype.flush = function(options) {
|
|
16791
16795
|
if (this.requestInProgress) {
|
|
16792
|
-
logger$
|
|
16796
|
+
logger$4.log('Flush: Request already in progress');
|
|
16793
16797
|
return PromisePolyfill.resolve();
|
|
16794
16798
|
}
|
|
16795
16799
|
|
|
@@ -16966,7 +16970,7 @@
|
|
|
16966
16970
|
if (options.unloading) {
|
|
16967
16971
|
requestOptions.transport = 'sendBeacon';
|
|
16968
16972
|
}
|
|
16969
|
-
logger$
|
|
16973
|
+
logger$4.log('MIXPANEL REQUEST:', dataForRequest);
|
|
16970
16974
|
return this.sendRequestPromise(dataForRequest, requestOptions).then(batchSendCallback);
|
|
16971
16975
|
}, this))
|
|
16972
16976
|
.catch(_.bind(function(err) {
|
|
@@ -16979,7 +16983,7 @@
|
|
|
16979
16983
|
* Log error to global logger and optional user-defined logger.
|
|
16980
16984
|
*/
|
|
16981
16985
|
RequestBatcher.prototype.reportError = function(msg, err) {
|
|
16982
|
-
logger$
|
|
16986
|
+
logger$4.error.apply(logger$4.error, arguments);
|
|
16983
16987
|
if (this.errorReporter) {
|
|
16984
16988
|
try {
|
|
16985
16989
|
if (!(err instanceof Error)) {
|
|
@@ -16987,7 +16991,7 @@
|
|
|
16987
16991
|
}
|
|
16988
16992
|
this.errorReporter(msg, err);
|
|
16989
16993
|
} catch(err) {
|
|
16990
|
-
logger$
|
|
16994
|
+
logger$4.error(err);
|
|
16991
16995
|
}
|
|
16992
16996
|
}
|
|
16993
16997
|
};
|
|
@@ -17003,7 +17007,7 @@
|
|
|
17003
17007
|
|
|
17004
17008
|
var RECORD_ENQUEUE_THROTTLE_MS = 250;
|
|
17005
17009
|
|
|
17006
|
-
var logger$
|
|
17010
|
+
var logger$3 = console_with_prefix('recorder');
|
|
17007
17011
|
var CompressionStream = win['CompressionStream'];
|
|
17008
17012
|
|
|
17009
17013
|
var RECORDER_BATCHER_LIB_CONFIG = {
|
|
@@ -17140,14 +17144,14 @@
|
|
|
17140
17144
|
}
|
|
17141
17145
|
|
|
17142
17146
|
if (this._stopRecording !== null) {
|
|
17143
|
-
logger$
|
|
17147
|
+
logger$3.log('Recording already in progress, skipping startRecording.');
|
|
17144
17148
|
return;
|
|
17145
17149
|
}
|
|
17146
17150
|
|
|
17147
17151
|
this.recordMaxMs = this.getConfig('record_max_ms');
|
|
17148
17152
|
if (this.recordMaxMs > MAX_RECORDING_MS) {
|
|
17149
17153
|
this.recordMaxMs = MAX_RECORDING_MS;
|
|
17150
|
-
logger$
|
|
17154
|
+
logger$3.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.');
|
|
17151
17155
|
}
|
|
17152
17156
|
|
|
17153
17157
|
if (!this.maxExpires) {
|
|
@@ -17157,7 +17161,7 @@
|
|
|
17157
17161
|
this.recordMinMs = this.getConfig('record_min_ms');
|
|
17158
17162
|
if (this.recordMinMs > MAX_VALUE_FOR_MIN_RECORDING_MS) {
|
|
17159
17163
|
this.recordMinMs = MAX_VALUE_FOR_MIN_RECORDING_MS;
|
|
17160
|
-
logger$
|
|
17164
|
+
logger$3.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.');
|
|
17161
17165
|
}
|
|
17162
17166
|
|
|
17163
17167
|
if (!this.replayStartTime) {
|
|
@@ -17441,14 +17445,14 @@
|
|
|
17441
17445
|
|
|
17442
17446
|
|
|
17443
17447
|
SessionRecording.prototype.reportError = function(msg, err) {
|
|
17444
|
-
logger$
|
|
17448
|
+
logger$3.error.apply(logger$3.error, arguments);
|
|
17445
17449
|
try {
|
|
17446
17450
|
if (!err && !(msg instanceof Error)) {
|
|
17447
17451
|
msg = new Error(msg);
|
|
17448
17452
|
}
|
|
17449
17453
|
this.getConfig('error_reporter')(msg, err);
|
|
17450
17454
|
} catch(err) {
|
|
17451
|
-
logger$
|
|
17455
|
+
logger$3.error(err);
|
|
17452
17456
|
}
|
|
17453
17457
|
};
|
|
17454
17458
|
|
|
@@ -17544,7 +17548,7 @@
|
|
|
17544
17548
|
.catch(this.handleError.bind(this));
|
|
17545
17549
|
};
|
|
17546
17550
|
|
|
17547
|
-
var logger$
|
|
17551
|
+
var logger$2 = console_with_prefix('recorder');
|
|
17548
17552
|
|
|
17549
17553
|
/**
|
|
17550
17554
|
* Recorder API: bundles rrweb and and exposes methods to start and stop recordings.
|
|
@@ -17560,7 +17564,7 @@
|
|
|
17560
17564
|
*/
|
|
17561
17565
|
this.recordingRegistry = new RecordingRegistry({
|
|
17562
17566
|
mixpanelInstance: this.mixpanelInstance,
|
|
17563
|
-
errorReporter: logger$
|
|
17567
|
+
errorReporter: logger$2.error,
|
|
17564
17568
|
sharedLockStorage: sharedLockStorage
|
|
17565
17569
|
});
|
|
17566
17570
|
this._flushInactivePromise = this.recordingRegistry.flushInactiveRecordings();
|
|
@@ -17571,17 +17575,17 @@
|
|
|
17571
17575
|
MixpanelRecorder.prototype.startRecording = function(options) {
|
|
17572
17576
|
options = options || {};
|
|
17573
17577
|
if (this.activeRecording && !this.activeRecording.isRrwebStopped()) {
|
|
17574
|
-
logger$
|
|
17578
|
+
logger$2.log('Recording already in progress, skipping startRecording.');
|
|
17575
17579
|
return;
|
|
17576
17580
|
}
|
|
17577
17581
|
|
|
17578
17582
|
var onIdleTimeout = function () {
|
|
17579
|
-
logger$
|
|
17583
|
+
logger$2.log('Idle timeout reached, restarting recording.');
|
|
17580
17584
|
this.resetRecording();
|
|
17581
17585
|
}.bind(this);
|
|
17582
17586
|
|
|
17583
17587
|
var onMaxLengthReached = function () {
|
|
17584
|
-
logger$
|
|
17588
|
+
logger$2.log('Max recording length reached, stopping recording.');
|
|
17585
17589
|
this.resetRecording();
|
|
17586
17590
|
}.bind(this);
|
|
17587
17591
|
|
|
@@ -17644,7 +17648,7 @@
|
|
|
17644
17648
|
} else if (startNewIfInactive) {
|
|
17645
17649
|
return this.startRecording({shouldStopBatcher: false});
|
|
17646
17650
|
} else {
|
|
17647
|
-
logger$
|
|
17651
|
+
logger$2.log('No resumable recording found.');
|
|
17648
17652
|
return null;
|
|
17649
17653
|
}
|
|
17650
17654
|
}.bind(this));
|
|
@@ -17702,7 +17706,7 @@
|
|
|
17702
17706
|
'href', 'name', 'role', 'title', 'type'
|
|
17703
17707
|
];
|
|
17704
17708
|
|
|
17705
|
-
var logger = console_with_prefix('autocapture');
|
|
17709
|
+
var logger$1 = console_with_prefix('autocapture');
|
|
17706
17710
|
|
|
17707
17711
|
|
|
17708
17712
|
function getClasses(el) {
|
|
@@ -17788,6 +17792,7 @@
|
|
|
17788
17792
|
var blockSelectors = config.blockSelectors || [];
|
|
17789
17793
|
var captureTextContent = config.captureTextContent || false;
|
|
17790
17794
|
var captureExtraAttrs = config.captureExtraAttrs || [];
|
|
17795
|
+
var capturedForHeatMap = config.capturedForHeatMap || false;
|
|
17791
17796
|
|
|
17792
17797
|
// convert array to set every time, as the config may have changed
|
|
17793
17798
|
var blockAttrsSet = {};
|
|
@@ -17842,7 +17847,9 @@
|
|
|
17842
17847
|
'$elements': elementsJson,
|
|
17843
17848
|
'$el_attr__href': href,
|
|
17844
17849
|
'$viewportHeight': Math.max(docElement['clientHeight'], win['innerHeight'] || 0),
|
|
17845
|
-
'$viewportWidth': Math.max(docElement['clientWidth'], win['innerWidth'] || 0)
|
|
17850
|
+
'$viewportWidth': Math.max(docElement['clientWidth'], win['innerWidth'] || 0),
|
|
17851
|
+
'$pageHeight': document$1['body']['offsetHeight'] || 0,
|
|
17852
|
+
'$pageWidth': document$1['body']['offsetWidth'] || 0,
|
|
17846
17853
|
};
|
|
17847
17854
|
_.each(captureExtraAttrs, function(attr) {
|
|
17848
17855
|
if (!blockAttrsSet[attr] && target.hasAttribute(attr)) {
|
|
@@ -17866,6 +17873,9 @@
|
|
|
17866
17873
|
props['$' + prop] = ev[prop];
|
|
17867
17874
|
}
|
|
17868
17875
|
});
|
|
17876
|
+
if (capturedForHeatMap) {
|
|
17877
|
+
props['$captured_for_heatmap'] = true;
|
|
17878
|
+
}
|
|
17869
17879
|
target = guessRealClickTarget(ev);
|
|
17870
17880
|
}
|
|
17871
17881
|
// prioritize text content from "real" click target if different from original target
|
|
@@ -17960,7 +17970,7 @@
|
|
|
17960
17970
|
return false;
|
|
17961
17971
|
}
|
|
17962
17972
|
} catch (err) {
|
|
17963
|
-
logger.critical('Error while checking element in allowElementCallback', err);
|
|
17973
|
+
logger$1.critical('Error while checking element in allowElementCallback', err);
|
|
17964
17974
|
return false;
|
|
17965
17975
|
}
|
|
17966
17976
|
}
|
|
@@ -17977,7 +17987,7 @@
|
|
|
17977
17987
|
return true;
|
|
17978
17988
|
}
|
|
17979
17989
|
} catch (err) {
|
|
17980
|
-
logger.critical('Error while checking selector: ' + sel, err);
|
|
17990
|
+
logger$1.critical('Error while checking selector: ' + sel, err);
|
|
17981
17991
|
}
|
|
17982
17992
|
}
|
|
17983
17993
|
return false;
|
|
@@ -17992,7 +18002,7 @@
|
|
|
17992
18002
|
return true;
|
|
17993
18003
|
}
|
|
17994
18004
|
} catch (err) {
|
|
17995
|
-
logger.critical('Error while checking element in blockElementCallback', err);
|
|
18005
|
+
logger$1.critical('Error while checking element in blockElementCallback', err);
|
|
17996
18006
|
return true;
|
|
17997
18007
|
}
|
|
17998
18008
|
}
|
|
@@ -18006,7 +18016,7 @@
|
|
|
18006
18016
|
return true;
|
|
18007
18017
|
}
|
|
18008
18018
|
} catch (err) {
|
|
18009
|
-
logger.critical('Error while checking selector: ' + sel, err);
|
|
18019
|
+
logger$1.critical('Error while checking selector: ' + sel, err);
|
|
18010
18020
|
}
|
|
18011
18021
|
}
|
|
18012
18022
|
}
|
|
@@ -18212,22 +18222,22 @@
|
|
|
18212
18222
|
var CONFIG_TRACK_SCROLL = 'scroll';
|
|
18213
18223
|
var CONFIG_TRACK_SUBMIT = 'submit';
|
|
18214
18224
|
|
|
18215
|
-
var CONFIG_DEFAULTS = {};
|
|
18216
|
-
CONFIG_DEFAULTS[CONFIG_ALLOW_SELECTORS] = [];
|
|
18217
|
-
CONFIG_DEFAULTS[CONFIG_ALLOW_URL_REGEXES] = [];
|
|
18218
|
-
CONFIG_DEFAULTS[CONFIG_BLOCK_ATTRS] = [];
|
|
18219
|
-
CONFIG_DEFAULTS[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
|
|
18220
|
-
CONFIG_DEFAULTS[CONFIG_BLOCK_SELECTORS] = [];
|
|
18221
|
-
CONFIG_DEFAULTS[CONFIG_BLOCK_URL_REGEXES] = [];
|
|
18222
|
-
CONFIG_DEFAULTS[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
|
|
18223
|
-
CONFIG_DEFAULTS[CONFIG_CAPTURE_TEXT_CONTENT] = false;
|
|
18224
|
-
CONFIG_DEFAULTS[CONFIG_SCROLL_CAPTURE_ALL] = false;
|
|
18225
|
-
CONFIG_DEFAULTS[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
|
|
18226
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_CLICK] = true;
|
|
18227
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_INPUT] = true;
|
|
18228
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
|
|
18229
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_SCROLL] = true;
|
|
18230
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_SUBMIT] = true;
|
|
18225
|
+
var CONFIG_DEFAULTS$1 = {};
|
|
18226
|
+
CONFIG_DEFAULTS$1[CONFIG_ALLOW_SELECTORS] = [];
|
|
18227
|
+
CONFIG_DEFAULTS$1[CONFIG_ALLOW_URL_REGEXES] = [];
|
|
18228
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_ATTRS] = [];
|
|
18229
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
|
|
18230
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_SELECTORS] = [];
|
|
18231
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_URL_REGEXES] = [];
|
|
18232
|
+
CONFIG_DEFAULTS$1[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
|
|
18233
|
+
CONFIG_DEFAULTS$1[CONFIG_CAPTURE_TEXT_CONTENT] = false;
|
|
18234
|
+
CONFIG_DEFAULTS$1[CONFIG_SCROLL_CAPTURE_ALL] = false;
|
|
18235
|
+
CONFIG_DEFAULTS$1[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
|
|
18236
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_CLICK] = true;
|
|
18237
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_INPUT] = true;
|
|
18238
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
|
|
18239
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_SCROLL] = true;
|
|
18240
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_SUBMIT] = true;
|
|
18231
18241
|
|
|
18232
18242
|
var DEFAULT_PROPS = {
|
|
18233
18243
|
'$mp_autocapture': true
|
|
@@ -18248,7 +18258,7 @@
|
|
|
18248
18258
|
|
|
18249
18259
|
Autocapture.prototype.init = function() {
|
|
18250
18260
|
if (!minDOMApisSupported()) {
|
|
18251
|
-
logger.critical('Autocapture unavailable: missing required DOM APIs');
|
|
18261
|
+
logger$1.critical('Autocapture unavailable: missing required DOM APIs');
|
|
18252
18262
|
return;
|
|
18253
18263
|
}
|
|
18254
18264
|
|
|
@@ -18265,10 +18275,10 @@
|
|
|
18265
18275
|
// Autocapture is completely off
|
|
18266
18276
|
return {};
|
|
18267
18277
|
} else if (_.isObject(autocaptureConfig)) {
|
|
18268
|
-
return _.extend({}, CONFIG_DEFAULTS, autocaptureConfig);
|
|
18278
|
+
return _.extend({}, CONFIG_DEFAULTS$1, autocaptureConfig);
|
|
18269
18279
|
} else {
|
|
18270
18280
|
// Autocapture config is non-object truthy value, return default
|
|
18271
|
-
return CONFIG_DEFAULTS;
|
|
18281
|
+
return CONFIG_DEFAULTS$1;
|
|
18272
18282
|
}
|
|
18273
18283
|
};
|
|
18274
18284
|
|
|
@@ -18292,7 +18302,7 @@
|
|
|
18292
18302
|
break;
|
|
18293
18303
|
}
|
|
18294
18304
|
} catch (err) {
|
|
18295
|
-
logger.critical('Error while checking block URL regex: ' + allowRegex, err);
|
|
18305
|
+
logger$1.critical('Error while checking block URL regex: ' + allowRegex, err);
|
|
18296
18306
|
return true;
|
|
18297
18307
|
}
|
|
18298
18308
|
}
|
|
@@ -18313,7 +18323,7 @@
|
|
|
18313
18323
|
return true;
|
|
18314
18324
|
}
|
|
18315
18325
|
} catch (err) {
|
|
18316
|
-
logger.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
|
|
18326
|
+
logger$1.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
|
|
18317
18327
|
return true;
|
|
18318
18328
|
}
|
|
18319
18329
|
}
|
|
@@ -18342,7 +18352,8 @@
|
|
|
18342
18352
|
blockElementCallback: this.getConfig(CONFIG_BLOCK_ELEMENT_CALLBACK),
|
|
18343
18353
|
blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
|
|
18344
18354
|
captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
|
|
18345
|
-
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT)
|
|
18355
|
+
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT),
|
|
18356
|
+
capturedForHeatMap: mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK) && this.mp.is_recording_heatmap_data(),
|
|
18346
18357
|
});
|
|
18347
18358
|
if (props) {
|
|
18348
18359
|
_.extend(props, DEFAULT_PROPS);
|
|
@@ -18353,13 +18364,13 @@
|
|
|
18353
18364
|
Autocapture.prototype.initClickTracking = function() {
|
|
18354
18365
|
win.removeEventListener(EV_CLICK, this.listenerClick);
|
|
18355
18366
|
|
|
18356
|
-
if (!this.getConfig(CONFIG_TRACK_CLICK)) {
|
|
18367
|
+
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
|
|
18357
18368
|
return;
|
|
18358
18369
|
}
|
|
18359
|
-
logger.log('Initializing click tracking');
|
|
18370
|
+
logger$1.log('Initializing click tracking');
|
|
18360
18371
|
|
|
18361
18372
|
this.listenerClick = win.addEventListener(EV_CLICK, function(ev) {
|
|
18362
|
-
if (!this.getConfig(CONFIG_TRACK_CLICK)) {
|
|
18373
|
+
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
|
|
18363
18374
|
return;
|
|
18364
18375
|
}
|
|
18365
18376
|
this.trackDomEvent(ev, MP_EV_CLICK);
|
|
@@ -18372,7 +18383,7 @@
|
|
|
18372
18383
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
18373
18384
|
return;
|
|
18374
18385
|
}
|
|
18375
|
-
logger.log('Initializing input tracking');
|
|
18386
|
+
logger$1.log('Initializing input tracking');
|
|
18376
18387
|
|
|
18377
18388
|
this.listenerChange = win.addEventListener(EV_CHANGE, function(ev) {
|
|
18378
18389
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
@@ -18390,7 +18401,7 @@
|
|
|
18390
18401
|
if (!this.pageviewTrackingConfig()) {
|
|
18391
18402
|
return;
|
|
18392
18403
|
}
|
|
18393
|
-
logger.log('Initializing pageview tracking');
|
|
18404
|
+
logger$1.log('Initializing pageview tracking');
|
|
18394
18405
|
|
|
18395
18406
|
var previousTrackedUrl = '';
|
|
18396
18407
|
var tracked = false;
|
|
@@ -18445,7 +18456,7 @@
|
|
|
18445
18456
|
}
|
|
18446
18457
|
if (didPathChange) {
|
|
18447
18458
|
this.lastScrollCheckpoint = 0;
|
|
18448
|
-
logger.log('Path change: re-initializing scroll depth checkpoints');
|
|
18459
|
+
logger$1.log('Path change: re-initializing scroll depth checkpoints');
|
|
18449
18460
|
}
|
|
18450
18461
|
}
|
|
18451
18462
|
}.bind(this)));
|
|
@@ -18457,7 +18468,7 @@
|
|
|
18457
18468
|
if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
|
|
18458
18469
|
return;
|
|
18459
18470
|
}
|
|
18460
|
-
logger.log('Initializing scroll tracking');
|
|
18471
|
+
logger$1.log('Initializing scroll tracking');
|
|
18461
18472
|
this.lastScrollCheckpoint = 0;
|
|
18462
18473
|
|
|
18463
18474
|
this.listenerScroll = win.addEventListener(EV_SCROLLEND, safewrap(function() {
|
|
@@ -18494,7 +18505,7 @@
|
|
|
18494
18505
|
}
|
|
18495
18506
|
}
|
|
18496
18507
|
} catch (err) {
|
|
18497
|
-
logger.critical('Error while calculating scroll percentage', err);
|
|
18508
|
+
logger$1.critical('Error while calculating scroll percentage', err);
|
|
18498
18509
|
}
|
|
18499
18510
|
if (shouldTrack) {
|
|
18500
18511
|
this.mp.track(MP_EV_SCROLL, props);
|
|
@@ -18508,7 +18519,7 @@
|
|
|
18508
18519
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
18509
18520
|
return;
|
|
18510
18521
|
}
|
|
18511
|
-
logger.log('Initializing submit tracking');
|
|
18522
|
+
logger$1.log('Initializing submit tracking');
|
|
18512
18523
|
|
|
18513
18524
|
this.listenerSubmit = win.addEventListener(EV_SUBMIT, function(ev) {
|
|
18514
18525
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
@@ -18521,6 +18532,202 @@
|
|
|
18521
18532
|
// TODO integrate error_reporter from mixpanel instance
|
|
18522
18533
|
safewrapClass(Autocapture);
|
|
18523
18534
|
|
|
18535
|
+
var fetch = win['fetch'];
|
|
18536
|
+
var logger = console_with_prefix('flags');
|
|
18537
|
+
|
|
18538
|
+
var FLAGS_CONFIG_KEY = 'flags';
|
|
18539
|
+
|
|
18540
|
+
var CONFIG_CONTEXT = 'context';
|
|
18541
|
+
var CONFIG_DEFAULTS = {};
|
|
18542
|
+
CONFIG_DEFAULTS[CONFIG_CONTEXT] = {};
|
|
18543
|
+
|
|
18544
|
+
/**
|
|
18545
|
+
* FeatureFlagManager: support for Mixpanel's feature flagging product
|
|
18546
|
+
* @constructor
|
|
18547
|
+
*/
|
|
18548
|
+
var FeatureFlagManager = function(initOptions) {
|
|
18549
|
+
this.getMpConfig = initOptions.getConfigFunc;
|
|
18550
|
+
this.getDistinctId = initOptions.getDistinctIdFunc;
|
|
18551
|
+
this.track = initOptions.trackingFunc;
|
|
18552
|
+
};
|
|
18553
|
+
|
|
18554
|
+
FeatureFlagManager.prototype.init = function() {
|
|
18555
|
+
if (!minApisSupported()) {
|
|
18556
|
+
logger.critical('Feature Flags unavailable: missing minimum required APIs');
|
|
18557
|
+
return;
|
|
18558
|
+
}
|
|
18559
|
+
|
|
18560
|
+
this.flags = null;
|
|
18561
|
+
this.fetchFlags();
|
|
18562
|
+
|
|
18563
|
+
this.trackedFeatures = new Set();
|
|
18564
|
+
};
|
|
18565
|
+
|
|
18566
|
+
FeatureFlagManager.prototype.getFullConfig = function() {
|
|
18567
|
+
var ffConfig = this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
18568
|
+
if (!ffConfig) {
|
|
18569
|
+
// flags are completely off
|
|
18570
|
+
return {};
|
|
18571
|
+
} else if (_.isObject(ffConfig)) {
|
|
18572
|
+
return _.extend({}, CONFIG_DEFAULTS, ffConfig);
|
|
18573
|
+
} else {
|
|
18574
|
+
// config is non-object truthy value, return default
|
|
18575
|
+
return CONFIG_DEFAULTS;
|
|
18576
|
+
}
|
|
18577
|
+
};
|
|
18578
|
+
|
|
18579
|
+
FeatureFlagManager.prototype.getConfig = function(key) {
|
|
18580
|
+
return this.getFullConfig()[key];
|
|
18581
|
+
};
|
|
18582
|
+
|
|
18583
|
+
FeatureFlagManager.prototype.isSystemEnabled = function() {
|
|
18584
|
+
return !!this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
18585
|
+
};
|
|
18586
|
+
|
|
18587
|
+
FeatureFlagManager.prototype.areFlagsReady = function() {
|
|
18588
|
+
if (!this.isSystemEnabled()) {
|
|
18589
|
+
logger.error('Feature Flags not enabled');
|
|
18590
|
+
}
|
|
18591
|
+
return !!this.flags;
|
|
18592
|
+
};
|
|
18593
|
+
|
|
18594
|
+
FeatureFlagManager.prototype.fetchFlags = function() {
|
|
18595
|
+
if (!this.isSystemEnabled()) {
|
|
18596
|
+
return;
|
|
18597
|
+
}
|
|
18598
|
+
|
|
18599
|
+
var distinctId = this.getDistinctId();
|
|
18600
|
+
logger.log('Fetching flags for distinct ID: ' + distinctId);
|
|
18601
|
+
var reqParams = {
|
|
18602
|
+
'context': _.extend({'distinct_id': distinctId}, this.getConfig(CONFIG_CONTEXT))
|
|
18603
|
+
};
|
|
18604
|
+
this.fetchPromise = win['fetch'](this.getMpConfig('api_host') + '/' + this.getMpConfig('api_routes')['flags'], {
|
|
18605
|
+
'method': 'POST',
|
|
18606
|
+
'headers': {
|
|
18607
|
+
'Authorization': 'Basic ' + btoa(this.getMpConfig('token') + ':'),
|
|
18608
|
+
'Content-Type': 'application/octet-stream'
|
|
18609
|
+
},
|
|
18610
|
+
'body': JSON.stringify(reqParams)
|
|
18611
|
+
}).then(function(response) {
|
|
18612
|
+
return response.json().then(function(responseBody) {
|
|
18613
|
+
var responseFlags = responseBody['flags'];
|
|
18614
|
+
if (!responseFlags) {
|
|
18615
|
+
throw new Error('No flags in API response');
|
|
18616
|
+
}
|
|
18617
|
+
var flags = new Map();
|
|
18618
|
+
_.each(responseFlags, function(data, key) {
|
|
18619
|
+
flags.set(key, {
|
|
18620
|
+
'key': data['variant_key'],
|
|
18621
|
+
'value': data['variant_value']
|
|
18622
|
+
});
|
|
18623
|
+
});
|
|
18624
|
+
this.flags = flags;
|
|
18625
|
+
}.bind(this)).catch(function(error) {
|
|
18626
|
+
logger.error(error);
|
|
18627
|
+
});
|
|
18628
|
+
}.bind(this)).catch(function() {});
|
|
18629
|
+
};
|
|
18630
|
+
|
|
18631
|
+
FeatureFlagManager.prototype.getVariant = function(featureName, fallback) {
|
|
18632
|
+
if (!this.fetchPromise) {
|
|
18633
|
+
return new Promise(function(resolve) {
|
|
18634
|
+
logger.critical('Feature Flags not initialized');
|
|
18635
|
+
resolve(fallback);
|
|
18636
|
+
});
|
|
18637
|
+
}
|
|
18638
|
+
|
|
18639
|
+
return this.fetchPromise.then(function() {
|
|
18640
|
+
return this.getVariantSync(featureName, fallback);
|
|
18641
|
+
}.bind(this)).catch(function(error) {
|
|
18642
|
+
logger.error(error);
|
|
18643
|
+
return fallback;
|
|
18644
|
+
});
|
|
18645
|
+
};
|
|
18646
|
+
|
|
18647
|
+
FeatureFlagManager.prototype.getVariantSync = function(featureName, fallback) {
|
|
18648
|
+
if (!this.areFlagsReady()) {
|
|
18649
|
+
logger.log('Flags not loaded yet');
|
|
18650
|
+
return fallback;
|
|
18651
|
+
}
|
|
18652
|
+
var feature = this.flags.get(featureName);
|
|
18653
|
+
if (!feature) {
|
|
18654
|
+
logger.log('No flag found: "' + featureName + '"');
|
|
18655
|
+
return fallback;
|
|
18656
|
+
}
|
|
18657
|
+
this.trackFeatureCheck(featureName, feature);
|
|
18658
|
+
return feature;
|
|
18659
|
+
};
|
|
18660
|
+
|
|
18661
|
+
FeatureFlagManager.prototype.getVariantValue = function(featureName, fallbackValue) {
|
|
18662
|
+
return this.getVariant(featureName, {'value': fallbackValue}).then(function(feature) {
|
|
18663
|
+
return feature['value'];
|
|
18664
|
+
}).catch(function(error) {
|
|
18665
|
+
logger.error(error);
|
|
18666
|
+
return fallbackValue;
|
|
18667
|
+
});
|
|
18668
|
+
};
|
|
18669
|
+
|
|
18670
|
+
// TODO remove deprecated method
|
|
18671
|
+
FeatureFlagManager.prototype.getFeatureData = function(featureName, fallbackValue) {
|
|
18672
|
+
logger.critical('mixpanel.flags.get_feature_data() is deprecated and will be removed in a future release. Use mixpanel.flags.get_variant_value() instead.');
|
|
18673
|
+
return this.getVariantValue(featureName, fallbackValue);
|
|
18674
|
+
};
|
|
18675
|
+
|
|
18676
|
+
FeatureFlagManager.prototype.getVariantValueSync = function(featureName, fallbackValue) {
|
|
18677
|
+
return this.getVariantSync(featureName, {'value': fallbackValue})['value'];
|
|
18678
|
+
};
|
|
18679
|
+
|
|
18680
|
+
FeatureFlagManager.prototype.isEnabled = function(featureName, fallbackValue) {
|
|
18681
|
+
return this.getVariantValue(featureName).then(function() {
|
|
18682
|
+
return this.isEnabledSync(featureName, fallbackValue);
|
|
18683
|
+
}.bind(this)).catch(function(error) {
|
|
18684
|
+
logger.error(error);
|
|
18685
|
+
return fallbackValue;
|
|
18686
|
+
});
|
|
18687
|
+
};
|
|
18688
|
+
|
|
18689
|
+
FeatureFlagManager.prototype.isEnabledSync = function(featureName, fallbackValue) {
|
|
18690
|
+
fallbackValue = fallbackValue || false;
|
|
18691
|
+
var val = this.getVariantValueSync(featureName, fallbackValue);
|
|
18692
|
+
if (val !== true && val !== false) {
|
|
18693
|
+
logger.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
|
|
18694
|
+
val = fallbackValue;
|
|
18695
|
+
}
|
|
18696
|
+
return val;
|
|
18697
|
+
};
|
|
18698
|
+
|
|
18699
|
+
FeatureFlagManager.prototype.trackFeatureCheck = function(featureName, feature) {
|
|
18700
|
+
if (this.trackedFeatures.has(featureName)) {
|
|
18701
|
+
return;
|
|
18702
|
+
}
|
|
18703
|
+
this.trackedFeatures.add(featureName);
|
|
18704
|
+
this.track('$experiment_started', {
|
|
18705
|
+
'Experiment name': featureName,
|
|
18706
|
+
'Variant name': feature['key'],
|
|
18707
|
+
'$experiment_type': 'feature_flag'
|
|
18708
|
+
});
|
|
18709
|
+
};
|
|
18710
|
+
|
|
18711
|
+
function minApisSupported() {
|
|
18712
|
+
return !!fetch &&
|
|
18713
|
+
typeof Promise !== 'undefined' &&
|
|
18714
|
+
typeof Map !== 'undefined' &&
|
|
18715
|
+
typeof Set !== 'undefined';
|
|
18716
|
+
}
|
|
18717
|
+
|
|
18718
|
+
safewrapClass(FeatureFlagManager);
|
|
18719
|
+
|
|
18720
|
+
FeatureFlagManager.prototype['are_flags_ready'] = FeatureFlagManager.prototype.areFlagsReady;
|
|
18721
|
+
FeatureFlagManager.prototype['get_variant'] = FeatureFlagManager.prototype.getVariant;
|
|
18722
|
+
FeatureFlagManager.prototype['get_variant_sync'] = FeatureFlagManager.prototype.getVariantSync;
|
|
18723
|
+
FeatureFlagManager.prototype['get_variant_value'] = FeatureFlagManager.prototype.getVariantValue;
|
|
18724
|
+
FeatureFlagManager.prototype['get_variant_value_sync'] = FeatureFlagManager.prototype.getVariantValueSync;
|
|
18725
|
+
FeatureFlagManager.prototype['is_enabled'] = FeatureFlagManager.prototype.isEnabled;
|
|
18726
|
+
FeatureFlagManager.prototype['is_enabled_sync'] = FeatureFlagManager.prototype.isEnabledSync;
|
|
18727
|
+
|
|
18728
|
+
// Deprecated method
|
|
18729
|
+
FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
|
|
18730
|
+
|
|
18524
18731
|
/* eslint camelcase: "off" */
|
|
18525
18732
|
|
|
18526
18733
|
|
|
@@ -19215,18 +19422,8 @@
|
|
|
19215
19422
|
* @param {Function} [callback] If provided, the callback will be called when the server responds
|
|
19216
19423
|
* @deprecated
|
|
19217
19424
|
*/
|
|
19218
|
-
MixpanelPeople.prototype.track_charge = addOptOutCheckMixpanelPeople(function(
|
|
19219
|
-
|
|
19220
|
-
amount = parseFloat(amount);
|
|
19221
|
-
if (isNaN(amount)) {
|
|
19222
|
-
console$1.error('Invalid value passed to mixpanel.people.track_charge - must be a number');
|
|
19223
|
-
return;
|
|
19224
|
-
}
|
|
19225
|
-
}
|
|
19226
|
-
|
|
19227
|
-
return this.append('$transactions', _.extend({
|
|
19228
|
-
'$amount': amount
|
|
19229
|
-
}, properties), callback);
|
|
19425
|
+
MixpanelPeople.prototype.track_charge = addOptOutCheckMixpanelPeople(function() {
|
|
19426
|
+
console$1.error('mixpanel.people.track_charge() is deprecated and no longer has any effect.');
|
|
19230
19427
|
});
|
|
19231
19428
|
|
|
19232
19429
|
/*
|
|
@@ -19925,10 +20122,11 @@
|
|
|
19925
20122
|
}
|
|
19926
20123
|
|
|
19927
20124
|
var DEFAULT_API_ROUTES = {
|
|
19928
|
-
'track':
|
|
20125
|
+
'track': 'track/',
|
|
19929
20126
|
'engage': 'engage/',
|
|
19930
20127
|
'groups': 'groups/',
|
|
19931
|
-
'record': 'record/'
|
|
20128
|
+
'record': 'record/',
|
|
20129
|
+
'flags': 'flags/'
|
|
19932
20130
|
};
|
|
19933
20131
|
|
|
19934
20132
|
/*
|
|
@@ -19937,6 +20135,7 @@
|
|
|
19937
20135
|
var DEFAULT_CONFIG = {
|
|
19938
20136
|
'api_host': 'https://api-js.mixpanel.com',
|
|
19939
20137
|
'api_routes': DEFAULT_API_ROUTES,
|
|
20138
|
+
'api_extra_query_params': {},
|
|
19940
20139
|
'api_method': 'POST',
|
|
19941
20140
|
'api_transport': 'XHR',
|
|
19942
20141
|
'api_payload_format': PAYLOAD_TYPE_BASE64,
|
|
@@ -19946,6 +20145,7 @@
|
|
|
19946
20145
|
'cross_site_cookie': false,
|
|
19947
20146
|
'cross_subdomain_cookie': true,
|
|
19948
20147
|
'error_reporter': NOOP_FUNC,
|
|
20148
|
+
'flags': false,
|
|
19949
20149
|
'persistence': 'cookie',
|
|
19950
20150
|
'persistence_name': '',
|
|
19951
20151
|
'cookie_domain': '',
|
|
@@ -19986,6 +20186,7 @@
|
|
|
19986
20186
|
'record_block_selector': 'img, video',
|
|
19987
20187
|
'record_canvas': false,
|
|
19988
20188
|
'record_collect_fonts': false,
|
|
20189
|
+
'record_heatmap_data': false,
|
|
19989
20190
|
'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
|
|
19990
20191
|
'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'),
|
|
19991
20192
|
'record_mask_text_selector': '*',
|
|
@@ -20201,6 +20402,14 @@
|
|
|
20201
20402
|
}, '');
|
|
20202
20403
|
}
|
|
20203
20404
|
|
|
20405
|
+
this.flags = new FeatureFlagManager({
|
|
20406
|
+
getConfigFunc: _.bind(this.get_config, this),
|
|
20407
|
+
getDistinctIdFunc: _.bind(this.get_distinct_id, this),
|
|
20408
|
+
trackingFunc: _.bind(this.track, this)
|
|
20409
|
+
});
|
|
20410
|
+
this.flags.init();
|
|
20411
|
+
this['flags'] = this.flags;
|
|
20412
|
+
|
|
20204
20413
|
this.autocapture = new Autocapture(this);
|
|
20205
20414
|
this.autocapture.init();
|
|
20206
20415
|
|
|
@@ -20326,6 +20535,10 @@
|
|
|
20326
20535
|
}
|
|
20327
20536
|
};
|
|
20328
20537
|
|
|
20538
|
+
MixpanelLib.prototype.is_recording_heatmap_data = function () {
|
|
20539
|
+
return this._get_session_replay_id() && this.get_config('record_heatmap_data');
|
|
20540
|
+
};
|
|
20541
|
+
|
|
20329
20542
|
MixpanelLib.prototype.get_session_recording_properties = function () {
|
|
20330
20543
|
var props = {};
|
|
20331
20544
|
var replay_id = this._get_session_replay_id();
|
|
@@ -20510,6 +20723,8 @@
|
|
|
20510
20723
|
delete data['data'];
|
|
20511
20724
|
}
|
|
20512
20725
|
|
|
20726
|
+
_.extend(data, this.get_config('api_extra_query_params'));
|
|
20727
|
+
|
|
20513
20728
|
url += '?' + _.HTTPBuildQuery(data);
|
|
20514
20729
|
|
|
20515
20730
|
var lib = this;
|
|
@@ -21407,6 +21622,11 @@
|
|
|
21407
21622
|
'$anon_distinct_id': previous_distinct_id
|
|
21408
21623
|
}, {skip_hooks: true});
|
|
21409
21624
|
}
|
|
21625
|
+
|
|
21626
|
+
// check feature flags again if distinct id has changed
|
|
21627
|
+
if (new_distinct_id !== previous_distinct_id) {
|
|
21628
|
+
this.flags.fetchFlags();
|
|
21629
|
+
}
|
|
21410
21630
|
};
|
|
21411
21631
|
|
|
21412
21632
|
/**
|
|
@@ -21421,6 +21641,8 @@
|
|
|
21421
21641
|
'distinct_id': DEVICE_ID_PREFIX + uuid,
|
|
21422
21642
|
'$device_id': uuid
|
|
21423
21643
|
}, '');
|
|
21644
|
+
this.stop_session_recording();
|
|
21645
|
+
this._check_and_start_session_recording();
|
|
21424
21646
|
};
|
|
21425
21647
|
|
|
21426
21648
|
/**
|
|
@@ -21681,7 +21903,7 @@
|
|
|
21681
21903
|
}
|
|
21682
21904
|
Config.DEBUG = Config.DEBUG || this.get_config('debug');
|
|
21683
21905
|
|
|
21684
|
-
if ('autocapture' in config && this.autocapture) {
|
|
21906
|
+
if (('autocapture' in config || 'record_heatmap_data' in config) && this.autocapture) {
|
|
21685
21907
|
this.autocapture.init();
|
|
21686
21908
|
}
|
|
21687
21909
|
}
|