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.
@@ -1,5 +1,6 @@
1
- import { Constant, Event, VariableData } from "@clarity-types/data";
1
+ import { Constant, Event, IdentityData, Setting, VariableData } from "@clarity-types/data";
2
2
  import * as core from "@src/core";
3
+ import { scrub } from "@src/core/scrub";
3
4
  import encode from "./encode";
4
5
 
5
6
  export let data: VariableData = null;
@@ -13,10 +14,28 @@ export function set(variable: string, value: string | string[]): void {
13
14
  log(variable, values);
14
15
  }
15
16
 
16
- export function identify(userId: string, sessionId: string = null, pageId: string = null): void {
17
- log(Constant.UserId, [userId]);
18
- log(Constant.SessionId, [sessionId]);
19
- log(Constant.PageId, [pageId]);
17
+ export async function identify(userId: string, sessionId: string = null, pageId: string = null, userHint: string = null): Promise<IdentityData> {
18
+ let output: IdentityData = { userId: await sha256(userId), userHint: userHint || redact(userId) };
19
+
20
+ // By default, hash custom userId using SHA256 algorithm on the client to preserve privacy
21
+ log(Constant.UserId, [output.userId]);
22
+
23
+ // Optional non-identifying name for the user
24
+ // If name is not explicitly provided, we automatically generate a redacted version of the userId
25
+ log(Constant.UserHint, [output.userHint]);
26
+ log(Constant.UserType, [detect(userId)]);
27
+
28
+ // Log sessionId and pageId if provided
29
+ if (sessionId) {
30
+ log(Constant.SessionId, [sessionId]);
31
+ output.sessionId = sessionId;
32
+ }
33
+ if (pageId) {
34
+ log(Constant.PageId, [pageId]);
35
+ output.pageId = pageId;
36
+ }
37
+
38
+ return output;
20
39
  }
21
40
 
22
41
  function log(variable: string, value: string[]): void {
@@ -44,3 +63,22 @@ export function reset(): void {
44
63
  export function stop(): void {
45
64
  reset();
46
65
  }
66
+
67
+ function redact(input: string): string {
68
+ return input && input.length >= Setting.WordLength ?
69
+ `${input.substring(0,2)}${scrub(input.substring(2), Constant.Asterix, Constant.Asterix)}` : scrub(input, Constant.Asterix, Constant.Asterix);
70
+ }
71
+
72
+ async function sha256(input: string): Promise<string> {
73
+ try {
74
+ if (crypto && input) {
75
+ // Reference: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string
76
+ const buffer = await crypto.subtle.digest(Constant.SHA256, new TextEncoder().encode(input));
77
+ return Array.prototype.map.call(new Uint8Array(buffer), (x: any) =>(('00'+x.toString(16)).slice(-2))).join('');
78
+ } else { return Constant.Empty; }
79
+ } catch { return Constant.Empty; }
80
+ }
81
+
82
+ function detect(input: string): string {
83
+ return input && input.indexOf(Constant.At) > 0 ? Constant.Email : Constant.String;
84
+ }
@@ -92,10 +92,10 @@ function text(element: Node): string {
92
92
  // Grab text using "textContent" for most HTMLElements, however, use "value" for HTMLInputElements and "alt" for HTMLImageElement.
93
93
  let t = element.textContent || (element as HTMLInputElement).value || (element as HTMLImageElement).alt;
94
94
  if (t) {
95
- // Trim any spaces at the beginning or at the end of string
96
- // Also, replace multiple occurrence of space characters with a single white space
95
+ // Replace multiple occurrence of space characters with a single white space
96
+ // Also, trim any spaces at the beginning or at the end of string
97
97
  // Finally, send only first few characters as specified by the Setting
98
- output = t.trim().replace(/\s+/g, Constant.Space).substr(0, Setting.ClickText);
98
+ output = t.replace(/\s+/g, Constant.Space).trim().substr(0, Setting.ClickText);
99
99
  }
100
100
  }
101
101
  return output;
@@ -0,0 +1,7 @@
1
+ export * from "@src/insight/blank";
2
+
3
+ export let keys = [];
4
+
5
+ /* Intentionally blank module with empty code */
6
+ export function hashText(): void {}
7
+ export function trigger(): void {}
package/types/core.d.ts CHANGED
@@ -39,7 +39,7 @@ export const enum ExtractSource {
39
39
  }
40
40
 
41
41
  export const enum Type {
42
- Array = 1,
42
+ Array = 1,
43
43
  Object = 2,
44
44
  Simple = 3
45
45
  }
@@ -136,6 +136,7 @@ export interface Config {
136
136
  fallback?: string;
137
137
  upgrade?: (key: string) => void;
138
138
  action?: (key: string) => void;
139
+ dob?: number;
139
140
  }
140
141
 
141
142
  export const enum Constant {
package/types/data.d.ts CHANGED
@@ -5,7 +5,7 @@ export type DecodedToken = (any | any[]);
5
5
 
6
6
  export type MetadataCallback = (data: Metadata, playback: boolean) => void;
7
7
  export interface MetadataCallbackOptions {
8
- callback: MetadataCallback,
8
+ callback: MetadataCallback,
9
9
  wait: boolean
10
10
  }
11
11
 
@@ -105,7 +105,8 @@ export const enum Metric {
105
105
  Iframed = 31,
106
106
  MaxTouchPoints = 32,
107
107
  HardwareConcurrency = 33,
108
- DeviceMemory = 34
108
+ DeviceMemory = 34,
109
+ Electron = 35
109
110
  }
110
111
 
111
112
  export const enum Dimension {
@@ -136,7 +137,9 @@ export const enum Dimension {
136
137
  Brand = 24,
137
138
  Model = 25,
138
139
  DevicePixelRatio = 26,
139
- ConnectionType = 27
140
+ ConnectionType = 27,
141
+ Dob = 28,
142
+ CookieVersion = 29
140
143
  }
141
144
 
142
145
  export const enum Check {
@@ -146,7 +149,8 @@ export const enum Check {
146
149
  Retry = 3,
147
150
  Bytes = 4,
148
151
  Collection = 5,
149
- Server = 6
152
+ Server = 6,
153
+ Page = 7
150
154
  }
151
155
 
152
156
  export const enum Code {
@@ -190,7 +194,7 @@ export const enum IframeStatus {
190
194
  export const enum Setting {
191
195
  Expire = 365, // 1 Year
192
196
  SessionExpire = 1, // 1 Day
193
- CookieVersion = 1, // Increment this version every time there's a cookie schema change
197
+ CookieVersion = 2, // Increment this version every time there's a cookie schema change
194
198
  SessionTimeout = 30 * Time.Minute, // 30 minutes
195
199
  CookieInterval = 1, // 1 Day
196
200
  PingInterval = 1 * Time.Minute, // 1 Minute
@@ -198,6 +202,7 @@ export const enum Setting {
198
202
  SummaryInterval = 100, // Same events within 100ms will be collapsed into single summary
199
203
  ClickText = 25, // Maximum number of characters to send as part of Click event's text field
200
204
  PayloadLimit = 128, // Do not allow more than specified payloads per page
205
+ PageLimit = 128, // Do not allow more than 128 pages in a session
201
206
  ShutdownLimit = 2 * Time.Hour, // Shutdown instrumentation after specified time
202
207
  RetryLimit = 1, // Maximum number of attempts to upload a payload before giving up
203
208
  PlaybackBytesLimit = 10 * 1024 * 1024, // 10MB
@@ -218,7 +223,7 @@ export const enum Setting {
218
223
  MinUploadDelay = 100, // Minimum time before we are ready to flush events to the server
219
224
  MaxUploadDelay = 30 * Time.Second, // Do flush out payload once every 30s,
220
225
  ExtractLimit = 10000, // Do not extract more than 10000 characters
221
- ChecksumPrecision = 24, // n-bit integer to represent token hash
226
+ ChecksumPrecision = 24, // n-bit integer to represent token hash
222
227
  UploadTimeout = 15000 // Timeout in ms for XHR requests
223
228
  }
224
229
 
@@ -249,6 +254,8 @@ export const enum Constant {
249
254
  Dropped = "*na*",
250
255
  Comma = ",",
251
256
  Dot = ".",
257
+ At = "@",
258
+ Asterix = "*",
252
259
  Semicolon = ";",
253
260
  Equals = "=",
254
261
  Path = ";path=/",
@@ -258,6 +265,7 @@ export const enum Constant {
258
265
  Top = "_top",
259
266
  String = "string",
260
267
  Number = "number",
268
+ Email = "email",
261
269
  CookieKey = "_clck", // Clarity Cookie Key
262
270
  SessionKey = "_clsk", // Clarity Session Key
263
271
  TabKey = "_cltk", // Clarity Tab Key
@@ -266,6 +274,8 @@ export const enum Constant {
266
274
  Upgrade = "UPGRADE",
267
275
  Action = "ACTION",
268
276
  Extract = "EXTRACT",
277
+ UserHint = "userHint",
278
+ UserType = "userType",
269
279
  UserId = "userId",
270
280
  SessionId = "sessionId",
271
281
  PageId = "pageId",
@@ -290,7 +300,9 @@ export const enum Constant {
290
300
  ConditionEnd = "}",
291
301
  Seperator = "<SEP>",
292
302
  Timeout = "Timeout",
293
- Bang = "!"
303
+ Bang = "!",
304
+ SHA256 = "SHA-256",
305
+ Electron = "Electron"
294
306
  }
295
307
 
296
308
  export const enum XMLReadyState {
@@ -332,8 +344,10 @@ export interface Session {
332
344
 
333
345
  export interface User {
334
346
  id: string;
347
+ version: number;
335
348
  expiry: number;
336
349
  consent: BooleanFlag;
350
+ dob: number;
337
351
  }
338
352
 
339
353
  export interface Envelope extends Metadata {
@@ -372,6 +386,13 @@ export interface BaselineData {
372
386
  activityTime: number;
373
387
  }
374
388
 
389
+ export interface IdentityData {
390
+ userId: string;
391
+ userHint: string;
392
+ sessionId?: string;
393
+ pageId?: string;
394
+ }
395
+
375
396
  export interface DimensionData {
376
397
  [key: number]: string[];
377
398
  }
package/types/index.d.ts CHANGED
@@ -14,7 +14,7 @@ interface Clarity {
14
14
  consent: () => void;
15
15
  event: (name: string, value: string) => void;
16
16
  set: (variable: string, value: string | string[]) => void;
17
- identify: (userId: string, sessionId?: string, pageId?: string) => void;
17
+ identify: (userId: string, sessionId?: string, pageId?: string, userHint?: string) => void;
18
18
  metadata: (callback: Data.MetadataCallback, wait?: boolean) => void;
19
19
  }
20
20