clarity-js 0.7.6 → 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.js CHANGED
@@ -80,6 +80,8 @@ function setup() {
80
80
  if (typeof w !== "undefined") {
81
81
  w[c] = function () {
82
82
  (w[c].q = w[c].q || []).push(arguments);
83
+ // if the start function was called, don't queue it and instead process the queue
84
+ arguments[0] === "start" && w[c].q.unshift(w[c].q.pop()) && process$7();
83
85
  };
84
86
  }
85
87
  }
@@ -126,7 +128,8 @@ var config$1 = {
126
128
  upload: null,
127
129
  fallback: null,
128
130
  upgrade: null,
129
- action: null
131
+ action: null,
132
+ dob: null
130
133
  };
131
134
 
132
135
  function api(method) {
@@ -149,7 +152,7 @@ function stop$D() {
149
152
  startTime = 0;
150
153
  }
151
154
 
152
- var version$1 = "0.7.6";
155
+ var version$1 = "0.7.8";
153
156
 
154
157
  // tslint:disable: no-bitwise
155
158
  function hash (input, precision) {
@@ -189,7 +192,7 @@ function text$1(value, hint, privacy, mangle) {
189
192
  case "value":
190
193
  case "placeholder":
191
194
  case "click":
192
- return redact(value);
195
+ return redact$1(value);
193
196
  case "input":
194
197
  case "change":
195
198
  return mangleToken(value);
@@ -233,7 +236,7 @@ function text$1(value, hint, privacy, mangle) {
233
236
  switch (hint) {
234
237
  case "*T" /* Layout.Constant.TextTag */:
235
238
  case "data-" /* Layout.Constant.DataAttribute */:
236
- return scrub(value);
239
+ return scrub(value, "\u25AA" /* Data.Constant.Letter */, "\u25AB" /* Data.Constant.Digit */);
237
240
  case "value":
238
241
  case "input":
239
242
  case "click":
@@ -251,7 +254,12 @@ function text$1(value, hint, privacy, mangle) {
251
254
  }
252
255
  return value;
253
256
  }
254
- function url$1(input) {
257
+ function url$1(input, electron) {
258
+ if (electron === void 0) { electron = false; }
259
+ // Replace the URL for Electron apps so we don't send back file:/// URL
260
+ if (electron) {
261
+ return "".concat("https://" /* Data.Constant.HTTPS */).concat("Electron" /* Data.Constant.Electron */);
262
+ }
255
263
  var drop = config$1.drop;
256
264
  if (drop && drop.length > 0 && input && input.indexOf("?") > 0) {
257
265
  var _a = input.split("?"), path = _a[0], query = _a[1];
@@ -274,9 +282,9 @@ function mangleText(value) {
274
282
  function mask(value) {
275
283
  return value.replace(catchallRegex, "\u2022" /* Data.Constant.Mask */);
276
284
  }
277
- function scrub(value) {
285
+ function scrub(value, letter, digit) {
278
286
  regex(); // Initialize regular expressions
279
- return value.replace(letterRegex, "\u25AA" /* Data.Constant.Letter */).replace(digitRegex, "\u25AB" /* Data.Constant.Digit */);
287
+ return value ? value.replace(letterRegex, letter).replace(digitRegex, digit) : value;
280
288
  }
281
289
  function mangleToken(value) {
282
290
  var length = ((Math.floor(value.length / 5 /* Data.Setting.WordLength */) + 1) * 5 /* Data.Setting.WordLength */);
@@ -300,7 +308,7 @@ function regex() {
300
308
  }
301
309
  }
302
310
  }
303
- function redact(value) {
311
+ function redact$1(value) {
304
312
  var spaceIndex = -1;
305
313
  var gap = 0;
306
314
  var hasDigit = false;
@@ -325,7 +333,7 @@ function redact(value) {
325
333
  // Check if unicode regex is supported, otherwise fallback to calling mask function on this token
326
334
  if (unicodeRegex && currencyRegex !== null) {
327
335
  // Do not redact information if the token contains a currency symbol
328
- token = token.match(currencyRegex) ? token : token.replace(letterRegex, "\u25AA" /* Data.Constant.Letter */).replace(digitRegex, "\u25AB" /* Data.Constant.Digit */);
336
+ token = token.match(currencyRegex) ? token : scrub(token, "\u25AA" /* Data.Constant.Letter */, "\u25AB" /* Data.Constant.Digit */);
329
337
  }
330
338
  else {
331
339
  token = mask(token);
@@ -626,57 +634,6 @@ var upgrade$1 = /*#__PURE__*/Object.freeze({
626
634
  upgrade: upgrade
627
635
  });
628
636
 
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
637
  /******************************************************************************
681
638
  Copyright (c) Microsoft Corporation.
682
639
 
@@ -730,6 +687,113 @@ function __generator(thisArg, body) {
730
687
  }
731
688
  }
732
689
 
690
+ var data$e = null;
691
+ function start$A() {
692
+ reset$m();
693
+ }
694
+ function set(variable, value) {
695
+ var values = typeof value === "string" /* Constant.String */ ? [value] : value;
696
+ log$2(variable, values);
697
+ }
698
+ function identify(userId, sessionId, pageId, userHint) {
699
+ if (sessionId === void 0) { sessionId = null; }
700
+ if (pageId === void 0) { pageId = null; }
701
+ if (userHint === void 0) { userHint = null; }
702
+ return __awaiter(this, void 0, void 0, function () {
703
+ var output;
704
+ var _a;
705
+ return __generator(this, function (_b) {
706
+ switch (_b.label) {
707
+ case 0:
708
+ _a = {};
709
+ return [4 /*yield*/, sha256(userId)];
710
+ case 1:
711
+ output = (_a.userId = _b.sent(), _a.userHint = userHint || redact(userId), _a);
712
+ // By default, hash custom userId using SHA256 algorithm on the client to preserve privacy
713
+ log$2("userId" /* Constant.UserId */, [output.userId]);
714
+ // Optional non-identifying name for the user
715
+ // If name is not explicitly provided, we automatically generate a redacted version of the userId
716
+ log$2("userHint" /* Constant.UserHint */, [output.userHint]);
717
+ log$2("userType" /* Constant.UserType */, [detect(userId)]);
718
+ // Log sessionId and pageId if provided
719
+ if (sessionId) {
720
+ log$2("sessionId" /* Constant.SessionId */, [sessionId]);
721
+ output.sessionId = sessionId;
722
+ }
723
+ if (pageId) {
724
+ log$2("pageId" /* Constant.PageId */, [pageId]);
725
+ output.pageId = pageId;
726
+ }
727
+ return [2 /*return*/, output];
728
+ }
729
+ });
730
+ });
731
+ }
732
+ function log$2(variable, value) {
733
+ if (active() &&
734
+ variable &&
735
+ value &&
736
+ typeof variable === "string" /* Constant.String */ &&
737
+ variable.length < 255) {
738
+ var validValues = variable in data$e ? data$e[variable] : [];
739
+ for (var i = 0; i < value.length; i++) {
740
+ if (typeof value[i] === "string" /* Constant.String */ && value[i].length < 255) {
741
+ validValues.push(value[i]);
742
+ }
743
+ }
744
+ data$e[variable] = validValues;
745
+ }
746
+ }
747
+ function compute$9() {
748
+ encode$1(34 /* Event.Variable */);
749
+ }
750
+ function reset$m() {
751
+ data$e = {};
752
+ }
753
+ function stop$x() {
754
+ reset$m();
755
+ }
756
+ function redact(input) {
757
+ return input && input.length >= 5 /* Setting.WordLength */ ?
758
+ "".concat(input.substring(0, 2)).concat(scrub(input.substring(2), "*" /* Constant.Asterix */, "*" /* Constant.Asterix */)) : scrub(input, "*" /* Constant.Asterix */, "*" /* Constant.Asterix */);
759
+ }
760
+ function sha256(input) {
761
+ return __awaiter(this, void 0, void 0, function () {
762
+ var buffer;
763
+ return __generator(this, function (_b) {
764
+ switch (_b.label) {
765
+ case 0:
766
+ _b.trys.push([0, 4, , 5]);
767
+ if (!(crypto && input)) return [3 /*break*/, 2];
768
+ return [4 /*yield*/, crypto.subtle.digest("SHA-256" /* Constant.SHA256 */, new TextEncoder().encode(input))];
769
+ case 1:
770
+ buffer = _b.sent();
771
+ return [2 /*return*/, Array.prototype.map.call(new Uint8Array(buffer), function (x) { return (('00' + x.toString(16)).slice(-2)); }).join('')];
772
+ case 2: return [2 /*return*/, "" /* Constant.Empty */];
773
+ case 3: return [3 /*break*/, 5];
774
+ case 4:
775
+ _b.sent();
776
+ return [2 /*return*/, "" /* Constant.Empty */];
777
+ case 5: return [2 /*return*/];
778
+ }
779
+ });
780
+ });
781
+ }
782
+ function detect(input) {
783
+ return input && input.indexOf("@" /* Constant.At */) > 0 ? "email" /* Constant.Email */ : "string" /* Constant.String */;
784
+ }
785
+
786
+ var variable = /*#__PURE__*/Object.freeze({
787
+ __proto__: null,
788
+ compute: compute$9,
789
+ get data () { return data$e; },
790
+ identify: identify,
791
+ reset: reset$m,
792
+ set: set,
793
+ start: start$A,
794
+ stop: stop$x
795
+ });
796
+
733
797
  var supported$1 = "CompressionStream" /* Constant.CompressionStream */ in window;
734
798
  function compress (input) {
735
799
  return __awaiter(this, void 0, void 0, function () {
@@ -1970,10 +2034,10 @@ function text(element) {
1970
2034
  // Grab text using "textContent" for most HTMLElements, however, use "value" for HTMLInputElements and "alt" for HTMLImageElement.
1971
2035
  var t = element.textContent || element.value || element.alt;
1972
2036
  if (t) {
1973
- // Trim any spaces at the beginning or at the end of string
1974
- // Also, replace multiple occurrence of space characters with a single white space
2037
+ // Replace multiple occurrence of space characters with a single white space
2038
+ // Also, trim any spaces at the beginning or at the end of string
1975
2039
  // Finally, send only first few characters as specified by the Setting
1976
- output = t.trim().replace(/\s+/g, " " /* Constant.Space */).substr(0, 25 /* Setting.ClickText */);
2040
+ output = t.replace(/\s+/g, " " /* Constant.Space */).trim().substr(0, 25 /* Setting.ClickText */);
1977
2041
  }
1978
2042
  }
1979
2043
  return output;
@@ -3659,12 +3723,18 @@ function stop$c() {
3659
3723
  }
3660
3724
 
3661
3725
  var data$5 = {};
3662
- var keys = [];
3726
+ var keys = new Set();
3663
3727
  var variables = {};
3664
3728
  var selectors = {};
3729
+ var hashes = {};
3665
3730
  function start$c() {
3666
3731
  reset$4();
3667
3732
  }
3733
+ // Input string is of the following form:
3734
+ // EXTRACT 101 { "1": ".class1", "2": "~window.a.b", "3": "!abc"}
3735
+ // Which will set up event 101 to grab the contents of the class1 selector into component 1,
3736
+ // the javascript evaluated contents of window.a.b into component 2,
3737
+ // and the contents of Clarity's hash abc into component 3
3668
3738
  function trigger$1(input) {
3669
3739
  try {
3670
3740
  var parts = input && input.length > 0 ? input.split(/ (.*)/) : ["" /* Constant.Empty */];
@@ -3672,10 +3742,19 @@ function trigger$1(input) {
3672
3742
  var values = parts.length > 1 ? JSON.parse(parts[1]) : {};
3673
3743
  variables[key] = {};
3674
3744
  selectors[key] = {};
3745
+ hashes[key] = {};
3675
3746
  for (var v in values) {
3747
+ // values is a set of strings for proper JSON parsing, but it's more efficient
3748
+ // to interact with them as numbers
3676
3749
  var id = parseInt(v);
3677
3750
  var value = values[v];
3678
- var source = value.startsWith("~" /* Constant.Tilde */) ? 0 /* ExtractSource.Javascript */ : 2 /* ExtractSource.Text */;
3751
+ var source = 2 /* ExtractSource.Text */;
3752
+ if (value.startsWith("~" /* Constant.Tilde */)) {
3753
+ source = 0 /* ExtractSource.Javascript */;
3754
+ }
3755
+ else if (value.startsWith("!" /* Constant.Bang */)) {
3756
+ source = 4 /* ExtractSource.Hash */;
3757
+ }
3679
3758
  switch (source) {
3680
3759
  case 0 /* ExtractSource.Javascript */:
3681
3760
  var variable = value.substring(1, value.length);
@@ -3684,6 +3763,10 @@ function trigger$1(input) {
3684
3763
  case 2 /* ExtractSource.Text */:
3685
3764
  selectors[key][id] = value;
3686
3765
  break;
3766
+ case 4 /* ExtractSource.Hash */:
3767
+ var hash = value.substring(1, value.length);
3768
+ hashes[key][id] = hash;
3769
+ break;
3687
3770
  }
3688
3771
  }
3689
3772
  }
@@ -3698,44 +3781,56 @@ function compute$4() {
3698
3781
  try {
3699
3782
  for (var v in variables) {
3700
3783
  var key = parseInt(v);
3701
- if (!(key in keys)) {
3702
- var variableData = variables[key];
3703
- for (var v_1 in variableData) {
3704
- var variableKey = parseInt(v_1);
3705
- var value = str(evaluate(clone(variableData[variableKey])));
3706
- if (value) {
3707
- update(key, variableKey, value);
3708
- }
3784
+ var variableData = variables[key];
3785
+ for (var v_1 in variableData) {
3786
+ var variableKey = parseInt(v_1);
3787
+ var value = str(evaluate(clone(variableData[variableKey])));
3788
+ if (value) {
3789
+ update(key, variableKey, value);
3709
3790
  }
3710
- var selectorData = selectors[key];
3711
- for (var s in selectorData) {
3712
- var selectorKey = parseInt(s);
3713
- var nodes = document.querySelectorAll(selectorData[selectorKey]);
3714
- if (nodes) {
3715
- var text = Array.from(nodes).map(function (e) { return e.innerText; });
3716
- update(key, selectorKey, text.join("<SEP>" /* Constant.Seperator */).substring(0, 10000 /* Setting.ExtractLimit */));
3717
- }
3791
+ }
3792
+ var selectorData = selectors[key];
3793
+ for (var s in selectorData) {
3794
+ var selectorKey = parseInt(s);
3795
+ var nodes = document.querySelectorAll(selectorData[selectorKey]);
3796
+ if (nodes) {
3797
+ var text = Array.from(nodes).map(function (e) { return e.textContent; });
3798
+ update(key, selectorKey, text.join("<SEP>" /* Constant.Seperator */).substring(0, 10000 /* Setting.ExtractLimit */));
3718
3799
  }
3719
3800
  }
3801
+ var hashData = hashes[key];
3802
+ for (var h in hashData) {
3803
+ var hashKey = parseInt(h);
3804
+ var content = hashText(hashData[hashKey]).trim().substring(0, 10000 /* Setting.ExtractLimit */);
3805
+ update(key, hashKey, content);
3806
+ }
3807
+ }
3808
+ if (keys.size > 0) {
3809
+ encode$1(40 /* Event.Extract */);
3720
3810
  }
3721
3811
  }
3722
3812
  catch (e) {
3723
3813
  log$1(5 /* Code.Selector */, 1 /* Severity.Warning */, e ? e.name : null);
3724
3814
  }
3725
- encode$1(40 /* Event.Extract */);
3726
3815
  }
3727
3816
  function reset$4() {
3728
- data$5 = {};
3729
- keys = [];
3730
- variables = {};
3731
- selectors = {};
3817
+ keys.clear();
3732
3818
  }
3733
3819
  function update(key, subkey, value) {
3820
+ var update = false;
3734
3821
  if (!(key in data$5)) {
3735
- data$5[key] = [];
3736
- keys.push(key);
3822
+ data$5[key] = {};
3823
+ update = true;
3824
+ }
3825
+ if (!isEmpty(hashes[key])
3826
+ && (!(subkey in data$5[key]) || data$5[key][subkey] != value)) {
3827
+ update = true;
3828
+ }
3829
+ data$5[key][subkey] = value;
3830
+ if (update) {
3831
+ keys.add(key);
3737
3832
  }
3738
- data$5[key].push([subkey, value]);
3833
+ return;
3739
3834
  }
3740
3835
  function stop$b() {
3741
3836
  reset$4();
@@ -3798,6 +3893,9 @@ function match(base, condition) {
3798
3893
  return prop.length > 1 ? base[prop[0]] == prop[1] : base[prop[0]];
3799
3894
  }
3800
3895
  return true;
3896
+ }
3897
+ function isEmpty(obj) {
3898
+ return Object.keys(obj).length == 0;
3801
3899
  }
3802
3900
 
3803
3901
  function encode$1 (event) {
@@ -3900,11 +3998,16 @@ function encode$1 (event) {
3900
3998
  break;
3901
3999
  case 40 /* Event.Extract */:
3902
4000
  var extractKeys = keys;
3903
- for (var _d = 0, extractKeys_1 = extractKeys; _d < extractKeys_1.length; _d++) {
3904
- var e = extractKeys_1[_d];
4001
+ extractKeys.forEach((function (e) {
3905
4002
  tokens.push(e);
3906
- tokens.push([].concat.apply([], data$5[e]));
3907
- }
4003
+ var token = [];
4004
+ for (var d in data$5[e]) {
4005
+ var key = parseInt(d, 10);
4006
+ token.push(key);
4007
+ token.push(data$5[e][d]);
4008
+ }
4009
+ tokens.push(token);
4010
+ }));
3908
4011
  reset$4();
3909
4012
  queue(tokens, false);
3910
4013
  }
@@ -3918,6 +4021,7 @@ function check$2(bytes) {
3918
4021
  if (data$4.check === 0 /* Check.None */) {
3919
4022
  var reason = data$4.check;
3920
4023
  reason = data$1.sequence >= 128 /* Setting.PayloadLimit */ ? 1 /* Check.Payload */ : reason;
4024
+ reason = data$1.pageNum >= 128 /* Setting.PageLimit */ ? 7 /* Check.Page */ : reason;
3921
4025
  reason = time() > 7200000 /* Setting.ShutdownLimit */ ? 2 /* Check.Shutdown */ : reason;
3922
4026
  reason = bytes > 10485760 /* Setting.PlaybackBytesLimit */ ? 2 /* Check.Shutdown */ : reason;
3923
4027
  if (reason !== data$4.check) {
@@ -3986,6 +4090,7 @@ function start$9() {
3986
4090
  rootDomain = null;
3987
4091
  var ua = navigator && "userAgent" in navigator ? navigator.userAgent : "" /* Constant.Empty */;
3988
4092
  var title = document && document.title ? document.title : "" /* Constant.Empty */;
4093
+ var electron = ua.indexOf("Electron" /* Constant.Electron */) > 0 ? 1 /* BooleanFlag.True */ : 0 /* BooleanFlag.False */;
3989
4094
  // Populate ids for this page
3990
4095
  var s = session();
3991
4096
  var u = user();
@@ -3997,15 +4102,18 @@ function start$9() {
3997
4102
  // Log page metadata as dimensions
3998
4103
  log(0 /* Dimension.UserAgent */, ua);
3999
4104
  log(3 /* Dimension.PageTitle */, title);
4000
- log(1 /* Dimension.Url */, url$1(location.href));
4105
+ log(1 /* Dimension.Url */, url$1(location.href, !!electron));
4001
4106
  log(2 /* Dimension.Referrer */, document.referrer);
4002
4107
  log(15 /* Dimension.TabId */, tab());
4003
4108
  log(16 /* Dimension.PageLanguage */, document.documentElement.lang);
4004
4109
  log(17 /* Dimension.DocumentDirection */, document.dir);
4005
4110
  log(26 /* Dimension.DevicePixelRatio */, "".concat(window.devicePixelRatio));
4111
+ log(28 /* Dimension.Dob */, u.dob.toString());
4112
+ log(29 /* Dimension.CookieVersion */, u.version.toString());
4006
4113
  // Capture additional metadata as metrics
4007
4114
  max(0 /* Metric.ClientTimestamp */, s.ts);
4008
4115
  max(1 /* Metric.Playback */, 0 /* BooleanFlag.False */);
4116
+ max(35 /* Metric.Electron */, electron);
4009
4117
  // Capture navigator specific dimensions
4010
4118
  if (navigator) {
4011
4119
  log(9 /* Dimension.Language */, navigator.language);
@@ -4052,11 +4160,17 @@ function stop$8() {
4052
4160
  }
4053
4161
  function metadata(cb, wait) {
4054
4162
  if (wait === void 0) { wait = true; }
4055
- if (data$2 && wait === false) {
4163
+ var upgraded = config$1.lean ? 0 /* BooleanFlag.False */ : 1 /* BooleanFlag.True */;
4164
+ // if caller hasn't specified that they want to skip waiting for upgrade but we've already upgraded, we need to
4165
+ // directly execute the callback rather than adding to our list as we only process callbacks at the moment
4166
+ // we go through the upgrading flow.
4167
+ if (data$2 && (upgraded || wait === false)) {
4056
4168
  // Immediately invoke the callback if the caller explicitly doesn't want to wait for the upgrade confirmation
4057
4169
  cb(data$2, !config$1.lean);
4058
4170
  }
4059
- callbacks.push({ callback: cb, wait: wait });
4171
+ else {
4172
+ callbacks.push({ callback: cb, wait: wait });
4173
+ }
4060
4174
  }
4061
4175
  function id() {
4062
4176
  return data$2 ? [data$2.userId, data$2.sessionId, data$2.pageNum].join("." /* Constant.Dot */) : "" /* Constant.Empty */;
@@ -4111,9 +4225,12 @@ function track(u, consent) {
4111
4225
  // Convert time precision into days to reduce number of bytes we have to write in a cookie
4112
4226
  // E.g. Math.ceil(1628735962643 / (24*60*60*1000)) => 18852 (days) => ejo in base36 (13 bytes => 3 bytes)
4113
4227
  var end = Math.ceil((Date.now() + (365 /* Setting.Expire */ * 86400000 /* Time.Day */)) / 86400000 /* Time.Day */);
4228
+ // If DOB is not set in the user object, use the date set in the config as a DOB
4229
+ var dob = u.dob === 0 ? (config$1.dob === null ? 0 : config$1.dob) : u.dob;
4114
4230
  // To avoid cookie churn, write user id cookie only once every day
4115
- if (u.expiry === null || Math.abs(end - u.expiry) >= 1 /* Setting.CookieInterval */ || u.consent !== consent) {
4116
- setCookie("_clck" /* Constant.CookieKey */, [data$2.userId, 1 /* Setting.CookieVersion */, end.toString(36), consent].join("|" /* Constant.Pipe */), 365 /* Setting.Expire */);
4231
+ if (u.expiry === null || Math.abs(end - u.expiry) >= 1 /* Setting.CookieInterval */ || u.consent !== consent || u.dob !== dob) {
4232
+ var cookieParts = [data$2.userId, 2 /* Setting.CookieVersion */, end.toString(36), consent, dob];
4233
+ setCookie("_clck" /* Constant.CookieKey */, cookieParts.join("|" /* Constant.Pipe */), 365 /* Setting.Expire */);
4117
4234
  }
4118
4235
  }
4119
4236
  function shortid() {
@@ -4144,7 +4261,7 @@ function num(string, base) {
4144
4261
  return parseInt(string, base);
4145
4262
  }
4146
4263
  function user() {
4147
- var output = { id: shortid(), expiry: null, consent: 0 /* BooleanFlag.False */ };
4264
+ var output = { id: shortid(), version: 0, expiry: null, consent: 0 /* BooleanFlag.False */, dob: 0 };
4148
4265
  var cookie = getCookie("_clck" /* Constant.CookieKey */);
4149
4266
  if (cookie && cookie.length > 0) {
4150
4267
  // Splitting and looking up first part for forward compatibility, in case we wish to store additional information in a cookie
@@ -4167,6 +4284,9 @@ function user() {
4167
4284
  }
4168
4285
  // End code for backward compatibility
4169
4286
  // Read version information and timestamp from cookie, if available
4287
+ if (parts.length > 1) {
4288
+ output.version = num(parts[1]);
4289
+ }
4170
4290
  if (parts.length > 2) {
4171
4291
  output.expiry = num(parts[2], 36);
4172
4292
  }
@@ -4174,6 +4294,9 @@ function user() {
4174
4294
  if (parts.length > 3 && num(parts[3]) === 1) {
4175
4295
  output.consent = 1 /* BooleanFlag.True */;
4176
4296
  }
4297
+ if (parts.length > 4 && num(parts[1]) > 1) {
4298
+ output.dob = num(parts[4]);
4299
+ }
4177
4300
  // Set track configuration to true for this user if we have explicit consent, regardless of project setting
4178
4301
  config$1.track = config$1.track || output.consent === 1 /* BooleanFlag.True */;
4179
4302
  // Get user id from cookie only if we tracking is enabled, otherwise fallback to a random id