clarity-js 0.7.7 → 0.7.8
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/build/clarity.insight.js +1 -1
- package/build/clarity.js +144 -68
- package/build/clarity.min.js +1 -1
- package/build/clarity.module.js +144 -68
- package/build/clarity.performance.js +1 -0
- package/package.json +2 -1
- package/rollup.config.ts +22 -0
- package/src/core/config.ts +2 -1
- package/src/core/scrub.ts +8 -5
- package/src/core/version.ts +1 -1
- package/src/data/extract.ts +1 -1
- package/src/data/limit.ts +1 -0
- package/src/data/metadata.ts +24 -14
- package/src/data/variable.ts +43 -5
- package/src/interaction/click.ts +3 -3
- package/src/performance/blank.ts +7 -0
- package/types/core.d.ts +2 -1
- package/types/data.d.ts +28 -7
- package/types/index.d.ts +1 -1
package/build/clarity.module.js
CHANGED
|
@@ -126,7 +126,8 @@ var config$1 = {
|
|
|
126
126
|
upload: null,
|
|
127
127
|
fallback: null,
|
|
128
128
|
upgrade: null,
|
|
129
|
-
action: null
|
|
129
|
+
action: null,
|
|
130
|
+
dob: null
|
|
130
131
|
};
|
|
131
132
|
|
|
132
133
|
function api(method) {
|
|
@@ -149,7 +150,7 @@ function stop$D() {
|
|
|
149
150
|
startTime = 0;
|
|
150
151
|
}
|
|
151
152
|
|
|
152
|
-
var version$1 = "0.7.
|
|
153
|
+
var version$1 = "0.7.8";
|
|
153
154
|
|
|
154
155
|
// tslint:disable: no-bitwise
|
|
155
156
|
function hash (input, precision) {
|
|
@@ -189,7 +190,7 @@ function text$1(value, hint, privacy, mangle) {
|
|
|
189
190
|
case "value":
|
|
190
191
|
case "placeholder":
|
|
191
192
|
case "click":
|
|
192
|
-
return redact(value);
|
|
193
|
+
return redact$1(value);
|
|
193
194
|
case "input":
|
|
194
195
|
case "change":
|
|
195
196
|
return mangleToken(value);
|
|
@@ -233,7 +234,7 @@ function text$1(value, hint, privacy, mangle) {
|
|
|
233
234
|
switch (hint) {
|
|
234
235
|
case "*T" /* Layout.Constant.TextTag */:
|
|
235
236
|
case "data-" /* Layout.Constant.DataAttribute */:
|
|
236
|
-
return scrub(value);
|
|
237
|
+
return scrub(value, "\u25AA" /* Data.Constant.Letter */, "\u25AB" /* Data.Constant.Digit */);
|
|
237
238
|
case "value":
|
|
238
239
|
case "input":
|
|
239
240
|
case "click":
|
|
@@ -251,7 +252,12 @@ function text$1(value, hint, privacy, mangle) {
|
|
|
251
252
|
}
|
|
252
253
|
return value;
|
|
253
254
|
}
|
|
254
|
-
function url$1(input) {
|
|
255
|
+
function url$1(input, electron) {
|
|
256
|
+
if (electron === void 0) { electron = false; }
|
|
257
|
+
// Replace the URL for Electron apps so we don't send back file:/// URL
|
|
258
|
+
if (electron) {
|
|
259
|
+
return "".concat("https://" /* Data.Constant.HTTPS */).concat("Electron" /* Data.Constant.Electron */);
|
|
260
|
+
}
|
|
255
261
|
var drop = config$1.drop;
|
|
256
262
|
if (drop && drop.length > 0 && input && input.indexOf("?") > 0) {
|
|
257
263
|
var _a = input.split("?"), path = _a[0], query = _a[1];
|
|
@@ -274,9 +280,9 @@ function mangleText(value) {
|
|
|
274
280
|
function mask(value) {
|
|
275
281
|
return value.replace(catchallRegex, "\u2022" /* Data.Constant.Mask */);
|
|
276
282
|
}
|
|
277
|
-
function scrub(value) {
|
|
283
|
+
function scrub(value, letter, digit) {
|
|
278
284
|
regex(); // Initialize regular expressions
|
|
279
|
-
return value.replace(letterRegex,
|
|
285
|
+
return value ? value.replace(letterRegex, letter).replace(digitRegex, digit) : value;
|
|
280
286
|
}
|
|
281
287
|
function mangleToken(value) {
|
|
282
288
|
var length = ((Math.floor(value.length / 5 /* Data.Setting.WordLength */) + 1) * 5 /* Data.Setting.WordLength */);
|
|
@@ -300,7 +306,7 @@ function regex() {
|
|
|
300
306
|
}
|
|
301
307
|
}
|
|
302
308
|
}
|
|
303
|
-
function redact(value) {
|
|
309
|
+
function redact$1(value) {
|
|
304
310
|
var spaceIndex = -1;
|
|
305
311
|
var gap = 0;
|
|
306
312
|
var hasDigit = false;
|
|
@@ -325,7 +331,7 @@ function redact(value) {
|
|
|
325
331
|
// Check if unicode regex is supported, otherwise fallback to calling mask function on this token
|
|
326
332
|
if (unicodeRegex && currencyRegex !== null) {
|
|
327
333
|
// Do not redact information if the token contains a currency symbol
|
|
328
|
-
token = token.match(currencyRegex) ? token : token
|
|
334
|
+
token = token.match(currencyRegex) ? token : scrub(token, "\u25AA" /* Data.Constant.Letter */, "\u25AB" /* Data.Constant.Digit */);
|
|
329
335
|
}
|
|
330
336
|
else {
|
|
331
337
|
token = mask(token);
|
|
@@ -626,57 +632,6 @@ var upgrade$1 = /*#__PURE__*/Object.freeze({
|
|
|
626
632
|
upgrade: upgrade
|
|
627
633
|
});
|
|
628
634
|
|
|
629
|
-
var data$e = null;
|
|
630
|
-
function start$A() {
|
|
631
|
-
reset$m();
|
|
632
|
-
}
|
|
633
|
-
function set(variable, value) {
|
|
634
|
-
var values = typeof value === "string" /* Constant.String */ ? [value] : value;
|
|
635
|
-
log$2(variable, values);
|
|
636
|
-
}
|
|
637
|
-
function identify(userId, sessionId, pageId) {
|
|
638
|
-
if (sessionId === void 0) { sessionId = null; }
|
|
639
|
-
if (pageId === void 0) { pageId = null; }
|
|
640
|
-
log$2("userId" /* Constant.UserId */, [userId]);
|
|
641
|
-
log$2("sessionId" /* Constant.SessionId */, [sessionId]);
|
|
642
|
-
log$2("pageId" /* Constant.PageId */, [pageId]);
|
|
643
|
-
}
|
|
644
|
-
function log$2(variable, value) {
|
|
645
|
-
if (active() &&
|
|
646
|
-
variable &&
|
|
647
|
-
value &&
|
|
648
|
-
typeof variable === "string" /* Constant.String */ &&
|
|
649
|
-
variable.length < 255) {
|
|
650
|
-
var validValues = variable in data$e ? data$e[variable] : [];
|
|
651
|
-
for (var i = 0; i < value.length; i++) {
|
|
652
|
-
if (typeof value[i] === "string" /* Constant.String */ && value[i].length < 255) {
|
|
653
|
-
validValues.push(value[i]);
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
data$e[variable] = validValues;
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
function compute$9() {
|
|
660
|
-
encode$1(34 /* Event.Variable */);
|
|
661
|
-
}
|
|
662
|
-
function reset$m() {
|
|
663
|
-
data$e = {};
|
|
664
|
-
}
|
|
665
|
-
function stop$x() {
|
|
666
|
-
reset$m();
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
var variable = /*#__PURE__*/Object.freeze({
|
|
670
|
-
__proto__: null,
|
|
671
|
-
compute: compute$9,
|
|
672
|
-
get data () { return data$e; },
|
|
673
|
-
identify: identify,
|
|
674
|
-
reset: reset$m,
|
|
675
|
-
set: set,
|
|
676
|
-
start: start$A,
|
|
677
|
-
stop: stop$x
|
|
678
|
-
});
|
|
679
|
-
|
|
680
635
|
/******************************************************************************
|
|
681
636
|
Copyright (c) Microsoft Corporation.
|
|
682
637
|
|
|
@@ -730,6 +685,113 @@ function __generator(thisArg, body) {
|
|
|
730
685
|
}
|
|
731
686
|
}
|
|
732
687
|
|
|
688
|
+
var data$e = null;
|
|
689
|
+
function start$A() {
|
|
690
|
+
reset$m();
|
|
691
|
+
}
|
|
692
|
+
function set(variable, value) {
|
|
693
|
+
var values = typeof value === "string" /* Constant.String */ ? [value] : value;
|
|
694
|
+
log$2(variable, values);
|
|
695
|
+
}
|
|
696
|
+
function identify(userId, sessionId, pageId, userHint) {
|
|
697
|
+
if (sessionId === void 0) { sessionId = null; }
|
|
698
|
+
if (pageId === void 0) { pageId = null; }
|
|
699
|
+
if (userHint === void 0) { userHint = null; }
|
|
700
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
701
|
+
var output;
|
|
702
|
+
var _a;
|
|
703
|
+
return __generator(this, function (_b) {
|
|
704
|
+
switch (_b.label) {
|
|
705
|
+
case 0:
|
|
706
|
+
_a = {};
|
|
707
|
+
return [4 /*yield*/, sha256(userId)];
|
|
708
|
+
case 1:
|
|
709
|
+
output = (_a.userId = _b.sent(), _a.userHint = userHint || redact(userId), _a);
|
|
710
|
+
// By default, hash custom userId using SHA256 algorithm on the client to preserve privacy
|
|
711
|
+
log$2("userId" /* Constant.UserId */, [output.userId]);
|
|
712
|
+
// Optional non-identifying name for the user
|
|
713
|
+
// If name is not explicitly provided, we automatically generate a redacted version of the userId
|
|
714
|
+
log$2("userHint" /* Constant.UserHint */, [output.userHint]);
|
|
715
|
+
log$2("userType" /* Constant.UserType */, [detect(userId)]);
|
|
716
|
+
// Log sessionId and pageId if provided
|
|
717
|
+
if (sessionId) {
|
|
718
|
+
log$2("sessionId" /* Constant.SessionId */, [sessionId]);
|
|
719
|
+
output.sessionId = sessionId;
|
|
720
|
+
}
|
|
721
|
+
if (pageId) {
|
|
722
|
+
log$2("pageId" /* Constant.PageId */, [pageId]);
|
|
723
|
+
output.pageId = pageId;
|
|
724
|
+
}
|
|
725
|
+
return [2 /*return*/, output];
|
|
726
|
+
}
|
|
727
|
+
});
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
function log$2(variable, value) {
|
|
731
|
+
if (active() &&
|
|
732
|
+
variable &&
|
|
733
|
+
value &&
|
|
734
|
+
typeof variable === "string" /* Constant.String */ &&
|
|
735
|
+
variable.length < 255) {
|
|
736
|
+
var validValues = variable in data$e ? data$e[variable] : [];
|
|
737
|
+
for (var i = 0; i < value.length; i++) {
|
|
738
|
+
if (typeof value[i] === "string" /* Constant.String */ && value[i].length < 255) {
|
|
739
|
+
validValues.push(value[i]);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
data$e[variable] = validValues;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
function compute$9() {
|
|
746
|
+
encode$1(34 /* Event.Variable */);
|
|
747
|
+
}
|
|
748
|
+
function reset$m() {
|
|
749
|
+
data$e = {};
|
|
750
|
+
}
|
|
751
|
+
function stop$x() {
|
|
752
|
+
reset$m();
|
|
753
|
+
}
|
|
754
|
+
function redact(input) {
|
|
755
|
+
return input && input.length >= 5 /* Setting.WordLength */ ?
|
|
756
|
+
"".concat(input.substring(0, 2)).concat(scrub(input.substring(2), "*" /* Constant.Asterix */, "*" /* Constant.Asterix */)) : scrub(input, "*" /* Constant.Asterix */, "*" /* Constant.Asterix */);
|
|
757
|
+
}
|
|
758
|
+
function sha256(input) {
|
|
759
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
760
|
+
var buffer;
|
|
761
|
+
return __generator(this, function (_b) {
|
|
762
|
+
switch (_b.label) {
|
|
763
|
+
case 0:
|
|
764
|
+
_b.trys.push([0, 4, , 5]);
|
|
765
|
+
if (!(crypto && input)) return [3 /*break*/, 2];
|
|
766
|
+
return [4 /*yield*/, crypto.subtle.digest("SHA-256" /* Constant.SHA256 */, new TextEncoder().encode(input))];
|
|
767
|
+
case 1:
|
|
768
|
+
buffer = _b.sent();
|
|
769
|
+
return [2 /*return*/, Array.prototype.map.call(new Uint8Array(buffer), function (x) { return (('00' + x.toString(16)).slice(-2)); }).join('')];
|
|
770
|
+
case 2: return [2 /*return*/, "" /* Constant.Empty */];
|
|
771
|
+
case 3: return [3 /*break*/, 5];
|
|
772
|
+
case 4:
|
|
773
|
+
_b.sent();
|
|
774
|
+
return [2 /*return*/, "" /* Constant.Empty */];
|
|
775
|
+
case 5: return [2 /*return*/];
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
function detect(input) {
|
|
781
|
+
return input && input.indexOf("@" /* Constant.At */) > 0 ? "email" /* Constant.Email */ : "string" /* Constant.String */;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
var variable = /*#__PURE__*/Object.freeze({
|
|
785
|
+
__proto__: null,
|
|
786
|
+
compute: compute$9,
|
|
787
|
+
get data () { return data$e; },
|
|
788
|
+
identify: identify,
|
|
789
|
+
reset: reset$m,
|
|
790
|
+
set: set,
|
|
791
|
+
start: start$A,
|
|
792
|
+
stop: stop$x
|
|
793
|
+
});
|
|
794
|
+
|
|
733
795
|
var supported$1 = "CompressionStream" /* Constant.CompressionStream */ in window;
|
|
734
796
|
function compress (input) {
|
|
735
797
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -1970,10 +2032,10 @@ function text(element) {
|
|
|
1970
2032
|
// Grab text using "textContent" for most HTMLElements, however, use "value" for HTMLInputElements and "alt" for HTMLImageElement.
|
|
1971
2033
|
var t = element.textContent || element.value || element.alt;
|
|
1972
2034
|
if (t) {
|
|
1973
|
-
//
|
|
1974
|
-
// Also,
|
|
2035
|
+
// Replace multiple occurrence of space characters with a single white space
|
|
2036
|
+
// Also, trim any spaces at the beginning or at the end of string
|
|
1975
2037
|
// Finally, send only first few characters as specified by the Setting
|
|
1976
|
-
output = t.
|
|
2038
|
+
output = t.replace(/\s+/g, " " /* Constant.Space */).trim().substr(0, 25 /* Setting.ClickText */);
|
|
1977
2039
|
}
|
|
1978
2040
|
}
|
|
1979
2041
|
return output;
|
|
@@ -3730,7 +3792,7 @@ function compute$4() {
|
|
|
3730
3792
|
var selectorKey = parseInt(s);
|
|
3731
3793
|
var nodes = document.querySelectorAll(selectorData[selectorKey]);
|
|
3732
3794
|
if (nodes) {
|
|
3733
|
-
var text = Array.from(nodes).map(function (e) { return e.
|
|
3795
|
+
var text = Array.from(nodes).map(function (e) { return e.textContent; });
|
|
3734
3796
|
update(key, selectorKey, text.join("<SEP>" /* Constant.Seperator */).substring(0, 10000 /* Setting.ExtractLimit */));
|
|
3735
3797
|
}
|
|
3736
3798
|
}
|
|
@@ -3957,6 +4019,7 @@ function check$2(bytes) {
|
|
|
3957
4019
|
if (data$4.check === 0 /* Check.None */) {
|
|
3958
4020
|
var reason = data$4.check;
|
|
3959
4021
|
reason = data$1.sequence >= 128 /* Setting.PayloadLimit */ ? 1 /* Check.Payload */ : reason;
|
|
4022
|
+
reason = data$1.pageNum >= 128 /* Setting.PageLimit */ ? 7 /* Check.Page */ : reason;
|
|
3960
4023
|
reason = time() > 7200000 /* Setting.ShutdownLimit */ ? 2 /* Check.Shutdown */ : reason;
|
|
3961
4024
|
reason = bytes > 10485760 /* Setting.PlaybackBytesLimit */ ? 2 /* Check.Shutdown */ : reason;
|
|
3962
4025
|
if (reason !== data$4.check) {
|
|
@@ -4025,6 +4088,7 @@ function start$9() {
|
|
|
4025
4088
|
rootDomain = null;
|
|
4026
4089
|
var ua = navigator && "userAgent" in navigator ? navigator.userAgent : "" /* Constant.Empty */;
|
|
4027
4090
|
var title = document && document.title ? document.title : "" /* Constant.Empty */;
|
|
4091
|
+
var electron = ua.indexOf("Electron" /* Constant.Electron */) > 0 ? 1 /* BooleanFlag.True */ : 0 /* BooleanFlag.False */;
|
|
4028
4092
|
// Populate ids for this page
|
|
4029
4093
|
var s = session();
|
|
4030
4094
|
var u = user();
|
|
@@ -4036,15 +4100,18 @@ function start$9() {
|
|
|
4036
4100
|
// Log page metadata as dimensions
|
|
4037
4101
|
log(0 /* Dimension.UserAgent */, ua);
|
|
4038
4102
|
log(3 /* Dimension.PageTitle */, title);
|
|
4039
|
-
log(1 /* Dimension.Url */, url$1(location.href));
|
|
4103
|
+
log(1 /* Dimension.Url */, url$1(location.href, !!electron));
|
|
4040
4104
|
log(2 /* Dimension.Referrer */, document.referrer);
|
|
4041
4105
|
log(15 /* Dimension.TabId */, tab());
|
|
4042
4106
|
log(16 /* Dimension.PageLanguage */, document.documentElement.lang);
|
|
4043
4107
|
log(17 /* Dimension.DocumentDirection */, document.dir);
|
|
4044
4108
|
log(26 /* Dimension.DevicePixelRatio */, "".concat(window.devicePixelRatio));
|
|
4109
|
+
log(28 /* Dimension.Dob */, u.dob.toString());
|
|
4110
|
+
log(29 /* Dimension.CookieVersion */, u.version.toString());
|
|
4045
4111
|
// Capture additional metadata as metrics
|
|
4046
4112
|
max(0 /* Metric.ClientTimestamp */, s.ts);
|
|
4047
4113
|
max(1 /* Metric.Playback */, 0 /* BooleanFlag.False */);
|
|
4114
|
+
max(35 /* Metric.Electron */, electron);
|
|
4048
4115
|
// Capture navigator specific dimensions
|
|
4049
4116
|
if (navigator) {
|
|
4050
4117
|
log(9 /* Dimension.Language */, navigator.language);
|
|
@@ -4156,9 +4223,12 @@ function track(u, consent) {
|
|
|
4156
4223
|
// Convert time precision into days to reduce number of bytes we have to write in a cookie
|
|
4157
4224
|
// E.g. Math.ceil(1628735962643 / (24*60*60*1000)) => 18852 (days) => ejo in base36 (13 bytes => 3 bytes)
|
|
4158
4225
|
var end = Math.ceil((Date.now() + (365 /* Setting.Expire */ * 86400000 /* Time.Day */)) / 86400000 /* Time.Day */);
|
|
4226
|
+
// If DOB is not set in the user object, use the date set in the config as a DOB
|
|
4227
|
+
var dob = u.dob === 0 ? (config$1.dob === null ? 0 : config$1.dob) : u.dob;
|
|
4159
4228
|
// To avoid cookie churn, write user id cookie only once every day
|
|
4160
|
-
if (u.expiry === null || Math.abs(end - u.expiry) >= 1 /* Setting.CookieInterval */ || u.consent !== consent) {
|
|
4161
|
-
|
|
4229
|
+
if (u.expiry === null || Math.abs(end - u.expiry) >= 1 /* Setting.CookieInterval */ || u.consent !== consent || u.dob !== dob) {
|
|
4230
|
+
var cookieParts = [data$2.userId, 2 /* Setting.CookieVersion */, end.toString(36), consent, dob];
|
|
4231
|
+
setCookie("_clck" /* Constant.CookieKey */, cookieParts.join("|" /* Constant.Pipe */), 365 /* Setting.Expire */);
|
|
4162
4232
|
}
|
|
4163
4233
|
}
|
|
4164
4234
|
function shortid() {
|
|
@@ -4189,7 +4259,7 @@ function num(string, base) {
|
|
|
4189
4259
|
return parseInt(string, base);
|
|
4190
4260
|
}
|
|
4191
4261
|
function user() {
|
|
4192
|
-
var output = { id: shortid(), expiry: null, consent: 0 /* BooleanFlag.False
|
|
4262
|
+
var output = { id: shortid(), version: 0, expiry: null, consent: 0 /* BooleanFlag.False */, dob: 0 };
|
|
4193
4263
|
var cookie = getCookie("_clck" /* Constant.CookieKey */);
|
|
4194
4264
|
if (cookie && cookie.length > 0) {
|
|
4195
4265
|
// Splitting and looking up first part for forward compatibility, in case we wish to store additional information in a cookie
|
|
@@ -4212,6 +4282,9 @@ function user() {
|
|
|
4212
4282
|
}
|
|
4213
4283
|
// End code for backward compatibility
|
|
4214
4284
|
// Read version information and timestamp from cookie, if available
|
|
4285
|
+
if (parts.length > 1) {
|
|
4286
|
+
output.version = num(parts[1]);
|
|
4287
|
+
}
|
|
4215
4288
|
if (parts.length > 2) {
|
|
4216
4289
|
output.expiry = num(parts[2], 36);
|
|
4217
4290
|
}
|
|
@@ -4219,6 +4292,9 @@ function user() {
|
|
|
4219
4292
|
if (parts.length > 3 && num(parts[3]) === 1) {
|
|
4220
4293
|
output.consent = 1 /* BooleanFlag.True */;
|
|
4221
4294
|
}
|
|
4295
|
+
if (parts.length > 4 && num(parts[1]) > 1) {
|
|
4296
|
+
output.dob = num(parts[4]);
|
|
4297
|
+
}
|
|
4222
4298
|
// Set track configuration to true for this user if we have explicit consent, regardless of project setting
|
|
4223
4299
|
config$1.track = config$1.track || output.consent === 1 /* BooleanFlag.True */;
|
|
4224
4300
|
// Get user id from cookie only if we tracking is enabled, otherwise fallback to a random id
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(){"use strict";var t=Object.freeze({__proto__:null,get queue(){return ht},get start(){return ft},get stop(){return vt},get track(){return ct}}),n=Object.freeze({__proto__:null,get check(){return _t},get compute(){return Et},get data(){return it},get start(){return kt},get stop(){return It},get trigger(){return St}}),e=Object.freeze({__proto__:null,get compute(){return zt},get data(){return Mt},get log(){return jt},get reset(){return qt},get start(){return Ot},get stop(){return Tt},get updates(){return xt}}),r=Object.freeze({__proto__:null,get callbacks(){return At},get clear(){return Bt},get consent(){return Ut},get data(){return Ct},get id(){return Ht},get metadata(){return Dt},get save(){return Vt},get start(){return Rt},get stop(){return Pt}}),o=Object.freeze({__proto__:null,get data(){return Kt},get envelope(){return tn},get start(){return Qt},get stop(){return $t}}),a={projectId:null,delay:1e3,lean:!1,track:!0,content:!0,drop:[],mask:[],unmask:[],regions:[],cookies:[],fraud:!0,checksum:[],report:null,upload:null,fallback:null,upgrade:null,action:null,dob:null};function u(t){return window.Zone&&"__symbol__"in window.Zone?window.Zone.__symbol__(t):t}var c=0;function i(t){void 0===t&&(t=null);var n=t&&t.timeStamp>0?t.timeStamp:performance.now();return Math.max(Math.round(n-c),0)}var s="0.7.8";var l=!0,p=null,d=null;function f(t,n,e){return function(){if(l&&null===p)try{p=new RegExp("\\p{N}","gu"),d=new RegExp("\\p{L}","gu"),new RegExp("\\p{Sc}","gu")}catch(t){l=!1}}(),t?t.replace(d,n).replace(p,e):t}var h=[],v=null;function g(){}var m=[];function y(){}function b(){}var w=Object.freeze({__proto__:null,compute:function(){},data:v,hashText:y,keys:m,log:g,observe:function(){},reset:function(){},start:function(){},state:h,stop:function(){},trigger:b}),k=null;function _(t,n){Mn()&&t&&n&&"string"==typeof t&&"string"==typeof n&&t.length<255&&n.length<255&&(k={key:t,value:n},wt(24))}var S,E=null,I=null;function M(t){t in E||(E[t]=0),t in I||(I[t]=0),E[t]++,I[t]++}function x(t,n){null!==n&&(t in E||(E[t]=0),t in I||(I[t]=0),E[t]+=n,I[t]+=n)}function O(t,n){null!==n&&!1===isNaN(n)&&(t in E||(E[t]=0),(n>E[t]||0===E[t])&&(I[t]=n,E[t]=n))}function T(t,n,e){return window.setTimeout(rn(t),n,e)}function j(t){return window.clearTimeout(t)}var z=0,q=0,C=null;function A(){C&&j(C),C=T(N,q),z=i()}function N(){var t=i();S={gap:t-z},wt(25),S.gap<3e5?C=T(N,q):Sn&&(_("clarity","suspend"),Hn(),["mousemove","touchstart"].forEach((function(t){return an(document,t,On)})),["resize","scroll","pageshow"].forEach((function(t){return an(window,t,On)})))}var R=Object.freeze({__proto__:null,get data(){return S},reset:A,start:function(){q=6e4,z=0},stop:function(){j(C),z=0,q=0}}),P=null;function D(t){Mn()&&a.lean&&(a.lean=!1,P={key:t},Vt(),a.upgrade&&a.upgrade(t),wt(3))}var H=Object.freeze({__proto__:null,get data(){return P},start:function(){!a.lean&&a.upgrade&&a.upgrade("Config"),P=null},stop:function(){P=null},upgrade:D});function U(t,n,e,r){return new(e||(e=Promise))((function(o,a){function u(t){try{i(r.next(t))}catch(t){a(t)}}function c(t){try{i(r.throw(t))}catch(t){a(t)}}function i(t){var n;t.done?o(t.value):(n=t.value,n instanceof e?n:new e((function(t){t(n)}))).then(u,c)}i((r=r.apply(t,n||[])).next())}))}function B(t,n){var e,r,o,a,u={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function c(c){return function(i){return function(c){if(e)throw new TypeError("Generator is already executing.");for(;a&&(a=0,c[0]&&(u=0)),u;)try{if(e=1,r&&(o=2&c[0]?r.return:c[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,c[1])).done)return o;switch(r=0,o&&(c=[2&c[0],o.value]),c[0]){case 0:case 1:o=c;break;case 4:return u.label++,{value:c[1],done:!1};case 5:u.label++,r=c[1],c=[0];continue;case 7:c=u.ops.pop(),u.trys.pop();continue;default:if(!(o=u.trys,(o=o.length>0&&o[o.length-1])||6!==c[0]&&2!==c[0])){u=0;continue}if(3===c[0]&&(!o||c[1]>o[0]&&c[1]<o[3])){u.label=c[1];break}if(6===c[0]&&u.label<o[1]){u.label=o[1],o=c;break}if(o&&u.label<o[2]){u.label=o[2],u.ops.push(c);break}o[2]&&u.ops.pop(),u.trys.pop();continue}c=n.call(t,u)}catch(t){c=[6,t],r=0}finally{e=o=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}([c,i])}}}var V=null;function L(t,n){W(t,"string"==typeof n?[n]:n)}function X(t,n,e,r){return void 0===n&&(n=null),void 0===e&&(e=null),void 0===r&&(r=null),U(this,void 0,void 0,(function(){var o,a;return B(this,(function(u){switch(u.label){case 0:return a={},[4,G(t)];case 1:return a.userId=u.sent(),a.userHint=r||((c=t)&&c.length>=5?"".concat(c.substring(0,2)).concat(f(c.substring(2),"*","*")):f(c,"*","*")),W("userId",[(o=a).userId]),W("userHint",[o.userHint]),W("userType",[Y(t)]),n&&(W("sessionId",[n]),o.sessionId=n),e&&(W("pageId",[e]),o.pageId=e),[2,o]}var c}))}))}function W(t,n){if(Mn()&&t&&n&&"string"==typeof t&&t.length<255){for(var e=(t in V?V[t]:[]),r=0;r<n.length;r++)"string"==typeof n[r]&&n[r].length<255&&e.push(n[r]);V[t]=e}}function J(){wt(34)}function Z(){V={}}function G(t){return U(this,void 0,void 0,(function(){var n;return B(this,(function(e){switch(e.label){case 0:return e.trys.push([0,4,,5]),crypto&&t?[4,crypto.subtle.digest("SHA-256",(new TextEncoder).encode(t))]:[3,2];case 1:return n=e.sent(),[2,Array.prototype.map.call(new Uint8Array(n),(function(t){return("00"+t.toString(16)).slice(-2)})).join("")];case 2:return[2,""];case 3:return[3,5];case 4:return e.sent(),[2,""];case 5:return[2]}}))}))}function Y(t){return t&&t.indexOf("@")>0?"email":"string"}var F="CompressionStream"in window;function K(t){return U(this,void 0,void 0,(function(){var n,e;return B(this,(function(r){switch(r.label){case 0:return r.trys.push([0,3,,4]),F?(n=new ReadableStream({start:function(n){return U(this,void 0,void 0,(function(){return B(this,(function(e){return n.enqueue(t),n.close(),[2]}))}))}}).pipeThrough(new TextEncoderStream).pipeThrough(new window.CompressionStream("gzip")),e=Uint8Array.bind,[4,Q(n)]):[3,2];case 1:return[2,new(e.apply(Uint8Array,[void 0,r.sent()]))];case 2:return[3,4];case 3:return r.sent(),[3,4];case 4:return[2,null]}}))}))}function Q(t){return U(this,void 0,void 0,(function(){var n,e,r,o,a;return B(this,(function(u){switch(u.label){case 0:n=t.getReader(),e=[],r=!1,o=[],u.label=1;case 1:return r?[3,3]:[4,n.read()];case 2:return a=u.sent(),r=a.done,o=a.value,r?[2,e]:(e.push.apply(e,o),[3,1]);case 3:return[2,e]}}))}))}var $=[w,e,Object.freeze({__proto__:null,compute:J,get data(){return V},identify:X,reset:Z,set:L,start:function(){Z()},stop:function(){Z()}}),n,w,r,o,t,R,H,w];function tt(){E={},I={},M(5),$.forEach((function(t){return rn(t.start)()}))}function nt(){$.slice().reverse().forEach((function(t){return rn(t.stop)()})),E={},I={}}function et(){J(),zt(),wt(0),Et()}var rt,ot,at,ut,ct,it,st=0,lt=0,pt=null,dt=0;function ft(){ut=!0,st=0,lt=0,dt=0,rt=[],ot=[],at={},ct=null}function ht(t,n){if(void 0===n&&(n=!0),ut){var e=i(),r=t.length>1?t[1]:null,o=JSON.stringify(t);switch(r){case 5:st+=o.length;case 37:case 6:case 43:lt+=o.length,rt.push(o);break;default:ot.push(o)}M(25);var u=function(){var t=!1===a.lean&&st>0?100:Kt.sequence*a.delay;return"string"==typeof a.upload?Math.max(Math.min(t,3e4),100):a.delay}();e-dt>2*u&&(j(pt),pt=null),n&&null===pt&&(25!==r&&A(),pt=T(gt,u),dt=e,_t(lt))}}function vt(){j(pt),gt(!0),st=0,lt=0,dt=0,rt=[],ot=[],at={},ct=null,ut=!1}function gt(t){return void 0===t&&(t=!1),U(this,void 0,void 0,(function(){var n,e,r,o,u,c,i,s;return B(this,(function(l){switch(l.label){case 0:return pt=null,(n=!1===a.lean&<>0&&(lt<1048576||Kt.sequence>0))&&O(1,1),et(),e=!0===t,r=JSON.stringify(tn(e)),o="[".concat(ot.join(),"]"),u=n?"[".concat(rt.join(),"]"):"",c=function(t){return t.p.length>0?'{"e":'.concat(t.e,',"a":').concat(t.a,',"p":').concat(t.p,"}"):'{"e":'.concat(t.e,',"a":').concat(t.a,"}")}({e:r,a:o,p:u}),e?(s=null,[3,3]):[3,1];case 1:return[4,K(c)];case 2:s=l.sent(),l.label=3;case 3:return x(2,(i=s)?i.length:c.length),mt(c,i,Kt.sequence,e),ot=[],n&&(rt=[],lt=0,st=0),[2]}}))}))}function mt(t,n,e,r){if(void 0===r&&(r=!1),"string"==typeof a.upload){var o=a.upload,u=!1;if(r&&"sendBeacon"in navigator)try{(u=navigator.sendBeacon.bind(navigator)(o,t))&&bt(e)}catch(t){}if(!1===u){e in at?at[e].attempts++:at[e]={data:t,attempts:1};var c=new XMLHttpRequest;c.open("POST",o,!0),c.timeout=15e3,c.ontimeout=function(){en(new Error("".concat("Timeout"," : ").concat(o)))},null!==e&&(c.onreadystatechange=function(){rn(yt)(c,e)}),c.withCredentials=!0,n?(c.setRequestHeader("Accept","application/x-clarity-gzip"),c.send(n)):c.send(t)}}else if(a.upload){(0,a.upload)(t),bt(e)}}function yt(t,n){var e=at[n];t&&4===t.readyState&&e&&((t.status<200||t.status>208)&&e.attempts<=1?t.status>=400&&t.status<500?St(6):(0===t.status&&(a.upload=a.fallback?a.fallback:a.upload),mt(e.data,null,n)):(ct={sequence:n,attempts:e.attempts,status:t.status},e.attempts>1&&wt(2),200===t.status&&t.responseText&&function(t){for(var n=t&&t.length>0?t.split("\n"):[],e=0,r=n;e<r.length;e++){var o=r[e],u=o&&o.length>0?o.split(/ (.*)/):[""];switch(u[0]){case"END":St(6);break;case"UPGRADE":D("Auto");break;case"ACTION":a.action&&u.length>1&&a.action(u[1]);break;case"EXTRACT":u.length>1&&u[1]}}}(t.responseText),0===t.status&&(mt(e.data,null,n,!0),St(3)),t.status>=200&&t.status<=208&&bt(n),delete at[n]))}function bt(t){1===t&&Vt()}function wt(t){var n=[i(),t];switch(t){case 4:var e=h;e&&((n=[e.time,e.event]).push(e.data.visible),n.push(e.data.docWidth),n.push(e.data.docHeight),n.push(e.data.screenWidth),n.push(e.data.screenHeight),n.push(e.data.scrollX),n.push(e.data.scrollY),n.push(e.data.pointerX),n.push(e.data.pointerY),n.push(e.data.activityTime),ht(n,!1));break;case 25:n.push(S.gap),ht(n);break;case 35:n.push(it.check),ht(n,!1);break;case 3:n.push(P.key),ht(n);break;case 2:n.push(ct.sequence),n.push(ct.attempts),n.push(ct.status),ht(n,!1);break;case 24:n.push(k.key),n.push(k.value),ht(n);break;case 34:var r=Object.keys(V);if(r.length>0){for(var o=0,a=r;o<a.length;o++){var u=a[o];n.push(u),n.push(V[u])}Z(),ht(n,!1)}break;case 0:var c=Object.keys(I);if(c.length>0){for(var s=0,l=c;s<l.length;s++){var p=l[s],d=parseInt(p,10);n.push(d),n.push(Math.round(I[p]))}I={},ht(n,!1)}break;case 1:var f=Object.keys(xt);if(f.length>0){for(var g=0,y=f;g<y.length;g++){var b=y[g];d=parseInt(b,10);n.push(d),n.push(xt[b])}qt(),ht(n,!1)}break;case 36:var w=Object.keys(v);if(w.length>0){for(var _=0,E=w;_<E.length;_++){var M=E[_];d=parseInt(M,10);n.push(d),n.push([].concat.apply([],v[M]))}ht(n,!1)}break;case 40:m.forEach((function(t){n.push(t);var e=[];for(var r in v[t]){var o=parseInt(r,10);e.push(o),e.push(v[t][r])}n.push(e)})),ht(n,!1)}}function kt(){it={check:0}}function _t(t){if(0===it.check){var n=it.check;n=Kt.sequence>=128?1:n,n=Kt.pageNum>=128?7:n,n=i()>72e5?2:n,(n=t>10485760?2:n)!==it.check&&St(n)}}function St(t){it.check=t,Bt(),Hn()}function Et(){0!==it.check&&wt(35)}function It(){it=null}var Mt=null,xt=null;function Ot(){Mt={},xt={}}function Tt(){Mt={},xt={}}function jt(t,n){n&&(n="".concat(n),t in Mt||(Mt[t]=[]),Mt[t].indexOf(n)<0&&(Mt[t].push(n),t in xt||(xt[t]=[]),xt[t].push(n),Mt[t].length>128&&St(5)))}function zt(){wt(1)}function qt(){xt={}}var Ct=null,At=[],Nt=null;function Rt(){Nt=null;var t,n=navigator&&"userAgent"in navigator?navigator.userAgent:"",e=document&&document.title?document.title:"",r=n.indexOf("Electron")>0?1:0,o=function(){var t={session:Wt(),ts:Math.round(Date.now()),count:1,upgrade:null,upload:""},n=Gt("_clsk");if(n){var e=n.split("|");e.length>=5&&t.ts-Jt(e[1])<18e5&&(t.session=e[0],t.count=Jt(e[2])+1,t.upgrade=Jt(e[3]),t.upload=e.length>=6?"".concat("https://").concat(e[5],"/").concat(e[4]):"".concat("https://").concat(e[4]))}return t}(),u=Zt(),c=a.projectId||function(t,n){void 0===n&&(n=null);for(var e,r=5381,o=r,a=0;a<t.length;a+=2)r=(r<<5)+r^t.charCodeAt(a),a+1<t.length&&(o=(o<<5)+o^t.charCodeAt(a+1));return e=Math.abs(r+11579*o),(n?e%Math.pow(2,n):e).toString(36)}(location.host);Ct={projectId:c,userId:u.id,sessionId:o.session,pageNum:o.count},a.lean=a.track&&null!==o.upgrade?0===o.upgrade:a.lean,a.upload=a.track&&"string"==typeof a.upload&&o.upload&&o.upload.length>"https://".length?o.upload:a.upload,jt(0,n),jt(3,e),jt(1,function(t,n){if(void 0===n&&(n=!1),n)return"".concat("https://").concat("Electron");var e=a.drop;if(e&&e.length>0&&t&&t.indexOf("?")>0){var r=t.split("?");return r[0]+"?"+r[1].split("&").map((function(t){return e.some((function(n){return 0===t.indexOf("".concat(n,"="))}))?"".concat(t.split("=")[0],"=").concat("*na*"):t})).join("&")}return t}(location.href,!!r)),jt(2,document.referrer),jt(15,function(){var t=Wt();if(a.track&&Lt(window,"sessionStorage")){var n=sessionStorage.getItem("_cltk");t=n||t,sessionStorage.setItem("_cltk",t)}return t}()),jt(16,document.documentElement.lang),jt(17,document.dir),jt(26,"".concat(window.devicePixelRatio)),jt(28,u.dob.toString()),jt(29,u.version.toString()),O(0,o.ts),O(1,0),O(35,r),navigator&&(jt(9,navigator.language),O(33,navigator.hardwareConcurrency),O(32,navigator.maxTouchPoints),O(34,Math.round(navigator.deviceMemory)),(t=navigator.userAgentData)&&t.getHighEntropyValues?t.getHighEntropyValues(["model","platform","platformVersion","uaFullVersion"]).then((function(t){var n;jt(22,t.platform),jt(23,t.platformVersion),null===(n=t.brands)||void 0===n||n.forEach((function(t){jt(24,t.name+"~"+t.version)})),jt(25,t.model),O(27,t.mobile?1:0)})):jt(22,navigator.platform)),screen&&(O(14,Math.round(screen.width)),O(15,Math.round(screen.height)),O(16,Math.round(screen.colorDepth)));for(var i=0,s=a.cookies;i<s.length;i++){var l=s[i],p=Gt(l);p&&L(l,p)}Xt(u)}function Pt(){Nt=null,Ct=null}function Dt(t,n){void 0===n&&(n=!0);var e=a.lean?0:1;Ct&&(e||!1===n)?t(Ct,!a.lean):At.push({callback:t,wait:n})}function Ht(){return Ct?[Ct.userId,Ct.sessionId,Ct.pageNum].join("."):""}function Ut(){Mn()&&(a.track=!0,Xt(Zt(),1))}function Bt(){Yt("_clsk","",0)}function Vt(){var t=Math.round(Date.now()),n=a.upload&&"string"==typeof a.upload?a.upload.replace("https://",""):"",e=a.lean?0:1;!function(t){At.length>0&&At.forEach((function(n){!n.callback||n.wait&&!t||n.callback(Ct,!a.lean)}))}(e),Yt("_clsk",[Ct.sessionId,t,Ct.pageNum,e,n].join("|"),1)}function Lt(t,n){try{return!!t[n]}catch(t){return!1}}function Xt(t,n){void 0===n&&(n=null),n=null===n?t.consent:n;var e=Math.ceil((Date.now()+31536e6)/864e5),r=0===t.dob?null===a.dob?0:a.dob:t.dob;(null===t.expiry||Math.abs(e-t.expiry)>=1||t.consent!==n||t.dob!==r)&&Yt("_clck",[Ct.userId,2,e.toString(36),n,r].join("|"),365)}function Wt(){var t=Math.floor(Math.random()*Math.pow(2,32));return window&&window.crypto&&window.crypto.getRandomValues&&Uint32Array&&(t=window.crypto.getRandomValues(new Uint32Array(1))[0]),t.toString(36)}function Jt(t,n){return void 0===n&&(n=10),parseInt(t,n)}function Zt(){var t={id:Wt(),version:0,expiry:null,consent:0,dob:0},n=Gt("_clck");if(n&&n.length>0){for(var e=n.split("|"),r=0,o=0,u=document.cookie.split(";");o<u.length;o++){r+="_clck"===u[o].split("=")[0].trim()?1:0}if(1===e.length||r>1){var c="".concat(";").concat("expires=").concat(new Date(0).toUTCString()).concat(";path=/");document.cookie="".concat("_clck","=").concat(c),document.cookie="".concat("_clsk","=").concat(c)}e.length>1&&(t.version=Jt(e[1])),e.length>2&&(t.expiry=Jt(e[2],36)),e.length>3&&1===Jt(e[3])&&(t.consent=1),e.length>4&&Jt(e[1])>1&&(t.dob=Jt(e[4])),a.track=a.track||1===t.consent,t.id=a.track?e[0]:t.id}return t}function Gt(t){if(Lt(document,"cookie")){var n=document.cookie.split(";");if(n)for(var e=0;e<n.length;e++){var r=n[e].split("=");if(r.length>1&&r[0]&&r[0].trim()===t)return r[1]}}return null}function Yt(t,n,e){if(a.track&&(navigator&&navigator.cookieEnabled||Lt(document,"cookie"))){var r=new Date;r.setDate(r.getDate()+e);var o=r?"expires="+r.toUTCString():"",u="".concat(t,"=").concat(n).concat(";").concat(o).concat(";path=/");try{if(null===Nt){for(var c=location.hostname?location.hostname.split("."):[],i=c.length-1;i>=0;i--)if(Nt=".".concat(c[i]).concat(Nt||""),i<c.length-1&&(document.cookie="".concat(u).concat(";").concat("domain=").concat(Nt),Gt(t)===n))return;Nt=""}}catch(t){Nt=""}document.cookie=Nt?"".concat(u).concat(";").concat("domain=").concat(Nt):u}}var Ft,Kt=null;function Qt(){var t=Ct;Kt={version:s,sequence:0,start:0,duration:0,projectId:t.projectId,userId:t.userId,sessionId:t.sessionId,pageNum:t.pageNum,upload:0,end:0}}function $t(){Kt=null}function tn(t){return Kt.start=Kt.start+Kt.duration,Kt.duration=i()-Kt.start,Kt.sequence++,Kt.upload=t&&"sendBeacon"in navigator?1:0,Kt.end=t?1:0,[Kt.version,Kt.sequence,Kt.start,Kt.duration,Kt.projectId,Kt.userId,Kt.sessionId,Kt.pageNum,Kt.upload,Kt.end]}function nn(){Ft=[]}function en(t){if(Ft&&-1===Ft.indexOf(t.message)){var n=a.report;if(n&&n.length>0){var e={v:Kt.version,p:Kt.projectId,u:Kt.userId,s:Kt.sessionId,n:Kt.pageNum};t.message&&(e.m=t.message),t.stack&&(e.e=t.stack);var r=new XMLHttpRequest;r.open("POST",n,!0),r.send(JSON.stringify(e)),Ft.push(t.message)}}return t}function rn(t){return function(){var n=performance.now();try{t.apply(this,arguments)}catch(t){throw en(t)}var e=performance.now()-n;x(4,e),e>30&&(M(7),O(6,e))}}var on=[];function an(t,n,e,r){void 0===r&&(r=!1),e=rn(e);try{t[u("addEventListener")](n,e,r),on.push({event:n,target:t,listener:e,capture:r})}catch(t){}}function un(){for(var t=0,n=on;t<n.length;t++){var e=n[t];try{e.target[u("removeEventListener")](e.event,e.listener,e.capture)}catch(t){}}on=[]}var cn=null,sn=null,ln=null,pn=0;function dn(){return!(pn++>20)}function fn(){pn=0,ln!==vn()&&(Hn(),window.setTimeout(hn,250))}function hn(){Dn(),O(29,1)}function vn(){return location.href?location.href.replace(location.hash,""):location.href}var gn=[],mn=null,yn=null,bn=null;function wn(){yn&&(bn(),yn=null,null===mn&&_n())}function kn(){gn=[],mn=null,yn=null}function _n(){var t=gn.shift();t&&(mn=t,t.task().then((function(){t.id===Ht()&&(t.resolve(),mn=null,_n())})).catch((function(n){t.id===Ht()&&(n&&(n.name,n.message,n.stack),mn=null,_n())})))}var Sn=!1;function En(){Sn=!0,c=performance.now(),kn(),un(),nn(),ln=vn(),pn=0,an(window,"popstate",fn),null===cn&&(cn=history.pushState,history.pushState=function(){cn.apply(this,arguments),Mn()&&dn()&&fn()}),null===sn&&(sn=history.replaceState,history.replaceState=function(){sn.apply(this,arguments),Mn()&&dn()&&fn()})}function In(){ln=null,pn=0,nn(),un(),kn(),c=0,Sn=!1}function Mn(){return Sn}function xn(t){if(null===t||Sn)return!1;for(var n in t)n in a&&(a[n]=t[n]);return!0}function On(){Dn(),_("clarity","restart")}var Tn,jn=null;function zn(){jn=null}function qn(t){jn={fetchStart:Math.round(t.fetchStart),connectStart:Math.round(t.connectStart),connectEnd:Math.round(t.connectEnd),requestStart:Math.round(t.requestStart),responseStart:Math.round(t.responseStart),responseEnd:Math.round(t.responseEnd),domInteractive:Math.round(t.domInteractive),domComplete:Math.round(t.domComplete),loadEventStart:Math.round(t.loadEventStart),loadEventEnd:Math.round(t.loadEventEnd),redirectCount:Math.round(t.redirectCount),size:t.transferSize?t.transferSize:0,type:t.type,protocol:t.nextHopProtocol,encodedSize:t.encodedBodySize?t.encodedBodySize:0,decodedSize:t.decodedBodySize?t.decodedBodySize:0},function(t){U(this,void 0,void 0,(function(){var n,e;return B(this,(function(r){return n=i(),e=[n,t],29===t&&(e.push(jn.fetchStart),e.push(jn.connectStart),e.push(jn.connectEnd),e.push(jn.requestStart),e.push(jn.responseStart),e.push(jn.responseEnd),e.push(jn.domInteractive),e.push(jn.domComplete),e.push(jn.loadEventStart),e.push(jn.loadEventEnd),e.push(jn.redirectCount),e.push(jn.size),e.push(jn.type),e.push(jn.protocol),e.push(jn.encodedSize),e.push(jn.decodedSize),zn(),ht(e,!1)),[2]}))}))}(29)}var Cn=["navigation","resource","longtask","first-input","layout-shift","largest-contentful-paint"];function An(){try{Tn&&Tn.disconnect(),Tn=new PerformanceObserver(rn(Nn));for(var t=0,n=Cn;t<n.length;t++){var e=n[t];PerformanceObserver.supportedEntryTypes.indexOf(e)>=0&&("layout-shift"===e&&x(9,0),Tn.observe({type:e,buffered:!0}))}}catch(t){}}function Nn(t){!function(t){for(var n=(!("visibilityState"in document)||"visible"===document.visibilityState),e=0;e<t.length;e++){var r=t[e];switch(r.entryType){case"navigation":qn(r);break;case"resource":var o=r.name;jt(4,Rn(o)),o!==a.upload&&o!==a.fallback||O(28,r.duration);break;case"longtask":M(7);break;case"first-input":n&&O(10,r.processingStart-r.startTime);break;case"layout-shift":n&&!r.hadRecentInput&&x(9,1e3*r.value);break;case"largest-contentful-paint":n&&O(8,r.startTime)}}}(t.getEntries())}function Rn(t){var n=document.createElement("a");return n.href=t,n.host}var Pn=[w,w,w,Object.freeze({__proto__:null,start:function(){zn(),function(){navigator&&"connection"in navigator&&jt(27,navigator.connection.effectiveType),window.PerformanceObserver&&PerformanceObserver.supportedEntryTypes&&("complete"!==document.readyState?an(window,"load",T.bind(this,An,0)):An())}()},stop:function(){Tn&&Tn.disconnect(),Tn=null,zn()}})];function Dn(t){void 0===t&&(t=null),function(){try{return!1===Sn&&"undefined"!=typeof Promise&&window.MutationObserver&&document.createTreeWalker&&"now"in Date&&"now"in performance&&"undefined"!=typeof WeakMap}catch(t){return!1}}()&&(xn(t),En(),tt(),Pn.forEach((function(t){return rn(t.start)()})),null===t&&Ln())}function Hn(){Mn()&&(Pn.slice().reverse().forEach((function(t){return rn(t.stop)()})),nt(),In(),void 0!==Bn&&(Bn[Vn]=function(){(Bn[Vn].q=Bn[Vn].q||[]).push(arguments),"start"===arguments[0]&&Bn[Vn].q.unshift(Bn[Vn].q.pop())&&Ln()}))}var Un=Object.freeze({__proto__:null,consent:Ut,event:_,hashText:y,identify:X,metadata:Dt,pause:function(){Mn()&&(_("clarity","pause"),null===yn&&(yn=new Promise((function(t){bn=t}))))},resume:function(){Mn()&&(wn(),_("clarity","resume"))},set:L,start:Dn,stop:Hn,upgrade:D,version:s}),Bn=window,Vn="clarity";function Ln(){if(void 0!==Bn){if(Bn[Vn]&&Bn[Vn].v)return console.warn("Error CL001: Multiple Clarity tags detected.");var t=Bn[Vn]&&Bn[Vn].q||[];for(Bn[Vn]=function(t){for(var n=[],e=1;e<arguments.length;e++)n[e-1]=arguments[e];return Un[t].apply(Un,n)},Bn[Vn].v=s;t.length>0;)Bn[Vn].apply(Bn,t.shift())}}Ln()}();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clarity-js",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.8",
|
|
4
4
|
"description": "An analytics library that uses web page interactions to generate aggregated insights",
|
|
5
5
|
"author": "Microsoft Corp.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"module": "build/clarity.module.js",
|
|
9
9
|
"unpkg": "build/clarity.min.js",
|
|
10
10
|
"insight": "build/clarity.insight.js",
|
|
11
|
+
"performance": "build/clarity.performance.js",
|
|
11
12
|
"types": "types/index.d.ts",
|
|
12
13
|
"keywords": [
|
|
13
14
|
"clarity",
|
package/rollup.config.ts
CHANGED
|
@@ -58,5 +58,27 @@ export default [
|
|
|
58
58
|
terser({output: {comments: false}}),
|
|
59
59
|
commonjs({ include: ["node_modules/**"] })
|
|
60
60
|
]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
input: "src/global.ts",
|
|
64
|
+
output: [ { file: pkg.performance, format: "iife", exports: "named" } ],
|
|
65
|
+
onwarn(message, warn) {
|
|
66
|
+
if (message.code === 'CIRCULAR_DEPENDENCY') { return; }
|
|
67
|
+
warn(message);
|
|
68
|
+
},
|
|
69
|
+
plugins: [
|
|
70
|
+
alias({
|
|
71
|
+
entries: [
|
|
72
|
+
{ find: /@src\/interaction.*/, replacement: '@src/performance/blank' },
|
|
73
|
+
{ find: /@src\/layout.*/, replacement: '@src/performance/blank' },
|
|
74
|
+
{ find: /@src\/diagnostic.*/, replacement: '@src/performance/blank' },
|
|
75
|
+
{ find: /@src\/data\/(extract|baseline|summary)/, replacement: '@src/performance/blank' }
|
|
76
|
+
]
|
|
77
|
+
}),
|
|
78
|
+
resolve(),
|
|
79
|
+
typescript(),
|
|
80
|
+
terser({output: {comments: false}}),
|
|
81
|
+
commonjs({ include: ["node_modules/**"] })
|
|
82
|
+
]
|
|
61
83
|
}
|
|
62
84
|
];
|
package/src/core/config.ts
CHANGED
package/src/core/scrub.ts
CHANGED
|
@@ -64,7 +64,7 @@ export function text(value: string, hint: string, privacy: Privacy, mangle: bool
|
|
|
64
64
|
switch (hint) {
|
|
65
65
|
case Layout.Constant.TextTag:
|
|
66
66
|
case Layout.Constant.DataAttribute:
|
|
67
|
-
return scrub(value);
|
|
67
|
+
return scrub(value, Data.Constant.Letter, Data.Constant.Digit);
|
|
68
68
|
case "value":
|
|
69
69
|
case "input":
|
|
70
70
|
case "click":
|
|
@@ -83,7 +83,10 @@ export function text(value: string, hint: string, privacy: Privacy, mangle: bool
|
|
|
83
83
|
return value;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
export function url(input: string): string {
|
|
86
|
+
export function url(input: string, electron: boolean = false): string {
|
|
87
|
+
// Replace the URL for Electron apps so we don't send back file:/// URL
|
|
88
|
+
if (electron) { return `${Data.Constant.HTTPS}${Data.Constant.Electron}`; }
|
|
89
|
+
|
|
87
90
|
let drop = config.drop;
|
|
88
91
|
if (drop && drop.length > 0 && input && input.indexOf("?") > 0) {
|
|
89
92
|
let [path, query] = input.split("?");
|
|
@@ -109,9 +112,9 @@ function mask(value: string): string {
|
|
|
109
112
|
return value.replace(catchallRegex, Data.Constant.Mask);
|
|
110
113
|
}
|
|
111
114
|
|
|
112
|
-
function scrub(value: string): string {
|
|
115
|
+
export function scrub(value: string, letter: string, digit: string): string {
|
|
113
116
|
regex(); // Initialize regular expressions
|
|
114
|
-
return value.replace(letterRegex,
|
|
117
|
+
return value ? value.replace(letterRegex, letter).replace(digitRegex, digit) : value;
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
function mangleToken(value: string): string {
|
|
@@ -161,7 +164,7 @@ function redact(value: string): string {
|
|
|
161
164
|
// Check if unicode regex is supported, otherwise fallback to calling mask function on this token
|
|
162
165
|
if (unicodeRegex && currencyRegex !== null) {
|
|
163
166
|
// Do not redact information if the token contains a currency symbol
|
|
164
|
-
token = token.match(currencyRegex) ? token : token
|
|
167
|
+
token = token.match(currencyRegex) ? token : scrub(token, Data.Constant.Letter, Data.Constant.Digit);
|
|
165
168
|
} else {
|
|
166
169
|
token = mask(token);
|
|
167
170
|
}
|
package/src/core/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
let version = "0.7.
|
|
1
|
+
let version = "0.7.8";
|
|
2
2
|
export default version;
|
package/src/data/extract.ts
CHANGED
|
@@ -81,7 +81,7 @@ export function compute(): void {
|
|
|
81
81
|
let selectorKey = parseInt(s);
|
|
82
82
|
let nodes = document.querySelectorAll(selectorData[selectorKey]) as NodeListOf<HTMLElement>;
|
|
83
83
|
if (nodes) {
|
|
84
|
-
let text = Array.from(nodes).map(e => e.
|
|
84
|
+
let text = Array.from(nodes).map(e => e.textContent)
|
|
85
85
|
update(key, selectorKey, text.join(Constant.Seperator).substring(0, Setting.ExtractLimit));
|
|
86
86
|
}
|
|
87
87
|
}
|
package/src/data/limit.ts
CHANGED
|
@@ -15,6 +15,7 @@ export function check(bytes: number): void {
|
|
|
15
15
|
if (data.check === Check.None) {
|
|
16
16
|
let reason = data.check;
|
|
17
17
|
reason = envelope.data.sequence >= Setting.PayloadLimit ? Check.Payload : reason;
|
|
18
|
+
reason = envelope.data.pageNum >= Setting.PageLimit ? Check.Page : reason;
|
|
18
19
|
reason = time() > Setting.ShutdownLimit ? Check.Shutdown : reason;
|
|
19
20
|
reason = bytes > Setting.PlaybackBytesLimit ? Check.Shutdown : reason;
|
|
20
21
|
if (reason !== data.check) {
|
package/src/data/metadata.ts
CHANGED
|
@@ -16,6 +16,7 @@ export function start(): void {
|
|
|
16
16
|
rootDomain = null;
|
|
17
17
|
const ua = navigator && "userAgent" in navigator ? navigator.userAgent : Constant.Empty;
|
|
18
18
|
const title = document && document.title ? document.title : Constant.Empty;
|
|
19
|
+
const electron = ua.indexOf(Constant.Electron) > 0 ? BooleanFlag.True : BooleanFlag.False;
|
|
19
20
|
|
|
20
21
|
// Populate ids for this page
|
|
21
22
|
let s = session();
|
|
@@ -26,20 +27,23 @@ export function start(): void {
|
|
|
26
27
|
// Override configuration based on what's in the session storage, unless it is blank (e.g. using upload callback, like in devtools)
|
|
27
28
|
config.lean = config.track && s.upgrade !== null ? s.upgrade === BooleanFlag.False : config.lean;
|
|
28
29
|
config.upload = config.track && typeof config.upload === Constant.String && s.upload && s.upload.length > Constant.HTTPS.length ? s.upload : config.upload;
|
|
29
|
-
|
|
30
|
+
|
|
30
31
|
// Log page metadata as dimensions
|
|
31
32
|
dimension.log(Dimension.UserAgent, ua);
|
|
32
33
|
dimension.log(Dimension.PageTitle, title);
|
|
33
|
-
dimension.log(Dimension.Url, scrub.url(location.href));
|
|
34
|
+
dimension.log(Dimension.Url, scrub.url(location.href, !!electron));
|
|
34
35
|
dimension.log(Dimension.Referrer, document.referrer);
|
|
35
36
|
dimension.log(Dimension.TabId, tab());
|
|
36
37
|
dimension.log(Dimension.PageLanguage, document.documentElement.lang);
|
|
37
38
|
dimension.log(Dimension.DocumentDirection, document.dir);
|
|
38
39
|
dimension.log(Dimension.DevicePixelRatio, `${window.devicePixelRatio}`);
|
|
39
|
-
|
|
40
|
+
dimension.log(Dimension.Dob, u.dob.toString());
|
|
41
|
+
dimension.log(Dimension.CookieVersion, u.version.toString());
|
|
42
|
+
|
|
40
43
|
// Capture additional metadata as metrics
|
|
41
44
|
metric.max(Metric.ClientTimestamp, s.ts);
|
|
42
|
-
metric.max(Metric.Playback, BooleanFlag.False);
|
|
45
|
+
metric.max(Metric.Playback, BooleanFlag.False);
|
|
46
|
+
metric.max(Metric.Electron, electron);
|
|
43
47
|
|
|
44
48
|
// Capture navigator specific dimensions
|
|
45
49
|
if (navigator) {
|
|
@@ -48,7 +52,7 @@ export function start(): void {
|
|
|
48
52
|
metric.max(Metric.MaxTouchPoints, navigator.maxTouchPoints);
|
|
49
53
|
metric.max(Metric.DeviceMemory, Math.round((<any>navigator).deviceMemory));
|
|
50
54
|
userAgentData();
|
|
51
|
-
}
|
|
55
|
+
}
|
|
52
56
|
|
|
53
57
|
if (screen) {
|
|
54
58
|
metric.max(Metric.ScreenWidth, Math.round(screen.width));
|
|
@@ -69,12 +73,12 @@ export function start(): void {
|
|
|
69
73
|
function userAgentData(): void {
|
|
70
74
|
let uaData = navigator["userAgentData"];
|
|
71
75
|
if (uaData && uaData.getHighEntropyValues) {
|
|
72
|
-
uaData.getHighEntropyValues(["model","platform","platformVersion","uaFullVersion"]).then(ua => {
|
|
73
|
-
dimension.log(Dimension.Platform, ua.platform);
|
|
74
|
-
dimension.log(Dimension.PlatformVersion, ua.platformVersion);
|
|
76
|
+
uaData.getHighEntropyValues(["model","platform","platformVersion","uaFullVersion"]).then(ua => {
|
|
77
|
+
dimension.log(Dimension.Platform, ua.platform);
|
|
78
|
+
dimension.log(Dimension.PlatformVersion, ua.platformVersion);
|
|
75
79
|
ua.brands?.forEach(brand => { dimension.log(Dimension.Brand, brand.name + Constant.Tilde + brand.version); });
|
|
76
|
-
dimension.log(Dimension.Model, ua.model);
|
|
77
|
-
metric.max(Metric.Mobile, ua.mobile ? BooleanFlag.True : BooleanFlag.False);
|
|
80
|
+
dimension.log(Dimension.Model, ua.model);
|
|
81
|
+
metric.max(Metric.Mobile, ua.mobile ? BooleanFlag.True : BooleanFlag.False);
|
|
78
82
|
});
|
|
79
83
|
} else { dimension.log(Dimension.Platform, navigator.platform); }
|
|
80
84
|
}
|
|
@@ -149,9 +153,13 @@ function track(u: User, consent: BooleanFlag = null): void {
|
|
|
149
153
|
// Convert time precision into days to reduce number of bytes we have to write in a cookie
|
|
150
154
|
// E.g. Math.ceil(1628735962643 / (24*60*60*1000)) => 18852 (days) => ejo in base36 (13 bytes => 3 bytes)
|
|
151
155
|
let end = Math.ceil((Date.now() + (Setting.Expire * Time.Day))/Time.Day);
|
|
156
|
+
// If DOB is not set in the user object, use the date set in the config as a DOB
|
|
157
|
+
let dob = u.dob === 0 ? (config.dob === null ? 0 : config.dob) : u.dob;
|
|
158
|
+
|
|
152
159
|
// To avoid cookie churn, write user id cookie only once every day
|
|
153
|
-
if (u.expiry === null || Math.abs(end - u.expiry) >= Setting.CookieInterval || u.consent !== consent) {
|
|
154
|
-
|
|
160
|
+
if (u.expiry === null || Math.abs(end - u.expiry) >= Setting.CookieInterval || u.consent !== consent || u.dob !== dob) {
|
|
161
|
+
let cookieParts = [data.userId, Setting.CookieVersion, end.toString(36), consent, dob];
|
|
162
|
+
setCookie(Constant.CookieKey, cookieParts.join(Constant.Pipe), Setting.Expire);
|
|
155
163
|
}
|
|
156
164
|
}
|
|
157
165
|
|
|
@@ -185,7 +193,7 @@ function num(string: string, base: number = 10): number {
|
|
|
185
193
|
}
|
|
186
194
|
|
|
187
195
|
function user(): User {
|
|
188
|
-
let output: User = { id: shortid(), expiry: null, consent: BooleanFlag.False };
|
|
196
|
+
let output: User = { id: shortid(), version: 0, expiry: null, consent: BooleanFlag.False, dob: 0 };
|
|
189
197
|
let cookie = getCookie(Constant.CookieKey);
|
|
190
198
|
if(cookie && cookie.length > 0) {
|
|
191
199
|
// Splitting and looking up first part for forward compatibility, in case we wish to store additional information in a cookie
|
|
@@ -205,9 +213,11 @@ function user(): User {
|
|
|
205
213
|
}
|
|
206
214
|
// End code for backward compatibility
|
|
207
215
|
// Read version information and timestamp from cookie, if available
|
|
216
|
+
if (parts.length > 1) { output.version = num(parts[1]); }
|
|
208
217
|
if (parts.length > 2) { output.expiry = num(parts[2], 36); }
|
|
209
218
|
// Check if we have explicit consent to track this user
|
|
210
219
|
if (parts.length > 3 && num(parts[3]) === 1) { output.consent = BooleanFlag.True; }
|
|
220
|
+
if (parts.length > 4 && num(parts[1]) > 1) { output.dob = num(parts[4]); }
|
|
211
221
|
// Set track configuration to true for this user if we have explicit consent, regardless of project setting
|
|
212
222
|
config.track = config.track || output.consent === BooleanFlag.True;
|
|
213
223
|
// Get user id from cookie only if we tracking is enabled, otherwise fallback to a random id
|
|
@@ -246,7 +256,7 @@ function setCookie(key: string, value: string, time: number): void {
|
|
|
246
256
|
rootDomain = `.${hostname[i]}${rootDomain ? rootDomain : Constant.Empty}`;
|
|
247
257
|
// We do not wish to attempt writing a cookie on the absolute last part of the domain, e.g. .com or .net.
|
|
248
258
|
// So we start attempting after second-last part, e.g. .domain.com (PASS) or .co.uk (FAIL)
|
|
249
|
-
if (i < hostname.length - 1) {
|
|
259
|
+
if (i < hostname.length - 1) {
|
|
250
260
|
// Write the cookie on the current computed top level domain
|
|
251
261
|
document.cookie = `${cookie}${Constant.Semicolon}${Constant.Domain}${rootDomain}`;
|
|
252
262
|
// Once written, check if the cookie exists and its value matches exactly with what we intended to set
|