mixpanel-browser 2.59.0 → 2.60.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 +5 -1
- package/README.md +1 -1
- package/dist/mixpanel-core.cjs.js +215 -49
- 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 +215 -49
- package/dist/mixpanel.amd.js +215 -49
- package/dist/mixpanel.cjs.js +215 -49
- package/dist/mixpanel.globals.js +215 -49
- package/dist/mixpanel.min.js +138 -134
- package/dist/mixpanel.module.js +215 -49
- package/dist/mixpanel.umd.js +215 -49
- package/package.json +1 -1
- package/src/autocapture/index.js +80 -9
- package/src/autocapture/utils.js +129 -38
- package/src/config.js +1 -1
- package/src/mixpanel-persistence.js +6 -2
package/dist/mixpanel.globals.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
var Config = {
|
|
5
5
|
DEBUG: false,
|
|
6
|
-
LIB_VERSION: '2.
|
|
6
|
+
LIB_VERSION: '2.60.0'
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
// since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
|
|
@@ -2197,7 +2197,7 @@
|
|
|
2197
2197
|
}
|
|
2198
2198
|
}
|
|
2199
2199
|
|
|
2200
|
-
function getPropertiesFromElement(el) {
|
|
2200
|
+
function getPropertiesFromElement(el, ev, blockAttrsSet, extraAttrs, allowElementCallback, allowSelectors) {
|
|
2201
2201
|
var props = {
|
|
2202
2202
|
'$classes': getClassName(el).split(' '),
|
|
2203
2203
|
'$tag_name': el.tagName.toLowerCase()
|
|
@@ -2207,9 +2207,9 @@
|
|
|
2207
2207
|
props['$id'] = elId;
|
|
2208
2208
|
}
|
|
2209
2209
|
|
|
2210
|
-
if (
|
|
2211
|
-
_.each(TRACKED_ATTRS, function(attr) {
|
|
2212
|
-
if (el.hasAttribute(attr)) {
|
|
2210
|
+
if (shouldTrackElementDetails(el, ev, allowElementCallback, allowSelectors)) {
|
|
2211
|
+
_.each(TRACKED_ATTRS.concat(extraAttrs), function(attr) {
|
|
2212
|
+
if (el.hasAttribute(attr) && !blockAttrsSet[attr]) {
|
|
2213
2213
|
var attrVal = el.getAttribute(attr);
|
|
2214
2214
|
if (shouldTrackValue(attrVal)) {
|
|
2215
2215
|
props['$attr-' + attr] = attrVal;
|
|
@@ -2233,8 +2233,21 @@
|
|
|
2233
2233
|
return props;
|
|
2234
2234
|
}
|
|
2235
2235
|
|
|
2236
|
-
function getPropsForDOMEvent(ev,
|
|
2237
|
-
|
|
2236
|
+
function getPropsForDOMEvent(ev, config) {
|
|
2237
|
+
var allowElementCallback = config.allowElementCallback;
|
|
2238
|
+
var allowSelectors = config.allowSelectors || [];
|
|
2239
|
+
var blockAttrs = config.blockAttrs || [];
|
|
2240
|
+
var blockElementCallback = config.blockElementCallback;
|
|
2241
|
+
var blockSelectors = config.blockSelectors || [];
|
|
2242
|
+
var captureTextContent = config.captureTextContent || false;
|
|
2243
|
+
var captureExtraAttrs = config.captureExtraAttrs || [];
|
|
2244
|
+
|
|
2245
|
+
// convert array to set every time, as the config may have changed
|
|
2246
|
+
var blockAttrsSet = {};
|
|
2247
|
+
_.each(blockAttrs, function(attr) {
|
|
2248
|
+
blockAttrsSet[attr] = true;
|
|
2249
|
+
});
|
|
2250
|
+
|
|
2238
2251
|
var props = null;
|
|
2239
2252
|
|
|
2240
2253
|
var target = typeof ev.target === 'undefined' ? ev.srcElement : ev.target;
|
|
@@ -2242,7 +2255,11 @@
|
|
|
2242
2255
|
target = target.parentNode;
|
|
2243
2256
|
}
|
|
2244
2257
|
|
|
2245
|
-
if (
|
|
2258
|
+
if (
|
|
2259
|
+
shouldTrackDomEvent(target, ev) &&
|
|
2260
|
+
isElementAllowed(target, ev, allowElementCallback, allowSelectors) &&
|
|
2261
|
+
!isElementBlocked(target, ev, blockElementCallback, blockSelectors)
|
|
2262
|
+
) {
|
|
2246
2263
|
var targetElementList = [target];
|
|
2247
2264
|
var curEl = target;
|
|
2248
2265
|
while (curEl.parentNode && !isTag(curEl, 'body')) {
|
|
@@ -2253,37 +2270,20 @@
|
|
|
2253
2270
|
var elementsJson = [];
|
|
2254
2271
|
var href, explicitNoTrack = false;
|
|
2255
2272
|
_.each(targetElementList, function(el) {
|
|
2256
|
-
var
|
|
2273
|
+
var shouldTrackDetails = shouldTrackElementDetails(el, ev, allowElementCallback, allowSelectors);
|
|
2257
2274
|
|
|
2258
2275
|
// if the element or a parent element is an anchor tag
|
|
2259
2276
|
// include the href as a property
|
|
2260
|
-
if (el.tagName.toLowerCase() === 'a') {
|
|
2277
|
+
if (!blockAttrsSet['href'] && el.tagName.toLowerCase() === 'a') {
|
|
2261
2278
|
href = el.getAttribute('href');
|
|
2262
|
-
href =
|
|
2279
|
+
href = shouldTrackDetails && shouldTrackValue(href) && href;
|
|
2263
2280
|
}
|
|
2264
2281
|
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
_.each(OPT_OUT_CLASSES, function(cls) {
|
|
2268
|
-
if (classes[cls]) {
|
|
2269
|
-
explicitNoTrack = true;
|
|
2270
|
-
}
|
|
2271
|
-
});
|
|
2272
|
-
|
|
2273
|
-
if (!explicitNoTrack) {
|
|
2274
|
-
// programmatically prevent tracking of elements that match CSS selectors
|
|
2275
|
-
_.each(blockSelectors, function(sel) {
|
|
2276
|
-
try {
|
|
2277
|
-
if (el['matches'](sel)) {
|
|
2278
|
-
explicitNoTrack = true;
|
|
2279
|
-
}
|
|
2280
|
-
} catch (err) {
|
|
2281
|
-
logger$3.critical('Error while checking selector: ' + sel, err);
|
|
2282
|
-
}
|
|
2283
|
-
});
|
|
2282
|
+
if (isElementBlocked(el, ev, blockElementCallback, blockSelectors)) {
|
|
2283
|
+
explicitNoTrack = true;
|
|
2284
2284
|
}
|
|
2285
2285
|
|
|
2286
|
-
elementsJson.push(getPropertiesFromElement(el));
|
|
2286
|
+
elementsJson.push(getPropertiesFromElement(el, ev, blockAttrsSet, captureExtraAttrs, allowElementCallback, allowSelectors));
|
|
2287
2287
|
}, this);
|
|
2288
2288
|
|
|
2289
2289
|
if (!explicitNoTrack) {
|
|
@@ -2297,9 +2297,17 @@
|
|
|
2297
2297
|
'$viewportHeight': Math.max(docElement['clientHeight'], win['innerHeight'] || 0),
|
|
2298
2298
|
'$viewportWidth': Math.max(docElement['clientWidth'], win['innerWidth'] || 0)
|
|
2299
2299
|
};
|
|
2300
|
+
_.each(captureExtraAttrs, function(attr) {
|
|
2301
|
+
if (!blockAttrsSet[attr] && target.hasAttribute(attr)) {
|
|
2302
|
+
var attrVal = target.getAttribute(attr);
|
|
2303
|
+
if (shouldTrackValue(attrVal)) {
|
|
2304
|
+
props['$el_attr__' + attr] = attrVal;
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
});
|
|
2300
2308
|
|
|
2301
2309
|
if (captureTextContent) {
|
|
2302
|
-
elementText = getSafeText(target);
|
|
2310
|
+
elementText = getSafeText(target, ev, allowElementCallback, allowSelectors);
|
|
2303
2311
|
if (elementText && elementText.length) {
|
|
2304
2312
|
props['$el_text'] = elementText;
|
|
2305
2313
|
}
|
|
@@ -2315,14 +2323,22 @@
|
|
|
2315
2323
|
}
|
|
2316
2324
|
// prioritize text content from "real" click target if different from original target
|
|
2317
2325
|
if (captureTextContent) {
|
|
2318
|
-
var elementText = getSafeText(target);
|
|
2326
|
+
var elementText = getSafeText(target, ev, allowElementCallback, allowSelectors);
|
|
2319
2327
|
if (elementText && elementText.length) {
|
|
2320
2328
|
props['$el_text'] = elementText;
|
|
2321
2329
|
}
|
|
2322
2330
|
}
|
|
2323
2331
|
|
|
2324
2332
|
if (target) {
|
|
2325
|
-
|
|
2333
|
+
// target may have been recalculated; check allowlists and blocklists again
|
|
2334
|
+
if (
|
|
2335
|
+
!isElementAllowed(target, ev, allowElementCallback, allowSelectors) ||
|
|
2336
|
+
isElementBlocked(target, ev, blockElementCallback, blockSelectors)
|
|
2337
|
+
) {
|
|
2338
|
+
return null;
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
var targetProps = getPropertiesFromElement(target, ev, blockAttrsSet, captureExtraAttrs, allowElementCallback, allowSelectors);
|
|
2326
2342
|
props['$target'] = targetProps;
|
|
2327
2343
|
// pull up more props onto main event props
|
|
2328
2344
|
props['$el_classes'] = targetProps['$classes'];
|
|
@@ -2338,19 +2354,20 @@
|
|
|
2338
2354
|
}
|
|
2339
2355
|
|
|
2340
2356
|
|
|
2341
|
-
|
|
2357
|
+
/**
|
|
2342
2358
|
* Get the direct text content of an element, protecting against sensitive data collection.
|
|
2343
2359
|
* Concats textContent of each of the element's text node children; this avoids potential
|
|
2344
2360
|
* collection of sensitive data that could happen if we used element.textContent and the
|
|
2345
2361
|
* element had sensitive child elements, since element.textContent includes child content.
|
|
2346
2362
|
* Scrubs values that look like they could be sensitive (i.e. cc or ssn number).
|
|
2347
2363
|
* @param {Element} el - element to get the text of
|
|
2364
|
+
* @param {Array<string>} allowSelectors - CSS selectors for elements that should be included
|
|
2348
2365
|
* @returns {string} the element's direct text content
|
|
2349
2366
|
*/
|
|
2350
|
-
function getSafeText(el) {
|
|
2367
|
+
function getSafeText(el, ev, allowElementCallback, allowSelectors) {
|
|
2351
2368
|
var elText = '';
|
|
2352
2369
|
|
|
2353
|
-
if (
|
|
2370
|
+
if (shouldTrackElementDetails(el, ev, allowElementCallback, allowSelectors) && el.childNodes && el.childNodes.length) {
|
|
2354
2371
|
_.each(el.childNodes, function(child) {
|
|
2355
2372
|
if (isTextNode(child) && child.textContent) {
|
|
2356
2373
|
elText += _.trim(child.textContent)
|
|
@@ -2389,6 +2406,75 @@
|
|
|
2389
2406
|
return target;
|
|
2390
2407
|
}
|
|
2391
2408
|
|
|
2409
|
+
function isElementAllowed(el, ev, allowElementCallback, allowSelectors) {
|
|
2410
|
+
if (allowElementCallback) {
|
|
2411
|
+
try {
|
|
2412
|
+
if (!allowElementCallback(el, ev)) {
|
|
2413
|
+
return false;
|
|
2414
|
+
}
|
|
2415
|
+
} catch (err) {
|
|
2416
|
+
logger$3.critical('Error while checking element in allowElementCallback', err);
|
|
2417
|
+
return false;
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
|
|
2421
|
+
if (!allowSelectors.length) {
|
|
2422
|
+
// no allowlist; all elements are fair game
|
|
2423
|
+
return true;
|
|
2424
|
+
}
|
|
2425
|
+
|
|
2426
|
+
for (var i = 0; i < allowSelectors.length; i++) {
|
|
2427
|
+
var sel = allowSelectors[i];
|
|
2428
|
+
try {
|
|
2429
|
+
if (el['matches'](sel)) {
|
|
2430
|
+
return true;
|
|
2431
|
+
}
|
|
2432
|
+
} catch (err) {
|
|
2433
|
+
logger$3.critical('Error while checking selector: ' + sel, err);
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
return false;
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
function isElementBlocked(el, ev, blockElementCallback, blockSelectors) {
|
|
2440
|
+
var i;
|
|
2441
|
+
|
|
2442
|
+
if (blockElementCallback) {
|
|
2443
|
+
try {
|
|
2444
|
+
if (blockElementCallback(el, ev)) {
|
|
2445
|
+
return true;
|
|
2446
|
+
}
|
|
2447
|
+
} catch (err) {
|
|
2448
|
+
logger$3.critical('Error while checking element in blockElementCallback', err);
|
|
2449
|
+
return true;
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
if (blockSelectors && blockSelectors.length) {
|
|
2454
|
+
// programmatically prevent tracking of elements that match CSS selectors
|
|
2455
|
+
for (i = 0; i < blockSelectors.length; i++) {
|
|
2456
|
+
var sel = blockSelectors[i];
|
|
2457
|
+
try {
|
|
2458
|
+
if (el['matches'](sel)) {
|
|
2459
|
+
return true;
|
|
2460
|
+
}
|
|
2461
|
+
} catch (err) {
|
|
2462
|
+
logger$3.critical('Error while checking selector: ' + sel, err);
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
// allow users to programmatically prevent tracking of elements by adding default classes such as 'mp-no-track'
|
|
2468
|
+
var classes = getClasses(el);
|
|
2469
|
+
for (i = 0; i < OPT_OUT_CLASSES.length; i++) {
|
|
2470
|
+
if (classes[OPT_OUT_CLASSES[i]]) {
|
|
2471
|
+
return true;
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
|
|
2475
|
+
return false;
|
|
2476
|
+
}
|
|
2477
|
+
|
|
2392
2478
|
/*
|
|
2393
2479
|
* Check whether a DOM node has nodeType Node.ELEMENT_NODE
|
|
2394
2480
|
* @param {Node} node - node to check
|
|
@@ -2463,11 +2549,16 @@
|
|
|
2463
2549
|
* Check whether a DOM element should be "tracked" or if it may contain sensitive data
|
|
2464
2550
|
* using a variety of heuristics.
|
|
2465
2551
|
* @param {Element} el - element to check
|
|
2552
|
+
* @param {Array<string>} allowSelectors - CSS selectors for elements that should be included
|
|
2466
2553
|
* @returns {boolean} whether the element should be tracked
|
|
2467
2554
|
*/
|
|
2468
|
-
function
|
|
2555
|
+
function shouldTrackElementDetails(el, ev, allowElementCallback, allowSelectors) {
|
|
2469
2556
|
var i;
|
|
2470
2557
|
|
|
2558
|
+
if (!isElementAllowed(el, ev, allowElementCallback, allowSelectors)) {
|
|
2559
|
+
return false;
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2471
2562
|
for (var curEl = el; curEl.parentNode && !isTag(curEl, 'body'); curEl = curEl.parentNode) {
|
|
2472
2563
|
var classes = getClasses(curEl);
|
|
2473
2564
|
for (i = 0; i < SENSITIVE_DATA_CLASSES.length; i++) {
|
|
@@ -2557,9 +2648,17 @@
|
|
|
2557
2648
|
var PAGEVIEW_OPTION_URL_WITH_PATH_AND_QUERY_STRING = 'url-with-path-and-query-string';
|
|
2558
2649
|
var PAGEVIEW_OPTION_URL_WITH_PATH = 'url-with-path';
|
|
2559
2650
|
|
|
2651
|
+
var CONFIG_ALLOW_ELEMENT_CALLBACK = 'allow_element_callback';
|
|
2652
|
+
var CONFIG_ALLOW_SELECTORS = 'allow_selectors';
|
|
2653
|
+
var CONFIG_ALLOW_URL_REGEXES = 'allow_url_regexes';
|
|
2654
|
+
var CONFIG_BLOCK_ATTRS = 'block_attrs';
|
|
2655
|
+
var CONFIG_BLOCK_ELEMENT_CALLBACK = 'block_element_callback';
|
|
2560
2656
|
var CONFIG_BLOCK_SELECTORS = 'block_selectors';
|
|
2561
2657
|
var CONFIG_BLOCK_URL_REGEXES = 'block_url_regexes';
|
|
2658
|
+
var CONFIG_CAPTURE_EXTRA_ATTRS = 'capture_extra_attrs';
|
|
2562
2659
|
var CONFIG_CAPTURE_TEXT_CONTENT = 'capture_text_content';
|
|
2660
|
+
var CONFIG_SCROLL_CAPTURE_ALL = 'scroll_capture_all';
|
|
2661
|
+
var CONFIG_SCROLL_CHECKPOINTS = 'scroll_depth_percent_checkpoints';
|
|
2563
2662
|
var CONFIG_TRACK_CLICK = 'click';
|
|
2564
2663
|
var CONFIG_TRACK_INPUT = 'input';
|
|
2565
2664
|
var CONFIG_TRACK_PAGEVIEW = 'pageview';
|
|
@@ -2567,7 +2666,16 @@
|
|
|
2567
2666
|
var CONFIG_TRACK_SUBMIT = 'submit';
|
|
2568
2667
|
|
|
2569
2668
|
var CONFIG_DEFAULTS = {};
|
|
2669
|
+
CONFIG_DEFAULTS[CONFIG_ALLOW_SELECTORS] = [];
|
|
2670
|
+
CONFIG_DEFAULTS[CONFIG_ALLOW_URL_REGEXES] = [];
|
|
2671
|
+
CONFIG_DEFAULTS[CONFIG_BLOCK_ATTRS] = [];
|
|
2672
|
+
CONFIG_DEFAULTS[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
|
|
2673
|
+
CONFIG_DEFAULTS[CONFIG_BLOCK_SELECTORS] = [];
|
|
2674
|
+
CONFIG_DEFAULTS[CONFIG_BLOCK_URL_REGEXES] = [];
|
|
2675
|
+
CONFIG_DEFAULTS[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
|
|
2570
2676
|
CONFIG_DEFAULTS[CONFIG_CAPTURE_TEXT_CONTENT] = false;
|
|
2677
|
+
CONFIG_DEFAULTS[CONFIG_SCROLL_CAPTURE_ALL] = false;
|
|
2678
|
+
CONFIG_DEFAULTS[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
|
|
2571
2679
|
CONFIG_DEFAULTS[CONFIG_TRACK_CLICK] = true;
|
|
2572
2680
|
CONFIG_DEFAULTS[CONFIG_TRACK_INPUT] = true;
|
|
2573
2681
|
CONFIG_DEFAULTS[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
|
|
@@ -2622,13 +2730,37 @@
|
|
|
2622
2730
|
};
|
|
2623
2731
|
|
|
2624
2732
|
Autocapture.prototype.currentUrlBlocked = function() {
|
|
2733
|
+
var i;
|
|
2734
|
+
var currentUrl = _.info.currentUrl();
|
|
2735
|
+
|
|
2736
|
+
var allowUrlRegexes = this.getConfig(CONFIG_ALLOW_URL_REGEXES) || [];
|
|
2737
|
+
if (allowUrlRegexes.length) {
|
|
2738
|
+
// we're using an allowlist, only track if current URL matches
|
|
2739
|
+
var allowed = false;
|
|
2740
|
+
for (i = 0; i < allowUrlRegexes.length; i++) {
|
|
2741
|
+
var allowRegex = allowUrlRegexes[i];
|
|
2742
|
+
try {
|
|
2743
|
+
if (currentUrl.match(allowRegex)) {
|
|
2744
|
+
allowed = true;
|
|
2745
|
+
break;
|
|
2746
|
+
}
|
|
2747
|
+
} catch (err) {
|
|
2748
|
+
logger$3.critical('Error while checking block URL regex: ' + allowRegex, err);
|
|
2749
|
+
return true;
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
if (!allowed) {
|
|
2753
|
+
// wasn't allowed by any regex
|
|
2754
|
+
return true;
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
|
|
2625
2758
|
var blockUrlRegexes = this.getConfig(CONFIG_BLOCK_URL_REGEXES) || [];
|
|
2626
2759
|
if (!blockUrlRegexes || !blockUrlRegexes.length) {
|
|
2627
2760
|
return false;
|
|
2628
2761
|
}
|
|
2629
2762
|
|
|
2630
|
-
|
|
2631
|
-
for (var i = 0; i < blockUrlRegexes.length; i++) {
|
|
2763
|
+
for (i = 0; i < blockUrlRegexes.length; i++) {
|
|
2632
2764
|
try {
|
|
2633
2765
|
if (currentUrl.match(blockUrlRegexes[i])) {
|
|
2634
2766
|
return true;
|
|
@@ -2656,11 +2788,15 @@
|
|
|
2656
2788
|
return;
|
|
2657
2789
|
}
|
|
2658
2790
|
|
|
2659
|
-
var props = getPropsForDOMEvent(
|
|
2660
|
-
|
|
2661
|
-
this.getConfig(
|
|
2662
|
-
this.getConfig(
|
|
2663
|
-
|
|
2791
|
+
var props = getPropsForDOMEvent(ev, {
|
|
2792
|
+
allowElementCallback: this.getConfig(CONFIG_ALLOW_ELEMENT_CALLBACK),
|
|
2793
|
+
allowSelectors: this.getConfig(CONFIG_ALLOW_SELECTORS),
|
|
2794
|
+
blockAttrs: this.getConfig(CONFIG_BLOCK_ATTRS),
|
|
2795
|
+
blockElementCallback: this.getConfig(CONFIG_BLOCK_ELEMENT_CALLBACK),
|
|
2796
|
+
blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
|
|
2797
|
+
captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
|
|
2798
|
+
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT)
|
|
2799
|
+
});
|
|
2664
2800
|
if (props) {
|
|
2665
2801
|
_.extend(props, DEFAULT_PROPS);
|
|
2666
2802
|
this.mp.track(mpEventName, props);
|
|
@@ -2745,13 +2881,14 @@
|
|
|
2745
2881
|
|
|
2746
2882
|
var currentUrl = _.info.currentUrl();
|
|
2747
2883
|
var shouldTrack = false;
|
|
2884
|
+
var didPathChange = currentUrl.split('#')[0].split('?')[0] !== previousTrackedUrl.split('#')[0].split('?')[0];
|
|
2748
2885
|
var trackPageviewOption = this.pageviewTrackingConfig();
|
|
2749
2886
|
if (trackPageviewOption === PAGEVIEW_OPTION_FULL_URL) {
|
|
2750
2887
|
shouldTrack = currentUrl !== previousTrackedUrl;
|
|
2751
2888
|
} else if (trackPageviewOption === PAGEVIEW_OPTION_URL_WITH_PATH_AND_QUERY_STRING) {
|
|
2752
2889
|
shouldTrack = currentUrl.split('#')[0] !== previousTrackedUrl.split('#')[0];
|
|
2753
2890
|
} else if (trackPageviewOption === PAGEVIEW_OPTION_URL_WITH_PATH) {
|
|
2754
|
-
shouldTrack =
|
|
2891
|
+
shouldTrack = didPathChange;
|
|
2755
2892
|
}
|
|
2756
2893
|
|
|
2757
2894
|
if (shouldTrack) {
|
|
@@ -2759,6 +2896,10 @@
|
|
|
2759
2896
|
if (tracked) {
|
|
2760
2897
|
previousTrackedUrl = currentUrl;
|
|
2761
2898
|
}
|
|
2899
|
+
if (didPathChange) {
|
|
2900
|
+
this.lastScrollCheckpoint = 0;
|
|
2901
|
+
logger$3.log('Path change: re-initializing scroll depth checkpoints');
|
|
2902
|
+
}
|
|
2762
2903
|
}
|
|
2763
2904
|
}.bind(this)));
|
|
2764
2905
|
};
|
|
@@ -2770,6 +2911,7 @@
|
|
|
2770
2911
|
return;
|
|
2771
2912
|
}
|
|
2772
2913
|
logger$3.log('Initializing scroll tracking');
|
|
2914
|
+
this.lastScrollCheckpoint = 0;
|
|
2773
2915
|
|
|
2774
2916
|
this.listenerScroll = win.addEventListener(EV_SCROLLEND, safewrap(function() {
|
|
2775
2917
|
if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
|
|
@@ -2779,6 +2921,11 @@
|
|
|
2779
2921
|
return;
|
|
2780
2922
|
}
|
|
2781
2923
|
|
|
2924
|
+
var shouldTrack = this.getConfig(CONFIG_SCROLL_CAPTURE_ALL);
|
|
2925
|
+
var scrollCheckpoints = (this.getConfig(CONFIG_SCROLL_CHECKPOINTS) || [])
|
|
2926
|
+
.slice()
|
|
2927
|
+
.sort(function(a, b) { return a - b; });
|
|
2928
|
+
|
|
2782
2929
|
var scrollTop = win.scrollY;
|
|
2783
2930
|
var props = _.extend({'$scroll_top': scrollTop}, DEFAULT_PROPS);
|
|
2784
2931
|
try {
|
|
@@ -2786,10 +2933,25 @@
|
|
|
2786
2933
|
var scrollPercentage = Math.round((scrollTop / (scrollHeight - win.innerHeight)) * 100);
|
|
2787
2934
|
props['$scroll_height'] = scrollHeight;
|
|
2788
2935
|
props['$scroll_percentage'] = scrollPercentage;
|
|
2936
|
+
if (scrollPercentage > this.lastScrollCheckpoint) {
|
|
2937
|
+
for (var i = 0; i < scrollCheckpoints.length; i++) {
|
|
2938
|
+
var checkpoint = scrollCheckpoints[i];
|
|
2939
|
+
if (
|
|
2940
|
+
scrollPercentage >= checkpoint &&
|
|
2941
|
+
this.lastScrollCheckpoint < checkpoint
|
|
2942
|
+
) {
|
|
2943
|
+
props['$scroll_checkpoint'] = checkpoint;
|
|
2944
|
+
this.lastScrollCheckpoint = checkpoint;
|
|
2945
|
+
shouldTrack = true;
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2789
2949
|
} catch (err) {
|
|
2790
2950
|
logger$3.critical('Error while calculating scroll percentage', err);
|
|
2791
2951
|
}
|
|
2792
|
-
|
|
2952
|
+
if (shouldTrack) {
|
|
2953
|
+
this.mp.track(MP_EV_SCROLL, props);
|
|
2954
|
+
}
|
|
2793
2955
|
}.bind(this)));
|
|
2794
2956
|
};
|
|
2795
2957
|
|
|
@@ -5241,8 +5403,12 @@
|
|
|
5241
5403
|
if (!(k in union_q)) {
|
|
5242
5404
|
union_q[k] = [];
|
|
5243
5405
|
}
|
|
5244
|
-
//
|
|
5245
|
-
|
|
5406
|
+
// Prevent duplicate values
|
|
5407
|
+
_.each(v, function(item) {
|
|
5408
|
+
if (!_.include(union_q[k], item)) {
|
|
5409
|
+
union_q[k].push(item);
|
|
5410
|
+
}
|
|
5411
|
+
});
|
|
5246
5412
|
}
|
|
5247
5413
|
});
|
|
5248
5414
|
this._pop_from_people_queue(UNSET_ACTION, q_data);
|