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