@sessionlens/sdk 0.2.1 → 0.3.0
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/README.md +22 -0
- package/dist/core/config.d.ts +5 -2
- package/dist/core/enrich.d.ts +6 -0
- package/dist/core/identity.d.ts +14 -0
- package/dist/core/tracker.d.ts +16 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.esm.js +342 -120
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +342 -119
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/utils/ua.d.ts +8 -0
- package/dist/utils/uuid.d.ts +2 -0
- package/dist/version.d.ts +2 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,6 +4,106 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var react = require('react');
|
|
6
6
|
|
|
7
|
+
/** RFC 4122 v4 UUID: crypto.randomUUID() when available, else getRandomValues, else Math.random. */
|
|
8
|
+
function uuidv4() {
|
|
9
|
+
const c = typeof crypto !== 'undefined' ? crypto : undefined;
|
|
10
|
+
if (c && typeof c.randomUUID === 'function') {
|
|
11
|
+
return c.randomUUID();
|
|
12
|
+
}
|
|
13
|
+
const bytes = new Uint8Array(16);
|
|
14
|
+
if (c && typeof c.getRandomValues === 'function') {
|
|
15
|
+
c.getRandomValues(bytes);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
for (let i = 0; i < 16; i++)
|
|
19
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
20
|
+
}
|
|
21
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
|
|
22
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant 10
|
|
23
|
+
const hex = [];
|
|
24
|
+
for (let i = 0; i < 16; i++)
|
|
25
|
+
hex.push((bytes[i] + 0x100).toString(16).substring(1));
|
|
26
|
+
return (hex.slice(0, 4).join('') + '-' + hex.slice(4, 6).join('') + '-' + hex.slice(6, 8).join('') + '-' +
|
|
27
|
+
hex.slice(8, 10).join('') + '-' + hex.slice(10, 16).join(''));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Storage keys (localStorage). Deliberately not scoped per project: a device is one device.
|
|
31
|
+
const DEVICE_ID_KEY = '_sl_device_id';
|
|
32
|
+
const DISTINCT_ID_KEY = '_sl_distinct_id';
|
|
33
|
+
const USER_ID_KEY = '_sl_user_id';
|
|
34
|
+
const INITIAL_REFERRER_KEY = '_sl_initial_referrer';
|
|
35
|
+
// Used when localStorage is unavailable (SSR, private mode, blocked storage).
|
|
36
|
+
const memoryStore = {};
|
|
37
|
+
function storageGet(key) {
|
|
38
|
+
try {
|
|
39
|
+
if (typeof window !== 'undefined' && window.localStorage) {
|
|
40
|
+
return window.localStorage.getItem(key);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (_) {
|
|
44
|
+
// fall through to memory
|
|
45
|
+
}
|
|
46
|
+
return key in memoryStore ? memoryStore[key] : null;
|
|
47
|
+
}
|
|
48
|
+
function storageSet(key, value) {
|
|
49
|
+
memoryStore[key] = value;
|
|
50
|
+
try {
|
|
51
|
+
if (typeof window !== 'undefined' && window.localStorage) {
|
|
52
|
+
window.localStorage.setItem(key, value);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (_) {
|
|
56
|
+
// memory copy above keeps the identity stable for this page session
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function storageRemove(key) {
|
|
60
|
+
delete memoryStore[key];
|
|
61
|
+
try {
|
|
62
|
+
if (typeof window !== 'undefined' && window.localStorage) {
|
|
63
|
+
window.localStorage.removeItem(key);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch (_) {
|
|
67
|
+
// ignore
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function getDeviceId() {
|
|
71
|
+
let deviceId = storageGet(DEVICE_ID_KEY);
|
|
72
|
+
if (!deviceId) {
|
|
73
|
+
deviceId = uuidv4();
|
|
74
|
+
storageSet(DEVICE_ID_KEY, deviceId);
|
|
75
|
+
}
|
|
76
|
+
return deviceId;
|
|
77
|
+
}
|
|
78
|
+
/** Current identity. Anonymous visitors have distinct_id === device_id and no user_id. */
|
|
79
|
+
function getIdentity() {
|
|
80
|
+
const device_id = getDeviceId();
|
|
81
|
+
const user_id = storageGet(USER_ID_KEY) || undefined;
|
|
82
|
+
const distinct_id = storageGet(DISTINCT_ID_KEY) || user_id || device_id;
|
|
83
|
+
return { device_id, distinct_id, user_id };
|
|
84
|
+
}
|
|
85
|
+
/** Persist a user identity. From now on events carry distinct_id = userId. */
|
|
86
|
+
function setUser(userId) {
|
|
87
|
+
storageSet(USER_ID_KEY, userId);
|
|
88
|
+
storageSet(DISTINCT_ID_KEY, userId);
|
|
89
|
+
}
|
|
90
|
+
/** Forget the user and start a fresh anonymous identity on a new device id. */
|
|
91
|
+
function resetIdentity() {
|
|
92
|
+
storageRemove(USER_ID_KEY);
|
|
93
|
+
storageRemove(DISTINCT_ID_KEY);
|
|
94
|
+
storageRemove(DEVICE_ID_KEY);
|
|
95
|
+
return getIdentity();
|
|
96
|
+
}
|
|
97
|
+
/** Referrer of the very first page load, persisted once ('$direct' when there was none). */
|
|
98
|
+
function getInitialReferrer(currentReferrer) {
|
|
99
|
+
let value = storageGet(INITIAL_REFERRER_KEY);
|
|
100
|
+
if (value === null) {
|
|
101
|
+
value = currentReferrer || '$direct';
|
|
102
|
+
storageSet(INITIAL_REFERRER_KEY, value);
|
|
103
|
+
}
|
|
104
|
+
return value;
|
|
105
|
+
}
|
|
106
|
+
|
|
7
107
|
// Session timeout (30 minutes of inactivity)
|
|
8
108
|
const SESSION_TIMEOUT = 30 * 60 * 1000;
|
|
9
109
|
// Store the config and session info
|
|
@@ -61,7 +161,7 @@ const startNewSession = (config) => {
|
|
|
61
161
|
client_id: getOrCreateClientId(config),
|
|
62
162
|
org_id: config.org_id,
|
|
63
163
|
project_id: project_id,
|
|
64
|
-
user_id:
|
|
164
|
+
user_id: getIdentity().user_id,
|
|
65
165
|
started_at: now,
|
|
66
166
|
last_activity: now
|
|
67
167
|
};
|
|
@@ -79,6 +179,12 @@ const isSessionExpired = () => {
|
|
|
79
179
|
return true;
|
|
80
180
|
return Date.now() - currentSession.last_activity > SESSION_TIMEOUT;
|
|
81
181
|
};
|
|
182
|
+
// Begin a fresh session (used by reset())
|
|
183
|
+
function restartSession() {
|
|
184
|
+
if (currentConfig) {
|
|
185
|
+
startNewSession(currentConfig);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
82
188
|
// Update session activity timestamp
|
|
83
189
|
const updateSessionActivity = () => {
|
|
84
190
|
if (currentSession) {
|
|
@@ -106,14 +212,11 @@ const getEndpoint = (config, endpointType, defaultEndpoint) => {
|
|
|
106
212
|
return ((_a = config.endpoints) === null || _a === void 0 ? void 0 : _a[endpointType]) || defaultEndpoint;
|
|
107
213
|
};
|
|
108
214
|
// `sessionLensInit()` sets the config and validates with backend
|
|
109
|
-
async function sessionLensInit(config) {
|
|
215
|
+
async function sessionLensInit$1(config) {
|
|
110
216
|
// Validate required fields
|
|
111
217
|
if (!config.sdk_key) {
|
|
112
218
|
throw new Error('[SessionLens] sdk_key is required');
|
|
113
219
|
}
|
|
114
|
-
if (!config.user_id) {
|
|
115
|
-
throw new Error('[SessionLens] user_id is required');
|
|
116
|
-
}
|
|
117
220
|
if (!config.org_id) {
|
|
118
221
|
throw new Error('[SessionLens] org_id is required');
|
|
119
222
|
}
|
|
@@ -128,7 +231,9 @@ async function sessionLensInit(config) {
|
|
|
128
231
|
// Use GET with query parameters for org_id and user_id validation
|
|
129
232
|
const validationUrl = new URL(`${apiBaseUrl}${validateEndpoint}`);
|
|
130
233
|
validationUrl.searchParams.set('org_id', config.org_id);
|
|
131
|
-
|
|
234
|
+
if (config.user_id) {
|
|
235
|
+
validationUrl.searchParams.set('user_id', config.user_id);
|
|
236
|
+
}
|
|
132
237
|
const response = await fetch(validationUrl.toString(), {
|
|
133
238
|
method: 'GET',
|
|
134
239
|
headers: {
|
|
@@ -196,154 +301,260 @@ function getSessionLensApiBaseUrl() {
|
|
|
196
301
|
return getApiBaseUrl(currentConfig || undefined);
|
|
197
302
|
}
|
|
198
303
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
304
|
+
// Order matters: Edge/Opera/Samsung embed "Chrome", Chrome embeds "Safari".
|
|
305
|
+
const BROWSERS = [
|
|
306
|
+
['Edge', /(?:Edg|EdgA|EdgiOS|Edge)\/([\d.]+)/],
|
|
307
|
+
['Opera', /(?:OPR|Opera)\/([\d.]+)/],
|
|
308
|
+
['Samsung Internet', /SamsungBrowser\/([\d.]+)/],
|
|
309
|
+
['Firefox', /(?:Firefox|FxiOS)\/([\d.]+)/],
|
|
310
|
+
['Chrome', /(?:Chrome|CriOS)\/([\d.]+)/],
|
|
311
|
+
['Internet Explorer', /(?:MSIE |Trident\/.*rv:)([\d.]+)/],
|
|
312
|
+
['Safari', /Version\/([\d.]+).*Safari/],
|
|
313
|
+
];
|
|
314
|
+
const OSES = [
|
|
315
|
+
['Windows', /Windows NT ([\d.]+)/],
|
|
316
|
+
['iOS', /(?:iPhone|CPU) OS ([\d_]+)/],
|
|
317
|
+
['Android', /Android ([\d.]+)/],
|
|
318
|
+
['Mac OS X', /Mac OS X ([\d_.]+)/],
|
|
319
|
+
['Chrome OS', /CrOS \S+ ([\d.]+)/],
|
|
320
|
+
['Linux', /Linux()/],
|
|
321
|
+
];
|
|
322
|
+
function parseUserAgent(ua) {
|
|
323
|
+
const result = { browser: '', browser_version: '', os: '', os_version: '', device_type: '' };
|
|
324
|
+
if (!ua)
|
|
325
|
+
return result;
|
|
326
|
+
for (const [name, re] of BROWSERS) {
|
|
327
|
+
const m = ua.match(re);
|
|
328
|
+
if (m) {
|
|
329
|
+
result.browser = name;
|
|
330
|
+
result.browser_version = m[1];
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
for (const [name, re] of OSES) {
|
|
335
|
+
const m = ua.match(re);
|
|
336
|
+
if (m) {
|
|
337
|
+
result.os = name;
|
|
338
|
+
result.os_version = (m[1] || '').replace(/_/g, '.');
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
if (/iPad|Tablet|PlayBook|Silk/i.test(ua) || (/Android/i.test(ua) && !/Mobile/i.test(ua))) {
|
|
343
|
+
result.device_type = 'Tablet';
|
|
344
|
+
}
|
|
345
|
+
else if (/Mobi|iPhone|iPod|Android|Windows Phone/i.test(ua)) {
|
|
346
|
+
result.device_type = 'Mobile';
|
|
347
|
+
}
|
|
348
|
+
else if (result.os) {
|
|
349
|
+
result.device_type = 'Desktop';
|
|
350
|
+
}
|
|
351
|
+
return result;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Hand-maintained (bundling package.json would need an extra rollup plugin).
|
|
355
|
+
// Keep in sync with "version" in package.json when releasing.
|
|
356
|
+
const SDK_VERSION = '0.3.0';
|
|
357
|
+
const SDK_LIBRARY = 'sessionlens-js';
|
|
358
|
+
|
|
359
|
+
const UTM_KEYS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'];
|
|
360
|
+
function hostOf(url) {
|
|
361
|
+
try {
|
|
362
|
+
return new URL(url).hostname;
|
|
363
|
+
}
|
|
364
|
+
catch (_) {
|
|
365
|
+
return '';
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* System properties attached to every event. All browser access is guarded so this
|
|
370
|
+
* is safe to call during SSR (only identity/library fields are returned there).
|
|
371
|
+
* The server re-derives browser/os/geo authoritatively; the client UA fields are a fallback.
|
|
372
|
+
*/
|
|
373
|
+
function buildSystemProperties(clientTimestamp) {
|
|
374
|
+
const identity = getIdentity();
|
|
375
|
+
const props = {
|
|
376
|
+
$device_id: identity.device_id,
|
|
377
|
+
$distinct_id: identity.distinct_id,
|
|
378
|
+
$insert_id: uuidv4(),
|
|
379
|
+
$library: SDK_LIBRARY,
|
|
380
|
+
$library_version: SDK_VERSION,
|
|
381
|
+
$client_timestamp: clientTimestamp,
|
|
206
382
|
};
|
|
207
|
-
if (
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
383
|
+
if (identity.user_id)
|
|
384
|
+
props.$user_id = identity.user_id;
|
|
385
|
+
if (typeof window === 'undefined')
|
|
386
|
+
return props;
|
|
387
|
+
try {
|
|
388
|
+
const loc = window.location;
|
|
389
|
+
props.$current_url = loc.href;
|
|
390
|
+
props.$pathname = loc.pathname;
|
|
391
|
+
const referrer = typeof document !== 'undefined' ? document.referrer || '' : '';
|
|
392
|
+
props.$referrer = referrer || '$direct';
|
|
393
|
+
props.$referring_domain = referrer ? hostOf(referrer) : '$direct';
|
|
394
|
+
props.$initial_referrer = getInitialReferrer(referrer);
|
|
395
|
+
const params = new URLSearchParams(loc.search);
|
|
396
|
+
for (const key of UTM_KEYS) {
|
|
397
|
+
const value = params.get(key);
|
|
398
|
+
if (value)
|
|
399
|
+
props['$' + key] = value;
|
|
400
|
+
}
|
|
401
|
+
if (window.screen) {
|
|
402
|
+
props.$screen_width = window.screen.width;
|
|
403
|
+
props.$screen_height = window.screen.height;
|
|
404
|
+
}
|
|
405
|
+
if (typeof navigator !== 'undefined' && navigator.userAgent) {
|
|
406
|
+
const ua = parseUserAgent(navigator.userAgent);
|
|
407
|
+
if (ua.browser)
|
|
408
|
+
props.$browser = ua.browser;
|
|
409
|
+
if (ua.browser_version)
|
|
410
|
+
props.$browser_version = ua.browser_version;
|
|
411
|
+
if (ua.os)
|
|
412
|
+
props.$os = ua.os;
|
|
413
|
+
if (ua.os_version)
|
|
414
|
+
props.$os_version = ua.os_version;
|
|
415
|
+
if (ua.device_type)
|
|
416
|
+
props.$device_type = ua.device_type;
|
|
417
|
+
}
|
|
214
418
|
}
|
|
215
|
-
|
|
216
|
-
|
|
419
|
+
catch (_) {
|
|
420
|
+
// enrichment must never break tracking
|
|
421
|
+
}
|
|
422
|
+
return props;
|
|
217
423
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
});
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Initialize the SDK. If `config.user_id` is supplied (pre-0.3 integrations) it is treated
|
|
427
|
+
* as an implicit identify() - sent only when it differs from the persisted identity.
|
|
428
|
+
*/
|
|
429
|
+
async function sessionLensInit(config) {
|
|
430
|
+
await sessionLensInit$1(config);
|
|
431
|
+
if (config.user_id && getIdentity().user_id !== config.user_id) {
|
|
432
|
+
identify(config.user_id);
|
|
228
433
|
}
|
|
229
|
-
// Send identify event to backend with session context
|
|
230
|
-
sendIdentifyToBackend(user, config, sessionInfo);
|
|
231
434
|
}
|
|
232
|
-
function
|
|
435
|
+
function sessionLensTrack(event) {
|
|
233
436
|
const config = sessionLensGetConfig();
|
|
234
437
|
const sessionInfo = getSessionInfo(); // Get current session with activity update
|
|
438
|
+
const timestamp = event.timestamp || Date.now();
|
|
439
|
+
// Caller-supplied properties override auto-collected ones (e.g. to pass a stable $insert_id for retries).
|
|
440
|
+
const properties = { ...buildSystemProperties(timestamp), ...(event.properties || {}) };
|
|
441
|
+
const eventWithContext = { ...event, timestamp, properties };
|
|
235
442
|
if (config.debug) {
|
|
236
|
-
console.log('SessionLens
|
|
443
|
+
console.log('SessionLens Track:', eventWithContext);
|
|
237
444
|
console.log('Session Context:', {
|
|
238
445
|
session_id: sessionInfo.session_id,
|
|
239
446
|
client_id: sessionInfo.client_id,
|
|
240
447
|
project_id: sessionInfo.project_id
|
|
241
448
|
});
|
|
242
449
|
}
|
|
243
|
-
|
|
244
|
-
sendResetToBackend(config, sessionInfo);
|
|
450
|
+
sendEventToBackend(eventWithContext, config, sessionInfo);
|
|
245
451
|
}
|
|
246
|
-
|
|
247
|
-
|
|
452
|
+
/** Link the current device to `userId` (last identify wins) and optionally set traits. */
|
|
453
|
+
function identify(userId, traits) {
|
|
248
454
|
var _a;
|
|
249
|
-
const
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
'Content-Type': 'application/json',
|
|
256
|
-
'Authorization': `Bearer ${config.sdk_key}`
|
|
257
|
-
},
|
|
258
|
-
body: JSON.stringify({
|
|
259
|
-
org_id: config.org_id,
|
|
260
|
-
project_id: sessionInfo.project_id,
|
|
261
|
-
user_id: config.user_id,
|
|
262
|
-
session_id: sessionInfo.session_id,
|
|
263
|
-
client_id: sessionInfo.client_id,
|
|
264
|
-
session_started_at: sessionInfo.started_at,
|
|
265
|
-
event: event
|
|
266
|
-
})
|
|
267
|
-
});
|
|
268
|
-
if (!response.ok && config.debug) {
|
|
269
|
-
console.warn('SessionLens: Failed to send event:', response.status);
|
|
270
|
-
}
|
|
271
|
-
else if (config.debug) {
|
|
272
|
-
console.log('SessionLens: Event sent successfully with session context');
|
|
273
|
-
}
|
|
455
|
+
const config = sessionLensGetConfig();
|
|
456
|
+
const sessionInfo = getSessionInfo();
|
|
457
|
+
if (!userId) {
|
|
458
|
+
if (config.debug)
|
|
459
|
+
console.warn('SessionLens: identify() requires a userId');
|
|
460
|
+
return;
|
|
274
461
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
462
|
+
setUser(userId);
|
|
463
|
+
if (config.debug) {
|
|
464
|
+
console.log('SessionLens Identify:', { userId, traits });
|
|
279
465
|
}
|
|
466
|
+
post(config, ((_a = config.endpoints) === null || _a === void 0 ? void 0 : _a.identify) || '/identify', {
|
|
467
|
+
org_id: config.org_id,
|
|
468
|
+
project_id: sessionInfo.project_id,
|
|
469
|
+
app: config.app || 'unknown',
|
|
470
|
+
user_id: userId,
|
|
471
|
+
device_id: getIdentity().device_id,
|
|
472
|
+
session_id: sessionInfo.session_id,
|
|
473
|
+
client_id: sessionInfo.client_id,
|
|
474
|
+
session_started_at: sessionInfo.started_at,
|
|
475
|
+
traits: traits || {}
|
|
476
|
+
}, 'identify');
|
|
477
|
+
}
|
|
478
|
+
/** @deprecated Aliasing is subsumed by identify(); `oldId` is ignored (the device link is implicit). */
|
|
479
|
+
function alias(newId, _oldId) {
|
|
480
|
+
identify(newId);
|
|
481
|
+
}
|
|
482
|
+
/** Set traits on the current profile (`name` and `email` map to core profile fields). */
|
|
483
|
+
function setUserProperties(traits) {
|
|
484
|
+
var _a;
|
|
485
|
+
const config = sessionLensGetConfig();
|
|
486
|
+
const sessionInfo = getSessionInfo();
|
|
487
|
+
post(config, ((_a = config.endpoints) === null || _a === void 0 ? void 0 : _a.userProperties) || '/user-properties', {
|
|
488
|
+
org_id: config.org_id,
|
|
489
|
+
project_id: sessionInfo.project_id,
|
|
490
|
+
distinct_id: getIdentity().distinct_id,
|
|
491
|
+
traits: traits || {}
|
|
492
|
+
}, 'user properties');
|
|
493
|
+
}
|
|
494
|
+
/** Legacy signature: sessionLensIdentify({ user_id, properties }). */
|
|
495
|
+
function sessionLensIdentify(user) {
|
|
496
|
+
identify(user.user_id, user.properties);
|
|
280
497
|
}
|
|
281
|
-
|
|
498
|
+
/** Forget the user, start an anonymous identity on a new device id and a new session. */
|
|
499
|
+
function reset() {
|
|
282
500
|
var _a;
|
|
283
|
-
const
|
|
284
|
-
const
|
|
501
|
+
const config = sessionLensGetConfig();
|
|
502
|
+
const sessionInfo = getSessionInfo();
|
|
503
|
+
if (config.debug) {
|
|
504
|
+
console.log('SessionLens Reset');
|
|
505
|
+
}
|
|
506
|
+
post(config, ((_a = config.endpoints) === null || _a === void 0 ? void 0 : _a.reset) || '/reset', {
|
|
507
|
+
org_id: config.org_id,
|
|
508
|
+
project_id: sessionInfo.project_id,
|
|
509
|
+
session_id: sessionInfo.session_id,
|
|
510
|
+
client_id: sessionInfo.client_id,
|
|
511
|
+
session_started_at: sessionInfo.started_at
|
|
512
|
+
}, 'reset');
|
|
513
|
+
resetIdentity();
|
|
514
|
+
restartSession();
|
|
515
|
+
}
|
|
516
|
+
const sessionLensReset = reset;
|
|
517
|
+
async function post(config, endpoint, body, label) {
|
|
285
518
|
try {
|
|
286
|
-
const response = await fetch(`${
|
|
519
|
+
const response = await fetch(`${getSessionLensApiBaseUrl()}${endpoint}`, {
|
|
287
520
|
method: 'POST',
|
|
288
521
|
headers: {
|
|
289
522
|
'Content-Type': 'application/json',
|
|
290
523
|
'Authorization': `Bearer ${config.sdk_key}`
|
|
291
524
|
},
|
|
292
|
-
body: JSON.stringify(
|
|
293
|
-
org_id: config.org_id,
|
|
294
|
-
project_id: sessionInfo.project_id,
|
|
295
|
-
user_id: user.user_id,
|
|
296
|
-
session_id: sessionInfo.session_id,
|
|
297
|
-
client_id: sessionInfo.client_id,
|
|
298
|
-
session_started_at: sessionInfo.started_at,
|
|
299
|
-
properties: user.properties
|
|
300
|
-
})
|
|
525
|
+
body: JSON.stringify(body)
|
|
301
526
|
});
|
|
302
527
|
if (!response.ok && config.debug) {
|
|
303
|
-
console.warn(
|
|
528
|
+
console.warn(`SessionLens: Failed to send ${label}:`, response.status);
|
|
304
529
|
}
|
|
305
530
|
else if (config.debug) {
|
|
306
|
-
console.log(
|
|
531
|
+
console.log(`SessionLens: ${label} sent successfully`);
|
|
307
532
|
}
|
|
308
533
|
}
|
|
309
534
|
catch (error) {
|
|
310
535
|
if (config.debug) {
|
|
311
|
-
console.warn(
|
|
536
|
+
console.warn(`SessionLens: Network error sending ${label}:`, error);
|
|
312
537
|
}
|
|
313
538
|
}
|
|
314
539
|
}
|
|
315
|
-
|
|
540
|
+
function sendEventToBackend(event, config, sessionInfo) {
|
|
316
541
|
var _a;
|
|
317
|
-
const
|
|
318
|
-
const
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
client_id: sessionInfo.client_id,
|
|
332
|
-
session_started_at: sessionInfo.started_at
|
|
333
|
-
})
|
|
334
|
-
});
|
|
335
|
-
if (!response.ok && config.debug) {
|
|
336
|
-
console.warn('SessionLens: Failed to send reset:', response.status);
|
|
337
|
-
}
|
|
338
|
-
else if (config.debug) {
|
|
339
|
-
console.log('SessionLens: Reset sent successfully with session context');
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
catch (error) {
|
|
343
|
-
if (config.debug) {
|
|
344
|
-
console.warn('SessionLens: Network error sending reset:', error);
|
|
345
|
-
}
|
|
542
|
+
const identity = getIdentity();
|
|
543
|
+
const body = {
|
|
544
|
+
org_id: config.org_id,
|
|
545
|
+
project_id: sessionInfo.project_id,
|
|
546
|
+
app: event.app || config.app || 'unknown',
|
|
547
|
+
device_id: identity.device_id,
|
|
548
|
+
distinct_id: identity.distinct_id,
|
|
549
|
+
session_id: sessionInfo.session_id,
|
|
550
|
+
client_id: sessionInfo.client_id,
|
|
551
|
+
session_started_at: sessionInfo.started_at,
|
|
552
|
+
event: event
|
|
553
|
+
};
|
|
554
|
+
if (identity.user_id) {
|
|
555
|
+
body.user_id = identity.user_id;
|
|
346
556
|
}
|
|
557
|
+
return post(config, ((_a = config.endpoints) === null || _a === void 0 ? void 0 : _a.events) || '/events/ingest', body, 'event');
|
|
347
558
|
}
|
|
348
559
|
|
|
349
560
|
const useSessionLens = (config) => {
|
|
@@ -358,10 +569,8 @@ const useSessionLens = (config) => {
|
|
|
358
569
|
}
|
|
359
570
|
};
|
|
360
571
|
initializeSDK();
|
|
361
|
-
//
|
|
362
|
-
|
|
363
|
-
sessionLensReset();
|
|
364
|
-
};
|
|
572
|
+
// No cleanup reset: reset() now clears the persisted device/user identity, which must
|
|
573
|
+
// survive unmounts and re-renders. Call reset() explicitly on logout instead.
|
|
365
574
|
}, [config]);
|
|
366
575
|
};
|
|
367
576
|
const useSessionLensTrack = () => {
|
|
@@ -398,10 +607,24 @@ class SessionLens {
|
|
|
398
607
|
sessionLensReset() {
|
|
399
608
|
sessionLensReset();
|
|
400
609
|
}
|
|
610
|
+
identify(userId, traits) {
|
|
611
|
+
identify(userId, traits);
|
|
612
|
+
}
|
|
613
|
+
/** @deprecated Use identify(). */
|
|
614
|
+
alias(newId, oldId) {
|
|
615
|
+
alias(newId);
|
|
616
|
+
}
|
|
617
|
+
setUserProperties(traits) {
|
|
618
|
+
setUserProperties(traits);
|
|
619
|
+
}
|
|
620
|
+
reset() {
|
|
621
|
+
reset();
|
|
622
|
+
}
|
|
401
623
|
}
|
|
402
624
|
// Create and export singleton instance
|
|
403
625
|
const sessionLens = new SessionLens();
|
|
404
626
|
|
|
627
|
+
exports.SDK_VERSION = SDK_VERSION;
|
|
405
628
|
exports["default"] = sessionLens;
|
|
406
629
|
exports.useSessionLens = useSessionLens;
|
|
407
630
|
exports.useSessionLensIdentify = useSessionLensIdentify;
|