mixpanel-browser 2.63.0 → 2.64.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 +4 -0
- package/dist/mixpanel-core.cjs.js +252 -40
- package/dist/mixpanel-recorder.js +1 -1
- 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 +252 -40
- package/dist/mixpanel-with-recorder.js +273 -61
- package/dist/mixpanel-with-recorder.min.js +1 -1
- package/dist/mixpanel.amd.js +273 -61
- package/dist/mixpanel.cjs.js +273 -61
- package/dist/mixpanel.globals.js +252 -40
- package/dist/mixpanel.min.js +149 -143
- package/dist/mixpanel.module.js +273 -61
- package/dist/mixpanel.umd.js +273 -61
- package/package.json +1 -1
- package/src/autocapture/index.js +4 -3
- package/src/autocapture/utils.js +4 -0
- package/src/config.js +1 -1
- package/src/flags/index.js +191 -0
- package/src/mixpanel-core.js +24 -3
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.64.0'
|
|
13952
13952
|
};
|
|
13953
13953
|
|
|
13954
13954
|
/* eslint camelcase: "off", eqeqeq: "off" */
|
|
@@ -16107,7 +16107,7 @@
|
|
|
16107
16107
|
};
|
|
16108
16108
|
}
|
|
16109
16109
|
|
|
16110
|
-
var logger$
|
|
16110
|
+
var logger$6 = console_with_prefix('lock');
|
|
16111
16111
|
|
|
16112
16112
|
/**
|
|
16113
16113
|
* SharedLock: a mutex built on HTML5 localStorage, to ensure that only one browser
|
|
@@ -16159,7 +16159,7 @@
|
|
|
16159
16159
|
|
|
16160
16160
|
var delay = function(cb) {
|
|
16161
16161
|
if (new Date().getTime() - startTime > timeoutMS) {
|
|
16162
|
-
logger$
|
|
16162
|
+
logger$6.error('Timeout waiting for mutex on ' + key + '; clearing lock. [' + i + ']');
|
|
16163
16163
|
storage.removeItem(keyZ);
|
|
16164
16164
|
storage.removeItem(keyY);
|
|
16165
16165
|
loop();
|
|
@@ -16302,7 +16302,7 @@
|
|
|
16302
16302
|
}, this));
|
|
16303
16303
|
};
|
|
16304
16304
|
|
|
16305
|
-
var logger$
|
|
16305
|
+
var logger$5 = console_with_prefix('batch');
|
|
16306
16306
|
|
|
16307
16307
|
/**
|
|
16308
16308
|
* RequestQueue: queue for batching API requests with localStorage backup for retries.
|
|
@@ -16331,7 +16331,7 @@
|
|
|
16331
16331
|
timeoutMS: options.sharedLockTimeoutMS,
|
|
16332
16332
|
});
|
|
16333
16333
|
}
|
|
16334
|
-
this.reportError = options.errorReporter || _.bind(logger$
|
|
16334
|
+
this.reportError = options.errorReporter || _.bind(logger$5.error, logger$5);
|
|
16335
16335
|
|
|
16336
16336
|
this.pid = options.pid || null; // pass pid to test out storage lock contention scenarios
|
|
16337
16337
|
|
|
@@ -16664,7 +16664,7 @@
|
|
|
16664
16664
|
// maximum interval between request retries after exponential backoff
|
|
16665
16665
|
var MAX_RETRY_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
|
|
16666
16666
|
|
|
16667
|
-
var logger$
|
|
16667
|
+
var logger$4 = console_with_prefix('batch');
|
|
16668
16668
|
|
|
16669
16669
|
/**
|
|
16670
16670
|
* RequestBatcher: manages the queueing, flushing, retry etc of requests of one
|
|
@@ -16792,7 +16792,7 @@
|
|
|
16792
16792
|
*/
|
|
16793
16793
|
RequestBatcher.prototype.flush = function(options) {
|
|
16794
16794
|
if (this.requestInProgress) {
|
|
16795
|
-
logger$
|
|
16795
|
+
logger$4.log('Flush: Request already in progress');
|
|
16796
16796
|
return PromisePolyfill.resolve();
|
|
16797
16797
|
}
|
|
16798
16798
|
|
|
@@ -16969,7 +16969,7 @@
|
|
|
16969
16969
|
if (options.unloading) {
|
|
16970
16970
|
requestOptions.transport = 'sendBeacon';
|
|
16971
16971
|
}
|
|
16972
|
-
logger$
|
|
16972
|
+
logger$4.log('MIXPANEL REQUEST:', dataForRequest);
|
|
16973
16973
|
return this.sendRequestPromise(dataForRequest, requestOptions).then(batchSendCallback);
|
|
16974
16974
|
}, this))
|
|
16975
16975
|
.catch(_.bind(function(err) {
|
|
@@ -16982,7 +16982,7 @@
|
|
|
16982
16982
|
* Log error to global logger and optional user-defined logger.
|
|
16983
16983
|
*/
|
|
16984
16984
|
RequestBatcher.prototype.reportError = function(msg, err) {
|
|
16985
|
-
logger$
|
|
16985
|
+
logger$4.error.apply(logger$4.error, arguments);
|
|
16986
16986
|
if (this.errorReporter) {
|
|
16987
16987
|
try {
|
|
16988
16988
|
if (!(err instanceof Error)) {
|
|
@@ -16990,7 +16990,7 @@
|
|
|
16990
16990
|
}
|
|
16991
16991
|
this.errorReporter(msg, err);
|
|
16992
16992
|
} catch(err) {
|
|
16993
|
-
logger$
|
|
16993
|
+
logger$4.error(err);
|
|
16994
16994
|
}
|
|
16995
16995
|
}
|
|
16996
16996
|
};
|
|
@@ -17006,7 +17006,7 @@
|
|
|
17006
17006
|
|
|
17007
17007
|
var RECORD_ENQUEUE_THROTTLE_MS = 250;
|
|
17008
17008
|
|
|
17009
|
-
var logger$
|
|
17009
|
+
var logger$3 = console_with_prefix('recorder');
|
|
17010
17010
|
var CompressionStream = win['CompressionStream'];
|
|
17011
17011
|
|
|
17012
17012
|
var RECORDER_BATCHER_LIB_CONFIG = {
|
|
@@ -17143,14 +17143,14 @@
|
|
|
17143
17143
|
}
|
|
17144
17144
|
|
|
17145
17145
|
if (this._stopRecording !== null) {
|
|
17146
|
-
logger$
|
|
17146
|
+
logger$3.log('Recording already in progress, skipping startRecording.');
|
|
17147
17147
|
return;
|
|
17148
17148
|
}
|
|
17149
17149
|
|
|
17150
17150
|
this.recordMaxMs = this.getConfig('record_max_ms');
|
|
17151
17151
|
if (this.recordMaxMs > MAX_RECORDING_MS) {
|
|
17152
17152
|
this.recordMaxMs = MAX_RECORDING_MS;
|
|
17153
|
-
logger$
|
|
17153
|
+
logger$3.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.');
|
|
17154
17154
|
}
|
|
17155
17155
|
|
|
17156
17156
|
if (!this.maxExpires) {
|
|
@@ -17160,7 +17160,7 @@
|
|
|
17160
17160
|
this.recordMinMs = this.getConfig('record_min_ms');
|
|
17161
17161
|
if (this.recordMinMs > MAX_VALUE_FOR_MIN_RECORDING_MS) {
|
|
17162
17162
|
this.recordMinMs = MAX_VALUE_FOR_MIN_RECORDING_MS;
|
|
17163
|
-
logger$
|
|
17163
|
+
logger$3.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.');
|
|
17164
17164
|
}
|
|
17165
17165
|
|
|
17166
17166
|
if (!this.replayStartTime) {
|
|
@@ -17444,14 +17444,14 @@
|
|
|
17444
17444
|
|
|
17445
17445
|
|
|
17446
17446
|
SessionRecording.prototype.reportError = function(msg, err) {
|
|
17447
|
-
logger$
|
|
17447
|
+
logger$3.error.apply(logger$3.error, arguments);
|
|
17448
17448
|
try {
|
|
17449
17449
|
if (!err && !(msg instanceof Error)) {
|
|
17450
17450
|
msg = new Error(msg);
|
|
17451
17451
|
}
|
|
17452
17452
|
this.getConfig('error_reporter')(msg, err);
|
|
17453
17453
|
} catch(err) {
|
|
17454
|
-
logger$
|
|
17454
|
+
logger$3.error(err);
|
|
17455
17455
|
}
|
|
17456
17456
|
};
|
|
17457
17457
|
|
|
@@ -17547,7 +17547,7 @@
|
|
|
17547
17547
|
.catch(this.handleError.bind(this));
|
|
17548
17548
|
};
|
|
17549
17549
|
|
|
17550
|
-
var logger$
|
|
17550
|
+
var logger$2 = console_with_prefix('recorder');
|
|
17551
17551
|
|
|
17552
17552
|
/**
|
|
17553
17553
|
* Recorder API: bundles rrweb and and exposes methods to start and stop recordings.
|
|
@@ -17563,7 +17563,7 @@
|
|
|
17563
17563
|
*/
|
|
17564
17564
|
this.recordingRegistry = new RecordingRegistry({
|
|
17565
17565
|
mixpanelInstance: this.mixpanelInstance,
|
|
17566
|
-
errorReporter: logger$
|
|
17566
|
+
errorReporter: logger$2.error,
|
|
17567
17567
|
sharedLockStorage: sharedLockStorage
|
|
17568
17568
|
});
|
|
17569
17569
|
this._flushInactivePromise = this.recordingRegistry.flushInactiveRecordings();
|
|
@@ -17574,17 +17574,17 @@
|
|
|
17574
17574
|
MixpanelRecorder.prototype.startRecording = function(options) {
|
|
17575
17575
|
options = options || {};
|
|
17576
17576
|
if (this.activeRecording && !this.activeRecording.isRrwebStopped()) {
|
|
17577
|
-
logger$
|
|
17577
|
+
logger$2.log('Recording already in progress, skipping startRecording.');
|
|
17578
17578
|
return;
|
|
17579
17579
|
}
|
|
17580
17580
|
|
|
17581
17581
|
var onIdleTimeout = function () {
|
|
17582
|
-
logger$
|
|
17582
|
+
logger$2.log('Idle timeout reached, restarting recording.');
|
|
17583
17583
|
this.resetRecording();
|
|
17584
17584
|
}.bind(this);
|
|
17585
17585
|
|
|
17586
17586
|
var onMaxLengthReached = function () {
|
|
17587
|
-
logger$
|
|
17587
|
+
logger$2.log('Max recording length reached, stopping recording.');
|
|
17588
17588
|
this.resetRecording();
|
|
17589
17589
|
}.bind(this);
|
|
17590
17590
|
|
|
@@ -17647,7 +17647,7 @@
|
|
|
17647
17647
|
} else if (startNewIfInactive) {
|
|
17648
17648
|
return this.startRecording({shouldStopBatcher: false});
|
|
17649
17649
|
} else {
|
|
17650
|
-
logger$
|
|
17650
|
+
logger$2.log('No resumable recording found.');
|
|
17651
17651
|
return null;
|
|
17652
17652
|
}
|
|
17653
17653
|
}.bind(this));
|
|
@@ -17705,7 +17705,7 @@
|
|
|
17705
17705
|
'href', 'name', 'role', 'title', 'type'
|
|
17706
17706
|
];
|
|
17707
17707
|
|
|
17708
|
-
var logger = console_with_prefix('autocapture');
|
|
17708
|
+
var logger$1 = console_with_prefix('autocapture');
|
|
17709
17709
|
|
|
17710
17710
|
|
|
17711
17711
|
function getClasses(el) {
|
|
@@ -17791,6 +17791,7 @@
|
|
|
17791
17791
|
var blockSelectors = config.blockSelectors || [];
|
|
17792
17792
|
var captureTextContent = config.captureTextContent || false;
|
|
17793
17793
|
var captureExtraAttrs = config.captureExtraAttrs || [];
|
|
17794
|
+
var capturedForHeatMap = config.capturedForHeatMap || false;
|
|
17794
17795
|
|
|
17795
17796
|
// convert array to set every time, as the config may have changed
|
|
17796
17797
|
var blockAttrsSet = {};
|
|
@@ -17869,6 +17870,9 @@
|
|
|
17869
17870
|
props['$' + prop] = ev[prop];
|
|
17870
17871
|
}
|
|
17871
17872
|
});
|
|
17873
|
+
if (capturedForHeatMap) {
|
|
17874
|
+
props['$captured_for_heatmap'] = true;
|
|
17875
|
+
}
|
|
17872
17876
|
target = guessRealClickTarget(ev);
|
|
17873
17877
|
}
|
|
17874
17878
|
// prioritize text content from "real" click target if different from original target
|
|
@@ -17963,7 +17967,7 @@
|
|
|
17963
17967
|
return false;
|
|
17964
17968
|
}
|
|
17965
17969
|
} catch (err) {
|
|
17966
|
-
logger.critical('Error while checking element in allowElementCallback', err);
|
|
17970
|
+
logger$1.critical('Error while checking element in allowElementCallback', err);
|
|
17967
17971
|
return false;
|
|
17968
17972
|
}
|
|
17969
17973
|
}
|
|
@@ -17980,7 +17984,7 @@
|
|
|
17980
17984
|
return true;
|
|
17981
17985
|
}
|
|
17982
17986
|
} catch (err) {
|
|
17983
|
-
logger.critical('Error while checking selector: ' + sel, err);
|
|
17987
|
+
logger$1.critical('Error while checking selector: ' + sel, err);
|
|
17984
17988
|
}
|
|
17985
17989
|
}
|
|
17986
17990
|
return false;
|
|
@@ -17995,7 +17999,7 @@
|
|
|
17995
17999
|
return true;
|
|
17996
18000
|
}
|
|
17997
18001
|
} catch (err) {
|
|
17998
|
-
logger.critical('Error while checking element in blockElementCallback', err);
|
|
18002
|
+
logger$1.critical('Error while checking element in blockElementCallback', err);
|
|
17999
18003
|
return true;
|
|
18000
18004
|
}
|
|
18001
18005
|
}
|
|
@@ -18009,7 +18013,7 @@
|
|
|
18009
18013
|
return true;
|
|
18010
18014
|
}
|
|
18011
18015
|
} catch (err) {
|
|
18012
|
-
logger.critical('Error while checking selector: ' + sel, err);
|
|
18016
|
+
logger$1.critical('Error while checking selector: ' + sel, err);
|
|
18013
18017
|
}
|
|
18014
18018
|
}
|
|
18015
18019
|
}
|
|
@@ -18215,22 +18219,22 @@
|
|
|
18215
18219
|
var CONFIG_TRACK_SCROLL = 'scroll';
|
|
18216
18220
|
var CONFIG_TRACK_SUBMIT = 'submit';
|
|
18217
18221
|
|
|
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;
|
|
18222
|
+
var CONFIG_DEFAULTS$1 = {};
|
|
18223
|
+
CONFIG_DEFAULTS$1[CONFIG_ALLOW_SELECTORS] = [];
|
|
18224
|
+
CONFIG_DEFAULTS$1[CONFIG_ALLOW_URL_REGEXES] = [];
|
|
18225
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_ATTRS] = [];
|
|
18226
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
|
|
18227
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_SELECTORS] = [];
|
|
18228
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_URL_REGEXES] = [];
|
|
18229
|
+
CONFIG_DEFAULTS$1[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
|
|
18230
|
+
CONFIG_DEFAULTS$1[CONFIG_CAPTURE_TEXT_CONTENT] = false;
|
|
18231
|
+
CONFIG_DEFAULTS$1[CONFIG_SCROLL_CAPTURE_ALL] = false;
|
|
18232
|
+
CONFIG_DEFAULTS$1[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
|
|
18233
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_CLICK] = true;
|
|
18234
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_INPUT] = true;
|
|
18235
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
|
|
18236
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_SCROLL] = true;
|
|
18237
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_SUBMIT] = true;
|
|
18234
18238
|
|
|
18235
18239
|
var DEFAULT_PROPS = {
|
|
18236
18240
|
'$mp_autocapture': true
|
|
@@ -18251,7 +18255,7 @@
|
|
|
18251
18255
|
|
|
18252
18256
|
Autocapture.prototype.init = function() {
|
|
18253
18257
|
if (!minDOMApisSupported()) {
|
|
18254
|
-
logger.critical('Autocapture unavailable: missing required DOM APIs');
|
|
18258
|
+
logger$1.critical('Autocapture unavailable: missing required DOM APIs');
|
|
18255
18259
|
return;
|
|
18256
18260
|
}
|
|
18257
18261
|
|
|
@@ -18268,10 +18272,10 @@
|
|
|
18268
18272
|
// Autocapture is completely off
|
|
18269
18273
|
return {};
|
|
18270
18274
|
} else if (_.isObject(autocaptureConfig)) {
|
|
18271
|
-
return _.extend({}, CONFIG_DEFAULTS, autocaptureConfig);
|
|
18275
|
+
return _.extend({}, CONFIG_DEFAULTS$1, autocaptureConfig);
|
|
18272
18276
|
} else {
|
|
18273
18277
|
// Autocapture config is non-object truthy value, return default
|
|
18274
|
-
return CONFIG_DEFAULTS;
|
|
18278
|
+
return CONFIG_DEFAULTS$1;
|
|
18275
18279
|
}
|
|
18276
18280
|
};
|
|
18277
18281
|
|
|
@@ -18295,7 +18299,7 @@
|
|
|
18295
18299
|
break;
|
|
18296
18300
|
}
|
|
18297
18301
|
} catch (err) {
|
|
18298
|
-
logger.critical('Error while checking block URL regex: ' + allowRegex, err);
|
|
18302
|
+
logger$1.critical('Error while checking block URL regex: ' + allowRegex, err);
|
|
18299
18303
|
return true;
|
|
18300
18304
|
}
|
|
18301
18305
|
}
|
|
@@ -18316,7 +18320,7 @@
|
|
|
18316
18320
|
return true;
|
|
18317
18321
|
}
|
|
18318
18322
|
} catch (err) {
|
|
18319
|
-
logger.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
|
|
18323
|
+
logger$1.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
|
|
18320
18324
|
return true;
|
|
18321
18325
|
}
|
|
18322
18326
|
}
|
|
@@ -18345,7 +18349,8 @@
|
|
|
18345
18349
|
blockElementCallback: this.getConfig(CONFIG_BLOCK_ELEMENT_CALLBACK),
|
|
18346
18350
|
blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
|
|
18347
18351
|
captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
|
|
18348
|
-
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT)
|
|
18352
|
+
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT),
|
|
18353
|
+
capturedForHeatMap: mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK) && this.mp.is_recording_heatmap_data(),
|
|
18349
18354
|
});
|
|
18350
18355
|
if (props) {
|
|
18351
18356
|
_.extend(props, DEFAULT_PROPS);
|
|
@@ -18356,13 +18361,13 @@
|
|
|
18356
18361
|
Autocapture.prototype.initClickTracking = function() {
|
|
18357
18362
|
win.removeEventListener(EV_CLICK, this.listenerClick);
|
|
18358
18363
|
|
|
18359
|
-
if (!this.getConfig(CONFIG_TRACK_CLICK)) {
|
|
18364
|
+
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
|
|
18360
18365
|
return;
|
|
18361
18366
|
}
|
|
18362
|
-
logger.log('Initializing click tracking');
|
|
18367
|
+
logger$1.log('Initializing click tracking');
|
|
18363
18368
|
|
|
18364
18369
|
this.listenerClick = win.addEventListener(EV_CLICK, function(ev) {
|
|
18365
|
-
if (!this.getConfig(CONFIG_TRACK_CLICK)) {
|
|
18370
|
+
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
|
|
18366
18371
|
return;
|
|
18367
18372
|
}
|
|
18368
18373
|
this.trackDomEvent(ev, MP_EV_CLICK);
|
|
@@ -18375,7 +18380,7 @@
|
|
|
18375
18380
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
18376
18381
|
return;
|
|
18377
18382
|
}
|
|
18378
|
-
logger.log('Initializing input tracking');
|
|
18383
|
+
logger$1.log('Initializing input tracking');
|
|
18379
18384
|
|
|
18380
18385
|
this.listenerChange = win.addEventListener(EV_CHANGE, function(ev) {
|
|
18381
18386
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
@@ -18393,7 +18398,7 @@
|
|
|
18393
18398
|
if (!this.pageviewTrackingConfig()) {
|
|
18394
18399
|
return;
|
|
18395
18400
|
}
|
|
18396
|
-
logger.log('Initializing pageview tracking');
|
|
18401
|
+
logger$1.log('Initializing pageview tracking');
|
|
18397
18402
|
|
|
18398
18403
|
var previousTrackedUrl = '';
|
|
18399
18404
|
var tracked = false;
|
|
@@ -18448,7 +18453,7 @@
|
|
|
18448
18453
|
}
|
|
18449
18454
|
if (didPathChange) {
|
|
18450
18455
|
this.lastScrollCheckpoint = 0;
|
|
18451
|
-
logger.log('Path change: re-initializing scroll depth checkpoints');
|
|
18456
|
+
logger$1.log('Path change: re-initializing scroll depth checkpoints');
|
|
18452
18457
|
}
|
|
18453
18458
|
}
|
|
18454
18459
|
}.bind(this)));
|
|
@@ -18460,7 +18465,7 @@
|
|
|
18460
18465
|
if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
|
|
18461
18466
|
return;
|
|
18462
18467
|
}
|
|
18463
|
-
logger.log('Initializing scroll tracking');
|
|
18468
|
+
logger$1.log('Initializing scroll tracking');
|
|
18464
18469
|
this.lastScrollCheckpoint = 0;
|
|
18465
18470
|
|
|
18466
18471
|
this.listenerScroll = win.addEventListener(EV_SCROLLEND, safewrap(function() {
|
|
@@ -18497,7 +18502,7 @@
|
|
|
18497
18502
|
}
|
|
18498
18503
|
}
|
|
18499
18504
|
} catch (err) {
|
|
18500
|
-
logger.critical('Error while calculating scroll percentage', err);
|
|
18505
|
+
logger$1.critical('Error while calculating scroll percentage', err);
|
|
18501
18506
|
}
|
|
18502
18507
|
if (shouldTrack) {
|
|
18503
18508
|
this.mp.track(MP_EV_SCROLL, props);
|
|
@@ -18511,7 +18516,7 @@
|
|
|
18511
18516
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
18512
18517
|
return;
|
|
18513
18518
|
}
|
|
18514
|
-
logger.log('Initializing submit tracking');
|
|
18519
|
+
logger$1.log('Initializing submit tracking');
|
|
18515
18520
|
|
|
18516
18521
|
this.listenerSubmit = win.addEventListener(EV_SUBMIT, function(ev) {
|
|
18517
18522
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
@@ -18524,6 +18529,193 @@
|
|
|
18524
18529
|
// TODO integrate error_reporter from mixpanel instance
|
|
18525
18530
|
safewrapClass(Autocapture);
|
|
18526
18531
|
|
|
18532
|
+
var fetch = win['fetch'];
|
|
18533
|
+
var logger = console_with_prefix('flags');
|
|
18534
|
+
|
|
18535
|
+
var FLAGS_CONFIG_KEY = 'flags';
|
|
18536
|
+
|
|
18537
|
+
var CONFIG_CONTEXT = 'context';
|
|
18538
|
+
var CONFIG_DEFAULTS = {};
|
|
18539
|
+
CONFIG_DEFAULTS[CONFIG_CONTEXT] = {};
|
|
18540
|
+
|
|
18541
|
+
/**
|
|
18542
|
+
* FeatureFlagManager: support for Mixpanel's feature flagging product
|
|
18543
|
+
* @constructor
|
|
18544
|
+
*/
|
|
18545
|
+
var FeatureFlagManager = function(initOptions) {
|
|
18546
|
+
this.getMpConfig = initOptions.getConfigFunc;
|
|
18547
|
+
this.getDistinctId = initOptions.getDistinctIdFunc;
|
|
18548
|
+
this.track = initOptions.trackingFunc;
|
|
18549
|
+
};
|
|
18550
|
+
|
|
18551
|
+
FeatureFlagManager.prototype.init = function() {
|
|
18552
|
+
if (!minApisSupported()) {
|
|
18553
|
+
logger.critical('Feature Flags unavailable: missing minimum required APIs');
|
|
18554
|
+
return;
|
|
18555
|
+
}
|
|
18556
|
+
|
|
18557
|
+
this.flags = null;
|
|
18558
|
+
this.fetchFlags();
|
|
18559
|
+
|
|
18560
|
+
this.trackedFeatures = new Set();
|
|
18561
|
+
};
|
|
18562
|
+
|
|
18563
|
+
FeatureFlagManager.prototype.getFullConfig = function() {
|
|
18564
|
+
var ffConfig = this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
18565
|
+
if (!ffConfig) {
|
|
18566
|
+
// flags are completely off
|
|
18567
|
+
return {};
|
|
18568
|
+
} else if (_.isObject(ffConfig)) {
|
|
18569
|
+
return _.extend({}, CONFIG_DEFAULTS, ffConfig);
|
|
18570
|
+
} else {
|
|
18571
|
+
// config is non-object truthy value, return default
|
|
18572
|
+
return CONFIG_DEFAULTS;
|
|
18573
|
+
}
|
|
18574
|
+
};
|
|
18575
|
+
|
|
18576
|
+
FeatureFlagManager.prototype.getConfig = function(key) {
|
|
18577
|
+
return this.getFullConfig()[key];
|
|
18578
|
+
};
|
|
18579
|
+
|
|
18580
|
+
FeatureFlagManager.prototype.isEnabled = function() {
|
|
18581
|
+
return !!this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
18582
|
+
};
|
|
18583
|
+
|
|
18584
|
+
FeatureFlagManager.prototype.areFeaturesReady = function() {
|
|
18585
|
+
if (!this.isEnabled()) {
|
|
18586
|
+
logger.error('Feature Flags not enabled');
|
|
18587
|
+
}
|
|
18588
|
+
return !!this.flags;
|
|
18589
|
+
};
|
|
18590
|
+
|
|
18591
|
+
FeatureFlagManager.prototype.fetchFlags = function() {
|
|
18592
|
+
if (!this.isEnabled()) {
|
|
18593
|
+
return;
|
|
18594
|
+
}
|
|
18595
|
+
|
|
18596
|
+
var distinctId = this.getDistinctId();
|
|
18597
|
+
logger.log('Fetching flags for distinct ID: ' + distinctId);
|
|
18598
|
+
var reqParams = {
|
|
18599
|
+
'context': _.extend({'distinct_id': distinctId}, this.getConfig(CONFIG_CONTEXT))
|
|
18600
|
+
};
|
|
18601
|
+
this.fetchPromise = win['fetch'](this.getMpConfig('api_host') + '/' + this.getMpConfig('api_routes')['flags'], {
|
|
18602
|
+
'method': 'POST',
|
|
18603
|
+
'headers': {
|
|
18604
|
+
'Authorization': 'Basic ' + btoa(this.getMpConfig('token') + ':'),
|
|
18605
|
+
'Content-Type': 'application/octet-stream'
|
|
18606
|
+
},
|
|
18607
|
+
'body': JSON.stringify(reqParams)
|
|
18608
|
+
}).then(function(response) {
|
|
18609
|
+
return response.json().then(function(responseBody) {
|
|
18610
|
+
var responseFlags = responseBody['flags'];
|
|
18611
|
+
if (!responseFlags) {
|
|
18612
|
+
throw new Error('No flags in API response');
|
|
18613
|
+
}
|
|
18614
|
+
var flags = new Map();
|
|
18615
|
+
_.each(responseFlags, function(data, key) {
|
|
18616
|
+
flags.set(key, {
|
|
18617
|
+
'key': data['variant_key'],
|
|
18618
|
+
'data': data['variant_value']
|
|
18619
|
+
});
|
|
18620
|
+
});
|
|
18621
|
+
this.flags = flags;
|
|
18622
|
+
}.bind(this)).catch(function(error) {
|
|
18623
|
+
logger.error(error);
|
|
18624
|
+
});
|
|
18625
|
+
}.bind(this)).catch(function() {});
|
|
18626
|
+
};
|
|
18627
|
+
|
|
18628
|
+
FeatureFlagManager.prototype.getFeature = function(featureName, fallback) {
|
|
18629
|
+
if (!this.fetchPromise) {
|
|
18630
|
+
return new Promise(function(resolve) {
|
|
18631
|
+
logger.critical('Feature Flags not initialized');
|
|
18632
|
+
resolve(fallback);
|
|
18633
|
+
});
|
|
18634
|
+
}
|
|
18635
|
+
|
|
18636
|
+
return this.fetchPromise.then(function() {
|
|
18637
|
+
return this.getFeatureSync(featureName, fallback);
|
|
18638
|
+
}.bind(this)).catch(function(error) {
|
|
18639
|
+
logger.error(error);
|
|
18640
|
+
return fallback;
|
|
18641
|
+
});
|
|
18642
|
+
};
|
|
18643
|
+
|
|
18644
|
+
FeatureFlagManager.prototype.getFeatureSync = function(featureName, fallback) {
|
|
18645
|
+
if (!this.areFeaturesReady()) {
|
|
18646
|
+
logger.log('Flags not loaded yet');
|
|
18647
|
+
return fallback;
|
|
18648
|
+
}
|
|
18649
|
+
var feature = this.flags.get(featureName);
|
|
18650
|
+
if (!feature) {
|
|
18651
|
+
logger.log('No flag found: "' + featureName + '"');
|
|
18652
|
+
return fallback;
|
|
18653
|
+
}
|
|
18654
|
+
this.trackFeatureCheck(featureName, feature);
|
|
18655
|
+
return feature;
|
|
18656
|
+
};
|
|
18657
|
+
|
|
18658
|
+
FeatureFlagManager.prototype.getFeatureData = function(featureName, fallbackValue) {
|
|
18659
|
+
return this.getFeature(featureName, {'data': fallbackValue}).then(function(feature) {
|
|
18660
|
+
return feature['data'];
|
|
18661
|
+
}).catch(function(error) {
|
|
18662
|
+
logger.error(error);
|
|
18663
|
+
return fallbackValue;
|
|
18664
|
+
});
|
|
18665
|
+
};
|
|
18666
|
+
|
|
18667
|
+
FeatureFlagManager.prototype.getFeatureDataSync = function(featureName, fallbackValue) {
|
|
18668
|
+
return this.getFeatureSync(featureName, {'data': fallbackValue})['data'];
|
|
18669
|
+
};
|
|
18670
|
+
|
|
18671
|
+
FeatureFlagManager.prototype.isFeatureEnabled = function(featureName, fallbackValue) {
|
|
18672
|
+
return this.getFeatureData(featureName).then(function() {
|
|
18673
|
+
return this.isFeatureEnabledSync(featureName, fallbackValue);
|
|
18674
|
+
}.bind(this)).catch(function(error) {
|
|
18675
|
+
logger.error(error);
|
|
18676
|
+
return fallbackValue;
|
|
18677
|
+
});
|
|
18678
|
+
};
|
|
18679
|
+
|
|
18680
|
+
FeatureFlagManager.prototype.isFeatureEnabledSync = function(featureName, fallbackValue) {
|
|
18681
|
+
fallbackValue = fallbackValue || false;
|
|
18682
|
+
var val = this.getFeatureDataSync(featureName, fallbackValue);
|
|
18683
|
+
if (val !== true && val !== false) {
|
|
18684
|
+
logger.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
|
|
18685
|
+
val = fallbackValue;
|
|
18686
|
+
}
|
|
18687
|
+
return val;
|
|
18688
|
+
};
|
|
18689
|
+
|
|
18690
|
+
FeatureFlagManager.prototype.trackFeatureCheck = function(featureName, feature) {
|
|
18691
|
+
if (this.trackedFeatures.has(featureName)) {
|
|
18692
|
+
return;
|
|
18693
|
+
}
|
|
18694
|
+
this.trackedFeatures.add(featureName);
|
|
18695
|
+
this.track('$experiment_started', {
|
|
18696
|
+
'Experiment name': featureName,
|
|
18697
|
+
'Variant name': feature['key'],
|
|
18698
|
+
'$experiment_type': 'feature_flag'
|
|
18699
|
+
});
|
|
18700
|
+
};
|
|
18701
|
+
|
|
18702
|
+
function minApisSupported() {
|
|
18703
|
+
return !!fetch &&
|
|
18704
|
+
typeof Promise !== 'undefined' &&
|
|
18705
|
+
typeof Map !== 'undefined' &&
|
|
18706
|
+
typeof Set !== 'undefined';
|
|
18707
|
+
}
|
|
18708
|
+
|
|
18709
|
+
safewrapClass(FeatureFlagManager);
|
|
18710
|
+
|
|
18711
|
+
FeatureFlagManager.prototype['are_features_ready'] = FeatureFlagManager.prototype.areFeaturesReady;
|
|
18712
|
+
FeatureFlagManager.prototype['get_feature'] = FeatureFlagManager.prototype.getFeature;
|
|
18713
|
+
FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
|
|
18714
|
+
FeatureFlagManager.prototype['get_feature_data_sync'] = FeatureFlagManager.prototype.getFeatureDataSync;
|
|
18715
|
+
FeatureFlagManager.prototype['get_feature_sync'] = FeatureFlagManager.prototype.getFeatureSync;
|
|
18716
|
+
FeatureFlagManager.prototype['is_feature_enabled'] = FeatureFlagManager.prototype.isFeatureEnabled;
|
|
18717
|
+
FeatureFlagManager.prototype['is_feature_enabled_sync'] = FeatureFlagManager.prototype.isFeatureEnabledSync;
|
|
18718
|
+
|
|
18527
18719
|
/* eslint camelcase: "off" */
|
|
18528
18720
|
|
|
18529
18721
|
|
|
@@ -19928,10 +20120,11 @@
|
|
|
19928
20120
|
}
|
|
19929
20121
|
|
|
19930
20122
|
var DEFAULT_API_ROUTES = {
|
|
19931
|
-
'track':
|
|
20123
|
+
'track': 'track/',
|
|
19932
20124
|
'engage': 'engage/',
|
|
19933
20125
|
'groups': 'groups/',
|
|
19934
|
-
'record': 'record/'
|
|
20126
|
+
'record': 'record/',
|
|
20127
|
+
'flags': 'flags/'
|
|
19935
20128
|
};
|
|
19936
20129
|
|
|
19937
20130
|
/*
|
|
@@ -19949,6 +20142,7 @@
|
|
|
19949
20142
|
'cross_site_cookie': false,
|
|
19950
20143
|
'cross_subdomain_cookie': true,
|
|
19951
20144
|
'error_reporter': NOOP_FUNC,
|
|
20145
|
+
'flags': false,
|
|
19952
20146
|
'persistence': 'cookie',
|
|
19953
20147
|
'persistence_name': '',
|
|
19954
20148
|
'cookie_domain': '',
|
|
@@ -19989,6 +20183,7 @@
|
|
|
19989
20183
|
'record_block_selector': 'img, video',
|
|
19990
20184
|
'record_canvas': false,
|
|
19991
20185
|
'record_collect_fonts': false,
|
|
20186
|
+
'record_heatmap_data': false,
|
|
19992
20187
|
'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
|
|
19993
20188
|
'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'),
|
|
19994
20189
|
'record_mask_text_selector': '*',
|
|
@@ -20204,6 +20399,14 @@
|
|
|
20204
20399
|
}, '');
|
|
20205
20400
|
}
|
|
20206
20401
|
|
|
20402
|
+
this.flags = new FeatureFlagManager({
|
|
20403
|
+
getConfigFunc: _.bind(this.get_config, this),
|
|
20404
|
+
getDistinctIdFunc: _.bind(this.get_distinct_id, this),
|
|
20405
|
+
trackingFunc: _.bind(this.track, this)
|
|
20406
|
+
});
|
|
20407
|
+
this.flags.init();
|
|
20408
|
+
this['flags'] = this.flags;
|
|
20409
|
+
|
|
20207
20410
|
this.autocapture = new Autocapture(this);
|
|
20208
20411
|
this.autocapture.init();
|
|
20209
20412
|
|
|
@@ -20329,6 +20532,10 @@
|
|
|
20329
20532
|
}
|
|
20330
20533
|
};
|
|
20331
20534
|
|
|
20535
|
+
MixpanelLib.prototype.is_recording_heatmap_data = function () {
|
|
20536
|
+
return this._get_session_replay_id() && this.get_config('record_heatmap_data');
|
|
20537
|
+
};
|
|
20538
|
+
|
|
20332
20539
|
MixpanelLib.prototype.get_session_recording_properties = function () {
|
|
20333
20540
|
var props = {};
|
|
20334
20541
|
var replay_id = this._get_session_replay_id();
|
|
@@ -21410,6 +21617,11 @@
|
|
|
21410
21617
|
'$anon_distinct_id': previous_distinct_id
|
|
21411
21618
|
}, {skip_hooks: true});
|
|
21412
21619
|
}
|
|
21620
|
+
|
|
21621
|
+
// check feature flags again if distinct id has changed
|
|
21622
|
+
if (new_distinct_id !== previous_distinct_id) {
|
|
21623
|
+
this.flags.fetchFlags();
|
|
21624
|
+
}
|
|
21413
21625
|
};
|
|
21414
21626
|
|
|
21415
21627
|
/**
|
|
@@ -21684,7 +21896,7 @@
|
|
|
21684
21896
|
}
|
|
21685
21897
|
Config.DEBUG = Config.DEBUG || this.get_config('debug');
|
|
21686
21898
|
|
|
21687
|
-
if ('autocapture' in config && this.autocapture) {
|
|
21899
|
+
if (('autocapture' in config || 'record_heatmap_data' in config) && this.autocapture) {
|
|
21688
21900
|
this.autocapture.init();
|
|
21689
21901
|
}
|
|
21690
21902
|
}
|