@clianta/sdk 1.7.2 → 1.7.3
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/dist/angular.cjs.js +53 -47
- package/dist/angular.cjs.js.map +1 -1
- package/dist/angular.d.ts +12 -9
- package/dist/angular.esm.js +53 -47
- package/dist/angular.esm.js.map +1 -1
- package/dist/clianta.cjs.js +1237 -47
- package/dist/clianta.cjs.js.map +1 -1
- package/dist/clianta.esm.js +1237 -48
- package/dist/clianta.esm.js.map +1 -1
- package/dist/clianta.umd.js +1237 -47
- package/dist/clianta.umd.js.map +1 -1
- package/dist/clianta.umd.min.js +2 -2
- package/dist/clianta.umd.min.js.map +1 -1
- package/dist/index.d.ts +831 -11
- package/dist/react.cjs.js +53 -47
- package/dist/react.cjs.js.map +1 -1
- package/dist/react.d.ts +12 -9
- package/dist/react.esm.js +53 -47
- package/dist/react.esm.js.map +1 -1
- package/dist/svelte.cjs.js +53 -47
- package/dist/svelte.cjs.js.map +1 -1
- package/dist/svelte.d.ts +12 -9
- package/dist/svelte.esm.js +53 -47
- package/dist/svelte.esm.js.map +1 -1
- package/dist/vue.cjs.js +53 -47
- package/dist/vue.cjs.js.map +1 -1
- package/dist/vue.d.ts +12 -9
- package/dist/vue.esm.js +53 -47
- package/dist/vue.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/react.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Clianta SDK v1.7.
|
|
2
|
+
* Clianta SDK v1.7.3
|
|
3
3
|
* (c) 2026 Clianta
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -225,8 +225,9 @@ class Transport {
|
|
|
225
225
|
/**
|
|
226
226
|
* Send identify request.
|
|
227
227
|
* Returns contactId from the server response so the Tracker can store it.
|
|
228
|
+
* Retries on 5xx with exponential backoff (same policy as sendEvents).
|
|
228
229
|
*/
|
|
229
|
-
async sendIdentify(data) {
|
|
230
|
+
async sendIdentify(data, attempt = 1) {
|
|
230
231
|
const url = `${this.config.apiEndpoint}/api/public/track/identify`;
|
|
231
232
|
try {
|
|
232
233
|
const response = await this.fetchWithTimeout(url, {
|
|
@@ -244,16 +245,26 @@ class Transport {
|
|
|
244
245
|
contactId: body.contactId ?? undefined,
|
|
245
246
|
};
|
|
246
247
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
248
|
+
// Server error — retry with exponential backoff
|
|
249
|
+
if (response.status >= 500 && attempt < this.config.maxRetries) {
|
|
250
|
+
const backoff = this.config.retryDelay * Math.pow(2, attempt - 1);
|
|
251
|
+
logger.warn(`Identify server error (${response.status}), retrying in ${backoff}ms...`);
|
|
252
|
+
await this.delay(backoff);
|
|
253
|
+
return this.sendIdentify(data, attempt + 1);
|
|
252
254
|
}
|
|
255
|
+
logger.error(`Identify failed with status ${response.status}:`, body.message);
|
|
253
256
|
return { success: false, status: response.status };
|
|
254
257
|
}
|
|
255
258
|
catch (error) {
|
|
256
|
-
|
|
259
|
+
// Network error — retry if still online
|
|
260
|
+
const isOnline = typeof navigator === 'undefined' || navigator.onLine;
|
|
261
|
+
if (isOnline && attempt < this.config.maxRetries) {
|
|
262
|
+
const backoff = this.config.retryDelay * Math.pow(2, attempt - 1);
|
|
263
|
+
logger.warn(`Identify network error, retrying in ${backoff}ms (${attempt}/${this.config.maxRetries})...`);
|
|
264
|
+
await this.delay(backoff);
|
|
265
|
+
return this.sendIdentify(data, attempt + 1);
|
|
266
|
+
}
|
|
267
|
+
logger.error('Identify request failed after retries:', error);
|
|
257
268
|
return { success: false, error: error };
|
|
258
269
|
}
|
|
259
270
|
}
|
|
@@ -571,9 +582,6 @@ function resetIds(useCookies = false) {
|
|
|
571
582
|
// Ignore
|
|
572
583
|
}
|
|
573
584
|
}
|
|
574
|
-
// ============================================
|
|
575
|
-
// URL UTILITIES
|
|
576
|
-
// ============================================
|
|
577
585
|
/**
|
|
578
586
|
* Extract UTM parameters from URL
|
|
579
587
|
*/
|
|
@@ -730,8 +738,9 @@ class EventQueue {
|
|
|
730
738
|
flushInterval: config.flushInterval ?? 5000,
|
|
731
739
|
maxQueueSize: config.maxQueueSize ?? MAX_QUEUE_SIZE,
|
|
732
740
|
storageKey: config.storageKey ?? STORAGE_KEYS.EVENT_QUEUE,
|
|
741
|
+
persistMode: config.persistMode ?? 'session',
|
|
733
742
|
};
|
|
734
|
-
this.persistMode = config.persistMode
|
|
743
|
+
this.persistMode = this.config.persistMode;
|
|
735
744
|
this.isOnline = typeof navigator === 'undefined' || navigator.onLine;
|
|
736
745
|
// Restore persisted queue
|
|
737
746
|
this.restoreQueue();
|
|
@@ -795,9 +804,11 @@ class EventQueue {
|
|
|
795
804
|
// Send to backend
|
|
796
805
|
const result = await this.transport.sendEvents(events);
|
|
797
806
|
if (!result.success) {
|
|
798
|
-
// Re-queue events on failure (at the front)
|
|
807
|
+
// Re-queue events on failure (at the front), capped at maxQueueSize
|
|
799
808
|
logger.warn('Flush failed, re-queuing events');
|
|
800
|
-
this.queue.
|
|
809
|
+
const availableSpace = this.config.maxQueueSize - this.queue.length;
|
|
810
|
+
const eventsToRequeue = events.slice(0, Math.max(0, availableSpace));
|
|
811
|
+
this.queue.unshift(...eventsToRequeue);
|
|
801
812
|
this.persistQueue(this.queue);
|
|
802
813
|
}
|
|
803
814
|
else {
|
|
@@ -1244,7 +1255,7 @@ class FormsPlugin extends BasePlugin {
|
|
|
1244
1255
|
if (this.trackedForms.has(form))
|
|
1245
1256
|
return;
|
|
1246
1257
|
this.trackedForms.add(form);
|
|
1247
|
-
const formId = form.id || form.name || `form-${Math.random().toString(36).
|
|
1258
|
+
const formId = form.id || form.name || `form-${Math.random().toString(36).substring(2, 11)}`;
|
|
1248
1259
|
// Track form view
|
|
1249
1260
|
this.track('form_view', 'Form Viewed', {
|
|
1250
1261
|
formId,
|
|
@@ -1888,27 +1899,22 @@ class PopupFormsPlugin extends BasePlugin {
|
|
|
1888
1899
|
super.destroy();
|
|
1889
1900
|
}
|
|
1890
1901
|
loadShownForms() {
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1902
|
+
const stored = getLocalStorage('clianta_shown_forms');
|
|
1903
|
+
if (stored) {
|
|
1904
|
+
try {
|
|
1894
1905
|
const data = JSON.parse(stored);
|
|
1895
1906
|
this.shownForms = new Set(data.forms || []);
|
|
1896
1907
|
}
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1908
|
+
catch {
|
|
1909
|
+
// Ignore parse errors
|
|
1910
|
+
}
|
|
1900
1911
|
}
|
|
1901
1912
|
}
|
|
1902
1913
|
saveShownForms() {
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
}));
|
|
1908
|
-
}
|
|
1909
|
-
catch (e) {
|
|
1910
|
-
// Ignore storage errors
|
|
1911
|
-
}
|
|
1914
|
+
setLocalStorage('clianta_shown_forms', JSON.stringify({
|
|
1915
|
+
forms: Array.from(this.shownForms),
|
|
1916
|
+
timestamp: Date.now(),
|
|
1917
|
+
}));
|
|
1912
1918
|
}
|
|
1913
1919
|
async fetchForms() {
|
|
1914
1920
|
if (!this.tracker)
|
|
@@ -1927,7 +1933,7 @@ class PopupFormsPlugin extends BasePlugin {
|
|
|
1927
1933
|
}
|
|
1928
1934
|
}
|
|
1929
1935
|
catch (error) {
|
|
1930
|
-
|
|
1936
|
+
logger.error('Failed to fetch popup forms:', error);
|
|
1931
1937
|
}
|
|
1932
1938
|
}
|
|
1933
1939
|
shouldShowForm(form) {
|
|
@@ -1938,7 +1944,7 @@ class PopupFormsPlugin extends BasePlugin {
|
|
|
1938
1944
|
}
|
|
1939
1945
|
else if (form.showFrequency === 'once_per_session') {
|
|
1940
1946
|
const sessionKey = `clianta_form_${form._id}_shown`;
|
|
1941
|
-
if (
|
|
1947
|
+
if (getSessionStorage(sessionKey))
|
|
1942
1948
|
return false;
|
|
1943
1949
|
}
|
|
1944
1950
|
return true;
|
|
@@ -2010,7 +2016,7 @@ class PopupFormsPlugin extends BasePlugin {
|
|
|
2010
2016
|
// Mark as shown
|
|
2011
2017
|
this.shownForms.add(form._id);
|
|
2012
2018
|
this.saveShownForms();
|
|
2013
|
-
|
|
2019
|
+
setSessionStorage(`clianta_form_${form._id}_shown`, 'true');
|
|
2014
2020
|
// Track view
|
|
2015
2021
|
await this.trackFormView(form._id);
|
|
2016
2022
|
// Render form
|
|
@@ -2326,17 +2332,17 @@ class PopupFormsPlugin extends BasePlugin {
|
|
|
2326
2332
|
const redirect = new URL(form.redirectUrl, window.location.origin);
|
|
2327
2333
|
const isSameOrigin = redirect.origin === window.location.origin;
|
|
2328
2334
|
const isSafeProtocol = redirect.protocol === 'https:' || redirect.protocol === 'http:';
|
|
2329
|
-
if (isSameOrigin
|
|
2335
|
+
if (isSameOrigin && isSafeProtocol) {
|
|
2330
2336
|
setTimeout(() => {
|
|
2331
2337
|
window.location.href = redirect.href;
|
|
2332
2338
|
}, 1500);
|
|
2333
2339
|
}
|
|
2334
2340
|
else {
|
|
2335
|
-
|
|
2341
|
+
logger.warn('Blocked unsafe redirect URL:', form.redirectUrl);
|
|
2336
2342
|
}
|
|
2337
2343
|
}
|
|
2338
2344
|
catch {
|
|
2339
|
-
|
|
2345
|
+
logger.warn('Invalid redirect URL:', form.redirectUrl);
|
|
2340
2346
|
}
|
|
2341
2347
|
}
|
|
2342
2348
|
// Close after delay
|
|
@@ -2349,7 +2355,7 @@ class PopupFormsPlugin extends BasePlugin {
|
|
|
2349
2355
|
}
|
|
2350
2356
|
}
|
|
2351
2357
|
catch (error) {
|
|
2352
|
-
|
|
2358
|
+
logger.error('Form submit error:', error);
|
|
2353
2359
|
if (submitBtn) {
|
|
2354
2360
|
submitBtn.disabled = false;
|
|
2355
2361
|
submitBtn.textContent = form.submitButtonText || 'Subscribe';
|
|
@@ -2420,7 +2426,7 @@ const STORAGE_KEY_PATTERNS = [
|
|
|
2420
2426
|
'token', 'jwt', 'auth', 'user', 'session', 'credential', 'account',
|
|
2421
2427
|
];
|
|
2422
2428
|
/** JWT/user object fields containing email */
|
|
2423
|
-
const EMAIL_CLAIMS = ['email', '
|
|
2429
|
+
const EMAIL_CLAIMS = ['email', 'preferred_username', 'user_email', 'mail', 'emailAddress', 'e_mail'];
|
|
2424
2430
|
/** Full name fields */
|
|
2425
2431
|
const NAME_CLAIMS = ['name', 'full_name', 'display_name', 'displayName'];
|
|
2426
2432
|
/** First name fields */
|
|
@@ -3364,6 +3370,7 @@ class Tracker {
|
|
|
3364
3370
|
this.queue = new EventQueue(this.transport, {
|
|
3365
3371
|
batchSize: this.config.batchSize,
|
|
3366
3372
|
flushInterval: this.config.flushInterval,
|
|
3373
|
+
persistMode: this.config.persistMode,
|
|
3367
3374
|
});
|
|
3368
3375
|
// Get or create visitor and session IDs based on mode
|
|
3369
3376
|
this.visitorId = this.createVisitorId();
|
|
@@ -3480,10 +3487,13 @@ class Tracker {
|
|
|
3480
3487
|
logger.warn('SDK not initialized, event dropped');
|
|
3481
3488
|
return;
|
|
3482
3489
|
}
|
|
3490
|
+
const utmParams = getUTMParams();
|
|
3483
3491
|
const event = {
|
|
3484
3492
|
workspaceId: this.workspaceId,
|
|
3485
3493
|
visitorId: this.visitorId,
|
|
3486
3494
|
sessionId: this.sessionId,
|
|
3495
|
+
contactId: this.contactId ?? undefined,
|
|
3496
|
+
groupId: this.groupId ?? undefined,
|
|
3487
3497
|
eventType: eventType,
|
|
3488
3498
|
eventName,
|
|
3489
3499
|
url: typeof window !== 'undefined' ? window.location.href : '',
|
|
@@ -3494,18 +3504,14 @@ class Tracker {
|
|
|
3494
3504
|
websiteDomain: typeof window !== 'undefined' ? window.location.hostname : undefined,
|
|
3495
3505
|
},
|
|
3496
3506
|
device: getDeviceInfo(),
|
|
3497
|
-
|
|
3507
|
+
utmSource: utmParams.utmSource,
|
|
3508
|
+
utmMedium: utmParams.utmMedium,
|
|
3509
|
+
utmCampaign: utmParams.utmCampaign,
|
|
3510
|
+
utmTerm: utmParams.utmTerm,
|
|
3511
|
+
utmContent: utmParams.utmContent,
|
|
3498
3512
|
timestamp: new Date().toISOString(),
|
|
3499
3513
|
sdkVersion: SDK_VERSION,
|
|
3500
3514
|
};
|
|
3501
|
-
// Attach contactId if known (from a prior identify() call)
|
|
3502
|
-
if (this.contactId) {
|
|
3503
|
-
event.contactId = this.contactId;
|
|
3504
|
-
}
|
|
3505
|
-
// Attach groupId if known (from a prior group() call)
|
|
3506
|
-
if (this.groupId) {
|
|
3507
|
-
event.groupId = this.groupId;
|
|
3508
|
-
}
|
|
3509
3515
|
// Validate event against registered schema (debug mode only)
|
|
3510
3516
|
this.validateEventSchema(eventType, properties);
|
|
3511
3517
|
// Check consent before tracking
|