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
|
@@ -13945,7 +13945,7 @@
|
|
|
13945
13945
|
|
|
13946
13946
|
var Config = {
|
|
13947
13947
|
DEBUG: false,
|
|
13948
|
-
LIB_VERSION: '2.
|
|
13948
|
+
LIB_VERSION: '2.64.0'
|
|
13949
13949
|
};
|
|
13950
13950
|
|
|
13951
13951
|
/* eslint camelcase: "off", eqeqeq: "off" */
|
|
@@ -16104,7 +16104,7 @@
|
|
|
16104
16104
|
};
|
|
16105
16105
|
}
|
|
16106
16106
|
|
|
16107
|
-
var logger$
|
|
16107
|
+
var logger$6 = console_with_prefix('lock');
|
|
16108
16108
|
|
|
16109
16109
|
/**
|
|
16110
16110
|
* SharedLock: a mutex built on HTML5 localStorage, to ensure that only one browser
|
|
@@ -16156,7 +16156,7 @@
|
|
|
16156
16156
|
|
|
16157
16157
|
var delay = function(cb) {
|
|
16158
16158
|
if (new Date().getTime() - startTime > timeoutMS) {
|
|
16159
|
-
logger$
|
|
16159
|
+
logger$6.error('Timeout waiting for mutex on ' + key + '; clearing lock. [' + i + ']');
|
|
16160
16160
|
storage.removeItem(keyZ);
|
|
16161
16161
|
storage.removeItem(keyY);
|
|
16162
16162
|
loop();
|
|
@@ -16299,7 +16299,7 @@
|
|
|
16299
16299
|
}, this));
|
|
16300
16300
|
};
|
|
16301
16301
|
|
|
16302
|
-
var logger$
|
|
16302
|
+
var logger$5 = console_with_prefix('batch');
|
|
16303
16303
|
|
|
16304
16304
|
/**
|
|
16305
16305
|
* RequestQueue: queue for batching API requests with localStorage backup for retries.
|
|
@@ -16328,7 +16328,7 @@
|
|
|
16328
16328
|
timeoutMS: options.sharedLockTimeoutMS,
|
|
16329
16329
|
});
|
|
16330
16330
|
}
|
|
16331
|
-
this.reportError = options.errorReporter || _.bind(logger$
|
|
16331
|
+
this.reportError = options.errorReporter || _.bind(logger$5.error, logger$5);
|
|
16332
16332
|
|
|
16333
16333
|
this.pid = options.pid || null; // pass pid to test out storage lock contention scenarios
|
|
16334
16334
|
|
|
@@ -16661,7 +16661,7 @@
|
|
|
16661
16661
|
// maximum interval between request retries after exponential backoff
|
|
16662
16662
|
var MAX_RETRY_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
|
|
16663
16663
|
|
|
16664
|
-
var logger$
|
|
16664
|
+
var logger$4 = console_with_prefix('batch');
|
|
16665
16665
|
|
|
16666
16666
|
/**
|
|
16667
16667
|
* RequestBatcher: manages the queueing, flushing, retry etc of requests of one
|
|
@@ -16789,7 +16789,7 @@
|
|
|
16789
16789
|
*/
|
|
16790
16790
|
RequestBatcher.prototype.flush = function(options) {
|
|
16791
16791
|
if (this.requestInProgress) {
|
|
16792
|
-
logger$
|
|
16792
|
+
logger$4.log('Flush: Request already in progress');
|
|
16793
16793
|
return PromisePolyfill.resolve();
|
|
16794
16794
|
}
|
|
16795
16795
|
|
|
@@ -16966,7 +16966,7 @@
|
|
|
16966
16966
|
if (options.unloading) {
|
|
16967
16967
|
requestOptions.transport = 'sendBeacon';
|
|
16968
16968
|
}
|
|
16969
|
-
logger$
|
|
16969
|
+
logger$4.log('MIXPANEL REQUEST:', dataForRequest);
|
|
16970
16970
|
return this.sendRequestPromise(dataForRequest, requestOptions).then(batchSendCallback);
|
|
16971
16971
|
}, this))
|
|
16972
16972
|
.catch(_.bind(function(err) {
|
|
@@ -16979,7 +16979,7 @@
|
|
|
16979
16979
|
* Log error to global logger and optional user-defined logger.
|
|
16980
16980
|
*/
|
|
16981
16981
|
RequestBatcher.prototype.reportError = function(msg, err) {
|
|
16982
|
-
logger$
|
|
16982
|
+
logger$4.error.apply(logger$4.error, arguments);
|
|
16983
16983
|
if (this.errorReporter) {
|
|
16984
16984
|
try {
|
|
16985
16985
|
if (!(err instanceof Error)) {
|
|
@@ -16987,7 +16987,7 @@
|
|
|
16987
16987
|
}
|
|
16988
16988
|
this.errorReporter(msg, err);
|
|
16989
16989
|
} catch(err) {
|
|
16990
|
-
logger$
|
|
16990
|
+
logger$4.error(err);
|
|
16991
16991
|
}
|
|
16992
16992
|
}
|
|
16993
16993
|
};
|
|
@@ -17003,7 +17003,7 @@
|
|
|
17003
17003
|
|
|
17004
17004
|
var RECORD_ENQUEUE_THROTTLE_MS = 250;
|
|
17005
17005
|
|
|
17006
|
-
var logger$
|
|
17006
|
+
var logger$3 = console_with_prefix('recorder');
|
|
17007
17007
|
var CompressionStream = win['CompressionStream'];
|
|
17008
17008
|
|
|
17009
17009
|
var RECORDER_BATCHER_LIB_CONFIG = {
|
|
@@ -17140,14 +17140,14 @@
|
|
|
17140
17140
|
}
|
|
17141
17141
|
|
|
17142
17142
|
if (this._stopRecording !== null) {
|
|
17143
|
-
logger$
|
|
17143
|
+
logger$3.log('Recording already in progress, skipping startRecording.');
|
|
17144
17144
|
return;
|
|
17145
17145
|
}
|
|
17146
17146
|
|
|
17147
17147
|
this.recordMaxMs = this.getConfig('record_max_ms');
|
|
17148
17148
|
if (this.recordMaxMs > MAX_RECORDING_MS) {
|
|
17149
17149
|
this.recordMaxMs = MAX_RECORDING_MS;
|
|
17150
|
-
logger$
|
|
17150
|
+
logger$3.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.');
|
|
17151
17151
|
}
|
|
17152
17152
|
|
|
17153
17153
|
if (!this.maxExpires) {
|
|
@@ -17157,7 +17157,7 @@
|
|
|
17157
17157
|
this.recordMinMs = this.getConfig('record_min_ms');
|
|
17158
17158
|
if (this.recordMinMs > MAX_VALUE_FOR_MIN_RECORDING_MS) {
|
|
17159
17159
|
this.recordMinMs = MAX_VALUE_FOR_MIN_RECORDING_MS;
|
|
17160
|
-
logger$
|
|
17160
|
+
logger$3.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.');
|
|
17161
17161
|
}
|
|
17162
17162
|
|
|
17163
17163
|
if (!this.replayStartTime) {
|
|
@@ -17441,14 +17441,14 @@
|
|
|
17441
17441
|
|
|
17442
17442
|
|
|
17443
17443
|
SessionRecording.prototype.reportError = function(msg, err) {
|
|
17444
|
-
logger$
|
|
17444
|
+
logger$3.error.apply(logger$3.error, arguments);
|
|
17445
17445
|
try {
|
|
17446
17446
|
if (!err && !(msg instanceof Error)) {
|
|
17447
17447
|
msg = new Error(msg);
|
|
17448
17448
|
}
|
|
17449
17449
|
this.getConfig('error_reporter')(msg, err);
|
|
17450
17450
|
} catch(err) {
|
|
17451
|
-
logger$
|
|
17451
|
+
logger$3.error(err);
|
|
17452
17452
|
}
|
|
17453
17453
|
};
|
|
17454
17454
|
|
|
@@ -17544,7 +17544,7 @@
|
|
|
17544
17544
|
.catch(this.handleError.bind(this));
|
|
17545
17545
|
};
|
|
17546
17546
|
|
|
17547
|
-
var logger$
|
|
17547
|
+
var logger$2 = console_with_prefix('recorder');
|
|
17548
17548
|
|
|
17549
17549
|
/**
|
|
17550
17550
|
* Recorder API: bundles rrweb and and exposes methods to start and stop recordings.
|
|
@@ -17560,7 +17560,7 @@
|
|
|
17560
17560
|
*/
|
|
17561
17561
|
this.recordingRegistry = new RecordingRegistry({
|
|
17562
17562
|
mixpanelInstance: this.mixpanelInstance,
|
|
17563
|
-
errorReporter: logger$
|
|
17563
|
+
errorReporter: logger$2.error,
|
|
17564
17564
|
sharedLockStorage: sharedLockStorage
|
|
17565
17565
|
});
|
|
17566
17566
|
this._flushInactivePromise = this.recordingRegistry.flushInactiveRecordings();
|
|
@@ -17571,17 +17571,17 @@
|
|
|
17571
17571
|
MixpanelRecorder.prototype.startRecording = function(options) {
|
|
17572
17572
|
options = options || {};
|
|
17573
17573
|
if (this.activeRecording && !this.activeRecording.isRrwebStopped()) {
|
|
17574
|
-
logger$
|
|
17574
|
+
logger$2.log('Recording already in progress, skipping startRecording.');
|
|
17575
17575
|
return;
|
|
17576
17576
|
}
|
|
17577
17577
|
|
|
17578
17578
|
var onIdleTimeout = function () {
|
|
17579
|
-
logger$
|
|
17579
|
+
logger$2.log('Idle timeout reached, restarting recording.');
|
|
17580
17580
|
this.resetRecording();
|
|
17581
17581
|
}.bind(this);
|
|
17582
17582
|
|
|
17583
17583
|
var onMaxLengthReached = function () {
|
|
17584
|
-
logger$
|
|
17584
|
+
logger$2.log('Max recording length reached, stopping recording.');
|
|
17585
17585
|
this.resetRecording();
|
|
17586
17586
|
}.bind(this);
|
|
17587
17587
|
|
|
@@ -17644,7 +17644,7 @@
|
|
|
17644
17644
|
} else if (startNewIfInactive) {
|
|
17645
17645
|
return this.startRecording({shouldStopBatcher: false});
|
|
17646
17646
|
} else {
|
|
17647
|
-
logger$
|
|
17647
|
+
logger$2.log('No resumable recording found.');
|
|
17648
17648
|
return null;
|
|
17649
17649
|
}
|
|
17650
17650
|
}.bind(this));
|
|
@@ -17702,7 +17702,7 @@
|
|
|
17702
17702
|
'href', 'name', 'role', 'title', 'type'
|
|
17703
17703
|
];
|
|
17704
17704
|
|
|
17705
|
-
var logger = console_with_prefix('autocapture');
|
|
17705
|
+
var logger$1 = console_with_prefix('autocapture');
|
|
17706
17706
|
|
|
17707
17707
|
|
|
17708
17708
|
function getClasses(el) {
|
|
@@ -17788,6 +17788,7 @@
|
|
|
17788
17788
|
var blockSelectors = config.blockSelectors || [];
|
|
17789
17789
|
var captureTextContent = config.captureTextContent || false;
|
|
17790
17790
|
var captureExtraAttrs = config.captureExtraAttrs || [];
|
|
17791
|
+
var capturedForHeatMap = config.capturedForHeatMap || false;
|
|
17791
17792
|
|
|
17792
17793
|
// convert array to set every time, as the config may have changed
|
|
17793
17794
|
var blockAttrsSet = {};
|
|
@@ -17866,6 +17867,9 @@
|
|
|
17866
17867
|
props['$' + prop] = ev[prop];
|
|
17867
17868
|
}
|
|
17868
17869
|
});
|
|
17870
|
+
if (capturedForHeatMap) {
|
|
17871
|
+
props['$captured_for_heatmap'] = true;
|
|
17872
|
+
}
|
|
17869
17873
|
target = guessRealClickTarget(ev);
|
|
17870
17874
|
}
|
|
17871
17875
|
// prioritize text content from "real" click target if different from original target
|
|
@@ -17960,7 +17964,7 @@
|
|
|
17960
17964
|
return false;
|
|
17961
17965
|
}
|
|
17962
17966
|
} catch (err) {
|
|
17963
|
-
logger.critical('Error while checking element in allowElementCallback', err);
|
|
17967
|
+
logger$1.critical('Error while checking element in allowElementCallback', err);
|
|
17964
17968
|
return false;
|
|
17965
17969
|
}
|
|
17966
17970
|
}
|
|
@@ -17977,7 +17981,7 @@
|
|
|
17977
17981
|
return true;
|
|
17978
17982
|
}
|
|
17979
17983
|
} catch (err) {
|
|
17980
|
-
logger.critical('Error while checking selector: ' + sel, err);
|
|
17984
|
+
logger$1.critical('Error while checking selector: ' + sel, err);
|
|
17981
17985
|
}
|
|
17982
17986
|
}
|
|
17983
17987
|
return false;
|
|
@@ -17992,7 +17996,7 @@
|
|
|
17992
17996
|
return true;
|
|
17993
17997
|
}
|
|
17994
17998
|
} catch (err) {
|
|
17995
|
-
logger.critical('Error while checking element in blockElementCallback', err);
|
|
17999
|
+
logger$1.critical('Error while checking element in blockElementCallback', err);
|
|
17996
18000
|
return true;
|
|
17997
18001
|
}
|
|
17998
18002
|
}
|
|
@@ -18006,7 +18010,7 @@
|
|
|
18006
18010
|
return true;
|
|
18007
18011
|
}
|
|
18008
18012
|
} catch (err) {
|
|
18009
|
-
logger.critical('Error while checking selector: ' + sel, err);
|
|
18013
|
+
logger$1.critical('Error while checking selector: ' + sel, err);
|
|
18010
18014
|
}
|
|
18011
18015
|
}
|
|
18012
18016
|
}
|
|
@@ -18212,22 +18216,22 @@
|
|
|
18212
18216
|
var CONFIG_TRACK_SCROLL = 'scroll';
|
|
18213
18217
|
var CONFIG_TRACK_SUBMIT = 'submit';
|
|
18214
18218
|
|
|
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;
|
|
18219
|
+
var CONFIG_DEFAULTS$1 = {};
|
|
18220
|
+
CONFIG_DEFAULTS$1[CONFIG_ALLOW_SELECTORS] = [];
|
|
18221
|
+
CONFIG_DEFAULTS$1[CONFIG_ALLOW_URL_REGEXES] = [];
|
|
18222
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_ATTRS] = [];
|
|
18223
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
|
|
18224
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_SELECTORS] = [];
|
|
18225
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_URL_REGEXES] = [];
|
|
18226
|
+
CONFIG_DEFAULTS$1[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
|
|
18227
|
+
CONFIG_DEFAULTS$1[CONFIG_CAPTURE_TEXT_CONTENT] = false;
|
|
18228
|
+
CONFIG_DEFAULTS$1[CONFIG_SCROLL_CAPTURE_ALL] = false;
|
|
18229
|
+
CONFIG_DEFAULTS$1[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
|
|
18230
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_CLICK] = true;
|
|
18231
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_INPUT] = true;
|
|
18232
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
|
|
18233
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_SCROLL] = true;
|
|
18234
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_SUBMIT] = true;
|
|
18231
18235
|
|
|
18232
18236
|
var DEFAULT_PROPS = {
|
|
18233
18237
|
'$mp_autocapture': true
|
|
@@ -18248,7 +18252,7 @@
|
|
|
18248
18252
|
|
|
18249
18253
|
Autocapture.prototype.init = function() {
|
|
18250
18254
|
if (!minDOMApisSupported()) {
|
|
18251
|
-
logger.critical('Autocapture unavailable: missing required DOM APIs');
|
|
18255
|
+
logger$1.critical('Autocapture unavailable: missing required DOM APIs');
|
|
18252
18256
|
return;
|
|
18253
18257
|
}
|
|
18254
18258
|
|
|
@@ -18265,10 +18269,10 @@
|
|
|
18265
18269
|
// Autocapture is completely off
|
|
18266
18270
|
return {};
|
|
18267
18271
|
} else if (_.isObject(autocaptureConfig)) {
|
|
18268
|
-
return _.extend({}, CONFIG_DEFAULTS, autocaptureConfig);
|
|
18272
|
+
return _.extend({}, CONFIG_DEFAULTS$1, autocaptureConfig);
|
|
18269
18273
|
} else {
|
|
18270
18274
|
// Autocapture config is non-object truthy value, return default
|
|
18271
|
-
return CONFIG_DEFAULTS;
|
|
18275
|
+
return CONFIG_DEFAULTS$1;
|
|
18272
18276
|
}
|
|
18273
18277
|
};
|
|
18274
18278
|
|
|
@@ -18292,7 +18296,7 @@
|
|
|
18292
18296
|
break;
|
|
18293
18297
|
}
|
|
18294
18298
|
} catch (err) {
|
|
18295
|
-
logger.critical('Error while checking block URL regex: ' + allowRegex, err);
|
|
18299
|
+
logger$1.critical('Error while checking block URL regex: ' + allowRegex, err);
|
|
18296
18300
|
return true;
|
|
18297
18301
|
}
|
|
18298
18302
|
}
|
|
@@ -18313,7 +18317,7 @@
|
|
|
18313
18317
|
return true;
|
|
18314
18318
|
}
|
|
18315
18319
|
} catch (err) {
|
|
18316
|
-
logger.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
|
|
18320
|
+
logger$1.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
|
|
18317
18321
|
return true;
|
|
18318
18322
|
}
|
|
18319
18323
|
}
|
|
@@ -18342,7 +18346,8 @@
|
|
|
18342
18346
|
blockElementCallback: this.getConfig(CONFIG_BLOCK_ELEMENT_CALLBACK),
|
|
18343
18347
|
blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
|
|
18344
18348
|
captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
|
|
18345
|
-
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT)
|
|
18349
|
+
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT),
|
|
18350
|
+
capturedForHeatMap: mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK) && this.mp.is_recording_heatmap_data(),
|
|
18346
18351
|
});
|
|
18347
18352
|
if (props) {
|
|
18348
18353
|
_.extend(props, DEFAULT_PROPS);
|
|
@@ -18353,13 +18358,13 @@
|
|
|
18353
18358
|
Autocapture.prototype.initClickTracking = function() {
|
|
18354
18359
|
win.removeEventListener(EV_CLICK, this.listenerClick);
|
|
18355
18360
|
|
|
18356
|
-
if (!this.getConfig(CONFIG_TRACK_CLICK)) {
|
|
18361
|
+
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
|
|
18357
18362
|
return;
|
|
18358
18363
|
}
|
|
18359
|
-
logger.log('Initializing click tracking');
|
|
18364
|
+
logger$1.log('Initializing click tracking');
|
|
18360
18365
|
|
|
18361
18366
|
this.listenerClick = win.addEventListener(EV_CLICK, function(ev) {
|
|
18362
|
-
if (!this.getConfig(CONFIG_TRACK_CLICK)) {
|
|
18367
|
+
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
|
|
18363
18368
|
return;
|
|
18364
18369
|
}
|
|
18365
18370
|
this.trackDomEvent(ev, MP_EV_CLICK);
|
|
@@ -18372,7 +18377,7 @@
|
|
|
18372
18377
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
18373
18378
|
return;
|
|
18374
18379
|
}
|
|
18375
|
-
logger.log('Initializing input tracking');
|
|
18380
|
+
logger$1.log('Initializing input tracking');
|
|
18376
18381
|
|
|
18377
18382
|
this.listenerChange = win.addEventListener(EV_CHANGE, function(ev) {
|
|
18378
18383
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
@@ -18390,7 +18395,7 @@
|
|
|
18390
18395
|
if (!this.pageviewTrackingConfig()) {
|
|
18391
18396
|
return;
|
|
18392
18397
|
}
|
|
18393
|
-
logger.log('Initializing pageview tracking');
|
|
18398
|
+
logger$1.log('Initializing pageview tracking');
|
|
18394
18399
|
|
|
18395
18400
|
var previousTrackedUrl = '';
|
|
18396
18401
|
var tracked = false;
|
|
@@ -18445,7 +18450,7 @@
|
|
|
18445
18450
|
}
|
|
18446
18451
|
if (didPathChange) {
|
|
18447
18452
|
this.lastScrollCheckpoint = 0;
|
|
18448
|
-
logger.log('Path change: re-initializing scroll depth checkpoints');
|
|
18453
|
+
logger$1.log('Path change: re-initializing scroll depth checkpoints');
|
|
18449
18454
|
}
|
|
18450
18455
|
}
|
|
18451
18456
|
}.bind(this)));
|
|
@@ -18457,7 +18462,7 @@
|
|
|
18457
18462
|
if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
|
|
18458
18463
|
return;
|
|
18459
18464
|
}
|
|
18460
|
-
logger.log('Initializing scroll tracking');
|
|
18465
|
+
logger$1.log('Initializing scroll tracking');
|
|
18461
18466
|
this.lastScrollCheckpoint = 0;
|
|
18462
18467
|
|
|
18463
18468
|
this.listenerScroll = win.addEventListener(EV_SCROLLEND, safewrap(function() {
|
|
@@ -18494,7 +18499,7 @@
|
|
|
18494
18499
|
}
|
|
18495
18500
|
}
|
|
18496
18501
|
} catch (err) {
|
|
18497
|
-
logger.critical('Error while calculating scroll percentage', err);
|
|
18502
|
+
logger$1.critical('Error while calculating scroll percentage', err);
|
|
18498
18503
|
}
|
|
18499
18504
|
if (shouldTrack) {
|
|
18500
18505
|
this.mp.track(MP_EV_SCROLL, props);
|
|
@@ -18508,7 +18513,7 @@
|
|
|
18508
18513
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
18509
18514
|
return;
|
|
18510
18515
|
}
|
|
18511
|
-
logger.log('Initializing submit tracking');
|
|
18516
|
+
logger$1.log('Initializing submit tracking');
|
|
18512
18517
|
|
|
18513
18518
|
this.listenerSubmit = win.addEventListener(EV_SUBMIT, function(ev) {
|
|
18514
18519
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
@@ -18521,6 +18526,193 @@
|
|
|
18521
18526
|
// TODO integrate error_reporter from mixpanel instance
|
|
18522
18527
|
safewrapClass(Autocapture);
|
|
18523
18528
|
|
|
18529
|
+
var fetch = win['fetch'];
|
|
18530
|
+
var logger = console_with_prefix('flags');
|
|
18531
|
+
|
|
18532
|
+
var FLAGS_CONFIG_KEY = 'flags';
|
|
18533
|
+
|
|
18534
|
+
var CONFIG_CONTEXT = 'context';
|
|
18535
|
+
var CONFIG_DEFAULTS = {};
|
|
18536
|
+
CONFIG_DEFAULTS[CONFIG_CONTEXT] = {};
|
|
18537
|
+
|
|
18538
|
+
/**
|
|
18539
|
+
* FeatureFlagManager: support for Mixpanel's feature flagging product
|
|
18540
|
+
* @constructor
|
|
18541
|
+
*/
|
|
18542
|
+
var FeatureFlagManager = function(initOptions) {
|
|
18543
|
+
this.getMpConfig = initOptions.getConfigFunc;
|
|
18544
|
+
this.getDistinctId = initOptions.getDistinctIdFunc;
|
|
18545
|
+
this.track = initOptions.trackingFunc;
|
|
18546
|
+
};
|
|
18547
|
+
|
|
18548
|
+
FeatureFlagManager.prototype.init = function() {
|
|
18549
|
+
if (!minApisSupported()) {
|
|
18550
|
+
logger.critical('Feature Flags unavailable: missing minimum required APIs');
|
|
18551
|
+
return;
|
|
18552
|
+
}
|
|
18553
|
+
|
|
18554
|
+
this.flags = null;
|
|
18555
|
+
this.fetchFlags();
|
|
18556
|
+
|
|
18557
|
+
this.trackedFeatures = new Set();
|
|
18558
|
+
};
|
|
18559
|
+
|
|
18560
|
+
FeatureFlagManager.prototype.getFullConfig = function() {
|
|
18561
|
+
var ffConfig = this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
18562
|
+
if (!ffConfig) {
|
|
18563
|
+
// flags are completely off
|
|
18564
|
+
return {};
|
|
18565
|
+
} else if (_.isObject(ffConfig)) {
|
|
18566
|
+
return _.extend({}, CONFIG_DEFAULTS, ffConfig);
|
|
18567
|
+
} else {
|
|
18568
|
+
// config is non-object truthy value, return default
|
|
18569
|
+
return CONFIG_DEFAULTS;
|
|
18570
|
+
}
|
|
18571
|
+
};
|
|
18572
|
+
|
|
18573
|
+
FeatureFlagManager.prototype.getConfig = function(key) {
|
|
18574
|
+
return this.getFullConfig()[key];
|
|
18575
|
+
};
|
|
18576
|
+
|
|
18577
|
+
FeatureFlagManager.prototype.isEnabled = function() {
|
|
18578
|
+
return !!this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
18579
|
+
};
|
|
18580
|
+
|
|
18581
|
+
FeatureFlagManager.prototype.areFeaturesReady = function() {
|
|
18582
|
+
if (!this.isEnabled()) {
|
|
18583
|
+
logger.error('Feature Flags not enabled');
|
|
18584
|
+
}
|
|
18585
|
+
return !!this.flags;
|
|
18586
|
+
};
|
|
18587
|
+
|
|
18588
|
+
FeatureFlagManager.prototype.fetchFlags = function() {
|
|
18589
|
+
if (!this.isEnabled()) {
|
|
18590
|
+
return;
|
|
18591
|
+
}
|
|
18592
|
+
|
|
18593
|
+
var distinctId = this.getDistinctId();
|
|
18594
|
+
logger.log('Fetching flags for distinct ID: ' + distinctId);
|
|
18595
|
+
var reqParams = {
|
|
18596
|
+
'context': _.extend({'distinct_id': distinctId}, this.getConfig(CONFIG_CONTEXT))
|
|
18597
|
+
};
|
|
18598
|
+
this.fetchPromise = win['fetch'](this.getMpConfig('api_host') + '/' + this.getMpConfig('api_routes')['flags'], {
|
|
18599
|
+
'method': 'POST',
|
|
18600
|
+
'headers': {
|
|
18601
|
+
'Authorization': 'Basic ' + btoa(this.getMpConfig('token') + ':'),
|
|
18602
|
+
'Content-Type': 'application/octet-stream'
|
|
18603
|
+
},
|
|
18604
|
+
'body': JSON.stringify(reqParams)
|
|
18605
|
+
}).then(function(response) {
|
|
18606
|
+
return response.json().then(function(responseBody) {
|
|
18607
|
+
var responseFlags = responseBody['flags'];
|
|
18608
|
+
if (!responseFlags) {
|
|
18609
|
+
throw new Error('No flags in API response');
|
|
18610
|
+
}
|
|
18611
|
+
var flags = new Map();
|
|
18612
|
+
_.each(responseFlags, function(data, key) {
|
|
18613
|
+
flags.set(key, {
|
|
18614
|
+
'key': data['variant_key'],
|
|
18615
|
+
'data': data['variant_value']
|
|
18616
|
+
});
|
|
18617
|
+
});
|
|
18618
|
+
this.flags = flags;
|
|
18619
|
+
}.bind(this)).catch(function(error) {
|
|
18620
|
+
logger.error(error);
|
|
18621
|
+
});
|
|
18622
|
+
}.bind(this)).catch(function() {});
|
|
18623
|
+
};
|
|
18624
|
+
|
|
18625
|
+
FeatureFlagManager.prototype.getFeature = function(featureName, fallback) {
|
|
18626
|
+
if (!this.fetchPromise) {
|
|
18627
|
+
return new Promise(function(resolve) {
|
|
18628
|
+
logger.critical('Feature Flags not initialized');
|
|
18629
|
+
resolve(fallback);
|
|
18630
|
+
});
|
|
18631
|
+
}
|
|
18632
|
+
|
|
18633
|
+
return this.fetchPromise.then(function() {
|
|
18634
|
+
return this.getFeatureSync(featureName, fallback);
|
|
18635
|
+
}.bind(this)).catch(function(error) {
|
|
18636
|
+
logger.error(error);
|
|
18637
|
+
return fallback;
|
|
18638
|
+
});
|
|
18639
|
+
};
|
|
18640
|
+
|
|
18641
|
+
FeatureFlagManager.prototype.getFeatureSync = function(featureName, fallback) {
|
|
18642
|
+
if (!this.areFeaturesReady()) {
|
|
18643
|
+
logger.log('Flags not loaded yet');
|
|
18644
|
+
return fallback;
|
|
18645
|
+
}
|
|
18646
|
+
var feature = this.flags.get(featureName);
|
|
18647
|
+
if (!feature) {
|
|
18648
|
+
logger.log('No flag found: "' + featureName + '"');
|
|
18649
|
+
return fallback;
|
|
18650
|
+
}
|
|
18651
|
+
this.trackFeatureCheck(featureName, feature);
|
|
18652
|
+
return feature;
|
|
18653
|
+
};
|
|
18654
|
+
|
|
18655
|
+
FeatureFlagManager.prototype.getFeatureData = function(featureName, fallbackValue) {
|
|
18656
|
+
return this.getFeature(featureName, {'data': fallbackValue}).then(function(feature) {
|
|
18657
|
+
return feature['data'];
|
|
18658
|
+
}).catch(function(error) {
|
|
18659
|
+
logger.error(error);
|
|
18660
|
+
return fallbackValue;
|
|
18661
|
+
});
|
|
18662
|
+
};
|
|
18663
|
+
|
|
18664
|
+
FeatureFlagManager.prototype.getFeatureDataSync = function(featureName, fallbackValue) {
|
|
18665
|
+
return this.getFeatureSync(featureName, {'data': fallbackValue})['data'];
|
|
18666
|
+
};
|
|
18667
|
+
|
|
18668
|
+
FeatureFlagManager.prototype.isFeatureEnabled = function(featureName, fallbackValue) {
|
|
18669
|
+
return this.getFeatureData(featureName).then(function() {
|
|
18670
|
+
return this.isFeatureEnabledSync(featureName, fallbackValue);
|
|
18671
|
+
}.bind(this)).catch(function(error) {
|
|
18672
|
+
logger.error(error);
|
|
18673
|
+
return fallbackValue;
|
|
18674
|
+
});
|
|
18675
|
+
};
|
|
18676
|
+
|
|
18677
|
+
FeatureFlagManager.prototype.isFeatureEnabledSync = function(featureName, fallbackValue) {
|
|
18678
|
+
fallbackValue = fallbackValue || false;
|
|
18679
|
+
var val = this.getFeatureDataSync(featureName, fallbackValue);
|
|
18680
|
+
if (val !== true && val !== false) {
|
|
18681
|
+
logger.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
|
|
18682
|
+
val = fallbackValue;
|
|
18683
|
+
}
|
|
18684
|
+
return val;
|
|
18685
|
+
};
|
|
18686
|
+
|
|
18687
|
+
FeatureFlagManager.prototype.trackFeatureCheck = function(featureName, feature) {
|
|
18688
|
+
if (this.trackedFeatures.has(featureName)) {
|
|
18689
|
+
return;
|
|
18690
|
+
}
|
|
18691
|
+
this.trackedFeatures.add(featureName);
|
|
18692
|
+
this.track('$experiment_started', {
|
|
18693
|
+
'Experiment name': featureName,
|
|
18694
|
+
'Variant name': feature['key'],
|
|
18695
|
+
'$experiment_type': 'feature_flag'
|
|
18696
|
+
});
|
|
18697
|
+
};
|
|
18698
|
+
|
|
18699
|
+
function minApisSupported() {
|
|
18700
|
+
return !!fetch &&
|
|
18701
|
+
typeof Promise !== 'undefined' &&
|
|
18702
|
+
typeof Map !== 'undefined' &&
|
|
18703
|
+
typeof Set !== 'undefined';
|
|
18704
|
+
}
|
|
18705
|
+
|
|
18706
|
+
safewrapClass(FeatureFlagManager);
|
|
18707
|
+
|
|
18708
|
+
FeatureFlagManager.prototype['are_features_ready'] = FeatureFlagManager.prototype.areFeaturesReady;
|
|
18709
|
+
FeatureFlagManager.prototype['get_feature'] = FeatureFlagManager.prototype.getFeature;
|
|
18710
|
+
FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
|
|
18711
|
+
FeatureFlagManager.prototype['get_feature_data_sync'] = FeatureFlagManager.prototype.getFeatureDataSync;
|
|
18712
|
+
FeatureFlagManager.prototype['get_feature_sync'] = FeatureFlagManager.prototype.getFeatureSync;
|
|
18713
|
+
FeatureFlagManager.prototype['is_feature_enabled'] = FeatureFlagManager.prototype.isFeatureEnabled;
|
|
18714
|
+
FeatureFlagManager.prototype['is_feature_enabled_sync'] = FeatureFlagManager.prototype.isFeatureEnabledSync;
|
|
18715
|
+
|
|
18524
18716
|
/* eslint camelcase: "off" */
|
|
18525
18717
|
|
|
18526
18718
|
|
|
@@ -19925,10 +20117,11 @@
|
|
|
19925
20117
|
}
|
|
19926
20118
|
|
|
19927
20119
|
var DEFAULT_API_ROUTES = {
|
|
19928
|
-
'track':
|
|
20120
|
+
'track': 'track/',
|
|
19929
20121
|
'engage': 'engage/',
|
|
19930
20122
|
'groups': 'groups/',
|
|
19931
|
-
'record': 'record/'
|
|
20123
|
+
'record': 'record/',
|
|
20124
|
+
'flags': 'flags/'
|
|
19932
20125
|
};
|
|
19933
20126
|
|
|
19934
20127
|
/*
|
|
@@ -19946,6 +20139,7 @@
|
|
|
19946
20139
|
'cross_site_cookie': false,
|
|
19947
20140
|
'cross_subdomain_cookie': true,
|
|
19948
20141
|
'error_reporter': NOOP_FUNC,
|
|
20142
|
+
'flags': false,
|
|
19949
20143
|
'persistence': 'cookie',
|
|
19950
20144
|
'persistence_name': '',
|
|
19951
20145
|
'cookie_domain': '',
|
|
@@ -19986,6 +20180,7 @@
|
|
|
19986
20180
|
'record_block_selector': 'img, video',
|
|
19987
20181
|
'record_canvas': false,
|
|
19988
20182
|
'record_collect_fonts': false,
|
|
20183
|
+
'record_heatmap_data': false,
|
|
19989
20184
|
'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
|
|
19990
20185
|
'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'),
|
|
19991
20186
|
'record_mask_text_selector': '*',
|
|
@@ -20201,6 +20396,14 @@
|
|
|
20201
20396
|
}, '');
|
|
20202
20397
|
}
|
|
20203
20398
|
|
|
20399
|
+
this.flags = new FeatureFlagManager({
|
|
20400
|
+
getConfigFunc: _.bind(this.get_config, this),
|
|
20401
|
+
getDistinctIdFunc: _.bind(this.get_distinct_id, this),
|
|
20402
|
+
trackingFunc: _.bind(this.track, this)
|
|
20403
|
+
});
|
|
20404
|
+
this.flags.init();
|
|
20405
|
+
this['flags'] = this.flags;
|
|
20406
|
+
|
|
20204
20407
|
this.autocapture = new Autocapture(this);
|
|
20205
20408
|
this.autocapture.init();
|
|
20206
20409
|
|
|
@@ -20326,6 +20529,10 @@
|
|
|
20326
20529
|
}
|
|
20327
20530
|
};
|
|
20328
20531
|
|
|
20532
|
+
MixpanelLib.prototype.is_recording_heatmap_data = function () {
|
|
20533
|
+
return this._get_session_replay_id() && this.get_config('record_heatmap_data');
|
|
20534
|
+
};
|
|
20535
|
+
|
|
20329
20536
|
MixpanelLib.prototype.get_session_recording_properties = function () {
|
|
20330
20537
|
var props = {};
|
|
20331
20538
|
var replay_id = this._get_session_replay_id();
|
|
@@ -21407,6 +21614,11 @@
|
|
|
21407
21614
|
'$anon_distinct_id': previous_distinct_id
|
|
21408
21615
|
}, {skip_hooks: true});
|
|
21409
21616
|
}
|
|
21617
|
+
|
|
21618
|
+
// check feature flags again if distinct id has changed
|
|
21619
|
+
if (new_distinct_id !== previous_distinct_id) {
|
|
21620
|
+
this.flags.fetchFlags();
|
|
21621
|
+
}
|
|
21410
21622
|
};
|
|
21411
21623
|
|
|
21412
21624
|
/**
|
|
@@ -21681,7 +21893,7 @@
|
|
|
21681
21893
|
}
|
|
21682
21894
|
Config.DEBUG = Config.DEBUG || this.get_config('debug');
|
|
21683
21895
|
|
|
21684
|
-
if ('autocapture' in config && this.autocapture) {
|
|
21896
|
+
if (('autocapture' in config || 'record_heatmap_data' in config) && this.autocapture) {
|
|
21685
21897
|
this.autocapture.init();
|
|
21686
21898
|
}
|
|
21687
21899
|
}
|