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.module.js
CHANGED
|
@@ -13942,7 +13942,7 @@ if (typeof Promise !== 'undefined' && Promise.toString().indexOf('[native code]'
|
|
|
13942
13942
|
|
|
13943
13943
|
var Config = {
|
|
13944
13944
|
DEBUG: false,
|
|
13945
|
-
LIB_VERSION: '2.
|
|
13945
|
+
LIB_VERSION: '2.64.0'
|
|
13946
13946
|
};
|
|
13947
13947
|
|
|
13948
13948
|
/* eslint camelcase: "off", eqeqeq: "off" */
|
|
@@ -16101,7 +16101,7 @@ function _addOptOutCheck(method, getConfigValue) {
|
|
|
16101
16101
|
};
|
|
16102
16102
|
}
|
|
16103
16103
|
|
|
16104
|
-
var logger$
|
|
16104
|
+
var logger$6 = console_with_prefix('lock');
|
|
16105
16105
|
|
|
16106
16106
|
/**
|
|
16107
16107
|
* SharedLock: a mutex built on HTML5 localStorage, to ensure that only one browser
|
|
@@ -16153,7 +16153,7 @@ SharedLock.prototype.withLock = function(lockedCB, pid) {
|
|
|
16153
16153
|
|
|
16154
16154
|
var delay = function(cb) {
|
|
16155
16155
|
if (new Date().getTime() - startTime > timeoutMS) {
|
|
16156
|
-
logger$
|
|
16156
|
+
logger$6.error('Timeout waiting for mutex on ' + key + '; clearing lock. [' + i + ']');
|
|
16157
16157
|
storage.removeItem(keyZ);
|
|
16158
16158
|
storage.removeItem(keyY);
|
|
16159
16159
|
loop();
|
|
@@ -16296,7 +16296,7 @@ LocalStorageWrapper.prototype.removeItem = function (key) {
|
|
|
16296
16296
|
}, this));
|
|
16297
16297
|
};
|
|
16298
16298
|
|
|
16299
|
-
var logger$
|
|
16299
|
+
var logger$5 = console_with_prefix('batch');
|
|
16300
16300
|
|
|
16301
16301
|
/**
|
|
16302
16302
|
* RequestQueue: queue for batching API requests with localStorage backup for retries.
|
|
@@ -16325,7 +16325,7 @@ var RequestQueue = function (storageKey, options) {
|
|
|
16325
16325
|
timeoutMS: options.sharedLockTimeoutMS,
|
|
16326
16326
|
});
|
|
16327
16327
|
}
|
|
16328
|
-
this.reportError = options.errorReporter || _.bind(logger$
|
|
16328
|
+
this.reportError = options.errorReporter || _.bind(logger$5.error, logger$5);
|
|
16329
16329
|
|
|
16330
16330
|
this.pid = options.pid || null; // pass pid to test out storage lock contention scenarios
|
|
16331
16331
|
|
|
@@ -16658,7 +16658,7 @@ RequestQueue.prototype.clear = function () {
|
|
|
16658
16658
|
// maximum interval between request retries after exponential backoff
|
|
16659
16659
|
var MAX_RETRY_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
|
|
16660
16660
|
|
|
16661
|
-
var logger$
|
|
16661
|
+
var logger$4 = console_with_prefix('batch');
|
|
16662
16662
|
|
|
16663
16663
|
/**
|
|
16664
16664
|
* RequestBatcher: manages the queueing, flushing, retry etc of requests of one
|
|
@@ -16786,7 +16786,7 @@ RequestBatcher.prototype.sendRequestPromise = function(data, options) {
|
|
|
16786
16786
|
*/
|
|
16787
16787
|
RequestBatcher.prototype.flush = function(options) {
|
|
16788
16788
|
if (this.requestInProgress) {
|
|
16789
|
-
logger$
|
|
16789
|
+
logger$4.log('Flush: Request already in progress');
|
|
16790
16790
|
return PromisePolyfill.resolve();
|
|
16791
16791
|
}
|
|
16792
16792
|
|
|
@@ -16963,7 +16963,7 @@ RequestBatcher.prototype.flush = function(options) {
|
|
|
16963
16963
|
if (options.unloading) {
|
|
16964
16964
|
requestOptions.transport = 'sendBeacon';
|
|
16965
16965
|
}
|
|
16966
|
-
logger$
|
|
16966
|
+
logger$4.log('MIXPANEL REQUEST:', dataForRequest);
|
|
16967
16967
|
return this.sendRequestPromise(dataForRequest, requestOptions).then(batchSendCallback);
|
|
16968
16968
|
}, this))
|
|
16969
16969
|
.catch(_.bind(function(err) {
|
|
@@ -16976,7 +16976,7 @@ RequestBatcher.prototype.flush = function(options) {
|
|
|
16976
16976
|
* Log error to global logger and optional user-defined logger.
|
|
16977
16977
|
*/
|
|
16978
16978
|
RequestBatcher.prototype.reportError = function(msg, err) {
|
|
16979
|
-
logger$
|
|
16979
|
+
logger$4.error.apply(logger$4.error, arguments);
|
|
16980
16980
|
if (this.errorReporter) {
|
|
16981
16981
|
try {
|
|
16982
16982
|
if (!(err instanceof Error)) {
|
|
@@ -16984,7 +16984,7 @@ RequestBatcher.prototype.reportError = function(msg, err) {
|
|
|
16984
16984
|
}
|
|
16985
16985
|
this.errorReporter(msg, err);
|
|
16986
16986
|
} catch(err) {
|
|
16987
|
-
logger$
|
|
16987
|
+
logger$4.error(err);
|
|
16988
16988
|
}
|
|
16989
16989
|
}
|
|
16990
16990
|
};
|
|
@@ -17000,7 +17000,7 @@ var isRecordingExpired = function(serializedRecording) {
|
|
|
17000
17000
|
|
|
17001
17001
|
var RECORD_ENQUEUE_THROTTLE_MS = 250;
|
|
17002
17002
|
|
|
17003
|
-
var logger$
|
|
17003
|
+
var logger$3 = console_with_prefix('recorder');
|
|
17004
17004
|
var CompressionStream = win['CompressionStream'];
|
|
17005
17005
|
|
|
17006
17006
|
var RECORDER_BATCHER_LIB_CONFIG = {
|
|
@@ -17137,14 +17137,14 @@ SessionRecording.prototype.startRecording = function (shouldStopBatcher) {
|
|
|
17137
17137
|
}
|
|
17138
17138
|
|
|
17139
17139
|
if (this._stopRecording !== null) {
|
|
17140
|
-
logger$
|
|
17140
|
+
logger$3.log('Recording already in progress, skipping startRecording.');
|
|
17141
17141
|
return;
|
|
17142
17142
|
}
|
|
17143
17143
|
|
|
17144
17144
|
this.recordMaxMs = this.getConfig('record_max_ms');
|
|
17145
17145
|
if (this.recordMaxMs > MAX_RECORDING_MS) {
|
|
17146
17146
|
this.recordMaxMs = MAX_RECORDING_MS;
|
|
17147
|
-
logger$
|
|
17147
|
+
logger$3.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.');
|
|
17148
17148
|
}
|
|
17149
17149
|
|
|
17150
17150
|
if (!this.maxExpires) {
|
|
@@ -17154,7 +17154,7 @@ SessionRecording.prototype.startRecording = function (shouldStopBatcher) {
|
|
|
17154
17154
|
this.recordMinMs = this.getConfig('record_min_ms');
|
|
17155
17155
|
if (this.recordMinMs > MAX_VALUE_FOR_MIN_RECORDING_MS) {
|
|
17156
17156
|
this.recordMinMs = MAX_VALUE_FOR_MIN_RECORDING_MS;
|
|
17157
|
-
logger$
|
|
17157
|
+
logger$3.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.');
|
|
17158
17158
|
}
|
|
17159
17159
|
|
|
17160
17160
|
if (!this.replayStartTime) {
|
|
@@ -17438,14 +17438,14 @@ SessionRecording.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da
|
|
|
17438
17438
|
|
|
17439
17439
|
|
|
17440
17440
|
SessionRecording.prototype.reportError = function(msg, err) {
|
|
17441
|
-
logger$
|
|
17441
|
+
logger$3.error.apply(logger$3.error, arguments);
|
|
17442
17442
|
try {
|
|
17443
17443
|
if (!err && !(msg instanceof Error)) {
|
|
17444
17444
|
msg = new Error(msg);
|
|
17445
17445
|
}
|
|
17446
17446
|
this.getConfig('error_reporter')(msg, err);
|
|
17447
17447
|
} catch(err) {
|
|
17448
|
-
logger$
|
|
17448
|
+
logger$3.error(err);
|
|
17449
17449
|
}
|
|
17450
17450
|
};
|
|
17451
17451
|
|
|
@@ -17541,7 +17541,7 @@ RecordingRegistry.prototype.flushInactiveRecordings = function () {
|
|
|
17541
17541
|
.catch(this.handleError.bind(this));
|
|
17542
17542
|
};
|
|
17543
17543
|
|
|
17544
|
-
var logger$
|
|
17544
|
+
var logger$2 = console_with_prefix('recorder');
|
|
17545
17545
|
|
|
17546
17546
|
/**
|
|
17547
17547
|
* Recorder API: bundles rrweb and and exposes methods to start and stop recordings.
|
|
@@ -17557,7 +17557,7 @@ var MixpanelRecorder = function(mixpanelInstance, rrwebRecord, sharedLockStorage
|
|
|
17557
17557
|
*/
|
|
17558
17558
|
this.recordingRegistry = new RecordingRegistry({
|
|
17559
17559
|
mixpanelInstance: this.mixpanelInstance,
|
|
17560
|
-
errorReporter: logger$
|
|
17560
|
+
errorReporter: logger$2.error,
|
|
17561
17561
|
sharedLockStorage: sharedLockStorage
|
|
17562
17562
|
});
|
|
17563
17563
|
this._flushInactivePromise = this.recordingRegistry.flushInactiveRecordings();
|
|
@@ -17568,17 +17568,17 @@ var MixpanelRecorder = function(mixpanelInstance, rrwebRecord, sharedLockStorage
|
|
|
17568
17568
|
MixpanelRecorder.prototype.startRecording = function(options) {
|
|
17569
17569
|
options = options || {};
|
|
17570
17570
|
if (this.activeRecording && !this.activeRecording.isRrwebStopped()) {
|
|
17571
|
-
logger$
|
|
17571
|
+
logger$2.log('Recording already in progress, skipping startRecording.');
|
|
17572
17572
|
return;
|
|
17573
17573
|
}
|
|
17574
17574
|
|
|
17575
17575
|
var onIdleTimeout = function () {
|
|
17576
|
-
logger$
|
|
17576
|
+
logger$2.log('Idle timeout reached, restarting recording.');
|
|
17577
17577
|
this.resetRecording();
|
|
17578
17578
|
}.bind(this);
|
|
17579
17579
|
|
|
17580
17580
|
var onMaxLengthReached = function () {
|
|
17581
|
-
logger$
|
|
17581
|
+
logger$2.log('Max recording length reached, stopping recording.');
|
|
17582
17582
|
this.resetRecording();
|
|
17583
17583
|
}.bind(this);
|
|
17584
17584
|
|
|
@@ -17641,7 +17641,7 @@ MixpanelRecorder.prototype.resumeRecording = function (startNewIfInactive) {
|
|
|
17641
17641
|
} else if (startNewIfInactive) {
|
|
17642
17642
|
return this.startRecording({shouldStopBatcher: false});
|
|
17643
17643
|
} else {
|
|
17644
|
-
logger$
|
|
17644
|
+
logger$2.log('No resumable recording found.');
|
|
17645
17645
|
return null;
|
|
17646
17646
|
}
|
|
17647
17647
|
}.bind(this));
|
|
@@ -17699,7 +17699,7 @@ var TRACKED_ATTRS = [
|
|
|
17699
17699
|
'href', 'name', 'role', 'title', 'type'
|
|
17700
17700
|
];
|
|
17701
17701
|
|
|
17702
|
-
var logger = console_with_prefix('autocapture');
|
|
17702
|
+
var logger$1 = console_with_prefix('autocapture');
|
|
17703
17703
|
|
|
17704
17704
|
|
|
17705
17705
|
function getClasses(el) {
|
|
@@ -17785,6 +17785,7 @@ function getPropsForDOMEvent(ev, config) {
|
|
|
17785
17785
|
var blockSelectors = config.blockSelectors || [];
|
|
17786
17786
|
var captureTextContent = config.captureTextContent || false;
|
|
17787
17787
|
var captureExtraAttrs = config.captureExtraAttrs || [];
|
|
17788
|
+
var capturedForHeatMap = config.capturedForHeatMap || false;
|
|
17788
17789
|
|
|
17789
17790
|
// convert array to set every time, as the config may have changed
|
|
17790
17791
|
var blockAttrsSet = {};
|
|
@@ -17863,6 +17864,9 @@ function getPropsForDOMEvent(ev, config) {
|
|
|
17863
17864
|
props['$' + prop] = ev[prop];
|
|
17864
17865
|
}
|
|
17865
17866
|
});
|
|
17867
|
+
if (capturedForHeatMap) {
|
|
17868
|
+
props['$captured_for_heatmap'] = true;
|
|
17869
|
+
}
|
|
17866
17870
|
target = guessRealClickTarget(ev);
|
|
17867
17871
|
}
|
|
17868
17872
|
// prioritize text content from "real" click target if different from original target
|
|
@@ -17957,7 +17961,7 @@ function isElementAllowed(el, ev, allowElementCallback, allowSelectors) {
|
|
|
17957
17961
|
return false;
|
|
17958
17962
|
}
|
|
17959
17963
|
} catch (err) {
|
|
17960
|
-
logger.critical('Error while checking element in allowElementCallback', err);
|
|
17964
|
+
logger$1.critical('Error while checking element in allowElementCallback', err);
|
|
17961
17965
|
return false;
|
|
17962
17966
|
}
|
|
17963
17967
|
}
|
|
@@ -17974,7 +17978,7 @@ function isElementAllowed(el, ev, allowElementCallback, allowSelectors) {
|
|
|
17974
17978
|
return true;
|
|
17975
17979
|
}
|
|
17976
17980
|
} catch (err) {
|
|
17977
|
-
logger.critical('Error while checking selector: ' + sel, err);
|
|
17981
|
+
logger$1.critical('Error while checking selector: ' + sel, err);
|
|
17978
17982
|
}
|
|
17979
17983
|
}
|
|
17980
17984
|
return false;
|
|
@@ -17989,7 +17993,7 @@ function isElementBlocked(el, ev, blockElementCallback, blockSelectors) {
|
|
|
17989
17993
|
return true;
|
|
17990
17994
|
}
|
|
17991
17995
|
} catch (err) {
|
|
17992
|
-
logger.critical('Error while checking element in blockElementCallback', err);
|
|
17996
|
+
logger$1.critical('Error while checking element in blockElementCallback', err);
|
|
17993
17997
|
return true;
|
|
17994
17998
|
}
|
|
17995
17999
|
}
|
|
@@ -18003,7 +18007,7 @@ function isElementBlocked(el, ev, blockElementCallback, blockSelectors) {
|
|
|
18003
18007
|
return true;
|
|
18004
18008
|
}
|
|
18005
18009
|
} catch (err) {
|
|
18006
|
-
logger.critical('Error while checking selector: ' + sel, err);
|
|
18010
|
+
logger$1.critical('Error while checking selector: ' + sel, err);
|
|
18007
18011
|
}
|
|
18008
18012
|
}
|
|
18009
18013
|
}
|
|
@@ -18209,22 +18213,22 @@ var CONFIG_TRACK_PAGEVIEW = 'pageview';
|
|
|
18209
18213
|
var CONFIG_TRACK_SCROLL = 'scroll';
|
|
18210
18214
|
var CONFIG_TRACK_SUBMIT = 'submit';
|
|
18211
18215
|
|
|
18212
|
-
var CONFIG_DEFAULTS = {};
|
|
18213
|
-
CONFIG_DEFAULTS[CONFIG_ALLOW_SELECTORS] = [];
|
|
18214
|
-
CONFIG_DEFAULTS[CONFIG_ALLOW_URL_REGEXES] = [];
|
|
18215
|
-
CONFIG_DEFAULTS[CONFIG_BLOCK_ATTRS] = [];
|
|
18216
|
-
CONFIG_DEFAULTS[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
|
|
18217
|
-
CONFIG_DEFAULTS[CONFIG_BLOCK_SELECTORS] = [];
|
|
18218
|
-
CONFIG_DEFAULTS[CONFIG_BLOCK_URL_REGEXES] = [];
|
|
18219
|
-
CONFIG_DEFAULTS[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
|
|
18220
|
-
CONFIG_DEFAULTS[CONFIG_CAPTURE_TEXT_CONTENT] = false;
|
|
18221
|
-
CONFIG_DEFAULTS[CONFIG_SCROLL_CAPTURE_ALL] = false;
|
|
18222
|
-
CONFIG_DEFAULTS[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
|
|
18223
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_CLICK] = true;
|
|
18224
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_INPUT] = true;
|
|
18225
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
|
|
18226
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_SCROLL] = true;
|
|
18227
|
-
CONFIG_DEFAULTS[CONFIG_TRACK_SUBMIT] = true;
|
|
18216
|
+
var CONFIG_DEFAULTS$1 = {};
|
|
18217
|
+
CONFIG_DEFAULTS$1[CONFIG_ALLOW_SELECTORS] = [];
|
|
18218
|
+
CONFIG_DEFAULTS$1[CONFIG_ALLOW_URL_REGEXES] = [];
|
|
18219
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_ATTRS] = [];
|
|
18220
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
|
|
18221
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_SELECTORS] = [];
|
|
18222
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_URL_REGEXES] = [];
|
|
18223
|
+
CONFIG_DEFAULTS$1[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
|
|
18224
|
+
CONFIG_DEFAULTS$1[CONFIG_CAPTURE_TEXT_CONTENT] = false;
|
|
18225
|
+
CONFIG_DEFAULTS$1[CONFIG_SCROLL_CAPTURE_ALL] = false;
|
|
18226
|
+
CONFIG_DEFAULTS$1[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
|
|
18227
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_CLICK] = true;
|
|
18228
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_INPUT] = true;
|
|
18229
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
|
|
18230
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_SCROLL] = true;
|
|
18231
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_SUBMIT] = true;
|
|
18228
18232
|
|
|
18229
18233
|
var DEFAULT_PROPS = {
|
|
18230
18234
|
'$mp_autocapture': true
|
|
@@ -18245,7 +18249,7 @@ var Autocapture = function(mp) {
|
|
|
18245
18249
|
|
|
18246
18250
|
Autocapture.prototype.init = function() {
|
|
18247
18251
|
if (!minDOMApisSupported()) {
|
|
18248
|
-
logger.critical('Autocapture unavailable: missing required DOM APIs');
|
|
18252
|
+
logger$1.critical('Autocapture unavailable: missing required DOM APIs');
|
|
18249
18253
|
return;
|
|
18250
18254
|
}
|
|
18251
18255
|
|
|
@@ -18262,10 +18266,10 @@ Autocapture.prototype.getFullConfig = function() {
|
|
|
18262
18266
|
// Autocapture is completely off
|
|
18263
18267
|
return {};
|
|
18264
18268
|
} else if (_.isObject(autocaptureConfig)) {
|
|
18265
|
-
return _.extend({}, CONFIG_DEFAULTS, autocaptureConfig);
|
|
18269
|
+
return _.extend({}, CONFIG_DEFAULTS$1, autocaptureConfig);
|
|
18266
18270
|
} else {
|
|
18267
18271
|
// Autocapture config is non-object truthy value, return default
|
|
18268
|
-
return CONFIG_DEFAULTS;
|
|
18272
|
+
return CONFIG_DEFAULTS$1;
|
|
18269
18273
|
}
|
|
18270
18274
|
};
|
|
18271
18275
|
|
|
@@ -18289,7 +18293,7 @@ Autocapture.prototype.currentUrlBlocked = function() {
|
|
|
18289
18293
|
break;
|
|
18290
18294
|
}
|
|
18291
18295
|
} catch (err) {
|
|
18292
|
-
logger.critical('Error while checking block URL regex: ' + allowRegex, err);
|
|
18296
|
+
logger$1.critical('Error while checking block URL regex: ' + allowRegex, err);
|
|
18293
18297
|
return true;
|
|
18294
18298
|
}
|
|
18295
18299
|
}
|
|
@@ -18310,7 +18314,7 @@ Autocapture.prototype.currentUrlBlocked = function() {
|
|
|
18310
18314
|
return true;
|
|
18311
18315
|
}
|
|
18312
18316
|
} catch (err) {
|
|
18313
|
-
logger.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
|
|
18317
|
+
logger$1.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
|
|
18314
18318
|
return true;
|
|
18315
18319
|
}
|
|
18316
18320
|
}
|
|
@@ -18339,7 +18343,8 @@ Autocapture.prototype.trackDomEvent = function(ev, mpEventName) {
|
|
|
18339
18343
|
blockElementCallback: this.getConfig(CONFIG_BLOCK_ELEMENT_CALLBACK),
|
|
18340
18344
|
blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
|
|
18341
18345
|
captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
|
|
18342
|
-
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT)
|
|
18346
|
+
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT),
|
|
18347
|
+
capturedForHeatMap: mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK) && this.mp.is_recording_heatmap_data(),
|
|
18343
18348
|
});
|
|
18344
18349
|
if (props) {
|
|
18345
18350
|
_.extend(props, DEFAULT_PROPS);
|
|
@@ -18350,13 +18355,13 @@ Autocapture.prototype.trackDomEvent = function(ev, mpEventName) {
|
|
|
18350
18355
|
Autocapture.prototype.initClickTracking = function() {
|
|
18351
18356
|
win.removeEventListener(EV_CLICK, this.listenerClick);
|
|
18352
18357
|
|
|
18353
|
-
if (!this.getConfig(CONFIG_TRACK_CLICK)) {
|
|
18358
|
+
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
|
|
18354
18359
|
return;
|
|
18355
18360
|
}
|
|
18356
|
-
logger.log('Initializing click tracking');
|
|
18361
|
+
logger$1.log('Initializing click tracking');
|
|
18357
18362
|
|
|
18358
18363
|
this.listenerClick = win.addEventListener(EV_CLICK, function(ev) {
|
|
18359
|
-
if (!this.getConfig(CONFIG_TRACK_CLICK)) {
|
|
18364
|
+
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
|
|
18360
18365
|
return;
|
|
18361
18366
|
}
|
|
18362
18367
|
this.trackDomEvent(ev, MP_EV_CLICK);
|
|
@@ -18369,7 +18374,7 @@ Autocapture.prototype.initInputTracking = function() {
|
|
|
18369
18374
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
18370
18375
|
return;
|
|
18371
18376
|
}
|
|
18372
|
-
logger.log('Initializing input tracking');
|
|
18377
|
+
logger$1.log('Initializing input tracking');
|
|
18373
18378
|
|
|
18374
18379
|
this.listenerChange = win.addEventListener(EV_CHANGE, function(ev) {
|
|
18375
18380
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
@@ -18387,7 +18392,7 @@ Autocapture.prototype.initPageviewTracking = function() {
|
|
|
18387
18392
|
if (!this.pageviewTrackingConfig()) {
|
|
18388
18393
|
return;
|
|
18389
18394
|
}
|
|
18390
|
-
logger.log('Initializing pageview tracking');
|
|
18395
|
+
logger$1.log('Initializing pageview tracking');
|
|
18391
18396
|
|
|
18392
18397
|
var previousTrackedUrl = '';
|
|
18393
18398
|
var tracked = false;
|
|
@@ -18442,7 +18447,7 @@ Autocapture.prototype.initPageviewTracking = function() {
|
|
|
18442
18447
|
}
|
|
18443
18448
|
if (didPathChange) {
|
|
18444
18449
|
this.lastScrollCheckpoint = 0;
|
|
18445
|
-
logger.log('Path change: re-initializing scroll depth checkpoints');
|
|
18450
|
+
logger$1.log('Path change: re-initializing scroll depth checkpoints');
|
|
18446
18451
|
}
|
|
18447
18452
|
}
|
|
18448
18453
|
}.bind(this)));
|
|
@@ -18454,7 +18459,7 @@ Autocapture.prototype.initScrollTracking = function() {
|
|
|
18454
18459
|
if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
|
|
18455
18460
|
return;
|
|
18456
18461
|
}
|
|
18457
|
-
logger.log('Initializing scroll tracking');
|
|
18462
|
+
logger$1.log('Initializing scroll tracking');
|
|
18458
18463
|
this.lastScrollCheckpoint = 0;
|
|
18459
18464
|
|
|
18460
18465
|
this.listenerScroll = win.addEventListener(EV_SCROLLEND, safewrap(function() {
|
|
@@ -18491,7 +18496,7 @@ Autocapture.prototype.initScrollTracking = function() {
|
|
|
18491
18496
|
}
|
|
18492
18497
|
}
|
|
18493
18498
|
} catch (err) {
|
|
18494
|
-
logger.critical('Error while calculating scroll percentage', err);
|
|
18499
|
+
logger$1.critical('Error while calculating scroll percentage', err);
|
|
18495
18500
|
}
|
|
18496
18501
|
if (shouldTrack) {
|
|
18497
18502
|
this.mp.track(MP_EV_SCROLL, props);
|
|
@@ -18505,7 +18510,7 @@ Autocapture.prototype.initSubmitTracking = function() {
|
|
|
18505
18510
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
18506
18511
|
return;
|
|
18507
18512
|
}
|
|
18508
|
-
logger.log('Initializing submit tracking');
|
|
18513
|
+
logger$1.log('Initializing submit tracking');
|
|
18509
18514
|
|
|
18510
18515
|
this.listenerSubmit = win.addEventListener(EV_SUBMIT, function(ev) {
|
|
18511
18516
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
@@ -18518,6 +18523,193 @@ Autocapture.prototype.initSubmitTracking = function() {
|
|
|
18518
18523
|
// TODO integrate error_reporter from mixpanel instance
|
|
18519
18524
|
safewrapClass(Autocapture);
|
|
18520
18525
|
|
|
18526
|
+
var fetch = win['fetch'];
|
|
18527
|
+
var logger = console_with_prefix('flags');
|
|
18528
|
+
|
|
18529
|
+
var FLAGS_CONFIG_KEY = 'flags';
|
|
18530
|
+
|
|
18531
|
+
var CONFIG_CONTEXT = 'context';
|
|
18532
|
+
var CONFIG_DEFAULTS = {};
|
|
18533
|
+
CONFIG_DEFAULTS[CONFIG_CONTEXT] = {};
|
|
18534
|
+
|
|
18535
|
+
/**
|
|
18536
|
+
* FeatureFlagManager: support for Mixpanel's feature flagging product
|
|
18537
|
+
* @constructor
|
|
18538
|
+
*/
|
|
18539
|
+
var FeatureFlagManager = function(initOptions) {
|
|
18540
|
+
this.getMpConfig = initOptions.getConfigFunc;
|
|
18541
|
+
this.getDistinctId = initOptions.getDistinctIdFunc;
|
|
18542
|
+
this.track = initOptions.trackingFunc;
|
|
18543
|
+
};
|
|
18544
|
+
|
|
18545
|
+
FeatureFlagManager.prototype.init = function() {
|
|
18546
|
+
if (!minApisSupported()) {
|
|
18547
|
+
logger.critical('Feature Flags unavailable: missing minimum required APIs');
|
|
18548
|
+
return;
|
|
18549
|
+
}
|
|
18550
|
+
|
|
18551
|
+
this.flags = null;
|
|
18552
|
+
this.fetchFlags();
|
|
18553
|
+
|
|
18554
|
+
this.trackedFeatures = new Set();
|
|
18555
|
+
};
|
|
18556
|
+
|
|
18557
|
+
FeatureFlagManager.prototype.getFullConfig = function() {
|
|
18558
|
+
var ffConfig = this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
18559
|
+
if (!ffConfig) {
|
|
18560
|
+
// flags are completely off
|
|
18561
|
+
return {};
|
|
18562
|
+
} else if (_.isObject(ffConfig)) {
|
|
18563
|
+
return _.extend({}, CONFIG_DEFAULTS, ffConfig);
|
|
18564
|
+
} else {
|
|
18565
|
+
// config is non-object truthy value, return default
|
|
18566
|
+
return CONFIG_DEFAULTS;
|
|
18567
|
+
}
|
|
18568
|
+
};
|
|
18569
|
+
|
|
18570
|
+
FeatureFlagManager.prototype.getConfig = function(key) {
|
|
18571
|
+
return this.getFullConfig()[key];
|
|
18572
|
+
};
|
|
18573
|
+
|
|
18574
|
+
FeatureFlagManager.prototype.isEnabled = function() {
|
|
18575
|
+
return !!this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
18576
|
+
};
|
|
18577
|
+
|
|
18578
|
+
FeatureFlagManager.prototype.areFeaturesReady = function() {
|
|
18579
|
+
if (!this.isEnabled()) {
|
|
18580
|
+
logger.error('Feature Flags not enabled');
|
|
18581
|
+
}
|
|
18582
|
+
return !!this.flags;
|
|
18583
|
+
};
|
|
18584
|
+
|
|
18585
|
+
FeatureFlagManager.prototype.fetchFlags = function() {
|
|
18586
|
+
if (!this.isEnabled()) {
|
|
18587
|
+
return;
|
|
18588
|
+
}
|
|
18589
|
+
|
|
18590
|
+
var distinctId = this.getDistinctId();
|
|
18591
|
+
logger.log('Fetching flags for distinct ID: ' + distinctId);
|
|
18592
|
+
var reqParams = {
|
|
18593
|
+
'context': _.extend({'distinct_id': distinctId}, this.getConfig(CONFIG_CONTEXT))
|
|
18594
|
+
};
|
|
18595
|
+
this.fetchPromise = win['fetch'](this.getMpConfig('api_host') + '/' + this.getMpConfig('api_routes')['flags'], {
|
|
18596
|
+
'method': 'POST',
|
|
18597
|
+
'headers': {
|
|
18598
|
+
'Authorization': 'Basic ' + btoa(this.getMpConfig('token') + ':'),
|
|
18599
|
+
'Content-Type': 'application/octet-stream'
|
|
18600
|
+
},
|
|
18601
|
+
'body': JSON.stringify(reqParams)
|
|
18602
|
+
}).then(function(response) {
|
|
18603
|
+
return response.json().then(function(responseBody) {
|
|
18604
|
+
var responseFlags = responseBody['flags'];
|
|
18605
|
+
if (!responseFlags) {
|
|
18606
|
+
throw new Error('No flags in API response');
|
|
18607
|
+
}
|
|
18608
|
+
var flags = new Map();
|
|
18609
|
+
_.each(responseFlags, function(data, key) {
|
|
18610
|
+
flags.set(key, {
|
|
18611
|
+
'key': data['variant_key'],
|
|
18612
|
+
'data': data['variant_value']
|
|
18613
|
+
});
|
|
18614
|
+
});
|
|
18615
|
+
this.flags = flags;
|
|
18616
|
+
}.bind(this)).catch(function(error) {
|
|
18617
|
+
logger.error(error);
|
|
18618
|
+
});
|
|
18619
|
+
}.bind(this)).catch(function() {});
|
|
18620
|
+
};
|
|
18621
|
+
|
|
18622
|
+
FeatureFlagManager.prototype.getFeature = function(featureName, fallback) {
|
|
18623
|
+
if (!this.fetchPromise) {
|
|
18624
|
+
return new Promise(function(resolve) {
|
|
18625
|
+
logger.critical('Feature Flags not initialized');
|
|
18626
|
+
resolve(fallback);
|
|
18627
|
+
});
|
|
18628
|
+
}
|
|
18629
|
+
|
|
18630
|
+
return this.fetchPromise.then(function() {
|
|
18631
|
+
return this.getFeatureSync(featureName, fallback);
|
|
18632
|
+
}.bind(this)).catch(function(error) {
|
|
18633
|
+
logger.error(error);
|
|
18634
|
+
return fallback;
|
|
18635
|
+
});
|
|
18636
|
+
};
|
|
18637
|
+
|
|
18638
|
+
FeatureFlagManager.prototype.getFeatureSync = function(featureName, fallback) {
|
|
18639
|
+
if (!this.areFeaturesReady()) {
|
|
18640
|
+
logger.log('Flags not loaded yet');
|
|
18641
|
+
return fallback;
|
|
18642
|
+
}
|
|
18643
|
+
var feature = this.flags.get(featureName);
|
|
18644
|
+
if (!feature) {
|
|
18645
|
+
logger.log('No flag found: "' + featureName + '"');
|
|
18646
|
+
return fallback;
|
|
18647
|
+
}
|
|
18648
|
+
this.trackFeatureCheck(featureName, feature);
|
|
18649
|
+
return feature;
|
|
18650
|
+
};
|
|
18651
|
+
|
|
18652
|
+
FeatureFlagManager.prototype.getFeatureData = function(featureName, fallbackValue) {
|
|
18653
|
+
return this.getFeature(featureName, {'data': fallbackValue}).then(function(feature) {
|
|
18654
|
+
return feature['data'];
|
|
18655
|
+
}).catch(function(error) {
|
|
18656
|
+
logger.error(error);
|
|
18657
|
+
return fallbackValue;
|
|
18658
|
+
});
|
|
18659
|
+
};
|
|
18660
|
+
|
|
18661
|
+
FeatureFlagManager.prototype.getFeatureDataSync = function(featureName, fallbackValue) {
|
|
18662
|
+
return this.getFeatureSync(featureName, {'data': fallbackValue})['data'];
|
|
18663
|
+
};
|
|
18664
|
+
|
|
18665
|
+
FeatureFlagManager.prototype.isFeatureEnabled = function(featureName, fallbackValue) {
|
|
18666
|
+
return this.getFeatureData(featureName).then(function() {
|
|
18667
|
+
return this.isFeatureEnabledSync(featureName, fallbackValue);
|
|
18668
|
+
}.bind(this)).catch(function(error) {
|
|
18669
|
+
logger.error(error);
|
|
18670
|
+
return fallbackValue;
|
|
18671
|
+
});
|
|
18672
|
+
};
|
|
18673
|
+
|
|
18674
|
+
FeatureFlagManager.prototype.isFeatureEnabledSync = function(featureName, fallbackValue) {
|
|
18675
|
+
fallbackValue = fallbackValue || false;
|
|
18676
|
+
var val = this.getFeatureDataSync(featureName, fallbackValue);
|
|
18677
|
+
if (val !== true && val !== false) {
|
|
18678
|
+
logger.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
|
|
18679
|
+
val = fallbackValue;
|
|
18680
|
+
}
|
|
18681
|
+
return val;
|
|
18682
|
+
};
|
|
18683
|
+
|
|
18684
|
+
FeatureFlagManager.prototype.trackFeatureCheck = function(featureName, feature) {
|
|
18685
|
+
if (this.trackedFeatures.has(featureName)) {
|
|
18686
|
+
return;
|
|
18687
|
+
}
|
|
18688
|
+
this.trackedFeatures.add(featureName);
|
|
18689
|
+
this.track('$experiment_started', {
|
|
18690
|
+
'Experiment name': featureName,
|
|
18691
|
+
'Variant name': feature['key'],
|
|
18692
|
+
'$experiment_type': 'feature_flag'
|
|
18693
|
+
});
|
|
18694
|
+
};
|
|
18695
|
+
|
|
18696
|
+
function minApisSupported() {
|
|
18697
|
+
return !!fetch &&
|
|
18698
|
+
typeof Promise !== 'undefined' &&
|
|
18699
|
+
typeof Map !== 'undefined' &&
|
|
18700
|
+
typeof Set !== 'undefined';
|
|
18701
|
+
}
|
|
18702
|
+
|
|
18703
|
+
safewrapClass(FeatureFlagManager);
|
|
18704
|
+
|
|
18705
|
+
FeatureFlagManager.prototype['are_features_ready'] = FeatureFlagManager.prototype.areFeaturesReady;
|
|
18706
|
+
FeatureFlagManager.prototype['get_feature'] = FeatureFlagManager.prototype.getFeature;
|
|
18707
|
+
FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
|
|
18708
|
+
FeatureFlagManager.prototype['get_feature_data_sync'] = FeatureFlagManager.prototype.getFeatureDataSync;
|
|
18709
|
+
FeatureFlagManager.prototype['get_feature_sync'] = FeatureFlagManager.prototype.getFeatureSync;
|
|
18710
|
+
FeatureFlagManager.prototype['is_feature_enabled'] = FeatureFlagManager.prototype.isFeatureEnabled;
|
|
18711
|
+
FeatureFlagManager.prototype['is_feature_enabled_sync'] = FeatureFlagManager.prototype.isFeatureEnabledSync;
|
|
18712
|
+
|
|
18521
18713
|
/* eslint camelcase: "off" */
|
|
18522
18714
|
|
|
18523
18715
|
|
|
@@ -19922,10 +20114,11 @@ if (navigator['sendBeacon']) {
|
|
|
19922
20114
|
}
|
|
19923
20115
|
|
|
19924
20116
|
var DEFAULT_API_ROUTES = {
|
|
19925
|
-
'track':
|
|
20117
|
+
'track': 'track/',
|
|
19926
20118
|
'engage': 'engage/',
|
|
19927
20119
|
'groups': 'groups/',
|
|
19928
|
-
'record': 'record/'
|
|
20120
|
+
'record': 'record/',
|
|
20121
|
+
'flags': 'flags/'
|
|
19929
20122
|
};
|
|
19930
20123
|
|
|
19931
20124
|
/*
|
|
@@ -19943,6 +20136,7 @@ var DEFAULT_CONFIG = {
|
|
|
19943
20136
|
'cross_site_cookie': false,
|
|
19944
20137
|
'cross_subdomain_cookie': true,
|
|
19945
20138
|
'error_reporter': NOOP_FUNC,
|
|
20139
|
+
'flags': false,
|
|
19946
20140
|
'persistence': 'cookie',
|
|
19947
20141
|
'persistence_name': '',
|
|
19948
20142
|
'cookie_domain': '',
|
|
@@ -19983,6 +20177,7 @@ var DEFAULT_CONFIG = {
|
|
|
19983
20177
|
'record_block_selector': 'img, video',
|
|
19984
20178
|
'record_canvas': false,
|
|
19985
20179
|
'record_collect_fonts': false,
|
|
20180
|
+
'record_heatmap_data': false,
|
|
19986
20181
|
'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
|
|
19987
20182
|
'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'),
|
|
19988
20183
|
'record_mask_text_selector': '*',
|
|
@@ -20198,6 +20393,14 @@ MixpanelLib.prototype._init = function(token, config, name) {
|
|
|
20198
20393
|
}, '');
|
|
20199
20394
|
}
|
|
20200
20395
|
|
|
20396
|
+
this.flags = new FeatureFlagManager({
|
|
20397
|
+
getConfigFunc: _.bind(this.get_config, this),
|
|
20398
|
+
getDistinctIdFunc: _.bind(this.get_distinct_id, this),
|
|
20399
|
+
trackingFunc: _.bind(this.track, this)
|
|
20400
|
+
});
|
|
20401
|
+
this.flags.init();
|
|
20402
|
+
this['flags'] = this.flags;
|
|
20403
|
+
|
|
20201
20404
|
this.autocapture = new Autocapture(this);
|
|
20202
20405
|
this.autocapture.init();
|
|
20203
20406
|
|
|
@@ -20323,6 +20526,10 @@ MixpanelLib.prototype.resume_session_recording = function () {
|
|
|
20323
20526
|
}
|
|
20324
20527
|
};
|
|
20325
20528
|
|
|
20529
|
+
MixpanelLib.prototype.is_recording_heatmap_data = function () {
|
|
20530
|
+
return this._get_session_replay_id() && this.get_config('record_heatmap_data');
|
|
20531
|
+
};
|
|
20532
|
+
|
|
20326
20533
|
MixpanelLib.prototype.get_session_recording_properties = function () {
|
|
20327
20534
|
var props = {};
|
|
20328
20535
|
var replay_id = this._get_session_replay_id();
|
|
@@ -21404,6 +21611,11 @@ MixpanelLib.prototype.identify = function(
|
|
|
21404
21611
|
'$anon_distinct_id': previous_distinct_id
|
|
21405
21612
|
}, {skip_hooks: true});
|
|
21406
21613
|
}
|
|
21614
|
+
|
|
21615
|
+
// check feature flags again if distinct id has changed
|
|
21616
|
+
if (new_distinct_id !== previous_distinct_id) {
|
|
21617
|
+
this.flags.fetchFlags();
|
|
21618
|
+
}
|
|
21407
21619
|
};
|
|
21408
21620
|
|
|
21409
21621
|
/**
|
|
@@ -21678,7 +21890,7 @@ MixpanelLib.prototype.set_config = function(config) {
|
|
|
21678
21890
|
}
|
|
21679
21891
|
Config.DEBUG = Config.DEBUG || this.get_config('debug');
|
|
21680
21892
|
|
|
21681
|
-
if ('autocapture' in config && this.autocapture) {
|
|
21893
|
+
if (('autocapture' in config || 'record_heatmap_data' in config) && this.autocapture) {
|
|
21682
21894
|
this.autocapture.init();
|
|
21683
21895
|
}
|
|
21684
21896
|
}
|