@metrone-io/sdk 1.0.1 → 1.1.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/dist/core/Metrone.d.ts +22 -70
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +160 -159
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +160 -159
- package/dist/index.js.map +1 -1
- package/dist/metrone.js +1 -1
- package/dist/metrone.js.map +1 -1
- package/dist/types/index.d.ts +12 -6
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -99,46 +99,51 @@ var Metrone = /** @class */ (function () {
|
|
|
99
99
|
function Metrone(config) {
|
|
100
100
|
var _this = this;
|
|
101
101
|
this.isInitialized = false;
|
|
102
|
+
this.trackingActive = false;
|
|
102
103
|
this.eventQueue = [];
|
|
103
104
|
this.isOnline = true;
|
|
104
|
-
this.version = '1.0
|
|
105
|
+
this.version = '1.1.0';
|
|
105
106
|
this.updateCheckInterval = null;
|
|
106
|
-
this.
|
|
107
|
-
|
|
107
|
+
this.flushTimerId = null;
|
|
108
|
+
this.boundVisibilityHandler = null;
|
|
109
|
+
this.boundBeforeUnloadHandler = null;
|
|
110
|
+
this.lastTrackedPath = '';
|
|
111
|
+
this.config = __assign({ endpoint: 'https://api.metrone.io/v1/events', debug: false, autoTrack: true, autoTrackSPA: false, autoUpdate: false, batchSize: 10, flushInterval: 5000, offlineQueue: true, maxQueueSize: 100, respectDoNotTrack: false, anonymizeIP: true, cookieConsent: 'optional' }, config);
|
|
108
112
|
if (!this.config.apiKey) {
|
|
109
|
-
throw new Error('API key is required');
|
|
113
|
+
throw new Error('[Metrone] API key is required');
|
|
110
114
|
}
|
|
111
115
|
var validPrefixes = ['metrone_live_', 'metrone_test_', 'mk_live_', 'mk_test_'];
|
|
112
116
|
if (!validPrefixes.some(function (p) { return _this.config.apiKey.startsWith(p); })) {
|
|
113
|
-
throw new Error('Invalid API key format. Must start with "metrone_live_", "metrone_test_", "mk_live_", or "mk_test_"');
|
|
117
|
+
throw new Error('[Metrone] Invalid API key format. Must start with "metrone_live_", "metrone_test_", "mk_live_", or "mk_test_"');
|
|
118
|
+
}
|
|
119
|
+
if (!this.config.batchEndpoint) {
|
|
120
|
+
this.config.batchEndpoint = this.config.endpoint.replace(/\/events\/?$/, '/events/batch');
|
|
114
121
|
}
|
|
115
122
|
this.sessionId = this.generateSessionId();
|
|
116
123
|
this.isInitialized = true;
|
|
117
|
-
// Check for Do Not Track
|
|
118
124
|
if (this.config.respectDoNotTrack && this.isDoNotTrackEnabled()) {
|
|
119
|
-
|
|
120
|
-
console.log('🔒 Do Not Track is enabled, analytics disabled');
|
|
121
|
-
}
|
|
125
|
+
console.warn('[Metrone] Do Not Track detected — analytics disabled. Set respectDoNotTrack: false to override.');
|
|
122
126
|
return;
|
|
123
127
|
}
|
|
124
|
-
// Check for cookie consent
|
|
125
128
|
if (this.config.cookieConsent === 'required' && !this.hasConsent()) {
|
|
126
|
-
|
|
127
|
-
console.log('🍪 Cookie consent required, analytics disabled');
|
|
128
|
-
}
|
|
129
|
+
console.warn('[Metrone] Cookie consent required but not granted — analytics disabled.');
|
|
129
130
|
return;
|
|
130
131
|
}
|
|
131
|
-
|
|
132
|
+
this.trackingActive = true;
|
|
132
133
|
this.setupOnlineDetection();
|
|
134
|
+
this.setupPageUnloadFlush();
|
|
133
135
|
if (this.config.autoTrack) {
|
|
136
|
+
this.lastTrackedPath = window.location.pathname;
|
|
134
137
|
this.pageview();
|
|
135
138
|
}
|
|
136
|
-
|
|
139
|
+
if (this.config.autoTrackSPA) {
|
|
140
|
+
this.setupSPATracking();
|
|
141
|
+
}
|
|
137
142
|
if (this.config.batchSize && this.config.batchSize > 1) {
|
|
138
143
|
this.setupBatchProcessing();
|
|
139
144
|
}
|
|
140
145
|
if (this.config.debug) {
|
|
141
|
-
console.log('Metrone SDK initialized:', {
|
|
146
|
+
console.log('[Metrone] SDK initialized:', {
|
|
142
147
|
apiKey: this.config.apiKey.substring(0, 12) + '...',
|
|
143
148
|
projectId: this.config.projectId,
|
|
144
149
|
sessionId: this.sessionId,
|
|
@@ -147,11 +152,17 @@ var Metrone = /** @class */ (function () {
|
|
|
147
152
|
});
|
|
148
153
|
}
|
|
149
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Whether the SDK is actively tracking events (not disabled by DNT/consent).
|
|
157
|
+
*/
|
|
158
|
+
Metrone.prototype.isActive = function () {
|
|
159
|
+
return this.isInitialized && this.trackingActive;
|
|
160
|
+
};
|
|
150
161
|
/**
|
|
151
162
|
* Track a page view
|
|
152
163
|
*/
|
|
153
164
|
Metrone.prototype.pageview = function (url, title, metadata) {
|
|
154
|
-
if (!this.isInitialized)
|
|
165
|
+
if (!this.isInitialized || !this.trackingActive)
|
|
155
166
|
return;
|
|
156
167
|
this.track('pageview', __assign({ page_url: url || window.location.href, page_path: window.location.pathname, page_title: title || document.title, referrer: document.referrer, source: 'web' }, metadata));
|
|
157
168
|
};
|
|
@@ -160,9 +171,11 @@ var Metrone = /** @class */ (function () {
|
|
|
160
171
|
*/
|
|
161
172
|
Metrone.prototype.track = function (eventName, data) {
|
|
162
173
|
if (!this.isInitialized) {
|
|
163
|
-
console.warn('
|
|
174
|
+
console.warn('[Metrone] SDK not initialized');
|
|
164
175
|
return;
|
|
165
176
|
}
|
|
177
|
+
if (!this.trackingActive)
|
|
178
|
+
return;
|
|
166
179
|
var _a = (data !== null && data !== void 0 ? data : {}), source = _a.source, channel = _a.channel, ai_provider = _a.ai_provider, ai_call_id = _a.ai_call_id, ai_session_id = _a.ai_session_id, ai_intent = _a.ai_intent, ai_duration_sec = _a.ai_duration_sec, utm_source = _a.utm_source, utm_medium = _a.utm_medium, utm_campaign = _a.utm_campaign, utm_term = _a.utm_term, utm_content = _a.utm_content, page_path = _a.page_path, page_title = _a.page_title, dataPageUrl = _a.page_url, dataReferrer = _a.referrer, event_name = _a.event_name, rest = __rest(_a, ["source", "channel", "ai_provider", "ai_call_id", "ai_session_id", "ai_intent", "ai_duration_sec", "utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content", "page_path", "page_title", "page_url", "referrer", "event_name"]);
|
|
167
180
|
var eventData = {
|
|
168
181
|
event_type: eventName,
|
|
@@ -254,9 +267,6 @@ var Metrone = /** @class */ (function () {
|
|
|
254
267
|
Metrone.prototype.trackAISession = function (data) {
|
|
255
268
|
this.track("ai_session_".concat(data.action), __assign({ source: 'assistant', ai_provider: data.provider || 'unknown', ai_session_id: data.session_id, ai_duration_sec: data.duration }, data.metadata));
|
|
256
269
|
};
|
|
257
|
-
/**
|
|
258
|
-
* Send event to analytics API
|
|
259
|
-
*/
|
|
260
270
|
Metrone.prototype.sendEvent = function (eventData) {
|
|
261
271
|
return __awaiter(this, void 0, void 0, function () {
|
|
262
272
|
var requestData, error_1;
|
|
@@ -266,7 +276,6 @@ var Metrone = /** @class */ (function () {
|
|
|
266
276
|
_a.trys.push([0, 6, , 7]);
|
|
267
277
|
requestData = __assign(__assign({}, eventData), { api_key: this.config.apiKey });
|
|
268
278
|
if (!(this.config.batchSize && this.config.batchSize > 1)) return [3 /*break*/, 3];
|
|
269
|
-
// Add to batch queue
|
|
270
279
|
this.eventQueue.push(requestData);
|
|
271
280
|
if (!(this.eventQueue.length >= this.config.batchSize)) return [3 /*break*/, 2];
|
|
272
281
|
return [4 /*yield*/, this.flushBatch()];
|
|
@@ -274,20 +283,14 @@ var Metrone = /** @class */ (function () {
|
|
|
274
283
|
_a.sent();
|
|
275
284
|
_a.label = 2;
|
|
276
285
|
case 2: return [3 /*break*/, 5];
|
|
277
|
-
case 3:
|
|
278
|
-
// Send immediately
|
|
279
|
-
return [4 /*yield*/, this.sendRequest(requestData)];
|
|
286
|
+
case 3: return [4 /*yield*/, this.sendRequest(requestData)];
|
|
280
287
|
case 4:
|
|
281
|
-
// Send immediately
|
|
282
288
|
_a.sent();
|
|
283
289
|
_a.label = 5;
|
|
284
290
|
case 5: return [3 /*break*/, 7];
|
|
285
291
|
case 6:
|
|
286
292
|
error_1 = _a.sent();
|
|
287
|
-
|
|
288
|
-
console.error('Failed to send analytics event:', error_1);
|
|
289
|
-
}
|
|
290
|
-
// Queue for retry if offline
|
|
293
|
+
console.warn('[Metrone] Failed to send event:', error_1.message);
|
|
291
294
|
if (this.config.offlineQueue && !this.isOnline) {
|
|
292
295
|
this.queueEvent(eventData);
|
|
293
296
|
}
|
|
@@ -297,9 +300,6 @@ var Metrone = /** @class */ (function () {
|
|
|
297
300
|
});
|
|
298
301
|
});
|
|
299
302
|
};
|
|
300
|
-
/**
|
|
301
|
-
* Send request to analytics API
|
|
302
|
-
*/
|
|
303
303
|
Metrone.prototype.sendRequest = function (data) {
|
|
304
304
|
return __awaiter(this, void 0, void 0, function () {
|
|
305
305
|
var response;
|
|
@@ -307,30 +307,25 @@ var Metrone = /** @class */ (function () {
|
|
|
307
307
|
switch (_a.label) {
|
|
308
308
|
case 0: return [4 /*yield*/, fetch(this.config.endpoint, {
|
|
309
309
|
method: 'POST',
|
|
310
|
-
headers: {
|
|
311
|
-
'Content-Type': 'application/json',
|
|
312
|
-
},
|
|
310
|
+
headers: { 'Content-Type': 'application/json' },
|
|
313
311
|
body: JSON.stringify(data)
|
|
314
312
|
})];
|
|
315
313
|
case 1:
|
|
316
314
|
response = _a.sent();
|
|
317
315
|
if (!response.ok) {
|
|
318
|
-
throw new Error("
|
|
316
|
+
throw new Error("".concat(response.status, " ").concat(response.statusText));
|
|
319
317
|
}
|
|
320
318
|
if (this.config.debug) {
|
|
321
|
-
console.log('
|
|
319
|
+
console.log('[Metrone] Event sent:', data.event_type);
|
|
322
320
|
}
|
|
323
321
|
return [2 /*return*/];
|
|
324
322
|
}
|
|
325
323
|
});
|
|
326
324
|
});
|
|
327
325
|
};
|
|
328
|
-
/**
|
|
329
|
-
* Flush batch of events
|
|
330
|
-
*/
|
|
331
326
|
Metrone.prototype.flushBatch = function () {
|
|
332
327
|
return __awaiter(this, void 0, void 0, function () {
|
|
333
|
-
var batch,
|
|
328
|
+
var batch, error_2;
|
|
334
329
|
var _a;
|
|
335
330
|
return __generator(this, function (_b) {
|
|
336
331
|
switch (_b.label) {
|
|
@@ -342,19 +337,16 @@ var Metrone = /** @class */ (function () {
|
|
|
342
337
|
_b.label = 1;
|
|
343
338
|
case 1:
|
|
344
339
|
_b.trys.push([1, 3, , 4]);
|
|
345
|
-
|
|
346
|
-
return [4 /*yield*/, this.sendBatchRequest(batchEndpoint, batch)];
|
|
340
|
+
return [4 /*yield*/, this.sendBatchRequest(batch)];
|
|
347
341
|
case 2:
|
|
348
342
|
_b.sent();
|
|
349
343
|
if (this.config.debug) {
|
|
350
|
-
console.log("Batch sent: ".concat(batch.length, " events"));
|
|
344
|
+
console.log("[Metrone] Batch sent: ".concat(batch.length, " events"));
|
|
351
345
|
}
|
|
352
346
|
return [3 /*break*/, 4];
|
|
353
347
|
case 3:
|
|
354
348
|
error_2 = _b.sent();
|
|
355
|
-
|
|
356
|
-
console.error('Failed to send batch:', error_2);
|
|
357
|
-
}
|
|
349
|
+
console.warn('[Metrone] Failed to send batch:', error_2.message);
|
|
358
350
|
if (this.config.offlineQueue && !this.isOnline) {
|
|
359
351
|
(_a = this.eventQueue).unshift.apply(_a, batch);
|
|
360
352
|
}
|
|
@@ -364,22 +356,20 @@ var Metrone = /** @class */ (function () {
|
|
|
364
356
|
});
|
|
365
357
|
});
|
|
366
358
|
};
|
|
367
|
-
Metrone.prototype.sendBatchRequest = function (
|
|
359
|
+
Metrone.prototype.sendBatchRequest = function (events) {
|
|
368
360
|
return __awaiter(this, void 0, void 0, function () {
|
|
369
361
|
var response;
|
|
370
362
|
return __generator(this, function (_a) {
|
|
371
363
|
switch (_a.label) {
|
|
372
|
-
case 0: return [4 /*yield*/, fetch(
|
|
364
|
+
case 0: return [4 /*yield*/, fetch(this.config.batchEndpoint, {
|
|
373
365
|
method: 'POST',
|
|
374
|
-
headers: {
|
|
375
|
-
'Content-Type': 'application/json',
|
|
376
|
-
},
|
|
366
|
+
headers: { 'Content-Type': 'application/json' },
|
|
377
367
|
body: JSON.stringify(events)
|
|
378
368
|
})];
|
|
379
369
|
case 1:
|
|
380
370
|
response = _a.sent();
|
|
381
371
|
if (!response.ok) {
|
|
382
|
-
throw new Error("
|
|
372
|
+
throw new Error("".concat(response.status, " ").concat(response.statusText));
|
|
383
373
|
}
|
|
384
374
|
return [2 /*return*/];
|
|
385
375
|
}
|
|
@@ -387,20 +377,33 @@ var Metrone = /** @class */ (function () {
|
|
|
387
377
|
});
|
|
388
378
|
};
|
|
389
379
|
/**
|
|
390
|
-
*
|
|
380
|
+
* Flush queued events using sendBeacon (survives page unload).
|
|
391
381
|
*/
|
|
382
|
+
Metrone.prototype.beaconFlush = function () {
|
|
383
|
+
if (this.eventQueue.length === 0)
|
|
384
|
+
return;
|
|
385
|
+
var batch = __spreadArray([], this.eventQueue, true);
|
|
386
|
+
this.eventQueue = [];
|
|
387
|
+
try {
|
|
388
|
+
var payload = JSON.stringify(batch);
|
|
389
|
+
var sent = navigator.sendBeacon(this.config.batchEndpoint, payload);
|
|
390
|
+
if (!sent && this.config.debug) {
|
|
391
|
+
console.warn('[Metrone] sendBeacon failed, events may be lost');
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
catch (_a) {
|
|
395
|
+
// sendBeacon not available or failed — nothing we can do at unload time
|
|
396
|
+
}
|
|
397
|
+
};
|
|
392
398
|
Metrone.prototype.queueEvent = function (eventData) {
|
|
393
399
|
if (this.eventQueue.length >= (this.config.maxQueueSize || 100)) {
|
|
394
|
-
this.eventQueue.shift();
|
|
400
|
+
this.eventQueue.shift();
|
|
395
401
|
}
|
|
396
402
|
this.eventQueue.push(eventData);
|
|
397
403
|
};
|
|
398
|
-
/**
|
|
399
|
-
* Process offline queue when back online
|
|
400
|
-
*/
|
|
401
404
|
Metrone.prototype.processQueue = function () {
|
|
402
405
|
return __awaiter(this, void 0, void 0, function () {
|
|
403
|
-
var queue, _i, queue_1, event_1
|
|
406
|
+
var queue, _i, queue_1, event_1;
|
|
404
407
|
return __generator(this, function (_a) {
|
|
405
408
|
switch (_a.label) {
|
|
406
409
|
case 0:
|
|
@@ -421,11 +424,7 @@ var Metrone = /** @class */ (function () {
|
|
|
421
424
|
_a.sent();
|
|
422
425
|
return [3 /*break*/, 5];
|
|
423
426
|
case 4:
|
|
424
|
-
|
|
425
|
-
if (this.config.debug) {
|
|
426
|
-
console.error('Failed to process queued event:', error_3);
|
|
427
|
-
}
|
|
428
|
-
// Re-queue failed events
|
|
427
|
+
_a.sent();
|
|
429
428
|
this.eventQueue.push(event_1);
|
|
430
429
|
return [3 /*break*/, 5];
|
|
431
430
|
case 5:
|
|
@@ -433,58 +432,80 @@ var Metrone = /** @class */ (function () {
|
|
|
433
432
|
return [3 /*break*/, 1];
|
|
434
433
|
case 6:
|
|
435
434
|
if (this.config.debug) {
|
|
436
|
-
console.log("
|
|
435
|
+
console.log("[Metrone] Processed ".concat(queue.length, " queued events"));
|
|
437
436
|
}
|
|
438
437
|
return [2 /*return*/];
|
|
439
438
|
}
|
|
440
439
|
});
|
|
441
440
|
});
|
|
442
441
|
};
|
|
443
|
-
/**
|
|
444
|
-
* Set up online/offline detection
|
|
445
|
-
*/
|
|
446
442
|
Metrone.prototype.setupOnlineDetection = function () {
|
|
447
443
|
var _this = this;
|
|
448
444
|
this.isOnline = navigator.onLine;
|
|
449
445
|
window.addEventListener('online', function () {
|
|
450
446
|
_this.isOnline = true;
|
|
451
447
|
if (_this.config.debug) {
|
|
452
|
-
console.log('
|
|
448
|
+
console.log('[Metrone] Back online, processing queue');
|
|
453
449
|
}
|
|
454
450
|
_this.processQueue();
|
|
455
451
|
});
|
|
456
452
|
window.addEventListener('offline', function () {
|
|
457
453
|
_this.isOnline = false;
|
|
458
454
|
if (_this.config.debug) {
|
|
459
|
-
console.log('
|
|
455
|
+
console.log('[Metrone] Gone offline, queuing events');
|
|
460
456
|
}
|
|
461
457
|
});
|
|
462
458
|
};
|
|
463
|
-
/**
|
|
464
|
-
* Set up batch processing
|
|
465
|
-
*/
|
|
466
459
|
Metrone.prototype.setupBatchProcessing = function () {
|
|
467
460
|
var _this = this;
|
|
468
461
|
if (this.config.flushInterval && this.config.flushInterval > 0) {
|
|
469
|
-
setInterval(function () {
|
|
462
|
+
this.flushTimerId = window.setInterval(function () {
|
|
470
463
|
_this.flushBatch();
|
|
471
464
|
}, this.config.flushInterval);
|
|
472
465
|
}
|
|
473
466
|
};
|
|
474
467
|
/**
|
|
475
|
-
*
|
|
468
|
+
* Flush pending events on page hide / beforeunload using sendBeacon.
|
|
469
|
+
*/
|
|
470
|
+
Metrone.prototype.setupPageUnloadFlush = function () {
|
|
471
|
+
var _this = this;
|
|
472
|
+
this.boundVisibilityHandler = function () {
|
|
473
|
+
if (document.visibilityState === 'hidden') {
|
|
474
|
+
_this.beaconFlush();
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
this.boundBeforeUnloadHandler = function () {
|
|
478
|
+
_this.beaconFlush();
|
|
479
|
+
};
|
|
480
|
+
document.addEventListener('visibilitychange', this.boundVisibilityHandler);
|
|
481
|
+
window.addEventListener('beforeunload', this.boundBeforeUnloadHandler);
|
|
482
|
+
};
|
|
483
|
+
/**
|
|
484
|
+
* Auto-track SPA route changes via History API and popstate.
|
|
476
485
|
*/
|
|
477
|
-
Metrone.prototype.
|
|
486
|
+
Metrone.prototype.setupSPATracking = function () {
|
|
478
487
|
var _this = this;
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
488
|
+
var origPushState = history.pushState.bind(history);
|
|
489
|
+
var origReplaceState = history.replaceState.bind(history);
|
|
490
|
+
var onRouteChange = function () {
|
|
491
|
+
var newPath = window.location.pathname;
|
|
492
|
+
if (newPath !== _this.lastTrackedPath) {
|
|
493
|
+
_this.lastTrackedPath = newPath;
|
|
494
|
+
setTimeout(function () { return _this.pageview(); }, 0);
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
history.pushState = function (data, unused, url) {
|
|
498
|
+
origPushState(data, unused, url);
|
|
499
|
+
onRouteChange();
|
|
500
|
+
};
|
|
501
|
+
history.replaceState = function (data, unused, url) {
|
|
502
|
+
origReplaceState(data, unused, url);
|
|
503
|
+
onRouteChange();
|
|
504
|
+
};
|
|
505
|
+
window.addEventListener('popstate', onRouteChange);
|
|
485
506
|
};
|
|
486
507
|
/**
|
|
487
|
-
* Check for SDK updates
|
|
508
|
+
* Check for SDK updates (only relevant for script-tag installations).
|
|
488
509
|
*/
|
|
489
510
|
Metrone.prototype.checkForUpdates = function () {
|
|
490
511
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -492,21 +513,35 @@ var Metrone = /** @class */ (function () {
|
|
|
492
513
|
return __generator(this, function (_a) {
|
|
493
514
|
switch (_a.label) {
|
|
494
515
|
case 0:
|
|
495
|
-
|
|
496
|
-
|
|
516
|
+
if (this.isModuleContext()) {
|
|
517
|
+
if (this.config.debug) {
|
|
518
|
+
console.log('[Metrone] Auto-update is not supported in module/bundler context. Update via npm instead.');
|
|
519
|
+
}
|
|
520
|
+
return [2 /*return*/, {
|
|
521
|
+
available: false,
|
|
522
|
+
current: this.version,
|
|
523
|
+
latest: this.version,
|
|
524
|
+
features: [],
|
|
525
|
+
changelog: []
|
|
526
|
+
}];
|
|
527
|
+
}
|
|
528
|
+
_a.label = 1;
|
|
497
529
|
case 1:
|
|
530
|
+
_a.trys.push([1, 4, , 5]);
|
|
531
|
+
return [4 /*yield*/, fetch('/api/analytics/version')];
|
|
532
|
+
case 2:
|
|
498
533
|
response = _a.sent();
|
|
499
534
|
return [4 /*yield*/, response.json()];
|
|
500
|
-
case
|
|
535
|
+
case 3:
|
|
501
536
|
updateInfo = _a.sent();
|
|
502
537
|
if (updateInfo.latest !== this.version) {
|
|
503
538
|
this.handleUpdate(updateInfo);
|
|
504
539
|
}
|
|
505
540
|
return [2 /*return*/, updateInfo];
|
|
506
|
-
case
|
|
541
|
+
case 4:
|
|
507
542
|
error_4 = _a.sent();
|
|
508
543
|
if (this.config.debug) {
|
|
509
|
-
console.log('Update check failed:', error_4);
|
|
544
|
+
console.log('[Metrone] Update check failed:', error_4);
|
|
510
545
|
}
|
|
511
546
|
return [2 /*return*/, {
|
|
512
547
|
available: false,
|
|
@@ -515,87 +550,76 @@ var Metrone = /** @class */ (function () {
|
|
|
515
550
|
features: [],
|
|
516
551
|
changelog: []
|
|
517
552
|
}];
|
|
518
|
-
case
|
|
553
|
+
case 5: return [2 /*return*/];
|
|
519
554
|
}
|
|
520
555
|
});
|
|
521
556
|
});
|
|
522
557
|
};
|
|
523
|
-
/**
|
|
524
|
-
* Handle SDK update
|
|
525
|
-
*/
|
|
526
558
|
Metrone.prototype.handleUpdate = function (updateInfo) {
|
|
527
|
-
if (this.config.autoUpdate !== false) {
|
|
559
|
+
if (this.config.autoUpdate !== false && !this.isModuleContext()) {
|
|
528
560
|
this.loadNewVersion(updateInfo.latest);
|
|
529
561
|
}
|
|
530
562
|
else {
|
|
531
563
|
this.notifyUpdate(updateInfo);
|
|
532
564
|
}
|
|
533
565
|
};
|
|
534
|
-
/**
|
|
535
|
-
* Load new SDK version
|
|
536
|
-
*/
|
|
537
566
|
Metrone.prototype.loadNewVersion = function (version) {
|
|
538
567
|
var _this = this;
|
|
539
568
|
if (this.config.debug) {
|
|
540
|
-
console.log("
|
|
569
|
+
console.log("[Metrone] Updating SDK to version ".concat(version));
|
|
541
570
|
}
|
|
542
|
-
// Reload the SDK script
|
|
543
571
|
var script = document.createElement('script');
|
|
544
572
|
script.src = '/js/metrone.js';
|
|
545
573
|
script.onload = function () {
|
|
546
574
|
if (_this.config.debug) {
|
|
547
|
-
console.log("
|
|
575
|
+
console.log("[Metrone] SDK updated to version ".concat(version));
|
|
548
576
|
}
|
|
549
577
|
};
|
|
550
578
|
document.head.appendChild(script);
|
|
551
579
|
};
|
|
552
|
-
/**
|
|
553
|
-
* Notify about available update
|
|
554
|
-
*/
|
|
555
580
|
Metrone.prototype.notifyUpdate = function (updateInfo) {
|
|
556
581
|
if (this.config.debug) {
|
|
557
|
-
console.log("
|
|
558
|
-
console.log('New features:', updateInfo.features);
|
|
582
|
+
console.log("[Metrone] SDK update available: ".concat(updateInfo.latest));
|
|
559
583
|
}
|
|
560
|
-
// Dispatch custom event for update notification
|
|
561
584
|
window.dispatchEvent(new CustomEvent('metrone-update', {
|
|
562
585
|
detail: updateInfo
|
|
563
586
|
}));
|
|
564
587
|
};
|
|
565
588
|
/**
|
|
566
|
-
*
|
|
589
|
+
* Detect whether the SDK is running inside a bundler/module context
|
|
590
|
+
* vs. a plain script-tag.
|
|
567
591
|
*/
|
|
592
|
+
Metrone.prototype.isModuleContext = function () {
|
|
593
|
+
try {
|
|
594
|
+
// If this code is part of a bundle, `module` or import.meta will be defined.
|
|
595
|
+
// The simplest heuristic: check if the current script tag has type="module"
|
|
596
|
+
// or if we're in a context where document.currentScript is null (bundled).
|
|
597
|
+
return typeof document === 'undefined' || document.currentScript === null;
|
|
598
|
+
}
|
|
599
|
+
catch (_a) {
|
|
600
|
+
return true;
|
|
601
|
+
}
|
|
602
|
+
};
|
|
568
603
|
Metrone.prototype.generateSessionId = function () {
|
|
569
604
|
var timestamp = Date.now().toString(36);
|
|
570
605
|
var random = Math.random().toString(36).substring(2, 15);
|
|
571
606
|
return "sess_".concat(timestamp, "_").concat(random);
|
|
572
607
|
};
|
|
573
|
-
/**
|
|
574
|
-
* Check if Do Not Track is enabled
|
|
575
|
-
*/
|
|
576
608
|
Metrone.prototype.isDoNotTrackEnabled = function () {
|
|
577
609
|
return navigator.doNotTrack === '1' ||
|
|
578
610
|
navigator.doNotTrack === 'yes' ||
|
|
579
611
|
window.doNotTrack === '1';
|
|
580
612
|
};
|
|
581
|
-
/**
|
|
582
|
-
* Check if user has given consent
|
|
583
|
-
*/
|
|
584
613
|
Metrone.prototype.hasConsent = function () {
|
|
585
|
-
// Check for common consent management platforms
|
|
586
614
|
var consent = localStorage.getItem('cookie-consent') ||
|
|
587
615
|
localStorage.getItem('gdpr-consent') ||
|
|
588
616
|
localStorage.getItem('cc-consent');
|
|
589
617
|
return consent === 'accepted' || consent === 'true';
|
|
590
618
|
};
|
|
591
|
-
/**
|
|
592
|
-
* Request user consent
|
|
593
|
-
*/
|
|
594
619
|
Metrone.prototype.requestConsent = function () {
|
|
595
620
|
return __awaiter(this, void 0, void 0, function () {
|
|
596
621
|
return __generator(this, function (_a) {
|
|
597
622
|
return [2 /*return*/, new Promise(function (resolve) {
|
|
598
|
-
// Dispatch custom event for consent request
|
|
599
623
|
window.dispatchEvent(new CustomEvent('metrone-consent-request', {
|
|
600
624
|
detail: { resolve: resolve }
|
|
601
625
|
}));
|
|
@@ -603,45 +627,30 @@ var Metrone = /** @class */ (function () {
|
|
|
603
627
|
});
|
|
604
628
|
});
|
|
605
629
|
};
|
|
606
|
-
/**
|
|
607
|
-
* Revoke user consent
|
|
608
|
-
*/
|
|
609
630
|
Metrone.prototype.revokeConsent = function () {
|
|
610
631
|
localStorage.removeItem('cookie-consent');
|
|
611
632
|
localStorage.removeItem('gdpr-consent');
|
|
612
633
|
localStorage.removeItem('cc-consent');
|
|
613
634
|
if (this.config.debug) {
|
|
614
|
-
console.log('
|
|
635
|
+
console.log('[Metrone] Consent revoked, analytics disabled');
|
|
615
636
|
}
|
|
616
637
|
};
|
|
617
|
-
/**
|
|
618
|
-
* Anonymize data
|
|
619
|
-
*/
|
|
620
638
|
Metrone.prototype.anonymize = function (data) {
|
|
621
639
|
var hash = this.simpleHash(data);
|
|
622
640
|
return "anon_".concat(hash);
|
|
623
641
|
};
|
|
624
|
-
/**
|
|
625
|
-
* Simple hash function
|
|
626
|
-
*/
|
|
627
642
|
Metrone.prototype.simpleHash = function (str) {
|
|
628
643
|
var hash = 0;
|
|
629
644
|
for (var i = 0; i < str.length; i++) {
|
|
630
645
|
var char = str.charCodeAt(i);
|
|
631
646
|
hash = ((hash << 5) - hash) + char;
|
|
632
|
-
hash = hash & hash;
|
|
647
|
+
hash = hash & hash;
|
|
633
648
|
}
|
|
634
649
|
return Math.abs(hash).toString(36);
|
|
635
650
|
};
|
|
636
|
-
/**
|
|
637
|
-
* Check if running on mobile device
|
|
638
|
-
*/
|
|
639
651
|
Metrone.prototype.isMobile = function () {
|
|
640
652
|
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
641
653
|
};
|
|
642
|
-
/**
|
|
643
|
-
* Get screen size
|
|
644
|
-
*/
|
|
645
654
|
Metrone.prototype.getScreenSize = function () {
|
|
646
655
|
var width = window.screen.width;
|
|
647
656
|
if (width < 768)
|
|
@@ -650,62 +659,54 @@ var Metrone = /** @class */ (function () {
|
|
|
650
659
|
return 'tablet';
|
|
651
660
|
return 'desktop';
|
|
652
661
|
};
|
|
653
|
-
/**
|
|
654
|
-
* Flush pending events
|
|
655
|
-
*/
|
|
656
662
|
Metrone.prototype.flush = function () {
|
|
657
663
|
this.flushBatch();
|
|
658
664
|
};
|
|
659
|
-
/**
|
|
660
|
-
* Destroy SDK instance
|
|
661
|
-
*/
|
|
662
665
|
Metrone.prototype.destroy = function () {
|
|
663
666
|
if (this.updateCheckInterval) {
|
|
664
667
|
clearInterval(this.updateCheckInterval);
|
|
665
668
|
}
|
|
666
|
-
this.
|
|
669
|
+
if (this.flushTimerId) {
|
|
670
|
+
clearInterval(this.flushTimerId);
|
|
671
|
+
}
|
|
672
|
+
if (this.boundVisibilityHandler) {
|
|
673
|
+
document.removeEventListener('visibilitychange', this.boundVisibilityHandler);
|
|
674
|
+
}
|
|
675
|
+
if (this.boundBeforeUnloadHandler) {
|
|
676
|
+
window.removeEventListener('beforeunload', this.boundBeforeUnloadHandler);
|
|
677
|
+
}
|
|
678
|
+
this.beaconFlush();
|
|
667
679
|
this.isInitialized = false;
|
|
680
|
+
this.trackingActive = false;
|
|
668
681
|
if (this.config.debug) {
|
|
669
|
-
console.log('
|
|
682
|
+
console.log('[Metrone] SDK destroyed');
|
|
670
683
|
}
|
|
671
684
|
};
|
|
672
|
-
/**
|
|
673
|
-
* Get current version
|
|
674
|
-
*/
|
|
675
685
|
Metrone.prototype.getVersion = function () {
|
|
676
686
|
return this.version;
|
|
677
687
|
};
|
|
678
|
-
/**
|
|
679
|
-
* Get session ID
|
|
680
|
-
*/
|
|
681
688
|
Metrone.prototype.getSessionId = function () {
|
|
682
689
|
return this.sessionId;
|
|
683
690
|
};
|
|
684
|
-
/**
|
|
685
|
-
* Get configuration
|
|
686
|
-
*/
|
|
687
691
|
Metrone.prototype.getConfig = function () {
|
|
688
692
|
return __assign({}, this.config);
|
|
689
693
|
};
|
|
690
694
|
return Metrone;
|
|
691
695
|
}());
|
|
692
|
-
|
|
696
|
+
var globalAnalytics = null;
|
|
693
697
|
function initAnalytics(config) {
|
|
694
|
-
|
|
698
|
+
globalAnalytics = new Metrone(config);
|
|
699
|
+
return globalAnalytics;
|
|
695
700
|
}
|
|
696
|
-
// Global instance for backward compatibility
|
|
697
|
-
var globalAnalytics = null;
|
|
698
701
|
function getAnalytics() {
|
|
699
702
|
return globalAnalytics;
|
|
700
703
|
}
|
|
701
|
-
// Auto-initialize if config is provided via window
|
|
702
704
|
if (typeof window !== 'undefined') {
|
|
703
705
|
var config = window.MetroneConfig;
|
|
704
706
|
if (config) {
|
|
705
707
|
globalAnalytics = new Metrone(config);
|
|
706
708
|
}
|
|
707
709
|
}
|
|
708
|
-
// Export for global usage
|
|
709
710
|
if (typeof window !== 'undefined') {
|
|
710
711
|
window.Metrone = Metrone;
|
|
711
712
|
window.initAnalytics = initAnalytics;
|
|
@@ -718,7 +719,7 @@ if (typeof window !== 'undefined') {
|
|
|
718
719
|
*/
|
|
719
720
|
// Core SDK
|
|
720
721
|
// Version
|
|
721
|
-
var VERSION = '1.0
|
|
722
|
+
var VERSION = '1.1.0';
|
|
722
723
|
|
|
723
724
|
export { Metrone, VERSION, Metrone as default, getAnalytics, initAnalytics };
|
|
724
725
|
//# sourceMappingURL=index.esm.js.map
|