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