govuk_publishing_components 35.14.0 → 35.15.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-page-views.js +15 -5
- data/app/assets/javascripts/govuk_publishing_components/components/cookie-banner.js +4 -5
- data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +327 -321
- data/app/assets/stylesheets/govuk_publishing_components/components/_accordion.scss +6 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/_govspeak.scss +6 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +1 -1
- data/app/views/govuk_publishing_components/components/_attachment.html.erb +2 -1
- data/app/views/govuk_publishing_components/components/_cookie_banner.html.erb +30 -2
- data/app/views/govuk_publishing_components/components/_devolved_nations.html.erb +15 -1
- data/app/views/govuk_publishing_components/components/_layout_super_navigation_header.html.erb +2 -2
- data/app/views/govuk_publishing_components/components/docs/cards.yml +2 -2
- data/app/views/govuk_publishing_components/components/docs/cookie_banner.yml +5 -0
- data/app/views/govuk_publishing_components/components/docs/devolved_nations.yml +16 -0
- data/app/views/govuk_publishing_components/components/layout_for_public/_account-layout.html.erb +1 -0
- data/config/locales/en.yml +2 -2
- data/lib/govuk_publishing_components/presenters/devolved_nations_helper.rb +16 -4
- data/lib/govuk_publishing_components/version.rb +1 -1
- metadata +3 -3
@@ -21,33 +21,34 @@
|
|
21
21
|
|
22
22
|
(function () {
|
23
23
|
'use strict';
|
24
|
+
|
24
25
|
/**
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
* Fit an array of user timing delimited strings into a URL and return both the entries that fit and
|
27
|
+
* the remaining entries that didn't fit.
|
28
|
+
*/
|
28
29
|
function fitUserTimingEntries(utValues, config, url) {
|
29
30
|
// Start with the maximum allowed UT entries per beacon
|
30
31
|
var beaconUtValues = utValues.slice(0, config.maxBeaconUTEntries);
|
31
32
|
var remainingUtValues = utValues.slice(config.maxBeaconUTEntries);
|
32
33
|
// Trim UT entries until they fit within the maximum URL length, ensuring at least one UT entry
|
33
34
|
// is included.
|
34
|
-
while ((url + "&UT=" + beaconUtValues.join(",")).length > config.maxBeaconUrlLength &&
|
35
|
-
beaconUtValues.length > 1) {
|
35
|
+
while ((url + "&UT=" + beaconUtValues.join(",")).length > config.maxBeaconUrlLength && beaconUtValues.length > 1) {
|
36
36
|
remainingUtValues.unshift(beaconUtValues.pop());
|
37
37
|
}
|
38
38
|
return [beaconUtValues, remainingUtValues];
|
39
39
|
}
|
40
40
|
|
41
|
+
var luxOrigin = "https://lux.speedcurve.com";
|
41
42
|
function fromObject(obj) {
|
42
43
|
var autoMode = getProperty(obj, "auto", true);
|
43
44
|
return {
|
44
45
|
auto: autoMode,
|
45
|
-
beaconUrl: getProperty(obj, "beaconUrl", "
|
46
|
-
conversions: getProperty(obj, "conversions"
|
47
|
-
customerid: getProperty(obj, "customerid"
|
48
|
-
errorBeaconUrl: getProperty(obj, "errorBeaconUrl", "
|
49
|
-
jspagelabel: getProperty(obj, "jspagelabel"
|
50
|
-
label: getProperty(obj, "label"
|
46
|
+
beaconUrl: getProperty(obj, "beaconUrl", luxOrigin + "/lux/"),
|
47
|
+
conversions: getProperty(obj, "conversions"),
|
48
|
+
customerid: getProperty(obj, "customerid"),
|
49
|
+
errorBeaconUrl: getProperty(obj, "errorBeaconUrl", luxOrigin + "/error/"),
|
50
|
+
jspagelabel: getProperty(obj, "jspagelabel"),
|
51
|
+
label: getProperty(obj, "label"),
|
51
52
|
maxBeaconUrlLength: getProperty(obj, "maxBeaconUrlLength", 8190),
|
52
53
|
maxBeaconUTEntries: getProperty(obj, "maxBeaconUTEntries", 20),
|
53
54
|
maxErrors: getProperty(obj, "maxErrors", 5),
|
@@ -56,10 +57,10 @@
|
|
56
57
|
newBeaconOnPageShow: getProperty(obj, "newBeaconOnPageShow", false),
|
57
58
|
samplerate: getProperty(obj, "samplerate", 100),
|
58
59
|
sendBeaconOnPageHidden: getProperty(obj, "sendBeaconOnPageHidden", autoMode),
|
59
|
-
serverTiming: getProperty(obj, "serverTiming"
|
60
|
+
serverTiming: getProperty(obj, "serverTiming"),
|
60
61
|
trackErrors: getProperty(obj, "trackErrors", true),
|
61
62
|
trackHiddenPages: getProperty(obj, "trackHiddenPages", false),
|
62
|
-
pagegroups: getProperty(obj, "pagegroups"
|
63
|
+
pagegroups: getProperty(obj, "pagegroups"),
|
63
64
|
};
|
64
65
|
}
|
65
66
|
function getProperty(obj, key, defaultValue) {
|
@@ -99,8 +100,8 @@
|
|
99
100
|
updatedCustomData = {};
|
100
101
|
}
|
101
102
|
/**
|
102
|
-
|
103
|
-
|
103
|
+
* Convert a set of custom data values to the string format expected by the backend.
|
104
|
+
*/
|
104
105
|
function valuesToString(values) {
|
105
106
|
var strings = [];
|
106
107
|
for (var key in values) {
|
@@ -119,11 +120,14 @@
|
|
119
120
|
}
|
120
121
|
var max = Math.max;
|
121
122
|
/**
|
122
|
-
|
123
|
-
|
123
|
+
* Clamp a number so that it is never less than 0
|
124
|
+
*/
|
124
125
|
function clamp(x) {
|
125
126
|
return max(0, x);
|
126
127
|
}
|
128
|
+
function sortNumeric(a, b) {
|
129
|
+
return a - b;
|
130
|
+
}
|
127
131
|
|
128
132
|
function now() {
|
129
133
|
return Date.now ? Date.now() : +new Date();
|
@@ -173,7 +177,7 @@
|
|
173
177
|
startTime: 0,
|
174
178
|
type: navType == 2 ? "back_forward" : navType === 1 ? "reload" : "navigate",
|
175
179
|
};
|
176
|
-
|
180
|
+
{
|
177
181
|
for (var key in timing) {
|
178
182
|
if (typeof timing[key] === "number" && key !== "navigationStart") {
|
179
183
|
entry[key] = floor(timing[key] - timing.navigationStart);
|
@@ -183,10 +187,10 @@
|
|
183
187
|
return entry;
|
184
188
|
}
|
185
189
|
/**
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
+
* Simple wrapper around performance.getEntriesByType to provide fallbacks for
|
191
|
+
* legacy browsers, and work around edge cases where undefined is returned instead
|
192
|
+
* of an empty PerformanceEntryList.
|
193
|
+
*/
|
190
194
|
function getEntriesByType(type) {
|
191
195
|
if (typeof performance.getEntriesByType === "function") {
|
192
196
|
var entries = performance.getEntriesByType(type);
|
@@ -245,7 +249,7 @@
|
|
245
249
|
PageLabelFromDocumentTitle: 1 << 6,
|
246
250
|
PageLabelFromLabelProp: 1 << 7,
|
247
251
|
PageLabelFromGlobalVariable: 1 << 8,
|
248
|
-
|
252
|
+
PageLabelFromUrlPattern: 1 << 9,
|
249
253
|
PageWasPrerendered: 1 << 10,
|
250
254
|
PageWasBfCacheRestored: 1 << 11,
|
251
255
|
};
|
@@ -261,8 +265,8 @@
|
|
261
265
|
}
|
262
266
|
|
263
267
|
/**
|
264
|
-
|
265
|
-
|
268
|
+
* Get the interaction attribution name for an element
|
269
|
+
*/
|
266
270
|
function interactionAttributionForElement(el) {
|
267
271
|
// Our first preference is to use the data-sctrack attribute from anywhere in the tree
|
268
272
|
var trackId = getClosestScTrackAttribute(el);
|
@@ -354,6 +358,7 @@
|
|
354
358
|
};
|
355
359
|
return Logger;
|
356
360
|
}());
|
361
|
+
|
357
362
|
var sessionValue = 0;
|
358
363
|
var sessionEntries = [];
|
359
364
|
var maximumSessionValue = 0;
|
@@ -363,9 +368,9 @@
|
|
363
368
|
var latestEntry = sessionEntries[sessionEntries.length - 1];
|
364
369
|
if (sessionEntries.length &&
|
365
370
|
(entry.startTime - latestEntry.startTime >= 1000 ||
|
366
|
-
|
367
|
-
|
368
|
-
|
371
|
+
entry.startTime - firstEntry.startTime >= 5000)) {
|
372
|
+
sessionValue = entry.value;
|
373
|
+
sessionEntries = [entry];
|
369
374
|
}
|
370
375
|
else {
|
371
376
|
sessionValue += entry.value;
|
@@ -384,9 +389,9 @@
|
|
384
389
|
}
|
385
390
|
|
386
391
|
/**
|
387
|
-
|
388
|
-
|
389
|
-
|
392
|
+
* This implementation is based on the web-vitals implementation, however it is stripped back to the
|
393
|
+
* bare minimum required to measure just the INP value and does not store the actual event entries.
|
394
|
+
*/
|
390
395
|
// The maximum number of interactions to store
|
391
396
|
var MAX_INTERACTIONS = 10;
|
392
397
|
// A list of the slowest interactions
|
@@ -423,9 +428,9 @@
|
|
423
428
|
return slowestEntries.some(function (e2) { return e1.startTime === e2.startTime && e1.duration === e2.duration; });
|
424
429
|
}
|
425
430
|
/**
|
426
|
-
|
427
|
-
|
428
|
-
|
431
|
+
* Returns an estimated high percentile INP value based on the total number of interactions on the
|
432
|
+
* current page.
|
433
|
+
*/
|
429
434
|
function getHighPercentileINP() {
|
430
435
|
var _a;
|
431
436
|
var index = Math.min(slowestEntries.length - 1, Math.floor(getInteractionCount() / 50));
|
@@ -440,8 +445,7 @@
|
|
440
445
|
|
441
446
|
var ALL_ENTRIES = [];
|
442
447
|
function observe(type, callback, options) {
|
443
|
-
if (typeof PerformanceObserver === "function" &&
|
444
|
-
PerformanceObserver.supportedEntryTypes.includes(type)) {
|
448
|
+
if (typeof PerformanceObserver === "function" && PerformanceObserver.supportedEntryTypes.includes(type)) {
|
445
449
|
var po = new PerformanceObserver(function (list) {
|
446
450
|
list.getEntries().forEach(function (entry) { return callback(entry); });
|
447
451
|
});
|
@@ -456,17 +460,14 @@
|
|
456
460
|
function addEntry(entry) {
|
457
461
|
ALL_ENTRIES.push(entry);
|
458
462
|
}
|
459
|
-
function clearEntries() {
|
460
|
-
ALL_ENTRIES.splice(0);
|
461
|
-
}
|
462
463
|
|
463
464
|
/**
|
464
|
-
|
465
|
-
|
465
|
+
* A server timing metric that has its value set to the duration field
|
466
|
+
*/
|
466
467
|
var TYPE_DURATION = "r";
|
467
468
|
/**
|
468
|
-
|
469
|
-
|
469
|
+
* When a description metric has no value, we consider it to be a boolean and set it to this value.
|
470
|
+
*/
|
470
471
|
var BOOLEAN_TRUE_VALUE = "true";
|
471
472
|
function getKeyValuePairs(config, serverTiming) {
|
472
473
|
var pairs = {};
|
@@ -500,7 +501,7 @@
|
|
500
501
|
if (Array.isArray(patterns)) {
|
501
502
|
for (var i in patterns) {
|
502
503
|
var pattern = patterns[i];
|
503
|
-
if (patternMatchesUrl(pattern, hostname, pathname)) {
|
504
|
+
if (typeof pattern === "string" && patternMatchesUrl(pattern, hostname, pathname)) {
|
504
505
|
if (firstOnly) {
|
505
506
|
return key;
|
506
507
|
}
|
@@ -542,10 +543,18 @@
|
|
542
543
|
// -------------------------------------------------------------------------
|
543
544
|
/// End
|
544
545
|
// -------------------------------------------------------------------------
|
545
|
-
var SCRIPT_VERSION = "
|
546
|
+
var SCRIPT_VERSION = "311";
|
546
547
|
var logger = new Logger();
|
547
548
|
var globalConfig = fromObject(LUX);
|
548
549
|
logger.logEvent(LogEvent.EvaluationStart, [SCRIPT_VERSION]);
|
550
|
+
// Variable aliases that allow the minifier to reduce file size.
|
551
|
+
var document = window.document;
|
552
|
+
var addEventListener = window.addEventListener;
|
553
|
+
var removeEventListener = window.removeEventListener;
|
554
|
+
var setTimeout = window.setTimeout;
|
555
|
+
var clearTimeout = window.clearTimeout;
|
556
|
+
var encodeURIComponent = window.encodeURIComponent;
|
557
|
+
var thisScript = document.currentScript || {};
|
549
558
|
// Log JS errors.
|
550
559
|
var nErrors = 0;
|
551
560
|
function errorHandler(e) {
|
@@ -560,30 +569,30 @@
|
|
560
569
|
// Sample & limit other errors.
|
561
570
|
// Send the error beacon.
|
562
571
|
new Image().src =
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
}
|
584
|
-
}
|
585
|
-
}
|
586
|
-
|
572
|
+
globalConfig.errorBeaconUrl +
|
573
|
+
"?v=" +
|
574
|
+
SCRIPT_VERSION +
|
575
|
+
"&id=" +
|
576
|
+
getCustomerId() +
|
577
|
+
"&fn=" +
|
578
|
+
encodeURIComponent(e.filename) +
|
579
|
+
"&ln=" +
|
580
|
+
e.lineno +
|
581
|
+
"&cn=" +
|
582
|
+
e.colno +
|
583
|
+
"&msg=" +
|
584
|
+
encodeURIComponent(e.message) +
|
585
|
+
"&l=" +
|
586
|
+
encodeURIComponent(_getPageLabel()) +
|
587
|
+
(connectionType() ? "&ct=" + connectionType() : "") +
|
588
|
+
"&HN=" +
|
589
|
+
encodeURIComponent(document.location.hostname) +
|
590
|
+
"&PN=" +
|
591
|
+
encodeURIComponent(document.location.pathname);
|
592
|
+
}
|
593
|
+
}
|
594
|
+
}
|
595
|
+
addEventListener("error", errorHandler);
|
587
596
|
var logEntry = function (entry) {
|
588
597
|
logger.logEvent(LogEvent.PerformanceEntryReceived, [entry]);
|
589
598
|
};
|
@@ -611,9 +620,9 @@
|
|
611
620
|
logEntry(entry);
|
612
621
|
});
|
613
622
|
observe("first-input", function (entry) {
|
614
|
-
var
|
615
|
-
if (!gFirstInputDelay || gFirstInputDelay <
|
616
|
-
gFirstInputDelay = floor(
|
623
|
+
var entryTime = entry.processingStart - entry.startTime;
|
624
|
+
if (!gFirstInputDelay || gFirstInputDelay < entryTime) {
|
625
|
+
gFirstInputDelay = floor(entryTime);
|
617
626
|
}
|
618
627
|
// Allow first-input events to be considered for INP
|
619
628
|
addEntry$1(entry);
|
@@ -642,11 +651,24 @@
|
|
642
651
|
var gMaxMeasureTimeout; // setTimeout timer for sending the beacon after a maximum measurement time
|
643
652
|
var pageRestoreTime; // ms since navigationStart representing when the page was restored from the bfcache
|
644
653
|
/**
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
var getZeroTime = function () {
|
654
|
+
* To measure the way a user experienced a metric, we measure metrics relative to the time the user
|
655
|
+
* started viewing the page. On prerendered pages, this is activationStart. On bfcache restores, this
|
656
|
+
* is the page restore time. On all other pages this value will be zero.
|
657
|
+
*/
|
658
|
+
var getZeroTime = function () {
|
659
|
+
var _a;
|
660
|
+
return Math.max(pageRestoreTime || 0, getNavigationEntry().activationStart, ((_a = _getMark(START_MARK)) === null || _a === void 0 ? void 0 : _a.startTime) || 0);
|
661
|
+
};
|
662
|
+
/**
|
663
|
+
* Most time-based metrics that LUX reports should be relative to the "zero" marker, rounded down
|
664
|
+
* to the nearest unit so as not to report times in the future, and clamped to zero.
|
665
|
+
*/
|
666
|
+
var processTimeMetric = function (value) { return clamp(floor(value - getZeroTime())); };
|
667
|
+
/**
|
668
|
+
* Some values should only be reported if they are non-zero. The exception to this is when the page
|
669
|
+
* was prerendered or restored from BF cache
|
670
|
+
*/
|
671
|
+
var shouldReportValue = function (value) { return value > 0 || pageRestoreTime || wasPrerendered(); };
|
650
672
|
if (_sample()) {
|
651
673
|
logger.logEvent(LogEvent.SessionIsSampled, [globalConfig.samplerate]);
|
652
674
|
}
|
@@ -688,11 +710,11 @@
|
|
688
710
|
removeListeners();
|
689
711
|
}
|
690
712
|
function removeListeners() {
|
691
|
-
|
692
|
-
|
713
|
+
removeEventListener("pointerup", onPointerUp, ghListenerOptions);
|
714
|
+
removeEventListener("pointercancel", onPointerCancel, ghListenerOptions);
|
693
715
|
}
|
694
|
-
|
695
|
-
|
716
|
+
addEventListener("pointerup", onPointerUp, ghListenerOptions);
|
717
|
+
addEventListener("pointercancel", onPointerCancel, ghListenerOptions);
|
696
718
|
}
|
697
719
|
// Record FID as the delta between when the event happened and when the
|
698
720
|
// listener was able to execute.
|
@@ -732,16 +754,16 @@
|
|
732
754
|
}
|
733
755
|
// Attach event listener to input events.
|
734
756
|
gaEventTypes.forEach(function (eventType) {
|
735
|
-
|
757
|
+
addEventListener(eventType, onInput, ghListenerOptions);
|
736
758
|
});
|
737
759
|
////////////////////// FID END
|
738
760
|
/**
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
761
|
+
* Returns the time elapsed (in ms) since navigationStart. For SPAs, returns
|
762
|
+
* the time elapsed since the last LUX.init call.
|
763
|
+
*
|
764
|
+
* When `absolute = true` the time is always relative to navigationStart, even
|
765
|
+
* in SPAs.
|
766
|
+
*/
|
745
767
|
function _now(absolute) {
|
746
768
|
var sinceNavigationStart = msSinceNavigationStart();
|
747
769
|
var startMark = _getMark(START_MARK);
|
@@ -766,7 +788,7 @@
|
|
766
788
|
return performance.mark.apply(performance, args);
|
767
789
|
}
|
768
790
|
// ...Otherwise provide a polyfill
|
769
|
-
|
791
|
+
{
|
770
792
|
var name_1 = args[0];
|
771
793
|
var detail = ((_a = args[1]) === null || _a === void 0 ? void 0 : _a.detail) || null;
|
772
794
|
var startTime = ((_b = args[1]) === null || _b === void 0 ? void 0 : _b.startTime) || _now();
|
@@ -829,14 +851,14 @@
|
|
829
851
|
return performance.measure.apply(performance, args);
|
830
852
|
}
|
831
853
|
// ...Otherwise provide a polyfill
|
832
|
-
|
854
|
+
{
|
833
855
|
var navEntry = getNavigationEntry();
|
834
856
|
var startTime = typeof startMarkName === "number" ? startMarkName : 0;
|
835
857
|
var endTime = typeof endMarkName === "number" ? endMarkName : _now();
|
836
858
|
var throwError = function (missingMark) {
|
837
859
|
throw new DOMException("Failed to execute 'measure' on 'Performance': The mark '" +
|
838
|
-
|
839
|
-
|
860
|
+
missingMark +
|
861
|
+
"' does not exist");
|
840
862
|
};
|
841
863
|
if (typeof startMarkName === "string") {
|
842
864
|
var startMark = _getMark(startMarkName);
|
@@ -924,7 +946,7 @@
|
|
924
946
|
var startMark = _getMark(START_MARK);
|
925
947
|
// For user timing values taken in a SPA page load, we need to adjust them
|
926
948
|
// so that they're zeroed against the last LUX.init() call.
|
927
|
-
var tZero =
|
949
|
+
var tZero = getZeroTime();
|
928
950
|
// marks
|
929
951
|
_getMarks().forEach(function (mark) {
|
930
952
|
var name = mark.name;
|
@@ -973,12 +995,13 @@
|
|
973
995
|
// Return a string of Element Timing Metrics formatted for beacon querystring.
|
974
996
|
function elementTimingValues() {
|
975
997
|
var aET = [];
|
976
|
-
var startMark = _getMark(START_MARK);
|
977
|
-
var tZero = startMark ? startMark.startTime : getZeroTime();
|
978
998
|
getEntries("element").forEach(function (entry) {
|
979
999
|
if (entry.identifier && entry.startTime) {
|
980
|
-
|
981
|
-
|
1000
|
+
var value = processTimeMetric(entry.startTime);
|
1001
|
+
if (shouldReportValue(value)) {
|
1002
|
+
logger.logEvent(LogEvent.PerformanceEntryProcessed, [entry]);
|
1003
|
+
aET.push(entry.identifier + "|" + value);
|
1004
|
+
}
|
982
1005
|
}
|
983
1006
|
});
|
984
1007
|
return aET.join(",");
|
@@ -995,20 +1018,7 @@
|
|
995
1018
|
var longTaskEntries = getEntries("longtask");
|
996
1019
|
// Add up totals for each "type" of long task
|
997
1020
|
if (longTaskEntries.length) {
|
998
|
-
|
999
|
-
// But if it is a SPA then the relative start time is gStartMark.
|
1000
|
-
var startMark = _getMark(START_MARK);
|
1001
|
-
var tZero_1 = startMark ? startMark.startTime : 0;
|
1002
|
-
// Do not include Long Tasks that start after the page is done.
|
1003
|
-
// For full page loads, "done" is loadEventEnd.
|
1004
|
-
var tEnd_1 = timing.loadEventEnd - timing.navigationStart;
|
1005
|
-
if (startMark) {
|
1006
|
-
// For SPA page loads (determined by the presence of a start mark), "done" is gEndMark.
|
1007
|
-
var endMark = _getMark(END_MARK);
|
1008
|
-
if (endMark) {
|
1009
|
-
tEnd_1 = endMark.startTime;
|
1010
|
-
}
|
1011
|
-
}
|
1021
|
+
var tZero_1 = getZeroTime();
|
1012
1022
|
longTaskEntries.forEach(function (entry) {
|
1013
1023
|
var dur = floor(entry.duration);
|
1014
1024
|
if (entry.startTime < tZero_1) {
|
@@ -1016,21 +1026,18 @@
|
|
1016
1026
|
// LUX.init() was called. If so, only include the duration after tZero.
|
1017
1027
|
dur -= tZero_1 - entry.startTime;
|
1018
1028
|
}
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
hCPUDetails[type]
|
1029
|
+
// Only process entries that we calculated to have a valid duration
|
1030
|
+
if (dur > 0) {
|
1031
|
+
logger.logEvent(LogEvent.PerformanceEntryProcessed, [entry]);
|
1032
|
+
var type = entry.attribution[0].name;
|
1033
|
+
if (!hCPU[type]) {
|
1034
|
+
hCPU[type] = 0;
|
1035
|
+
hCPUDetails[type] = "";
|
1036
|
+
}
|
1037
|
+
hCPU[type] += dur;
|
1038
|
+
// Send back the raw startTime and duration, as well as the adjusted duration.
|
1039
|
+
hCPUDetails[type] += "," + floor(entry.startTime) + "|" + dur;
|
1030
1040
|
}
|
1031
|
-
hCPU[type] += dur;
|
1032
|
-
// Send back the raw startTime and duration, as well as the adjusted duration.
|
1033
|
-
hCPUDetails[type] += "," + floor(entry.startTime) + "|" + dur;
|
1034
1041
|
});
|
1035
1042
|
}
|
1036
1043
|
// TODO - Add more types if/when they become available.
|
@@ -1042,12 +1049,12 @@
|
|
1042
1049
|
}
|
1043
1050
|
var hStats = cpuStats(hCPUDetails[jsType]);
|
1044
1051
|
var sStats = ",n|" +
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1052
|
+
hStats.count +
|
1053
|
+
",d|" +
|
1054
|
+
hStats.median +
|
1055
|
+
",x|" +
|
1056
|
+
hStats.max +
|
1057
|
+
(typeof hStats.fci === "undefined" ? "" : ",i|" + hStats.fci);
|
1051
1058
|
sCPU += "s|" + hCPU[jsType] + sStats + hCPUDetails[jsType];
|
1052
1059
|
return sCPU;
|
1053
1060
|
}
|
@@ -1055,11 +1062,11 @@
|
|
1055
1062
|
function cpuStats(sDetails) {
|
1056
1063
|
// tuples of starttime|duration, eg: ,456|250,789|250,1012|250
|
1057
1064
|
var max = 0;
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
//
|
1062
|
-
var bFoundFci =
|
1065
|
+
// FCI is beginning of 5 second window of no Long Tasks _after_ first contentful paint
|
1066
|
+
var fcp = getFcp();
|
1067
|
+
var fci = fcp || 0;
|
1068
|
+
// If FCP is not supported, we can't calculate a valid FCI.
|
1069
|
+
var bFoundFci = typeof fcp === "undefined";
|
1063
1070
|
var aValues = [];
|
1064
1071
|
var aTuples = sDetails.split(",");
|
1065
1072
|
for (var i = 0; i < aTuples.length; i++) {
|
@@ -1079,7 +1086,10 @@
|
|
1079
1086
|
}
|
1080
1087
|
else {
|
1081
1088
|
// Less than 5 seconds of inactivity
|
1082
|
-
|
1089
|
+
var val = processTimeMetric(start + dur);
|
1090
|
+
if (shouldReportValue(val)) {
|
1091
|
+
fci = val; // FCI is now the end of this Long Task
|
1092
|
+
}
|
1083
1093
|
}
|
1084
1094
|
}
|
1085
1095
|
}
|
@@ -1102,9 +1112,7 @@
|
|
1102
1112
|
return 0;
|
1103
1113
|
}
|
1104
1114
|
var half = floor(aValues.length / 2);
|
1105
|
-
aValues.sort(
|
1106
|
-
return a - b;
|
1107
|
-
});
|
1115
|
+
aValues.sort(sortNumeric);
|
1108
1116
|
if (aValues.length % 2) {
|
1109
1117
|
// Return the middle value.
|
1110
1118
|
return aValues[half];
|
@@ -1119,42 +1127,39 @@
|
|
1119
1127
|
var sLuxjs = "";
|
1120
1128
|
if (performance.getEntriesByName) {
|
1121
1129
|
// Get the lux script URL (including querystring params).
|
1122
|
-
var
|
1123
|
-
if (
|
1124
|
-
var
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
(scriptStartTime - timing.navigationStart) + // when lux.js started getting evaluated relative to navigationStart
|
1156
|
-
"";
|
1157
|
-
}
|
1130
|
+
var aResources = performance.getEntriesByName(thisScript.src);
|
1131
|
+
if (aResources && aResources.length) {
|
1132
|
+
var r = aResources[0];
|
1133
|
+
// DO NOT USE DURATION!!!!!
|
1134
|
+
// See https://www.stevesouders.com/blog/2014/11/25/serious-confusion-with-resource-timing/
|
1135
|
+
var dns = floor(r.domainLookupEnd - r.domainLookupStart);
|
1136
|
+
var tcp = floor(r.connectEnd - r.connectStart);
|
1137
|
+
var fb = floor(r.responseStart - r.requestStart);
|
1138
|
+
var content = floor(r.responseEnd - r.responseStart);
|
1139
|
+
var networkDuration = dns + tcp + fb + content;
|
1140
|
+
var parseEval = scriptEndTime - scriptStartTime;
|
1141
|
+
var transferSize = r.encodedBodySize ? r.encodedBodySize : 0;
|
1142
|
+
// Instead of a delimiter use a 1-letter abbreviation as a separator.
|
1143
|
+
sLuxjs =
|
1144
|
+
"d" +
|
1145
|
+
dns +
|
1146
|
+
"t" +
|
1147
|
+
tcp +
|
1148
|
+
"f" +
|
1149
|
+
fb +
|
1150
|
+
"c" +
|
1151
|
+
content +
|
1152
|
+
"n" +
|
1153
|
+
networkDuration +
|
1154
|
+
"e" +
|
1155
|
+
parseEval +
|
1156
|
+
"r" +
|
1157
|
+
globalConfig.samplerate + // sample rate
|
1158
|
+
(typeof transferSize === "number" ? "x" + transferSize : "") +
|
1159
|
+
(typeof gLuxSnippetStart === "number" ? "l" + gLuxSnippetStart : "") +
|
1160
|
+
"s" +
|
1161
|
+
(scriptStartTime - timing.navigationStart) + // when lux.js started getting evaluated relative to navigationStart
|
1162
|
+
"";
|
1158
1163
|
}
|
1159
1164
|
}
|
1160
1165
|
return sLuxjs;
|
@@ -1185,9 +1190,9 @@
|
|
1185
1190
|
if (gCustomerDataTimeout) {
|
1186
1191
|
// Cancel the timer for any previous beacons so that if they have not
|
1187
1192
|
// yet been sent we can combine all the data in a new beacon.
|
1188
|
-
|
1193
|
+
clearTimeout(gCustomerDataTimeout);
|
1189
1194
|
}
|
1190
|
-
gCustomerDataTimeout =
|
1195
|
+
gCustomerDataTimeout = setTimeout(_sendCustomerData, 100);
|
1191
1196
|
}
|
1192
1197
|
}
|
1193
1198
|
// _sample()
|
@@ -1200,9 +1205,9 @@
|
|
1200
1205
|
return parseInt(nThis) < globalConfig.samplerate;
|
1201
1206
|
}
|
1202
1207
|
/**
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1208
|
+
* Re-initialize lux.js to start a new "page". This is typically called within a SPA at the
|
1209
|
+
* beginning of a page transition, but is also called internally when the BF cache is restored.
|
1210
|
+
*/
|
1206
1211
|
function _init(startTime) {
|
1207
1212
|
// Some customers (incorrectly) call LUX.init on the very first page load of a SPA. This would
|
1208
1213
|
// cause some first-page-only data (like paint metrics) to be lost. To prevent this, we silently
|
@@ -1232,7 +1237,6 @@
|
|
1232
1237
|
gbFirstPV = 0;
|
1233
1238
|
gSyncId = createSyncId();
|
1234
1239
|
gUid = refreshUniqueId(gSyncId);
|
1235
|
-
clearEntries();
|
1236
1240
|
reset$1();
|
1237
1241
|
reset();
|
1238
1242
|
nErrors = 0;
|
@@ -1353,14 +1357,17 @@
|
|
1353
1357
|
ns += start; // "navigationStart" for a SPA is the real navigationStart plus the start mark
|
1354
1358
|
var end = floor(endMark.startTime) - start; // delta from start mark
|
1355
1359
|
s =
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1360
|
+
ns +
|
1361
|
+
// fetchStart and activationStart are the same as navigationStart for a SPA
|
1362
|
+
"as" +
|
1363
|
+
0 +
|
1364
|
+
"fs" +
|
1365
|
+
0 +
|
1366
|
+
"ls" +
|
1367
|
+
end +
|
1368
|
+
"le" +
|
1369
|
+
end +
|
1370
|
+
"";
|
1364
1371
|
}
|
1365
1372
|
else if (performance.timing) {
|
1366
1373
|
// Return the real Nav Timing metrics because this is the "main" page view (not a SPA)
|
@@ -1368,17 +1375,20 @@
|
|
1368
1375
|
var startRender = getStartRender();
|
1369
1376
|
var fcp = getFcp();
|
1370
1377
|
var lcp = getLcp();
|
1371
|
-
var prefixNTValue = function (key, prefix) {
|
1372
|
-
// activationStart is always absolute. Other values are relative to activationStart.
|
1373
|
-
var zero = key === "activationStart" ? 0 : getZeroTime();
|
1378
|
+
var prefixNTValue = function (key, prefix, ignoreZero) {
|
1374
1379
|
if (typeof navEntry_1[key] === "number") {
|
1375
|
-
var value =
|
1376
|
-
|
1380
|
+
var value = navEntry_1[key];
|
1381
|
+
// We allow zero values for most navigation timing metrics, but for some metrics we want
|
1382
|
+
// to ignore zeroes. The exceptions are that all metrics can be zero if the page was either
|
1383
|
+
// prerendered or restored from the BF cache.
|
1384
|
+
if (shouldReportValue(value) || !ignoreZero) {
|
1385
|
+
return prefix + processTimeMetric(value);
|
1386
|
+
}
|
1377
1387
|
}
|
1378
1388
|
return "";
|
1379
1389
|
};
|
1380
|
-
var loadEventStartStr = prefixNTValue("loadEventStart", "ls");
|
1381
|
-
var loadEventEndStr = prefixNTValue("loadEventEnd", "le");
|
1390
|
+
var loadEventStartStr = prefixNTValue("loadEventStart", "ls", true);
|
1391
|
+
var loadEventEndStr = prefixNTValue("loadEventEnd", "le", true);
|
1382
1392
|
if (pageRestoreTime && startMark && endMark) {
|
1383
1393
|
// For bfcache restores, we set the load time to the time it took for the page to be restored.
|
1384
1394
|
var loadTime = floor(endMark.startTime - startMark.startTime);
|
@@ -1386,43 +1396,44 @@
|
|
1386
1396
|
loadEventEndStr = "le" + loadTime;
|
1387
1397
|
}
|
1388
1398
|
var redirect = wasRedirected();
|
1399
|
+
var isSecure = document.location.protocol === "https:";
|
1389
1400
|
s = [
|
1390
1401
|
ns,
|
1391
|
-
|
1392
|
-
redirect ? prefixNTValue("redirectStart", "rs") : "",
|
1393
|
-
redirect ? prefixNTValue("redirectEnd", "re") : "",
|
1402
|
+
"as" + clamp(navEntry_1.activationStart),
|
1403
|
+
redirect && !pageRestoreTime ? prefixNTValue("redirectStart", "rs") : "",
|
1404
|
+
redirect && !pageRestoreTime ? prefixNTValue("redirectEnd", "re") : "",
|
1394
1405
|
prefixNTValue("fetchStart", "fs"),
|
1395
1406
|
prefixNTValue("domainLookupStart", "ds"),
|
1396
1407
|
prefixNTValue("domainLookupEnd", "de"),
|
1397
1408
|
prefixNTValue("connectStart", "cs"),
|
1398
|
-
prefixNTValue("secureConnectionStart", "sc"),
|
1409
|
+
isSecure ? prefixNTValue("secureConnectionStart", "sc") : "",
|
1399
1410
|
prefixNTValue("connectEnd", "ce"),
|
1400
1411
|
prefixNTValue("requestStart", "qs"),
|
1401
1412
|
prefixNTValue("responseStart", "bs"),
|
1402
1413
|
prefixNTValue("responseEnd", "be"),
|
1403
|
-
prefixNTValue("domInteractive", "oi"),
|
1404
|
-
prefixNTValue("domContentLoadedEventStart", "os"),
|
1405
|
-
prefixNTValue("domContentLoadedEventEnd", "oe"),
|
1406
|
-
prefixNTValue("domComplete", "oc"),
|
1414
|
+
prefixNTValue("domInteractive", "oi", true),
|
1415
|
+
prefixNTValue("domContentLoadedEventStart", "os", true),
|
1416
|
+
prefixNTValue("domContentLoadedEventEnd", "oe", true),
|
1417
|
+
prefixNTValue("domComplete", "oc", true),
|
1407
1418
|
loadEventStartStr,
|
1408
1419
|
loadEventEndStr,
|
1409
|
-
typeof startRender !== "undefined" ? "sr" +
|
1410
|
-
typeof fcp !== "undefined" ? "fc" +
|
1411
|
-
typeof lcp !== "undefined" ? "lc" +
|
1420
|
+
typeof startRender !== "undefined" ? "sr" + startRender : "",
|
1421
|
+
typeof fcp !== "undefined" ? "fc" + fcp : "",
|
1422
|
+
typeof lcp !== "undefined" ? "lc" + lcp : "",
|
1412
1423
|
].join("");
|
1413
1424
|
}
|
1414
1425
|
else if (endMark) {
|
1415
1426
|
// This is a "main" page view that does NOT support Navigation Timing - strange.
|
1416
1427
|
var end = floor(endMark.startTime);
|
1417
1428
|
s =
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1429
|
+
ns +
|
1430
|
+
"fs" +
|
1431
|
+
0 + // fetchStart is the same as navigationStart
|
1432
|
+
"ls" +
|
1433
|
+
end +
|
1434
|
+
"le" +
|
1435
|
+
end +
|
1436
|
+
"";
|
1426
1437
|
}
|
1427
1438
|
return s;
|
1428
1439
|
}
|
@@ -1432,7 +1443,10 @@
|
|
1432
1443
|
for (var i = 0; i < paintEntries.length; i++) {
|
1433
1444
|
var entry = paintEntries[i];
|
1434
1445
|
if (entry.name === "first-contentful-paint") {
|
1435
|
-
|
1446
|
+
var value = processTimeMetric(entry.startTime);
|
1447
|
+
if (shouldReportValue(value)) {
|
1448
|
+
return value;
|
1449
|
+
}
|
1436
1450
|
}
|
1437
1451
|
}
|
1438
1452
|
return undefined;
|
@@ -1442,8 +1456,11 @@
|
|
1442
1456
|
var lcpEntries = getEntries("largest-contentful-paint");
|
1443
1457
|
if (lcpEntries.length) {
|
1444
1458
|
var lastEntry = lcpEntries[lcpEntries.length - 1];
|
1445
|
-
|
1446
|
-
|
1459
|
+
var value = processTimeMetric(lastEntry.startTime);
|
1460
|
+
if (shouldReportValue(value)) {
|
1461
|
+
logger.logEvent(LogEvent.PerformanceEntryProcessed, [lastEntry]);
|
1462
|
+
return value;
|
1463
|
+
}
|
1447
1464
|
}
|
1448
1465
|
return undefined;
|
1449
1466
|
}
|
@@ -1454,12 +1471,17 @@
|
|
1454
1471
|
if ("PerformancePaintTiming" in self) {
|
1455
1472
|
var paintEntries = getEntriesByType("paint");
|
1456
1473
|
if (paintEntries.length) {
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1474
|
+
var paintValues = paintEntries.map(function (entry) { return entry.startTime; }).sort(sortNumeric);
|
1475
|
+
// Use the earliest valid paint entry as the start render time.
|
1476
|
+
for (var i = 0; i < paintValues.length; i++) {
|
1477
|
+
var value = processTimeMetric(paintValues[i]);
|
1478
|
+
if (shouldReportValue(value)) {
|
1479
|
+
return value;
|
1480
|
+
}
|
1481
|
+
}
|
1460
1482
|
}
|
1461
1483
|
}
|
1462
|
-
if (performance.timing && timing.msFirstPaint &&
|
1484
|
+
if (performance.timing && timing.msFirstPaint && true) {
|
1463
1485
|
// If IE/Edge, use the prefixed `msFirstPaint` property (see http://msdn.microsoft.com/ff974719).
|
1464
1486
|
return floor(timing.msFirstPaint - timing.navigationStart);
|
1465
1487
|
}
|
@@ -1473,40 +1495,11 @@
|
|
1473
1495
|
return getHighPercentileINP();
|
1474
1496
|
}
|
1475
1497
|
function getCustomerId() {
|
1476
|
-
if (
|
1477
|
-
|
1478
|
-
var luxScript = getScriptElement("/js/lux.js");
|
1479
|
-
if (luxScript) {
|
1480
|
-
LUX.customerid = getQuerystringParam(luxScript.src, "id");
|
1481
|
-
}
|
1498
|
+
if (!LUX.customerid) {
|
1499
|
+
LUX.customerid = thisScript.src.match(/id=(\d+)/).pop();
|
1482
1500
|
}
|
1483
1501
|
return LUX.customerid || "";
|
1484
1502
|
}
|
1485
|
-
// Return the SCRIPT DOM element whose SRC contains the URL snippet.
|
1486
|
-
// This is used to find the LUX script element.
|
1487
|
-
function getScriptElement(urlsnippet) {
|
1488
|
-
var aScripts = document.getElementsByTagName("script");
|
1489
|
-
for (var i = 0, len = aScripts.length; i < len; i++) {
|
1490
|
-
var script = aScripts[i];
|
1491
|
-
if (script.src && -1 !== script.src.indexOf(urlsnippet)) {
|
1492
|
-
return script;
|
1493
|
-
}
|
1494
|
-
}
|
1495
|
-
return undefined;
|
1496
|
-
}
|
1497
|
-
function getQuerystringParam(url, name) {
|
1498
|
-
var qs = url.split("?")[1];
|
1499
|
-
var aTuples = qs.split("&");
|
1500
|
-
for (var i = 0, len = aTuples.length; i < len; i++) {
|
1501
|
-
var tuple = aTuples[i];
|
1502
|
-
var aTuple = tuple.split("=");
|
1503
|
-
var key = aTuple[0];
|
1504
|
-
if (name === key) {
|
1505
|
-
return aTuple[1];
|
1506
|
-
}
|
1507
|
-
}
|
1508
|
-
return undefined;
|
1509
|
-
}
|
1510
1503
|
function avgDomDepth() {
|
1511
1504
|
var aElems = document.getElementsByTagName("*");
|
1512
1505
|
var i = aElems.length;
|
@@ -1645,14 +1638,14 @@
|
|
1645
1638
|
}
|
1646
1639
|
function createMaxMeasureTimeout() {
|
1647
1640
|
clearMaxMeasureTimeout();
|
1648
|
-
gMaxMeasureTimeout =
|
1641
|
+
gMaxMeasureTimeout = setTimeout(function () {
|
1649
1642
|
gFlags = addFlag(gFlags, Flags.BeaconSentAfterTimeout);
|
1650
1643
|
_sendLux();
|
1651
1644
|
}, globalConfig.maxMeasureTime - _now());
|
1652
1645
|
}
|
1653
1646
|
function clearMaxMeasureTimeout() {
|
1654
1647
|
if (gMaxMeasureTimeout) {
|
1655
|
-
|
1648
|
+
clearTimeout(gMaxMeasureTimeout);
|
1656
1649
|
}
|
1657
1650
|
}
|
1658
1651
|
function _getBeaconUrl(customData) {
|
@@ -1688,7 +1681,7 @@
|
|
1688
1681
|
!gSyncId ||
|
1689
1682
|
!_sample() || // OUTSIDE the sampled range
|
1690
1683
|
gbLuxSent // LUX data already sent
|
1691
|
-
|
1684
|
+
) {
|
1692
1685
|
return;
|
1693
1686
|
}
|
1694
1687
|
logger.logEvent(LogEvent.DataCollectionStart);
|
@@ -1741,49 +1734,49 @@
|
|
1741
1734
|
var is = inlineTagSize("script");
|
1742
1735
|
var ic = inlineTagSize("style");
|
1743
1736
|
var metricsQueryString =
|
1744
|
-
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1757
|
-
|
1758
|
-
|
1759
|
-
|
1760
|
-
|
1761
|
-
|
1762
|
-
|
1763
|
-
|
1764
|
-
|
1765
|
-
|
1766
|
-
|
1767
|
-
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1774
|
-
|
1775
|
-
|
1776
|
-
|
1777
|
-
|
1778
|
-
|
1779
|
-
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1783
|
-
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1737
|
+
// only send Nav Timing and lux.js metrics on initial pageload (not for SPA page views)
|
1738
|
+
(gbNavSent ? "" : "&NT=" + getNavTiming()) +
|
1739
|
+
(gbFirstPV ? "&LJS=" + sLuxjs : "") +
|
1740
|
+
// Page Stats
|
1741
|
+
"&PS=ns" +
|
1742
|
+
numScripts() +
|
1743
|
+
"bs" +
|
1744
|
+
blockingScripts() +
|
1745
|
+
(is > -1 ? "is" + is : "") +
|
1746
|
+
"ss" +
|
1747
|
+
numStylesheets() +
|
1748
|
+
"bc" +
|
1749
|
+
blockingStylesheets() +
|
1750
|
+
(ic > -1 ? "ic" + ic : "") +
|
1751
|
+
"ia" +
|
1752
|
+
imagesATF().length +
|
1753
|
+
"it" +
|
1754
|
+
document.getElementsByTagName("img").length + // total number of images
|
1755
|
+
"dd" +
|
1756
|
+
avgDomDepth() +
|
1757
|
+
"nd" +
|
1758
|
+
document.getElementsByTagName("*").length + // numdomelements
|
1759
|
+
"vh" +
|
1760
|
+
document.documentElement.clientHeight + // see http://www.quirksmode.org/mobile/viewports.html
|
1761
|
+
"vw" +
|
1762
|
+
document.documentElement.clientWidth +
|
1763
|
+
"dh" +
|
1764
|
+
docHeight(document) +
|
1765
|
+
"dw" +
|
1766
|
+
docWidth(document) +
|
1767
|
+
(docSize() ? "ds" + docSize() : "") + // document HTTP transfer size (bytes)
|
1768
|
+
(connectionType() ? "ct" + connectionType() + "_" : "") + // delimit with "_" since values can be non-numeric so need a way to extract with regex in VCL
|
1769
|
+
"er" +
|
1770
|
+
nErrors +
|
1771
|
+
"nt" +
|
1772
|
+
navigationType() +
|
1773
|
+
(navigator.deviceMemory ? "dm" + Math.round(navigator.deviceMemory) : "") + // device memory (GB)
|
1774
|
+
(sIx ? "&IX=" + sIx : "") +
|
1775
|
+
(typeof gFirstInputDelay !== "undefined" ? "&FID=" + gFirstInputDelay : "") +
|
1776
|
+
(sCPU ? "&CPU=" + sCPU : "") +
|
1777
|
+
(sET ? "&ET=" + sET : "") + // element timing
|
1778
|
+
(typeof CLS !== "undefined" ? "&CLS=" + CLS : "") +
|
1779
|
+
(typeof INP !== "undefined" ? "&INP=" + INP : "");
|
1787
1780
|
// We add the user timing entries last so that we can split them to reduce the URL size if necessary.
|
1788
1781
|
var utValues = userTimingValues();
|
1789
1782
|
var _b = fitUserTimingEntries(utValues, globalConfig, baseUrl + metricsQueryString), beaconUtValues = _b[0], remainingUtValues = _b[1];
|
@@ -1807,8 +1800,8 @@
|
|
1807
1800
|
}
|
1808
1801
|
var ixTimerId;
|
1809
1802
|
function _sendIxAfterDelay() {
|
1810
|
-
|
1811
|
-
ixTimerId =
|
1803
|
+
clearTimeout(ixTimerId);
|
1804
|
+
ixTimerId = setTimeout(_sendIx, 100);
|
1812
1805
|
}
|
1813
1806
|
// Beacon back the IX data separately (need to sync with LUX beacon on the backend).
|
1814
1807
|
function _sendIx() {
|
@@ -1842,7 +1835,7 @@
|
|
1842
1835
|
!gSyncId ||
|
1843
1836
|
!_sample() || // OUTSIDE the sampled range
|
1844
1837
|
!gbLuxSent // LUX has NOT been sent yet, so wait to include it there
|
1845
|
-
|
1838
|
+
) {
|
1846
1839
|
return;
|
1847
1840
|
}
|
1848
1841
|
var sCustomerData = valuesToString(getUpdatedCustomData());
|
@@ -1870,6 +1863,19 @@
|
|
1870
1863
|
}
|
1871
1864
|
}
|
1872
1865
|
function _keyHandler(e) {
|
1866
|
+
var keyCode = e.keyCode;
|
1867
|
+
/**
|
1868
|
+
* Ignore modifier keys
|
1869
|
+
*
|
1870
|
+
* 16 = Shift
|
1871
|
+
* 17 = Control
|
1872
|
+
* 18 = Alt
|
1873
|
+
* 20 = Caps Lock
|
1874
|
+
* 224 = Meta/Command
|
1875
|
+
*/
|
1876
|
+
if (keyCode === 16 || keyCode === 17 || keyCode === 18 || keyCode === 20 || keyCode === 224) {
|
1877
|
+
return;
|
1878
|
+
}
|
1873
1879
|
_removeIxHandlers();
|
1874
1880
|
if (typeof ghIx["k"] === "undefined") {
|
1875
1881
|
ghIx["k"] = _now();
|
@@ -1914,10 +1920,10 @@
|
|
1914
1920
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
1915
1921
|
function addListener(type, callback, useCapture) {
|
1916
1922
|
if (useCapture === void 0) { useCapture = false; }
|
1917
|
-
if (
|
1918
|
-
|
1923
|
+
if (addEventListener) {
|
1924
|
+
addEventListener(type, callback, useCapture);
|
1919
1925
|
}
|
1920
|
-
else if (window.attachEvent &&
|
1926
|
+
else if (window.attachEvent && true) {
|
1921
1927
|
window.attachEvent("on" + type, callback);
|
1922
1928
|
}
|
1923
1929
|
}
|
@@ -1925,10 +1931,10 @@
|
|
1925
1931
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
1926
1932
|
function removeListener(type, callback, useCapture) {
|
1927
1933
|
if (useCapture === void 0) { useCapture = false; }
|
1928
|
-
if (
|
1929
|
-
|
1934
|
+
if (removeEventListener) {
|
1935
|
+
removeEventListener(type, callback, useCapture);
|
1930
1936
|
}
|
1931
|
-
else if (window.detachEvent &&
|
1937
|
+
else if (window.detachEvent && true) {
|
1932
1938
|
window.detachEvent("on" + type, callback);
|
1933
1939
|
}
|
1934
1940
|
}
|
@@ -2016,7 +2022,7 @@
|
|
2016
2022
|
if (typeof LUX.pagegroups !== "undefined") {
|
2017
2023
|
var label = getMatchesFromPatternMap(LUX.pagegroups, location.hostname, location.pathname, true);
|
2018
2024
|
if (label) {
|
2019
|
-
gFlags = addFlag(gFlags, Flags.
|
2025
|
+
gFlags = addFlag(gFlags, Flags.PageLabelFromUrlPattern);
|
2020
2026
|
return label;
|
2021
2027
|
}
|
2022
2028
|
}
|
@@ -2057,11 +2063,11 @@
|
|
2057
2063
|
function _setCookie(name, value, seconds) {
|
2058
2064
|
try {
|
2059
2065
|
document.cookie =
|
2060
|
-
|
2061
|
-
|
2062
|
-
|
2063
|
-
|
2064
|
-
|
2066
|
+
name +
|
2067
|
+
"=" +
|
2068
|
+
escape(value) +
|
2069
|
+
(seconds ? "; max-age=" + seconds : "") +
|
2070
|
+
"; path=/; SameSite=Lax";
|
2065
2071
|
}
|
2066
2072
|
catch (e) {
|
2067
2073
|
logger.logEvent(LogEvent.CookieSetError);
|
@@ -2111,7 +2117,7 @@
|
|
2111
2117
|
// bfcache. Since we have no "onload" event to hook into after a bfcache restore, we rely on the
|
2112
2118
|
// unload and maxMeasureTime handlers to send the beacon.
|
2113
2119
|
if (globalConfig.newBeaconOnPageShow) {
|
2114
|
-
|
2120
|
+
addEventListener("pageshow", function (event) {
|
2115
2121
|
if (event.persisted) {
|
2116
2122
|
// Record the timestamp of the bfcache restore
|
2117
2123
|
pageRestoreTime = event.timeStamp;
|
@@ -2141,9 +2147,9 @@
|
|
2141
2147
|
// Set the maximum measurement timer
|
2142
2148
|
createMaxMeasureTimeout();
|
2143
2149
|
/**
|
2144
|
-
|
2145
|
-
|
2146
|
-
|
2150
|
+
* LUX functions and properties must be attached to the existing global object to ensure that
|
2151
|
+
* changes made to the global object are reflected in the "internal" LUX object, and vice versa.
|
2152
|
+
*/
|
2147
2153
|
var globalLux = globalConfig;
|
2148
2154
|
// Functions
|
2149
2155
|
globalLux.mark = _mark;
|
@@ -2168,8 +2174,8 @@
|
|
2168
2174
|
// Public properties
|
2169
2175
|
globalLux.version = SCRIPT_VERSION;
|
2170
2176
|
/**
|
2171
|
-
|
2172
|
-
|
2177
|
+
* Run a command from the command queue
|
2178
|
+
*/
|
2173
2179
|
function _runCommand(_a) {
|
2174
2180
|
var fn = _a[0], args = _a.slice(1);
|
2175
2181
|
if (typeof globalLux[fn] === "function") {
|