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