UNPKG

clarity-js

Version:

An analytics library that uses web page interactions to generate aggregated insights

1,319 lines (1,284 loc) 254 kB
'use strict'; var dom = /*#__PURE__*/Object.freeze({ __proto__: null, get add () { return add; }, get get () { return get; }, get getId () { return getId; }, get getNode () { return getNode; }, get getValue () { return getValue; }, get has () { return has$1; }, get hashText () { return hashText; }, get iframe () { return iframe; }, get iframeContent () { return iframeContent; }, get lookup () { return lookup; }, get parse () { return parse; }, get removeIFrame () { return removeIFrame; }, get sameorigin () { return sameorigin; }, get start () { return start$j; }, get stop () { return stop$h; }, get update () { return update; }, get updates () { return updates$2; } }); var upload$1 = /*#__PURE__*/Object.freeze({ __proto__: null, get queue () { return queue; }, get start () { return start$g; }, get stop () { return stop$e; }, get track () { return track$1; } }); var upgrade$1 = /*#__PURE__*/Object.freeze({ __proto__: null, get data () { return data$5; }, get start () { return start$b; }, get stop () { return stop$b; }, get upgrade () { return upgrade; } }); var limit = /*#__PURE__*/Object.freeze({ __proto__: null, get check () { return check$2; }, get compute () { return compute$3; }, get data () { return data$4; }, get start () { return start$a; }, get stop () { return stop$a; }, get trigger () { return trigger; } }); var dimension = /*#__PURE__*/Object.freeze({ __proto__: null, get compute () { return compute$2; }, get data () { return data$3; }, get log () { return log; }, get reset () { return reset$3; }, get start () { return start$9; }, get stop () { return stop$9; }, get updates () { return updates; } }); var metadata$1 = /*#__PURE__*/Object.freeze({ __proto__: null, get callback () { return callback; }, get callbacks () { return callbacks; }, get clear () { return clear; }, get consent () { return consent; }, get data () { return data$2; }, get electron () { return electron; }, get id () { return id; }, get metadata () { return metadata; }, get save () { return save; }, get shortid () { return shortid; }, get start () { return start$8; }, get stop () { return stop$8; } }); var envelope$1 = /*#__PURE__*/Object.freeze({ __proto__: null, get data () { return data$1; }, get envelope () { return envelope; }, get start () { return start$7; }, get stop () { return stop$7; } }); var clarity = /*#__PURE__*/Object.freeze({ __proto__: null, get consent () { return consent; }, get event () { return event; }, get hashText () { return hashText; }, get identify () { return identify; }, get metadata () { return metadata; }, get pause () { return pause; }, get resume () { return resume; }, get set () { return set; }, get signal () { return signal; }, get start () { return start; }, get stop () { return stop; }, get upgrade () { return upgrade; }, get version () { return version$1; } }); var w = window; var c = "clarity" /* Constant.Clarity */; function setup() { // Start queuing up calls while Clarity is inactive and we are in a browser enviornment if (typeof w !== "undefined") { w[c] = function () { (w[c].q = w[c].q || []).push(arguments); // if the start function was called, don't queue it and instead process the queue arguments[0] === "start" && w[c].q.unshift(w[c].q.pop()) && process$8(); }; } } function process$8() { if (typeof w !== "undefined") { // Do not execute or reset global "clarity" variable if a version of Clarity is already running on the page if (w[c] && w[c].v) { return console.warn("Error CL001: Multiple Clarity tags detected."); } // Expose clarity in a browser environment // To be efficient about queuing up operations while Clarity is wiring up, we expose clarity.*(args) => clarity(*, args); // This allows us to reprocess any calls that we missed once Clarity is available on the page // Once Clarity script bundle is loaded on the page, we also initialize a "v" property that holds current version // We use the presence or absence of "v" to determine if we are attempting to run a duplicate instance var queue = w[c] ? (w[c].q || []) : []; w[c] = function (method) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } return clarity[method].apply(clarity, args); }; w[c].v = version$1; while (queue.length > 0) { w[c].apply(w, queue.shift()); } } } var config$2 = { projectId: null, delay: 1 * 1000 /* Time.Second */, lean: false, lite: false, track: true, content: true, drop: [], mask: [], unmask: [], regions: [], cookies: [], fraud: true, checksum: [], report: null, upload: null, fallback: null, upgrade: null, action: null, dob: null, delayDom: false, throttleDom: true, conversions: false, includeSubdomains: true, throttleMutations: false, dropMutations: false, criticalMs: 200, discard: [], }; function api(method) { // Zone.js, a popular package for Angular, overrides native browser APIs which can lead to inconsistent state for single page applications. // Example issue: https://github.com/angular/angular/issues/31712 // As a work around, we ensuring Clarity access APIs outside of Zone (and use native implementation instead) return window["Zone" /* Constant.Zone */] && "__symbol__" /* Constant.Symbol */ in window["Zone" /* Constant.Zone */] ? window["Zone" /* Constant.Zone */]["__symbol__" /* Constant.Symbol */](method) : method; } var startTime = 0; function start$I() { startTime = performance.now() + performance.timeOrigin; } // event.timestamp is number of milliseconds elapsed since the document was loaded // since iframes can be loaded later the event timestamp is not the same as performance.now() // converting everything to absolute time by adding timeorigin of the event view // to synchronize times before calculating the difference with start time function time(event) { if (event === void 0) { event = null; } var ts = event && event.timeStamp > 0 ? event.timeStamp : performance.now(); var origin = event && event.view ? event.view.performance.timeOrigin : performance.timeOrigin; return Math.max(Math.round(ts + origin - startTime), 0); } function stop$F() { startTime = 0; } var version$1 = "0.8.6"; // tslint:disable: no-bitwise function hash (input, precision) { if (precision === void 0) { precision = null; } // Code inspired from C# GetHashCode: https://github.com/Microsoft/referencesource/blob/master/mscorlib/system/string.cs var hash = 0; var hashOne = 5381; var hashTwo = hashOne; for (var i = 0; i < input.length; i += 2) { var charOne = input.charCodeAt(i); hashOne = ((hashOne << 5) + hashOne) ^ charOne; if (i + 1 < input.length) { var charTwo = input.charCodeAt(i + 1); hashTwo = ((hashTwo << 5) + hashTwo) ^ charTwo; } } // Replace the magic number from C# implementation (1566083941) with a smaller prime number (11579) // This ensures we don't hit integer overflow and prevent collisions hash = Math.abs(hashOne + (hashTwo * 11579)); return (precision ? hash % Math.pow(2, precision) : hash).toString(36); } var catchallRegex = /\S/gi; var maxUrlLength = 255; var unicodeRegex = true; var digitRegex = null; var letterRegex = null; var currencyRegex = null; function text$1(value, hint, privacy, mangle, type) { if (mangle === void 0) { mangle = false; } if (value) { if (hint == "input" && (type === "checkbox" || type === "radio")) { return value; } switch (privacy) { case 0 /* Privacy.None */: return value; case 1 /* Privacy.Sensitive */: switch (hint) { case "*T" /* Layout.Constant.TextTag */: case "value": case "placeholder": case "click": return redact$1(value); case "input": case "change": return mangleToken(value); } return value; case 2 /* Privacy.Text */: case 3 /* Privacy.TextImage */: switch (hint) { case "*T" /* Layout.Constant.TextTag */: case "data-" /* Layout.Constant.DataAttribute */: return mangle ? mangleText(value) : mask(value); case "src": case "srcset": case "title": case "alt": return privacy === 3 /* Privacy.TextImage */ ? "" /* Data.Constant.Empty */ : value; case "value": case "click": case "input": case "change": return mangleToken(value); case "placeholder": return mask(value); } break; case 4 /* Privacy.Exclude */: switch (hint) { case "*T" /* Layout.Constant.TextTag */: case "data-" /* Layout.Constant.DataAttribute */: return mangle ? mangleText(value) : mask(value); case "value": case "input": case "click": case "change": return Array(5 /* Data.Setting.WordLength */).join("\u2022" /* Data.Constant.Mask */); case "checksum": return "" /* Data.Constant.Empty */; } break; case 5 /* Privacy.Snapshot */: switch (hint) { case "*T" /* Layout.Constant.TextTag */: case "data-" /* Layout.Constant.DataAttribute */: return scrub(value, "\u25AA" /* Data.Constant.Letter */, "\u25AB" /* Data.Constant.Digit */); case "value": case "input": case "click": case "change": return Array(5 /* Data.Setting.WordLength */).join("\u2022" /* Data.Constant.Mask */); case "checksum": case "src": case "srcset": case "alt": case "title": return "" /* Data.Constant.Empty */; } break; } } return value; } function url$1(input, electron, truncate) { if (electron === void 0) { electron = false; } if (truncate === void 0) { truncate = false; } var result = input; // Replace the URL for Electron apps so we don't send back file:/// URL if (electron) { result = "".concat("https://" /* Data.Constant.HTTPS */).concat("Electron" /* Data.Constant.Electron */); } else { var drop_1 = config$2.drop; if (drop_1 && drop_1.length > 0 && input && input.indexOf("?") > 0) { var _a = input.split("?"), path = _a[0], query = _a[1]; var swap_1 = "*na*" /* Data.Constant.Dropped */; result = path + "?" + query.split("&").map(function (p) { return drop_1.some(function (x) { return p.indexOf("".concat(x, "=")) === 0; }) ? "".concat(p.split("=")[0], "=").concat(swap_1) : p; }).join("&"); } } if (truncate) { result = result.substring(0, maxUrlLength); } return result; } function mangleText(value) { var trimmed = value.trim(); if (trimmed.length > 0) { var first = trimmed[0]; var index = value.indexOf(first); var prefix = value.substr(0, index); var suffix = value.substr(index + trimmed.length); return "".concat(prefix).concat(trimmed.length.toString(36)).concat(suffix); } return value; } function mask(value) { return value.replace(catchallRegex, "\u2022" /* Data.Constant.Mask */); } function scrub(value, letter, digit) { regex(); // Initialize regular expressions return value ? value.replace(letterRegex, letter).replace(digitRegex, digit) : value; } function mangleToken(value) { var length = ((Math.floor(value.length / 5 /* Data.Setting.WordLength */) + 1) * 5 /* Data.Setting.WordLength */); var output = "" /* Layout.Constant.Empty */; for (var i = 0; i < length; i++) { output += i > 0 && i % 5 /* Data.Setting.WordLength */ === 0 ? " " /* Data.Constant.Space */ : "\u2022" /* Data.Constant.Mask */; } return output; } function regex() { // Initialize unicode regex, if supported by the browser // Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Unicode_Property_Escapes if (unicodeRegex && digitRegex === null) { try { digitRegex = new RegExp("\\p{N}", "gu"); letterRegex = new RegExp("\\p{L}", "gu"); currencyRegex = new RegExp("\\p{Sc}", "gu"); } catch (_a) { unicodeRegex = false; } } } function redact$1(value) { var spaceIndex = -1; var gap = 0; var hasDigit = false; var hasEmail = false; var hasWhitespace = false; var array = null; regex(); // Initialize regular expressions for (var i = 0; i < value.length; i++) { var c = value.charCodeAt(i); hasDigit = hasDigit || (c >= 48 /* Data.Character.Zero */ && c <= 57 /* Data.Character.Nine */); // Check for digits in the current word hasEmail = hasEmail || c === 64 /* Data.Character.At */; // Check for @ sign anywhere within the current word hasWhitespace = c === 9 /* Data.Character.Tab */ || c === 10 /* Data.Character.NewLine */ || c === 13 /* Data.Character.Return */ || c === 32 /* Data.Character.Blank */; // Process each word as an individual token to redact any sensitive information if (i === 0 || i === value.length - 1 || hasWhitespace) { // Performance optimization: Lazy load string -> array conversion only when required if (hasDigit || hasEmail) { if (array === null) { array = value.split("" /* Data.Constant.Empty */); } // Work on a token at a time so we don't have to apply regex to a larger string var token = value.substring(spaceIndex + 1, hasWhitespace ? i : i + 1); // Check if unicode regex is supported, otherwise fallback to calling mask function on this token if (unicodeRegex && currencyRegex !== null) { // Do not redact information if the token contains a currency symbol token = token.match(currencyRegex) ? token : scrub(token, "\u25AA" /* Data.Constant.Letter */, "\u25AB" /* Data.Constant.Digit */); } else { token = mask(token); } // Merge token back into array at the right place array.splice(spaceIndex + 1 - gap, token.length, token); gap += token.length - 1; } // Reset digit and email flags after every word boundary, except the beginning of string if (hasWhitespace) { hasDigit = false; hasEmail = false; spaceIndex = i; } } } return array ? array.join("" /* Data.Constant.Empty */) : value; } var state$b = null; var buffer = null; var update$2 = false; function start$H() { update$2 = false; reset$s(); } function reset$s() { // Baseline state holds the previous values - if it is updated in the current payload, // reset the state to current value after sending the previous state if (update$2) { state$b = { time: time(), event: 4 /* Event.Baseline */, data: { visible: buffer.visible, docWidth: buffer.docWidth, docHeight: buffer.docHeight, screenWidth: buffer.screenWidth, screenHeight: buffer.screenHeight, scrollX: buffer.scrollX, scrollY: buffer.scrollY, pointerX: buffer.pointerX, pointerY: buffer.pointerY, activityTime: buffer.activityTime, scrollTime: buffer.scrollTime, pointerTime: buffer.pointerTime, moveX: buffer.moveX, moveY: buffer.moveY, moveTime: buffer.moveTime, downX: buffer.downX, downY: buffer.downY, downTime: buffer.downTime, upX: buffer.upX, upY: buffer.upY, upTime: buffer.upTime, pointerPrevX: buffer.pointerPrevX, pointerPrevY: buffer.pointerPrevY, pointerPrevTime: buffer.pointerPrevTime, } }; } buffer = buffer ? buffer : { visible: 1 /* BooleanFlag.True */, docWidth: 0, docHeight: 0, screenWidth: 0, screenHeight: 0, scrollX: 0, scrollY: 0, pointerX: 0, pointerY: 0, activityTime: 0, scrollTime: 0, pointerTime: undefined, moveX: undefined, moveY: undefined, moveTime: undefined, downX: undefined, downY: undefined, downTime: undefined, upX: undefined, upY: undefined, upTime: undefined, pointerPrevX: undefined, pointerPrevY: undefined, pointerPrevTime: undefined, }; } function track$8(event, x, y, time) { switch (event) { case 8 /* Event.Document */: buffer.docWidth = x; buffer.docHeight = y; break; case 11 /* Event.Resize */: buffer.screenWidth = x; buffer.screenHeight = y; break; case 10 /* Event.Scroll */: buffer.scrollX = x; buffer.scrollY = y; buffer.scrollTime = time; break; case 12 /* Event.MouseMove */: buffer.moveX = x; buffer.moveY = y; buffer.moveTime = time; buffer.pointerPrevX = buffer.pointerX; buffer.pointerPrevY = buffer.pointerY; buffer.pointerPrevTime = buffer.pointerTime; buffer.pointerX = x; buffer.pointerY = y; buffer.pointerTime = time; break; case 13 /* Event.MouseDown */: buffer.downX = x; buffer.downY = y; buffer.downTime = time; buffer.pointerPrevX = buffer.pointerX; buffer.pointerPrevY = buffer.pointerY; buffer.pointerPrevTime = buffer.pointerTime; buffer.pointerX = x; buffer.pointerY = y; buffer.pointerTime = time; break; case 14 /* Event.MouseUp */: buffer.upX = x; buffer.upY = y; buffer.upTime = time; buffer.pointerPrevX = buffer.pointerX; buffer.pointerPrevY = buffer.pointerY; buffer.pointerPrevTime = buffer.pointerTime; buffer.pointerX = x; buffer.pointerY = y; buffer.pointerTime = time; break; default: buffer.pointerPrevX = buffer.pointerX; buffer.pointerPrevY = buffer.pointerY; buffer.pointerPrevTime = buffer.pointerTime; buffer.pointerX = x; buffer.pointerY = y; buffer.pointerTime = time; break; } update$2 = true; } function activity(t) { buffer.activityTime = t; } function visibility(t, visible) { buffer.visible = visible === "visible" ? 1 /* BooleanFlag.True */ : 0 /* BooleanFlag.False */; if (!buffer.visible) { activity(t); } update$2 = true; } function compute$e() { if (update$2) { encode$1(4 /* Event.Baseline */); } } function stop$E() { reset$s(); } var baseline = /*#__PURE__*/Object.freeze({ __proto__: null, activity: activity, compute: compute$e, reset: reset$s, start: start$H, get state () { return state$b; }, stop: stop$E, track: track$8, visibility: visibility }); var data$j = null; // custom events allow 2 parameters or 1 parameter to be passed. If 2 are passed we // consider it a key value pair. If only 1 is passed we only consider the event to have a value. function event(a, b) { if (active() && a && typeof a === "string" /* Constant.String */ && a.length < 255) { if (b && typeof b === "string" /* Constant.String */ && b.length < 255) { data$j = { key: a, value: b }; } else { data$j = { value: a }; } encode$1(24 /* Event.Custom */); } } var data$i = null; var updates$3 = null; function start$G() { data$i = {}; updates$3 = {}; count$1(5 /* Metric.InvokeCount */); } function stop$D() { data$i = {}; updates$3 = {}; } function count$1(metric) { if (!(metric in data$i)) { data$i[metric] = 0; } if (!(metric in updates$3)) { updates$3[metric] = 0; } data$i[metric]++; updates$3[metric]++; } function sum(metric, value) { if (value !== null) { if (!(metric in data$i)) { data$i[metric] = 0; } if (!(metric in updates$3)) { updates$3[metric] = 0; } data$i[metric] += value; updates$3[metric] += value; } } function max(metric, value) { // Ensure that we do not process null or NaN values if (value !== null && isNaN(value) === false) { if (!(metric in data$i)) { data$i[metric] = 0; } if (value > data$i[metric] || data$i[metric] === 0) { updates$3[metric] = value; data$i[metric] = value; } } } function compute$d() { encode$1(0 /* Event.Metric */); } function reset$r() { updates$3 = {}; } function setTimeout(handler, timeout, event) { return window.setTimeout(measure(handler), timeout, event); } function clearTimeout(handle) { return window.clearTimeout(handle); } var data$h; var last = 0; var interval = 0; var timeout$7 = null; function start$F() { interval = 60000 /* Setting.PingInterval */; last = 0; } function reset$q() { if (timeout$7) { clearTimeout(timeout$7); } timeout$7 = setTimeout(ping, interval); last = time(); } function ping() { var now = time(); data$h = { gap: now - last }; encode$1(25 /* Event.Ping */); if (data$h.gap < 300000 /* Setting.PingTimeout */) { timeout$7 = setTimeout(ping, interval); } else { suspend(); } } function stop$C() { clearTimeout(timeout$7); last = 0; interval = 0; } var ping$1 = /*#__PURE__*/Object.freeze({ __proto__: null, get data () { return data$h; }, reset: reset$q, start: start$F, stop: stop$C }); var data$g = null; function start$E() { data$g = {}; } function stop$B() { data$g = {}; } function track$7(event, time) { if (!(event in data$g)) { data$g[event] = [[time, 0]]; } else { var e = data$g[event]; var last = e[e.length - 1]; // Add a new entry only if the new event occurs after configured interval // Otherwise, extend the duration of the previous entry if (time - last[0] > 100 /* Setting.SummaryInterval */) { data$g[event].push([time, 0]); } else { last[1] = time - last[0]; } } } function compute$c() { encode$1(36 /* Event.Summary */); } function reset$p() { data$g = {}; } var summary = /*#__PURE__*/Object.freeze({ __proto__: null, compute: compute$c, get data () { return data$g; }, reset: reset$p, start: start$E, stop: stop$B, track: track$7 }); /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise */ function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } } var supported$1 = "CompressionStream" /* Constant.CompressionStream */ in window; function compress (input) { return __awaiter(this, void 0, void 0, function () { var stream, _a; return __generator(this, function (_c) { switch (_c.label) { case 0: _c.trys.push([0, 3, , 4]); if (!supported$1) return [3 /*break*/, 2]; stream = new ReadableStream({ start: function (controller) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { controller.enqueue(input); controller.close(); return [2 /*return*/]; }); }); } }).pipeThrough(new TextEncoderStream()).pipeThrough(new window["CompressionStream" /* Constant.CompressionStream */]("gzip")); _a = Uint8Array.bind; return [4 /*yield*/, read(stream)]; case 1: return [2 /*return*/, new (_a.apply(Uint8Array, [void 0, _c.sent()]))()]; case 2: return [3 /*break*/, 4]; case 3: _c.sent(); return [3 /*break*/, 4]; case 4: return [2 /*return*/, null]; } }); }); } function read(stream) { return __awaiter(this, void 0, void 0, function () { var reader, chunks, done, value; var _a; return __generator(this, function (_b) { switch (_b.label) { case 0: reader = stream.getReader(); chunks = []; done = false; value = []; _b.label = 1; case 1: if (!!done) return [3 /*break*/, 3]; return [4 /*yield*/, reader.read()]; case 2: (_a = _b.sent(), done = _a.done, value = _a.value); if (done) { return [2 /*return*/, chunks]; } chunks.push.apply(chunks, value); return [3 /*break*/, 1]; case 3: return [2 /*return*/, chunks]; } }); }); } var data$f = null; function start$D() { reset$o(); } function set(variable, value) { var values = typeof value === "string" /* Constant.String */ ? [value] : value; log$2(variable, values); } function identify(userId, sessionId, pageId, userHint) { if (sessionId === void 0) { sessionId = null; } if (pageId === void 0) { pageId = null; } if (userHint === void 0) { userHint = null; } return __awaiter(this, void 0, void 0, function () { var output; var _a; return __generator(this, function (_b) { switch (_b.label) { case 0: _a = {}; return [4 /*yield*/, sha256(userId)]; case 1: output = (_a.userId = _b.sent(), _a.userHint = userHint || redact(userId), _a); // By default, hash custom userId using SHA256 algorithm on the client to preserve privacy log$2("userId" /* Constant.UserId */, [output.userId]); // Optional non-identifying name for the user // If name is not explicitly provided, we automatically generate a redacted version of the userId log$2("userHint" /* Constant.UserHint */, [output.userHint]); log$2("userType" /* Constant.UserType */, [detect(userId)]); // Log sessionId and pageId if provided if (sessionId) { log$2("sessionId" /* Constant.SessionId */, [sessionId]); output.sessionId = sessionId; } if (pageId) { log$2("pageId" /* Constant.PageId */, [pageId]); output.pageId = pageId; } return [2 /*return*/, output]; } }); }); } function log$2(variable, value) { if (active() && variable && value && typeof variable === "string" /* Constant.String */ && variable.length < 255) { var validValues = variable in data$f ? data$f[variable] : []; for (var i = 0; i < value.length; i++) { if (typeof value[i] === "string" /* Constant.String */ && value[i].length < 255) { validValues.push(value[i]); } } data$f[variable] = validValues; } } function compute$b() { encode$1(34 /* Event.Variable */); } function reset$o() { data$f = {}; } function stop$A() { reset$o(); } function redact(input) { return input && input.length >= 5 /* Setting.WordLength */ ? "".concat(input.substring(0, 2)).concat(scrub(input.substring(2), "*" /* Constant.Asterix */, "*" /* Constant.Asterix */)) : scrub(input, "*" /* Constant.Asterix */, "*" /* Constant.Asterix */); } function sha256(input) { return __awaiter(this, void 0, void 0, function () { var buffer; return __generator(this, function (_b) { switch (_b.label) { case 0: _b.trys.push([0, 4, , 5]); if (!(crypto && input)) return [3 /*break*/, 2]; return [4 /*yield*/, crypto.subtle.digest("SHA-256" /* Constant.SHA256 */, new TextEncoder().encode(input))]; case 1: buffer = _b.sent(); return [2 /*return*/, Array.prototype.map.call(new Uint8Array(buffer), function (x) { return (('00' + x.toString(16)).slice(-2)); }).join('')]; case 2: return [2 /*return*/, "" /* Constant.Empty */]; case 3: return [3 /*break*/, 5]; case 4: _b.sent(); return [2 /*return*/, "" /* Constant.Empty */]; case 5: return [2 /*return*/]; } }); }); } function detect(input) { return input && input.indexOf("@" /* Constant.At */) > 0 ? "email" /* Constant.Email */ : "string" /* Constant.String */; } var variable = /*#__PURE__*/Object.freeze({ __proto__: null, compute: compute$b, get data () { return data$f; }, identify: identify, reset: reset$o, set: set, start: start$D, stop: stop$A }); var data$e = {}; var keys = new Set(); var variables = {}; var selectors = {}; var hashes = {}; var validation = {}; function start$C() { reset$n(); } // Input string is of the following form: // EXTRACT 101|element { "1": ".class1", "2": "~window.a.b", "3": "!abc"} // if element is present on the page it will set up event 101 to grab the contents of the class1 selector into component 1, // the javascript evaluated contents of window.a.b into component 2, // and the contents of Clarity's hash abc into component 3 function trigger$2(input) { try { var parts = input && input.length > 0 ? input.split(/ (.*)/) : ["" /* Constant.Empty */]; var keyparts = parts[0].split(/\|(.*)/); var key = parseInt(keyparts[0]); var element = keyparts.length > 1 ? keyparts[1] : "" /* Constant.Empty */; var values = parts.length > 1 ? JSON.parse(parts[1]) : {}; variables[key] = {}; selectors[key] = {}; hashes[key] = {}; validation[key] = element; for (var v in values) { // values is a set of strings for proper JSON parsing, but it's more efficient // to interact with them as numbers var id = parseInt(v); var value = values[v]; var source = 2 /* ExtractSource.Text */; if (value.startsWith("~" /* Constant.Tilde */)) { source = 0 /* ExtractSource.Javascript */; } else if (value.startsWith("!" /* Constant.Bang */)) { source = 4 /* ExtractSource.Hash */; } switch (source) { case 0 /* ExtractSource.Javascript */: var variable = value.slice(1); variables[key][id] = parse$1(variable); break; case 2 /* ExtractSource.Text */: selectors[key][id] = value; break; case 4 /* ExtractSource.Hash */: var hash_1 = value.slice(1); hashes[key][id] = hash_1; break; } } } catch (e) { log$1(8 /* Code.Config */, 1 /* Severity.Warning */, e ? e.name : null); } } function clone$1(v) { return JSON.parse(JSON.stringify(v)); } function compute$a() { try { for (var v in variables) { var key = parseInt(v); if (validation[key] == "" /* Constant.Empty */ || document.querySelector(validation[key])) { var variableData = variables[key]; for (var v_1 in variableData) { var variableKey = parseInt(v_1); var value = str$1(evaluate(clone$1(variableData[variableKey]))); if (value) { update$1(key, variableKey, value); } } var selectorData = selectors[key]; for (var s in selectorData) { var shouldMask = false; var selectorKey = parseInt(s); var selector = selectorData[selectorKey]; if (selector.startsWith("@" /* Constant.At */)) { shouldMask = true; selector = selector.slice(1); } var nodes = document.querySelectorAll(selector); if (nodes) { var text = Array.from(nodes).map(function (e) { return e.textContent; }).join("<SEP>" /* Constant.Seperator */); update$1(key, selectorKey, (shouldMask ? hash(text).trim() : text).slice(0, 10000 /* Setting.ExtractLimit */)); } } var hashData = hashes[key]; for (var h in hashData) { var hashKey = parseInt(h); var content = hashText(hashData[hashKey]).trim().slice(0, 10000 /* Setting.ExtractLimit */); update$1(key, hashKey, content); } } } if (keys.size > 0) { encode$1(40 /* Event.Extract */); } } catch (e) { log$1(5 /* Code.Selector */, 1 /* Severity.Warning */, e ? e.name : null); } } function reset$n() { keys.clear(); } function update$1(key, subkey, value) { var update = false; if (!(key in data$e)) { data$e[key] = {}; update = true; } if (!isEmpty(hashes[key]) && (!(subkey in data$e[key]) || data$e[key][subkey] != value)) { update = true; } data$e[key][subkey] = value; if (update) { keys.add(key); } return; } function stop$z() { reset$n(); } function parse$1(variable) { var syntax = []; var parts = variable.split("." /* Constant.Dot */); while (parts.length > 0) { var part = parts.shift(); var arrayStart = part.indexOf("[" /* Constant.ArrayStart */); var conditionStart = part.indexOf("{" /* Constant.ConditionStart */); var conditionEnd = part.indexOf("}" /* Constant.ConditionEnd */); syntax.push({ name: arrayStart > 0 ? part.slice(0, arrayStart) : (conditionStart > 0 ? part.slice(0, conditionStart) : part), type: arrayStart > 0 ? 1 /* Type.Array */ : (conditionStart > 0 ? 2 /* Type.Object */ : 3 /* Type.Simple */), condition: conditionStart > 0 ? part.slice(conditionStart + 1, conditionEnd) : null }); } return syntax; } // The function below takes in a variable name in following format: "a.b.c" and safely evaluates its value in javascript context // For instance, for a.b.c, it will first check window["a"]. If it exists, it will recursively look at: window["a"]["b"] and finally, // return the value for window["a"]["b"]["c"]. function evaluate(variable, base) { if (base === void 0) { base = window; } if (variable.length == 0) { return base; } var part = variable.shift(); var output; if (base && base[part.name]) { var obj = base[part.name]; if (part.type !== 1 /* Type.Array */ && match(obj, part.condition)) { output = evaluate(variable, obj); } else if (Array.isArray(obj)) { var filtered = []; for (var _i = 0, obj_1 = obj; _i < obj_1.length; _i++) { var value = obj_1[_i]; if (match(value, part.condition)) { var op = evaluate(variable, value); if (op) { filtered.push(op); } } } output = filtered; } return output; } return null; } function str$1(input) { // Automatically trim string to max of Setting.ExtractLimit to avoid fetching long strings return input ? JSON.stringify(input).slice(0, 10000 /* Setting.ExtractLimit */) : input; } function match(base, condition) { if (condition) { var prop = condition.split(":"); return prop.length > 1 ? base[prop[0]] == prop[1] : base[prop[0]]; } return true; } function isEmpty(obj) { return Object.keys(obj).length == 0; } var extract = /*#__PURE__*/Object.freeze({ __proto__: null, clone: clone$1, compute: compute$a, data: data$e, keys: keys, reset: reset$n, start: start$C, stop: stop$z, trigger: trigger$2, update: update$1 }); var signalCallback = null; function signal(cb) { signalCallback = cb; } function parseSignals(signalsPayload) { try { var parsedSignals = JSON.parse(signalsPayload); return parsedSignals; } catch (_a) { return []; } } function signalsEvent(signalsPayload) { try { if (!signalCallback) { return; } var signals = parseSignals(signalsPayload); signals.forEach(function (signal) { signalCallback(signal); }); } catch (_a) { //do nothing } } var modules$1 = [baseline, dimension, variable, limit, summary, metadata$1, envelope$1, upload$1, ping$1, upgrade$1, extract]; function start$B() { // Metric needs to be initialized before we can start measuring. so metric is not wrapped in measure start$G(); modules$1.forEach(function (x) { return measure(x.start)(); }); } function stop$y() { // Stop modules in the reverse order of their initialization // The ordering below should respect inter-module dependency. // E.g. if upgrade depends on upload, then upgrade needs to end before upload. // Similarly, if upload depends on metadata, upload needs to end before metadata. modules$1.slice().reverse().forEach(function (x) { return measure(x.stop)(); }); stop$D(); } function compute$9() { compute$b(); compute$e(); compute$2(); compute$d(); compute$c(); compute$3(); compute$a(); } var history$5 = []; var data$d; function start$A() { history$5 = []; max(26 /* Metric.Automation */, navigator.webdriver ? 1 /* BooleanFlag.True */ : 0 /* BooleanFlag.False */); try { // some sites (unintentionally) overwrite the window.self property, so we also check for the main window object max(31 /* Metric.Iframed */, window.top == window.self || window.top == window ? 1 /* IframeStatus.TopFrame */ : 2 /* IframeStatus.Iframe */); } catch (ex) { max(31 /* Metric.Iframed */, 0 /* IframeStatus.Unknown */); } } function check$4(id, target, input) { // Compute hash for fraud detection, if enabled. Hash is computed only if input meets the minimum length criteria if (config$2.fraud && id !== null && input && input.length >= 5 /* Setting.WordLength */) { data$d = { id: id, target: target, checksum: hash(input, 28 /* Setting.ChecksumPrecision */) }; // Only encode this event if we haven't already reported this hash if (history$5.indexOf(data$d.checksum) < 0) { history$5.push(data$d.checksum); encode$2(41 /* Event.Fraud */); } } } var state$a = []; function start$z() { reset$m(); } function observe$c(root) { bind(root, "change", recompute$8, true); } function recompute$8(evt) { recompute$8.dn = 5 /* FunctionNames.ChangeRecompute */; var element = target(evt); if (element) { var value = element.value; var checksum = value && value.length >= 5 /* Setting.WordLength */ && config$2.fraud && "password,secret,pass,social,ssn,code,hidden" /* Mask.Exclude */.indexOf(element.type) === -1 ? hash(value, 28 /* Setting.ChecksumPrecision */) : "" /* Constant.Empty */; state$a.push({ time: time(evt), event: 42 /* Event.Change */, data: { target: target(evt), type: element.type, value: value, checksum: checksum } }); schedule(encode$3.bind(this, 42 /* Event.Change */)); } } function reset$m() { state$a = []; } function stop$x() { reset$m(); } function offset(element) { var output = { x: 0, y: 0 }; // Walk up the chain to ensure we compute offset distance correctly // In case where we may have nested IFRAMEs, we keep walking up until we get to the top most parent page if (element && element.offsetParent) { do { var parent_1 = element.offsetParent; var frame = parent_1 === null ? iframe(element.ownerDocument) : null; output.x += element.offsetLeft; output.y += element.offsetTop; element = frame ? frame : parent_1; } while (element); } return output; } var UserInputTags = ["input", "textarea", "radio", "button", "canvas", "select"]; var state$9 = []; function start$y() { reset$l(); } function observe$b(root) { bind(root, "click", handler$3.bind(this, 9 /* Event.Click */, root), true); } function handler$3(event, root, evt) { handler$3.dn = 6 /* FunctionNames.ClickHandler */; var frame = iframe(root); var d = frame ? frame.contentDocument.documentElement : document.documentElement; var x = "pageX" in evt ? Math.round(evt.pageX) : ("clientX" in evt ? Math.round(evt["clientX"] + d.scrollLeft) : null); var y = "pageY" in evt ? Math.round(evt.pageY) : ("clientY" in evt ? Math.round(evt["clientY"] + d.scrollTop) : null); // In case of iframe, we adjust (x,y) to be relative to top parent's origin if (frame) { var distance = offset(frame); x = x ? x + Math.round(distance.x) : x; y = y ? y + Math.round(distance.y) : y; } var t = target(evt); // Find nearest anchor tag (<a/>) parent if current target node is part of one // If present, we use the returned link element to populate text and link properties below var a = link(t); // Get layout rectangle for the target element var l = layout$1(t); // Reference: https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail // This property helps differentiate between a keyboard navigation vs. pointer click // In case of a keyboard navigation, we use center of target element as (x,y) if (evt.detail === 0 && l) { x = Math.round(l.x + (l.w / 2)); y = Math.round(l.y + (l.h / 2)); } var eX = l ? Math.max(Math.floor(((x - l.x) / l.w) * 32767 /* Setting.ClickPrecision */), 0) : 0; var eY = l ? Math.max(Math.floor(((y - l.y) / l.h) * 32767 /* Setting.ClickPrecision */), 0) : 0; // Check for null values before processing this event if (x !== null && y !== null) { var textInfo = text(t); state$9.push({ time: time(evt), event: event, data: { target: t, x: x, y: y, eX: eX, eY: eY, button: evt.button, reaction: reaction(t), context: context(a), text: textInfo.text, link: a ? a.href : null, hash: null, trust: evt.isTrusted ? 1 /* BooleanFlag.True */ : 0 /* BooleanFlag.False */, isFullText: textInfo.isFullText, } }); schedule(encode$3.bind(this, event)); } } function link(node) { while (node && node !== document) { if (node.nodeType === Node.ELEMENT_NODE) { var element = node; if (element.tagName === "A") { return element; }