clarity-js 0.6.32 → 0.6.35

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/types/data.d.ts CHANGED
@@ -4,9 +4,12 @@ export type Token = (string | number | number[] | string[]);
4
4
  export type DecodedToken = (any | any[]);
5
5
 
6
6
  export type MetadataCallback = (data: Metadata, playback: boolean) => void;
7
+ export interface MetadataCallbackOptions {
8
+ callback: MetadataCallback,
9
+ wait: boolean
10
+ }
7
11
 
8
12
  /* Enum */
9
-
10
13
  export const enum Event {
11
14
  /* Data */
12
15
  Metric = 0,
@@ -52,9 +55,14 @@ export const enum Event {
52
55
  Variable = 34,
53
56
  Limit = 35,
54
57
  Summary = 36,
58
+ /**
59
+ * @deprecated No longer support Box event
60
+ */
55
61
  Box = 37,
56
62
  Clipboard = 38,
57
- Submit = 39
63
+ Submit = 39,
64
+ Extract = 40,
65
+ Fraud = 41
58
66
  }
59
67
 
60
68
  export const enum Metric {
@@ -85,7 +93,10 @@ export const enum Metric {
85
93
  CartTotal = 24,
86
94
  EventCount = 25,
87
95
  Automation = 26,
88
- Mobile = 27
96
+ Mobile = 27,
97
+ UploadTime = 28,
98
+ SinglePage = 29,
99
+ UsedMemory = 30
89
100
  }
90
101
 
91
102
  export const enum Dimension {
@@ -138,7 +149,8 @@ export const enum Code {
138
149
  /**
139
150
  * @deprecated No longer support ContentSecurityPolicy
140
151
  */
141
- ContentSecurityPolicy = 7
152
+ ContentSecurityPolicy = 7,
153
+ Config = 8
142
154
  }
143
155
 
144
156
  export const enum Severity {
@@ -175,7 +187,6 @@ export const enum Setting {
175
187
  CollectionLimit = 128, // Number of unique entries for dimensions
176
188
  ClickPrecision = 32767, // 2^15 - 1
177
189
  BoxPrecision = 100, // Up to 2 decimal points (e.g. 34.56)
178
- ResizeObserverThreshold = 15, // At least 15 characters before we attach a resize observer for the node
179
190
  ScriptErrorLimit = 5, // Do not send the same script error more than 5 times per page
180
191
  DimensionLimit = 256, // Do not extract dimensions which are over 256 characters
181
192
  WordLength = 5, // Estimated average size of a word,
@@ -185,9 +196,11 @@ export const enum Setting {
185
196
  ViewportIntersectionRatio = 0.05, // Ratio of intersection area in comparison to viewport area before it's marked visible
186
197
  IntersectionRatio = 0.8, // Ratio of intersection area in comparison to element's area before it's marked visible
187
198
  MaxFirstPayloadBytes = 1 * 1024 * 1024, // 1MB: Cap the very first payload to a maximum of 1MB
199
+ MegaByte = 1024 * 1024, // 1MB
188
200
  UploadFactor = 3, // Slow down sequence by specified factor
189
201
  MinUploadDelay = 100, // Minimum time before we are ready to flush events to the server
190
- MaxUploadDelay = 30 * Time.Second // Do flush out payload once every 30s
202
+ MaxUploadDelay = 30 * Time.Second, // Do flush out payload once every 30s,
203
+ ExtractLimit = 10000 // Do not extract more than 10000 characters
191
204
  }
192
205
 
193
206
  export const enum Character {
@@ -209,6 +222,7 @@ export const enum Constant {
209
222
  Pause = "pause",
210
223
  Resume = "resume",
211
224
  Report = "report",
225
+ Memory = "memory",
212
226
  Empty = "",
213
227
  Space = " ",
214
228
  Expires = "expires=",
@@ -233,7 +247,6 @@ export const enum Constant {
233
247
  UserId = "userId",
234
248
  SessionId = "sessionId",
235
249
  PageId = "pageId",
236
- ResizeObserver = "ResizeObserver",
237
250
  Mask = "•",
238
251
  SessionStorage = "sessionStorage",
239
252
  Cookie = "cookie",
@@ -248,6 +261,9 @@ export const enum Constant {
248
261
  Accept = "Accept",
249
262
  ClarityGzip = "application/x-clarity-gzip",
250
263
  Tilde = "~",
264
+ ArrayStart = "[",
265
+ ConditionStart = "{",
266
+ ConditionEnd = "}"
251
267
  }
252
268
 
253
269
  export const enum XMLReadyState {
@@ -366,6 +382,10 @@ export interface UpgradeData {
366
382
  key: string;
367
383
  }
368
384
 
385
+ export interface ExtractData {
386
+ [key: string]: string | number;
387
+ }
388
+
369
389
  export interface UploadData {
370
390
  sequence: number;
371
391
  attempts: number;
@@ -16,3 +16,9 @@ export interface LogData {
16
16
  stack: string;
17
17
  severity: Severity;
18
18
  }
19
+
20
+ export interface FraudData {
21
+ id: number;
22
+ target: number;
23
+ hash: string;
24
+ }
@@ -103,6 +103,7 @@ export interface ClickData {
103
103
  text: string;
104
104
  link: string;
105
105
  hash: string;
106
+ trust: number;
106
107
  }
107
108
 
108
109
  export interface ClipboardData {
package/types/layout.d.ts CHANGED
@@ -28,6 +28,11 @@ export const enum RegionVisibility {
28
28
  ScrolledToEnd = 13
29
29
  }
30
30
 
31
+ export const enum Mask {
32
+ Text = "password,secret,pass,social,ssn,name,code,dob,cell,mob,contact,hidden,account,cvv,ccv,email,tel,phone,address,addr,card,zip",
33
+ Disable = "radio,checkbox,range,button,reset,submit"
34
+ }
35
+
31
36
  export const enum Constant {
32
37
  Empty = "",
33
38
  SvgPrefix = "svg:",
@@ -42,6 +47,7 @@ export const enum Constant {
42
47
  Box = "#",
43
48
  Bang = "!",
44
49
  Period = ".",
50
+ Comma = ",",
45
51
  MaskData = "data-clarity-mask",
46
52
  UnmaskData = "data-clarity-unmask",
47
53
  RegionData = "data-clarity-region",
@@ -154,6 +160,7 @@ export interface NodeValue {
154
160
  hash: [string, string];
155
161
  region: number;
156
162
  metadata: NodeMeta;
163
+ fragment: number;
157
164
  }
158
165
 
159
166
  export interface NodeMeta {
@@ -161,6 +168,7 @@ export interface NodeMeta {
161
168
  suspend: boolean;
162
169
  privacy: Privacy;
163
170
  position: number;
171
+ fraud: number;
164
172
  size: number[];
165
173
  }
166
174
 
@@ -197,12 +205,6 @@ export interface RegionData {
197
205
  name: string;
198
206
  }
199
207
 
200
- export interface BoxData {
201
- id: number;
202
- width: number;
203
- height: number;
204
- }
205
-
206
208
  export interface TargetMetadata {
207
209
  id: number;
208
210
  hash: [string, string];
@@ -31,10 +31,3 @@ export interface NavigationData {
31
31
  encodedSize: number;
32
32
  decodedSize: number;
33
33
  }
34
-
35
- export interface ConnectionData {
36
- downlink: number;
37
- rtt: number;
38
- saveData: BooleanFlag;
39
- type: string;
40
- }
package/src/layout/box.ts DELETED
@@ -1,83 +0,0 @@
1
- import { Event, Setting } from "@clarity-types/data";
2
- import { BoxData } from "@clarity-types/layout";
3
- import * as dom from "@src/layout/dom";
4
- import encode from "@src/layout/encode";
5
-
6
- export let data: BoxData[] = [];
7
- let enabled = false;
8
- let observer: ResizeObserver = null;
9
-
10
- export function start(): void {
11
- reset();
12
- observer = null;
13
- enabled = window["ResizeObserver"] ? true : false;
14
- }
15
-
16
- export function compute(id: number): void {
17
- if (enabled === false) { return; }
18
- observer = observer === null ? new ResizeObserver(handler) : observer;
19
- if (observer) {
20
- let value = dom.getValue(id);
21
- // If this is the first time computing size for this node, go ahead and wire up ResizeObserver
22
- // In all other cases, value.metadata.size will be null or an array with two elements [width, height]
23
- // And, in those cases, we will skip through the following section and not attach the observer
24
- if (value && value.metadata.size !== null && value.metadata.size.length === 0) {
25
- let node = dom.getNode(id);
26
- if (node && node.nodeType === Node.ELEMENT_NODE) {
27
- let e = node as HTMLElement;
28
- let r = e.getBoundingClientRect();
29
- value.metadata.size = [Math.floor(r.width * Setting.BoxPrecision), Math.floor(r.height * Setting.BoxPrecision)];
30
- observer.observe(e);
31
- }
32
- }
33
- }
34
- }
35
-
36
- function handler(entries: ResizeObserverEntry[]): void {
37
- window.requestAnimationFrame(() => {
38
- for (let entry of entries) {
39
- let target = entry.target;
40
- let id = target ? dom.getId(target) : null;
41
- if (id) {
42
- let v = dom.getValue(id);
43
- let s = v.metadata.size;
44
- let b = entry.borderBoxSize as any;
45
- let w = null;
46
- let h = null;
47
- // Check if browser supports borderBoxSize property on ResizeObserverEntry object
48
- // Otherwise, fall back to using getBoundingClientRect() to be cross browser compatible
49
- // Reference: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/borderBoxSize
50
- if(b && b.length > 0) {
51
- w = Math.floor(b[0].inlineSize * Setting.BoxPrecision);
52
- h = Math.floor(b[0].blockSize * Setting.BoxPrecision);
53
- } else {
54
- let r = target.getBoundingClientRect();
55
- w = Math.floor(r.width * Setting.BoxPrecision);
56
- h = Math.floor(r.height * Setting.BoxPrecision);
57
- }
58
-
59
- // Capture new width & height only if they are different from what we have in in-memory cache
60
- if (w !== s[0] && h !== s[1]) {
61
- s = [w,h];
62
- data.push({ id, width: w, height: h });
63
- }
64
- }
65
- }
66
-
67
- // Schedule encode only when we have at least one valid data entry
68
- if (data.length > 0) { encode(Event.Box); }
69
- });
70
- }
71
-
72
- export function reset(): void {
73
- data = [];
74
- }
75
-
76
- export function stop(): void {
77
- reset();
78
- if (observer) {
79
- observer.disconnect();
80
- observer = null;
81
- }
82
- enabled = false;
83
- }
@@ -1,94 +0,0 @@
1
- import { Dimension, Extract, Metric, Region, RegionFilter } from "@clarity-types/core";
2
- import { Constant, Setting } from "@clarity-types/data";
3
- import * as dimension from "@src/data/dimension";
4
- import * as metric from "@src/data/metric";
5
- import * as region from "@src/layout/region";
6
-
7
- const formatRegex = /1/g;
8
- const digitsRegex = /[^0-9\.]/g;
9
- const digitsWithCommaRegex = /[^0-9\.,]/g;
10
- const regexCache: {[key: string]: RegExp} = {};
11
-
12
- export function regions(root: ParentNode, value: Region[]): void {
13
- for (let v of value) {
14
- const [regionId, selector, filter, match] = v;
15
- let valid = true;
16
- switch (filter) {
17
- case RegionFilter.Url: valid = match && !!top.location.href.match(regex(match)); break;
18
- case RegionFilter.Javascript: valid = match && !!evaluate(match); break;
19
- }
20
- if (valid) { root.querySelectorAll(selector).forEach(e => region.observe(e, regionId.toString())); }
21
- }
22
- }
23
-
24
- export function metrics(root: ParentNode, value: Metric[]): void {
25
- for (let v of value) {
26
- const [metricId, source, match, scale] = v;
27
- if (match) {
28
- switch (source) {
29
- case Extract.Text: root.querySelectorAll(match).forEach(e => { metric.max(metricId, num((e as HTMLElement).innerText, scale)); }); break;
30
- case Extract.Attribute: root.querySelectorAll(`[${match}]`).forEach(e => { metric.max(metricId, num(e.getAttribute(match), scale, false)); }); break;
31
- case Extract.Javascript: metric.max(metricId, evaluate(match, Constant.Number) as number); break;
32
- }
33
- }
34
- }
35
- }
36
-
37
- export function dimensions(root: ParentNode, value: Dimension[]): void {
38
- for (let v of value) {
39
- const [dimensionId, source, match] = v;
40
- if (match) {
41
- switch (source) {
42
- case Extract.Text: root.querySelectorAll(match).forEach(e => { dimension.log(dimensionId, str((e as HTMLElement).innerText)); }); break;
43
- case Extract.Attribute: root.querySelectorAll(`[${match}]`).forEach(e => { dimension.log(dimensionId, str(e.getAttribute(match))); }); break;
44
- case Extract.Javascript: dimension.log(dimensionId, str(evaluate(match, Constant.String))); break;
45
- }
46
- }
47
- }
48
- }
49
-
50
- function regex(match: string): RegExp {
51
- regexCache[match] = match in regexCache ? regexCache[match] : new RegExp(match);
52
- return regexCache[match];
53
- }
54
-
55
- // The function below takes in a variable name in following format: "a.b.c" and safely evaluates its value in javascript context
56
- // 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,
57
- // return the value for window["a"]["b"]["c"].
58
- function evaluate(variable: string, type: string = null, base: Object = window): any {
59
- let parts = variable.split(Constant.Dot);
60
- let first = parts.shift();
61
- if (base && base[first]) {
62
- if (parts.length > 0) { return evaluate(parts.join(Constant.Dot), type, base[first]); }
63
- let output = type === null || type === typeof base[first] ? base[first] : null;
64
- return output;
65
- }
66
- return null;
67
- }
68
-
69
- function str(input: string): string {
70
- // Automatically trim string to max of Setting.DimensionLimit to avoid fetching long strings
71
- return input ? input.substr(0, Setting.DimensionLimit) : input;
72
- }
73
-
74
- function num(text: string, scale: number, localize: boolean = true): number {
75
- try {
76
- scale = scale || 1;
77
- // Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat
78
- let lang = document.documentElement.lang;
79
- if (Intl && Intl.NumberFormat && lang && localize) {
80
- text = text.replace(digitsWithCommaRegex, Constant.Empty);
81
- // Infer current group and decimal separator from current locale
82
- let group = Intl.NumberFormat(lang).format(11111).replace(formatRegex, Constant.Empty);
83
- let decimal = Intl.NumberFormat(lang).format(1.1).replace(formatRegex, Constant.Empty);
84
-
85
- // Parse number using inferred group and decimal separators
86
- return Math.round(parseFloat(text
87
- .replace(new RegExp('\\' + group, 'g'), Constant.Empty)
88
- .replace(new RegExp('\\' + decimal), Constant.Dot)
89
- ) * scale);
90
- }
91
- // Fallback to en locale
92
- return Math.round(parseFloat(text.replace(digitsRegex, Constant.Empty)) * scale);
93
- } catch { return null; }
94
- }