@aranova/tracking-next 0.24.0 → 0.25.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 +12 -1
- package/dist/client.d.mts +350 -0
- package/dist/client.d.ts +350 -0
- package/dist/client.js +3572 -0
- package/dist/client.js.map +1 -0
- package/dist/client.mjs +3540 -0
- package/dist/client.mjs.map +1 -0
- package/dist/index.d.mts +10 -1710
- package/dist/index.d.ts +10 -1710
- package/dist/index.js +37 -1919
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +38 -1911
- package/dist/index.mjs.map +1 -1
- package/dist/ingest-typed-BioxtBJD.d.mts +1365 -0
- package/dist/ingest-typed-C-SPiigr.d.ts +1365 -0
- package/dist/middleware.js.map +1 -1
- package/dist/middleware.mjs.map +1 -1
- package/dist/{phone-utils-FTQnybMz.d.mts → phone-utils-BVzSNBf1.d.mts} +8 -4
- package/dist/{phone-utils-FTQnybMz.d.ts → phone-utils-BVzSNBf1.d.ts} +8 -4
- package/dist/phone.d.mts +1 -1
- package/dist/phone.d.ts +1 -1
- package/dist/phone.js.map +1 -1
- package/dist/phone.mjs.map +1 -1
- package/dist/{sales-D_BTsRuM.d.ts → sales-Bv1tihaB.d.ts} +2 -190
- package/dist/{sales-CmlzRq3u.d.mts → sales-Xs375f6t.d.mts} +2 -190
- package/dist/sales.d.mts +2 -1
- package/dist/sales.d.ts +2 -1
- package/dist/server.d.mts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js.map +1 -1
- package/dist/server.mjs.map +1 -1
- package/dist/tracking-config-runtime-BnUlS_Ae.d.mts +190 -0
- package/dist/tracking-config-runtime-BnUlS_Ae.d.ts +190 -0
- package/package.json +18 -1
package/dist/index.mjs
CHANGED
|
@@ -40,44 +40,12 @@ function formatPhoneAsTyped(raw, country) {
|
|
|
40
40
|
|
|
41
41
|
// ../tracking-core/src/user-data.ts
|
|
42
42
|
var EMAIL_SHAPE = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
|
|
43
|
-
var EMAIL_NAME_HINT = /e[-_]?mail/i;
|
|
44
|
-
var PHONE_NAME_HINT = /(^|[^a-z])(phone|tel|mobile|cell)/i;
|
|
45
43
|
var stash = { email: null, phoneNumber: null };
|
|
46
44
|
function normalizeEmail(raw) {
|
|
47
45
|
if (typeof raw !== "string") return null;
|
|
48
46
|
const cleaned = raw.trim().toLowerCase();
|
|
49
47
|
return EMAIL_SHAPE.test(cleaned) ? cleaned : null;
|
|
50
48
|
}
|
|
51
|
-
function fieldText(field, key) {
|
|
52
|
-
const value = field[key];
|
|
53
|
-
return typeof value === "string" ? value : "";
|
|
54
|
-
}
|
|
55
|
-
function extractUserDataFromFormFields(fields, country) {
|
|
56
|
-
const result = { email: null, phoneNumber: null };
|
|
57
|
-
if (!Array.isArray(fields)) return result;
|
|
58
|
-
const passes = [
|
|
59
|
-
(field, _hint, type) => fieldText(field, "type").toLowerCase() === type,
|
|
60
|
-
(field, hint) => hint.test(fieldText(field, "name")) || hint.test(fieldText(field, "label"))
|
|
61
|
-
];
|
|
62
|
-
for (const matches of passes) {
|
|
63
|
-
for (const raw of fields) {
|
|
64
|
-
if (raw === null || typeof raw !== "object") continue;
|
|
65
|
-
const field = raw;
|
|
66
|
-
if (typeof field.value !== "string" || field.value.length === 0) continue;
|
|
67
|
-
if (result.email === null && matches(field, EMAIL_NAME_HINT, "email")) {
|
|
68
|
-
result.email = normalizeEmail(field.value);
|
|
69
|
-
}
|
|
70
|
-
if (result.phoneNumber === null && matches(field, PHONE_NAME_HINT, "tel")) {
|
|
71
|
-
try {
|
|
72
|
-
result.phoneNumber = toE164(field.value, country);
|
|
73
|
-
} catch {
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if (result.email !== null && result.phoneNumber !== null) break;
|
|
78
|
-
}
|
|
79
|
-
return result;
|
|
80
|
-
}
|
|
81
49
|
function stashUserData(data, country) {
|
|
82
50
|
const email = normalizeEmail(data.email);
|
|
83
51
|
let phoneNumber = null;
|
|
@@ -93,16 +61,6 @@ function stashUserData(data, country) {
|
|
|
93
61
|
phoneNumber: phoneNumber ?? stash.phoneNumber
|
|
94
62
|
};
|
|
95
63
|
}
|
|
96
|
-
function stashUserDataFromFormFields(fields, country) {
|
|
97
|
-
try {
|
|
98
|
-
const extracted = extractUserDataFromFormFields(fields, country);
|
|
99
|
-
stash = {
|
|
100
|
-
email: extracted.email ?? stash.email,
|
|
101
|
-
phoneNumber: extracted.phoneNumber ?? stash.phoneNumber
|
|
102
|
-
};
|
|
103
|
-
} catch {
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
64
|
function clearStashedUserData() {
|
|
107
65
|
stash = { email: null, phoneNumber: null };
|
|
108
66
|
}
|
|
@@ -243,20 +201,6 @@ function resetConsent() {
|
|
|
243
201
|
pushConsentToPlatforms("granted");
|
|
244
202
|
notifyConsentChanged(DEFAULT_CHOICE);
|
|
245
203
|
}
|
|
246
|
-
function createEffectiveConsentSnippet() {
|
|
247
|
-
return `
|
|
248
|
-
var aranovaConsent = (function () {
|
|
249
|
-
try {
|
|
250
|
-
if (window.localStorage.getItem('${CONSENT_STATE_KEY}') === 'denied') {
|
|
251
|
-
var exp = window.localStorage.getItem('${CONSENT_EXPIRES_AT_KEY}');
|
|
252
|
-
var expMs = exp ? Date.parse(exp) : NaN;
|
|
253
|
-
if (!(expMs <= Date.now())) return 'denied';
|
|
254
|
-
}
|
|
255
|
-
} catch (e) {}
|
|
256
|
-
return 'granted';
|
|
257
|
-
})();
|
|
258
|
-
`.trim();
|
|
259
|
-
}
|
|
260
204
|
|
|
261
205
|
// ../tracking-core/src/capabilities.ts
|
|
262
206
|
var TRACKING_CAPABILITIES = [
|
|
@@ -388,12 +332,6 @@ function getCookieValueFromDocument(key) {
|
|
|
388
332
|
function setTrackingCookie(key, value, maxAgeSeconds = TRACKING_COOKIE_MAX_AGE_SECONDS) {
|
|
389
333
|
persistCookieValue(key, value, maxAgeSeconds);
|
|
390
334
|
}
|
|
391
|
-
function mergeTrackingParams(primary, fallback) {
|
|
392
|
-
return TRACKING_PARAM_KEYS.reduce((merged, key) => {
|
|
393
|
-
merged[key] = primary[key] ?? fallback[key];
|
|
394
|
-
return merged;
|
|
395
|
-
}, createEmptyTrackingParams());
|
|
396
|
-
}
|
|
397
335
|
function persistTrackingParamsFromSearchParams(searchParams, maxAgeSeconds = TRACKING_COOKIE_MAX_AGE_SECONDS) {
|
|
398
336
|
const trackingValues = getTrackingQueryValues(searchParams);
|
|
399
337
|
Object.entries(trackingValues).forEach(([key, value]) => {
|
|
@@ -417,30 +355,6 @@ var GTAG_ID_PATTERN = /^[A-Z]{1,3}-[A-Za-z0-9_-]+$/;
|
|
|
417
355
|
function isValidGtagId(id) {
|
|
418
356
|
return GTAG_ID_PATTERN.test(id);
|
|
419
357
|
}
|
|
420
|
-
function createConsentDefaultScript() {
|
|
421
|
-
return `
|
|
422
|
-
window.dataLayer = window.dataLayer || [];
|
|
423
|
-
function gtag(){dataLayer.push(arguments);}
|
|
424
|
-
window.gtag = gtag;
|
|
425
|
-
${createEffectiveConsentSnippet()}
|
|
426
|
-
gtag('consent', 'default', {
|
|
427
|
-
ad_storage: aranovaConsent,
|
|
428
|
-
ad_user_data: aranovaConsent,
|
|
429
|
-
ad_personalization: aranovaConsent,
|
|
430
|
-
analytics_storage: aranovaConsent
|
|
431
|
-
});
|
|
432
|
-
`.trim();
|
|
433
|
-
}
|
|
434
|
-
function createGtagInitScript(gtagId) {
|
|
435
|
-
if (!isValidGtagId(gtagId)) return "";
|
|
436
|
-
return `
|
|
437
|
-
window.dataLayer = window.dataLayer || [];
|
|
438
|
-
function gtag(){dataLayer.push(arguments);}
|
|
439
|
-
window.gtag = gtag;
|
|
440
|
-
gtag('js', new Date());
|
|
441
|
-
gtag('config', '${gtagId}');
|
|
442
|
-
`.trim();
|
|
443
|
-
}
|
|
444
358
|
function ensureGtagFunction() {
|
|
445
359
|
window.dataLayer = window.dataLayer || [];
|
|
446
360
|
if (typeof window.gtag === "function") return window.gtag;
|
|
@@ -489,80 +403,16 @@ function loadGtagScript(gtagId) {
|
|
|
489
403
|
script.setAttribute(TRACKING_SCRIPT_ATTRIBUTE, marker);
|
|
490
404
|
document.head.append(script);
|
|
491
405
|
}
|
|
492
|
-
function createGtagInitScriptMulti(gtagIds) {
|
|
493
|
-
const safeIds = gtagIds.filter(isValidGtagId);
|
|
494
|
-
const configs = safeIds.map((id) => `gtag('config', '${id}');`).join("\n");
|
|
495
|
-
return `
|
|
496
|
-
window.dataLayer = window.dataLayer || [];
|
|
497
|
-
function gtag(){dataLayer.push(arguments);}
|
|
498
|
-
window.gtag = gtag;
|
|
499
|
-
gtag('js', new Date());
|
|
500
|
-
${configs}
|
|
501
|
-
`.trim();
|
|
502
|
-
}
|
|
503
406
|
|
|
504
407
|
// ../tracking-core/src/fbq.ts
|
|
505
|
-
var FB_EVENTS_SCRIPT_HOST = "https://connect.facebook.net/en_US/fbevents.js";
|
|
506
408
|
var FBC_COOKIE = "_fbc";
|
|
507
409
|
var FBP_COOKIE = "_fbp";
|
|
508
|
-
var META_PIXEL_ID_PATTERN = /^\d{15,16}$/;
|
|
509
|
-
function isValidMetaPixelId(id) {
|
|
510
|
-
return META_PIXEL_ID_PATTERN.test(id);
|
|
511
|
-
}
|
|
512
|
-
function computeFbSubdomainIndex(hostname) {
|
|
513
|
-
const labels = hostname.split(".").filter(Boolean);
|
|
514
|
-
return Math.max(0, labels.length - 1);
|
|
515
|
-
}
|
|
516
|
-
function buildFbc(fbclid, now, hostname) {
|
|
517
|
-
const host = hostname ?? (typeof window === "undefined" ? "" : window.location.hostname);
|
|
518
|
-
return `fb.${computeFbSubdomainIndex(host)}.${now}.${fbclid}`;
|
|
519
|
-
}
|
|
520
410
|
function getFbcCookie() {
|
|
521
411
|
return readCookieValue(FBC_COOKIE);
|
|
522
412
|
}
|
|
523
413
|
function getFbpCookie() {
|
|
524
414
|
return readCookieValue(FBP_COOKIE);
|
|
525
415
|
}
|
|
526
|
-
function readFbclidFromUrl() {
|
|
527
|
-
if (typeof window === "undefined") return null;
|
|
528
|
-
try {
|
|
529
|
-
const value = new URL(window.location.href).searchParams.get("fbclid");
|
|
530
|
-
return value && value.trim().length > 0 ? value : null;
|
|
531
|
-
} catch {
|
|
532
|
-
return null;
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
function captureFbc(now = typeof Date === "undefined" ? 0 : Date.now()) {
|
|
536
|
-
if (typeof window === "undefined") return;
|
|
537
|
-
if (getFbcCookie()) return;
|
|
538
|
-
const fbclid = readFbclidFromUrl() ?? readCookieValue("fbclid");
|
|
539
|
-
if (!fbclid) return;
|
|
540
|
-
persistCookieValue(FBC_COOKIE, buildFbc(fbclid, now), TRACKING_COOKIE_MAX_AGE_SECONDS);
|
|
541
|
-
}
|
|
542
|
-
function fbqStubScript() {
|
|
543
|
-
return `
|
|
544
|
-
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
|
|
545
|
-
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
|
|
546
|
-
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
|
|
547
|
-
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
|
|
548
|
-
document,'script','${FB_EVENTS_SCRIPT_HOST}');`.trim();
|
|
549
|
-
}
|
|
550
|
-
function createMetaConsentDefaultScript() {
|
|
551
|
-
return `${fbqStubScript()}
|
|
552
|
-
${createEffectiveConsentSnippet()}
|
|
553
|
-
fbq('consent', aranovaConsent === 'denied' ? 'revoke' : 'grant');`;
|
|
554
|
-
}
|
|
555
|
-
function createMetaPixelInitScript(pixelId) {
|
|
556
|
-
if (!isValidMetaPixelId(pixelId)) return "";
|
|
557
|
-
return `fbq('init', '${pixelId}');
|
|
558
|
-
fbq('track', 'PageView');`;
|
|
559
|
-
}
|
|
560
|
-
function createMetaPixelInitScriptMulti(pixelIds) {
|
|
561
|
-
const inits = pixelIds.filter(isValidMetaPixelId).map((id) => `fbq('init', '${id}');`);
|
|
562
|
-
if (inits.length === 0) return "";
|
|
563
|
-
return `${inits.join("\n")}
|
|
564
|
-
fbq('track', 'PageView');`;
|
|
565
|
-
}
|
|
566
416
|
|
|
567
417
|
// ../tracking-core/src/landing.ts
|
|
568
418
|
var LANDING_STORAGE_KEY = "_aranova_track_landing";
|
|
@@ -837,9 +687,9 @@ function resolveConversionConfig(options) {
|
|
|
837
687
|
}
|
|
838
688
|
}
|
|
839
689
|
function notifyResolved() {
|
|
840
|
-
const
|
|
690
|
+
const listeners = [...resolveListeners];
|
|
841
691
|
resolveListeners.clear();
|
|
842
|
-
for (const listener of
|
|
692
|
+
for (const listener of listeners) {
|
|
843
693
|
try {
|
|
844
694
|
listener();
|
|
845
695
|
} catch {
|
|
@@ -1404,124 +1254,8 @@ function getTrackingConfigRuntime(ref, fetchImpl) {
|
|
|
1404
1254
|
return runtime;
|
|
1405
1255
|
}
|
|
1406
1256
|
|
|
1407
|
-
// ../tracking-core/src/resources/conversion-autofire.ts
|
|
1408
|
-
function currentPath() {
|
|
1409
|
-
return typeof window === "undefined" ? "" : window.location.pathname;
|
|
1410
|
-
}
|
|
1411
|
-
var MAX_BUFFERED_EVENTS = 50;
|
|
1412
|
-
function createConversionAutoFire(store) {
|
|
1413
|
-
const pending = [];
|
|
1414
|
-
let subscribed = false;
|
|
1415
|
-
function fireMatching(eventType, metadata, transactionScope) {
|
|
1416
|
-
for (const goal of store.listGoals()) {
|
|
1417
|
-
if (goal.kind !== "event" || !goal.firing) continue;
|
|
1418
|
-
if (!automaticThresholdMet(goal, eventType, metadata)) continue;
|
|
1419
|
-
const transactionId = getAutomaticTransactionId(transactionScope, goal.key, currentPath());
|
|
1420
|
-
if ("queueAutomaticEvent" in store) {
|
|
1421
|
-
store.fireConversion(goal.key, {
|
|
1422
|
-
transactionId
|
|
1423
|
-
});
|
|
1424
|
-
continue;
|
|
1425
|
-
}
|
|
1426
|
-
const firing = goal.firing;
|
|
1427
|
-
const cents = firing.value_cents ?? null;
|
|
1428
|
-
const currency = firing.currency ?? null;
|
|
1429
|
-
fireConversionWithConsent({
|
|
1430
|
-
sendTo: firing.send_to,
|
|
1431
|
-
value: cents != null && currency ? fromMinor(cents, currency) : null,
|
|
1432
|
-
currency,
|
|
1433
|
-
transactionId
|
|
1434
|
-
});
|
|
1435
|
-
}
|
|
1436
|
-
}
|
|
1437
|
-
return {
|
|
1438
|
-
onAutomaticEvent(eventType, metadata, transactionScope) {
|
|
1439
|
-
if ("queueAutomaticEvent" in store) {
|
|
1440
|
-
store.queueAutomaticEvent(eventType, metadata, currentPath(), transactionScope);
|
|
1441
|
-
return;
|
|
1442
|
-
}
|
|
1443
|
-
if (store.isReady()) {
|
|
1444
|
-
fireMatching(eventType, metadata, transactionScope);
|
|
1445
|
-
return;
|
|
1446
|
-
}
|
|
1447
|
-
if (pending.length < MAX_BUFFERED_EVENTS) {
|
|
1448
|
-
pending.push({ eventType, metadata, transactionScope });
|
|
1449
|
-
}
|
|
1450
|
-
if (!subscribed) {
|
|
1451
|
-
subscribed = true;
|
|
1452
|
-
store.onResolve(() => {
|
|
1453
|
-
const buffered = pending.splice(0);
|
|
1454
|
-
for (const event of buffered) {
|
|
1455
|
-
fireMatching(event.eventType, event.metadata, event.transactionScope);
|
|
1456
|
-
}
|
|
1457
|
-
});
|
|
1458
|
-
}
|
|
1459
|
-
}
|
|
1460
|
-
};
|
|
1461
|
-
}
|
|
1462
|
-
function withConversionAutoFire(client, autoFire) {
|
|
1463
|
-
return {
|
|
1464
|
-
...client,
|
|
1465
|
-
trackEvent: (input) => {
|
|
1466
|
-
client.trackEvent(input);
|
|
1467
|
-
try {
|
|
1468
|
-
autoFire.onAutomaticEvent(input.eventType, input.metadata ?? {}, client.getSessionId());
|
|
1469
|
-
} catch {
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
|
-
};
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
1257
|
// ../tracking-core/src/session.ts
|
|
1476
|
-
var VISITOR_STORAGE_KEY = "aranova_tracking_visitor";
|
|
1477
|
-
var SESSION_STORAGE_KEY = "aranova_tracking_session";
|
|
1478
1258
|
var SESSION_IDLE_MS = 30 * 60 * 1e3;
|
|
1479
|
-
function safeUuid() {
|
|
1480
|
-
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function")
|
|
1481
|
-
return crypto.randomUUID();
|
|
1482
|
-
return `${Date.now().toString(16)}-${Math.random().toString(16).slice(2)}-${Math.random().toString(16).slice(2)}`;
|
|
1483
|
-
}
|
|
1484
|
-
function readLocalStorage(key) {
|
|
1485
|
-
try {
|
|
1486
|
-
return window.localStorage.getItem(key);
|
|
1487
|
-
} catch {
|
|
1488
|
-
return null;
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
|
-
function writeLocalStorage(key, value) {
|
|
1492
|
-
try {
|
|
1493
|
-
window.localStorage.setItem(key, value);
|
|
1494
|
-
} catch {
|
|
1495
|
-
}
|
|
1496
|
-
}
|
|
1497
|
-
function getVisitorId() {
|
|
1498
|
-
if (typeof window === "undefined") return safeUuid();
|
|
1499
|
-
const existing = readLocalStorage(VISITOR_STORAGE_KEY);
|
|
1500
|
-
if (existing && existing.length > 0) return existing;
|
|
1501
|
-
const fresh = safeUuid();
|
|
1502
|
-
writeLocalStorage(VISITOR_STORAGE_KEY, fresh);
|
|
1503
|
-
return fresh;
|
|
1504
|
-
}
|
|
1505
|
-
function getOrRotateSessionId(now = Date.now()) {
|
|
1506
|
-
if (typeof window === "undefined") return { id: safeUuid(), isNew: true };
|
|
1507
|
-
const raw = readLocalStorage(SESSION_STORAGE_KEY);
|
|
1508
|
-
if (raw) {
|
|
1509
|
-
try {
|
|
1510
|
-
const parsed = JSON.parse(raw);
|
|
1511
|
-
if (typeof parsed.id === "string" && typeof parsed.last_event_at === "number") {
|
|
1512
|
-
if (now - parsed.last_event_at <= SESSION_IDLE_MS) {
|
|
1513
|
-
const refreshed = { id: parsed.id, last_event_at: now };
|
|
1514
|
-
writeLocalStorage(SESSION_STORAGE_KEY, JSON.stringify(refreshed));
|
|
1515
|
-
return { id: parsed.id, isNew: false };
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
} catch {
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
const fresh = { id: safeUuid(), last_event_at: now };
|
|
1522
|
-
writeLocalStorage(SESSION_STORAGE_KEY, JSON.stringify(fresh));
|
|
1523
|
-
return { id: fresh.id, isNew: true };
|
|
1524
|
-
}
|
|
1525
1259
|
|
|
1526
1260
|
// ../tracking-core/src/events/page-view.ts
|
|
1527
1261
|
import { z } from "zod";
|
|
@@ -1543,495 +1277,12 @@ var pageViewMetadataSchema = z.object({
|
|
|
1543
1277
|
}).strict();
|
|
1544
1278
|
var pageViewConfigSchema = z.object({}).strict();
|
|
1545
1279
|
|
|
1546
|
-
// ../tracking-core/src/page-view.ts
|
|
1547
|
-
var LAST_FIRED_URL_STORAGE_KEY = "aranova_tracking_last_fired_url";
|
|
1548
|
-
var lastFiredUrl = null;
|
|
1549
|
-
var lastFiredUrlHydrated = false;
|
|
1550
|
-
function readSessionStorage(key) {
|
|
1551
|
-
try {
|
|
1552
|
-
if (typeof window === "undefined") return null;
|
|
1553
|
-
return window.sessionStorage.getItem(key);
|
|
1554
|
-
} catch {
|
|
1555
|
-
return null;
|
|
1556
|
-
}
|
|
1557
|
-
}
|
|
1558
|
-
function writeSessionStorage(key, value) {
|
|
1559
|
-
try {
|
|
1560
|
-
if (typeof window === "undefined") return;
|
|
1561
|
-
window.sessionStorage.setItem(key, value);
|
|
1562
|
-
} catch {
|
|
1563
|
-
}
|
|
1564
|
-
}
|
|
1565
|
-
function getLastFiredUrl() {
|
|
1566
|
-
if (!lastFiredUrlHydrated) {
|
|
1567
|
-
lastFiredUrlHydrated = true;
|
|
1568
|
-
const stored = readSessionStorage(LAST_FIRED_URL_STORAGE_KEY);
|
|
1569
|
-
if (stored !== null) lastFiredUrl = stored;
|
|
1570
|
-
}
|
|
1571
|
-
return lastFiredUrl;
|
|
1572
|
-
}
|
|
1573
|
-
function setLastFiredUrl(url) {
|
|
1574
|
-
lastFiredUrl = url;
|
|
1575
|
-
lastFiredUrlHydrated = true;
|
|
1576
|
-
writeSessionStorage(LAST_FIRED_URL_STORAGE_KEY, url);
|
|
1577
|
-
}
|
|
1578
|
-
function buildPageViewMetadata(referrerOverride) {
|
|
1579
|
-
if (typeof window === "undefined" || typeof document === "undefined") return null;
|
|
1580
|
-
return pageViewMetadataSchema.parse({
|
|
1581
|
-
page: {
|
|
1582
|
-
title: document.title || null,
|
|
1583
|
-
path: window.location.pathname,
|
|
1584
|
-
search: window.location.search,
|
|
1585
|
-
hash: window.location.hash
|
|
1586
|
-
},
|
|
1587
|
-
referrer: referrerOverride !== void 0 ? referrerOverride : document.referrer || null,
|
|
1588
|
-
viewport: { w: window.innerWidth, h: window.innerHeight }
|
|
1589
|
-
});
|
|
1590
|
-
}
|
|
1591
|
-
function fireManualPageView(client) {
|
|
1592
|
-
if (typeof window === "undefined") return;
|
|
1593
|
-
const currentHref = window.location.href;
|
|
1594
|
-
const previousFiredUrl = getLastFiredUrl();
|
|
1595
|
-
const internalReferrer = previousFiredUrl !== null && previousFiredUrl !== currentHref ? previousFiredUrl : null;
|
|
1596
|
-
const externalReferrer = typeof document !== "undefined" ? document.referrer || null : null;
|
|
1597
|
-
const referrer = internalReferrer ?? externalReferrer;
|
|
1598
|
-
const metadata = buildPageViewMetadata(referrer);
|
|
1599
|
-
client.trackEvent({
|
|
1600
|
-
eventType: "page_view",
|
|
1601
|
-
pageUrl: currentHref,
|
|
1602
|
-
metadata
|
|
1603
|
-
});
|
|
1604
|
-
if (currentHref !== previousFiredUrl) {
|
|
1605
|
-
setLastFiredUrl(currentHref);
|
|
1606
|
-
}
|
|
1607
|
-
}
|
|
1608
|
-
function attachBfcacheRestore(client) {
|
|
1609
|
-
if (typeof window === "undefined") return () => {
|
|
1610
|
-
};
|
|
1611
|
-
function handlePageShow(event) {
|
|
1612
|
-
if (!event.persisted) return;
|
|
1613
|
-
fireManualPageView(client);
|
|
1614
|
-
}
|
|
1615
|
-
window.addEventListener("pageshow", handlePageShow);
|
|
1616
|
-
return () => {
|
|
1617
|
-
window.removeEventListener("pageshow", handlePageShow);
|
|
1618
|
-
};
|
|
1619
|
-
}
|
|
1620
|
-
|
|
1621
|
-
// ../tracking-core/src/heartbeat.ts
|
|
1622
|
-
function serializeValue(value) {
|
|
1623
|
-
if (value instanceof RegExp) return value.source;
|
|
1624
|
-
if (Array.isArray(value)) return value.map(serializeValue);
|
|
1625
|
-
if (value !== null && typeof value === "object") {
|
|
1626
|
-
const out = {};
|
|
1627
|
-
for (const [k, v] of Object.entries(value)) {
|
|
1628
|
-
out[k] = serializeValue(v);
|
|
1629
|
-
}
|
|
1630
|
-
return out;
|
|
1631
|
-
}
|
|
1632
|
-
return value;
|
|
1633
|
-
}
|
|
1634
|
-
function buildHeartbeatMetadata(surface, sdkVersion, packageName, triggers, gtagIds = null) {
|
|
1635
|
-
const automaticNames = triggers ? Object.keys(triggers.automatic) : [];
|
|
1636
|
-
const manualNames = triggers?.manual ? Object.keys(triggers.manual) : [];
|
|
1637
|
-
let triggerConfig = null;
|
|
1638
|
-
if (triggers) {
|
|
1639
|
-
const cfg = {};
|
|
1640
|
-
for (const [name, config] of Object.entries(triggers.automatic)) {
|
|
1641
|
-
const serialized = serializeValue(config);
|
|
1642
|
-
if (Object.keys(serialized).length > 0) {
|
|
1643
|
-
cfg[name] = serialized;
|
|
1644
|
-
}
|
|
1645
|
-
}
|
|
1646
|
-
if (triggers.manual) {
|
|
1647
|
-
for (const [name, config] of Object.entries(triggers.manual)) {
|
|
1648
|
-
if (config === void 0) continue;
|
|
1649
|
-
const serialized = serializeValue(config);
|
|
1650
|
-
if (Object.keys(serialized).length > 0) {
|
|
1651
|
-
cfg[name] = serialized;
|
|
1652
|
-
}
|
|
1653
|
-
}
|
|
1654
|
-
}
|
|
1655
|
-
if (Object.keys(cfg).length > 0) {
|
|
1656
|
-
triggerConfig = cfg;
|
|
1657
|
-
}
|
|
1658
|
-
}
|
|
1659
|
-
return {
|
|
1660
|
-
sdk_version: sdkVersion ?? "unknown",
|
|
1661
|
-
package_name: packageName,
|
|
1662
|
-
surface,
|
|
1663
|
-
triggers: {
|
|
1664
|
-
automatic: automaticNames,
|
|
1665
|
-
manual: manualNames
|
|
1666
|
-
},
|
|
1667
|
-
trigger_config: triggerConfig,
|
|
1668
|
-
configured_gtag_ids: gtagIds
|
|
1669
|
-
};
|
|
1670
|
-
}
|
|
1671
|
-
|
|
1672
1280
|
// ../tracking-core/src/ingest.ts
|
|
1673
|
-
var DEFAULT_FLUSH_INTERVAL_MS = 2e3;
|
|
1674
|
-
var DEFAULT_MAX_QUEUE_SIZE = 10;
|
|
1675
|
-
var HARD_MAX_BATCH = 50;
|
|
1676
|
-
var MAX_RETRY_BACKOFF_MS = 6e4;
|
|
1677
|
-
var MAX_BUFFERED_EVENTS2 = 200;
|
|
1678
|
-
var RETRY_BUFFER_KEY_PREFIX = "aranova_tracking_pending_v1";
|
|
1679
1281
|
var API_KEY_HEADER = "X-Aranova-Api-Key";
|
|
1680
1282
|
var SDK_VERSION_HEADER = "X-Aranova-Sdk-Version";
|
|
1681
1283
|
var SDK_PACKAGE_HEADER = "X-Aranova-Sdk-Package";
|
|
1682
1284
|
var SDK_SURFACE_HEADER = "X-Aranova-Sdk-Surface";
|
|
1683
1285
|
var SDK_ENVIRONMENT_HEADER = "X-Aranova-Sdk-Environment";
|
|
1684
|
-
function buildContext(surface, sdkVersion, packageName, environment, activeGtagIds) {
|
|
1685
|
-
return {
|
|
1686
|
-
surface,
|
|
1687
|
-
sdk_version: sdkVersion,
|
|
1688
|
-
package_name: packageName,
|
|
1689
|
-
site_origin: typeof window === "undefined" ? null : window.location.origin,
|
|
1690
|
-
page_title: typeof document === "undefined" ? null : document.title || null,
|
|
1691
|
-
referrer: typeof document === "undefined" ? null : document.referrer || null,
|
|
1692
|
-
environment,
|
|
1693
|
-
active_gtag_ids: activeGtagIds,
|
|
1694
|
-
// Rebuilt per flush (this runs inside the payload builder), so a client
|
|
1695
|
-
// constructed later on a deeper route still gets reported.
|
|
1696
|
-
capabilities: getRegisteredCapabilities()
|
|
1697
|
-
};
|
|
1698
|
-
}
|
|
1699
|
-
function readTrackingParams() {
|
|
1700
|
-
if (typeof window === "undefined") return createEmptyTrackingParams();
|
|
1701
|
-
try {
|
|
1702
|
-
captureTrackingParamsFromLocation();
|
|
1703
|
-
} catch {
|
|
1704
|
-
}
|
|
1705
|
-
return getTrackingParamsFromCookieReader(getCookieValueFromDocument);
|
|
1706
|
-
}
|
|
1707
|
-
function consentSnapshot() {
|
|
1708
|
-
try {
|
|
1709
|
-
const choice = getConsentChoice();
|
|
1710
|
-
return {
|
|
1711
|
-
state: choice.state,
|
|
1712
|
-
source: choice.source,
|
|
1713
|
-
updated_at: choice.updatedAt,
|
|
1714
|
-
expires_at: choice.expiresAt
|
|
1715
|
-
};
|
|
1716
|
-
} catch {
|
|
1717
|
-
return null;
|
|
1718
|
-
}
|
|
1719
|
-
}
|
|
1720
|
-
async function postWithFetch(url, body, apiKey, identity, keepalive) {
|
|
1721
|
-
if (typeof fetch !== "function") return "drop";
|
|
1722
|
-
try {
|
|
1723
|
-
const response = await fetch(url, {
|
|
1724
|
-
method: "POST",
|
|
1725
|
-
headers: {
|
|
1726
|
-
"Content-Type": "application/json",
|
|
1727
|
-
[API_KEY_HEADER]: apiKey,
|
|
1728
|
-
[SDK_VERSION_HEADER]: identity.sdkVersion,
|
|
1729
|
-
[SDK_PACKAGE_HEADER]: identity.packageName,
|
|
1730
|
-
[SDK_SURFACE_HEADER]: identity.surface,
|
|
1731
|
-
[SDK_ENVIRONMENT_HEADER]: identity.environment
|
|
1732
|
-
},
|
|
1733
|
-
body,
|
|
1734
|
-
keepalive,
|
|
1735
|
-
// CORS is open on the tracking endpoint; never send cookies.
|
|
1736
|
-
credentials: "omit",
|
|
1737
|
-
mode: "cors"
|
|
1738
|
-
});
|
|
1739
|
-
if (response.ok) return "ok";
|
|
1740
|
-
if (response.status === 408 || response.status === 429 || response.status >= 500) {
|
|
1741
|
-
return "retry";
|
|
1742
|
-
}
|
|
1743
|
-
return "drop";
|
|
1744
|
-
} catch {
|
|
1745
|
-
return "retry";
|
|
1746
|
-
}
|
|
1747
|
-
}
|
|
1748
|
-
function retryBufferKey(apiKey, endpoint) {
|
|
1749
|
-
return `${RETRY_BUFFER_KEY_PREFIX}:${apiKey}:${endpoint}`;
|
|
1750
|
-
}
|
|
1751
|
-
function readPendingBatches(key) {
|
|
1752
|
-
if (typeof window === "undefined") return [];
|
|
1753
|
-
try {
|
|
1754
|
-
const raw = window.localStorage.getItem(key);
|
|
1755
|
-
if (!raw) return [];
|
|
1756
|
-
const parsed = JSON.parse(raw);
|
|
1757
|
-
if (!Array.isArray(parsed)) return [];
|
|
1758
|
-
return parsed.filter(
|
|
1759
|
-
(entry) => typeof entry === "object" && entry !== null && "session" in entry && Array.isArray(entry.events)
|
|
1760
|
-
);
|
|
1761
|
-
} catch {
|
|
1762
|
-
return [];
|
|
1763
|
-
}
|
|
1764
|
-
}
|
|
1765
|
-
function writePendingBatches(key, batches) {
|
|
1766
|
-
if (typeof window === "undefined") return;
|
|
1767
|
-
try {
|
|
1768
|
-
if (batches.length === 0) window.localStorage.removeItem(key);
|
|
1769
|
-
else window.localStorage.setItem(key, JSON.stringify(batches));
|
|
1770
|
-
} catch {
|
|
1771
|
-
}
|
|
1772
|
-
}
|
|
1773
|
-
function trimToBufferCap(batches) {
|
|
1774
|
-
let total = batches.reduce((sum, batch) => sum + batch.events.length, 0);
|
|
1775
|
-
const trimmed = batches.slice();
|
|
1776
|
-
while (total > MAX_BUFFERED_EVENTS2 && trimmed.length > 1) {
|
|
1777
|
-
const dropped = trimmed.shift();
|
|
1778
|
-
total -= dropped ? dropped.events.length : 0;
|
|
1779
|
-
}
|
|
1780
|
-
return trimmed;
|
|
1781
|
-
}
|
|
1782
|
-
var globalClient = null;
|
|
1783
|
-
var globalClientKey = null;
|
|
1784
|
-
function clientConfigKey(config) {
|
|
1785
|
-
return `${config.apiKey}@${config.endpoint}#${config.surface}`;
|
|
1786
|
-
}
|
|
1787
|
-
function getOrCreateTrackingClient(config) {
|
|
1788
|
-
const key = clientConfigKey(config);
|
|
1789
|
-
if (globalClient !== null && globalClientKey === key) {
|
|
1790
|
-
return globalClient;
|
|
1791
|
-
}
|
|
1792
|
-
if (globalClient !== null) {
|
|
1793
|
-
globalClient.destroy();
|
|
1794
|
-
}
|
|
1795
|
-
globalClient = createTrackingClient(config);
|
|
1796
|
-
globalClientKey = key;
|
|
1797
|
-
return globalClient;
|
|
1798
|
-
}
|
|
1799
|
-
var clientCaptureRegistry = /* @__PURE__ */ new WeakMap();
|
|
1800
|
-
function attachClientCapturesOnce(client, build) {
|
|
1801
|
-
let entry = clientCaptureRegistry.get(client);
|
|
1802
|
-
if (entry === void 0) {
|
|
1803
|
-
entry = { detach: build(), refCount: 0 };
|
|
1804
|
-
clientCaptureRegistry.set(client, entry);
|
|
1805
|
-
}
|
|
1806
|
-
entry.refCount += 1;
|
|
1807
|
-
let released = false;
|
|
1808
|
-
return () => {
|
|
1809
|
-
if (released) return;
|
|
1810
|
-
released = true;
|
|
1811
|
-
const current = clientCaptureRegistry.get(client);
|
|
1812
|
-
if (current === void 0) return;
|
|
1813
|
-
current.refCount -= 1;
|
|
1814
|
-
if (current.refCount <= 0) {
|
|
1815
|
-
current.detach();
|
|
1816
|
-
clientCaptureRegistry.delete(client);
|
|
1817
|
-
}
|
|
1818
|
-
};
|
|
1819
|
-
}
|
|
1820
|
-
function createTrackingClient(config) {
|
|
1821
|
-
const flushIntervalMs = config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;
|
|
1822
|
-
const maxQueueSize = Math.min(config.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE, HARD_MAX_BATCH);
|
|
1823
|
-
const sdkVersion = config.sdkVersion ?? null;
|
|
1824
|
-
const packageName = config.packageName ?? null;
|
|
1825
|
-
const environment = config.environment ?? "production";
|
|
1826
|
-
const activeGtagIds = config.activeGtagIds ?? null;
|
|
1827
|
-
const endpointBase = config.endpoint.replace(/\/$/, "");
|
|
1828
|
-
const eventsUrl = `${endpointBase}/events`;
|
|
1829
|
-
const identityHeaders2 = {
|
|
1830
|
-
sdkVersion: sdkVersion ?? "",
|
|
1831
|
-
packageName: packageName ?? "",
|
|
1832
|
-
surface: config.surface,
|
|
1833
|
-
environment
|
|
1834
|
-
};
|
|
1835
|
-
let queue = [];
|
|
1836
|
-
let flushTimer = null;
|
|
1837
|
-
const bufferKey = retryBufferKey(config.apiKey, endpointBase);
|
|
1838
|
-
let pending = readPendingBatches(bufferKey);
|
|
1839
|
-
let flushChain = Promise.resolve();
|
|
1840
|
-
let retryAttempt = 0;
|
|
1841
|
-
let firstPage = null;
|
|
1842
|
-
let initialParams = createEmptyTrackingParams();
|
|
1843
|
-
let destroyed = false;
|
|
1844
|
-
const visitorId = getVisitorId();
|
|
1845
|
-
const initialSession = getOrRotateSessionId();
|
|
1846
|
-
let sessionId = initialSession.id;
|
|
1847
|
-
if (typeof window !== "undefined") {
|
|
1848
|
-
firstPage = window.location.href;
|
|
1849
|
-
try {
|
|
1850
|
-
initialParams = captureTrackingParamsFromLocation();
|
|
1851
|
-
} catch {
|
|
1852
|
-
}
|
|
1853
|
-
getOrCaptureLandingParams(sessionId);
|
|
1854
|
-
try {
|
|
1855
|
-
captureFbc();
|
|
1856
|
-
} catch {
|
|
1857
|
-
}
|
|
1858
|
-
}
|
|
1859
|
-
function enqueueHeartbeat() {
|
|
1860
|
-
const metadata = buildHeartbeatMetadata(
|
|
1861
|
-
config.surface,
|
|
1862
|
-
sdkVersion,
|
|
1863
|
-
packageName,
|
|
1864
|
-
config.triggers ?? null,
|
|
1865
|
-
activeGtagIds
|
|
1866
|
-
);
|
|
1867
|
-
queue.push({
|
|
1868
|
-
event_type: "sdk_heartbeat",
|
|
1869
|
-
page_url: typeof window === "undefined" ? null : window.location.href,
|
|
1870
|
-
metadata,
|
|
1871
|
-
occurred_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1872
|
-
});
|
|
1873
|
-
}
|
|
1874
|
-
if (initialSession.isNew) {
|
|
1875
|
-
enqueueHeartbeat();
|
|
1876
|
-
}
|
|
1877
|
-
if (pending.length > 0) {
|
|
1878
|
-
scheduleFlush();
|
|
1879
|
-
}
|
|
1880
|
-
function buildSessionPayload() {
|
|
1881
|
-
const rotated = getOrRotateSessionId();
|
|
1882
|
-
if (rotated.isNew && rotated.id !== sessionId) {
|
|
1883
|
-
enqueueHeartbeat();
|
|
1884
|
-
}
|
|
1885
|
-
sessionId = rotated.id;
|
|
1886
|
-
const params = mergeTrackingParams(readTrackingParams(), initialParams);
|
|
1887
|
-
const context = buildContext(
|
|
1888
|
-
config.surface,
|
|
1889
|
-
sdkVersion,
|
|
1890
|
-
packageName,
|
|
1891
|
-
environment,
|
|
1892
|
-
activeGtagIds
|
|
1893
|
-
);
|
|
1894
|
-
return {
|
|
1895
|
-
session_id: sessionId,
|
|
1896
|
-
visitor_id: visitorId,
|
|
1897
|
-
gclid: params.gclid,
|
|
1898
|
-
wbraid: params.wbraid,
|
|
1899
|
-
gbraid: params.gbraid,
|
|
1900
|
-
ylpcid: params.ylpcid,
|
|
1901
|
-
fbclid: params.fbclid,
|
|
1902
|
-
fbc: getFbcCookie(),
|
|
1903
|
-
fbp: getFbpCookie(),
|
|
1904
|
-
utm_source: params.utm_source,
|
|
1905
|
-
utm_medium: params.utm_medium,
|
|
1906
|
-
utm_campaign: params.utm_campaign,
|
|
1907
|
-
utm_term: params.utm_term,
|
|
1908
|
-
utm_content: params.utm_content,
|
|
1909
|
-
// Landing params for the CURRENT session id — captured on the spot when
|
|
1910
|
-
// the session just rotated (the current URL is the rotated session's
|
|
1911
|
-
// landing), reused from the stored record otherwise. Keys are omitted
|
|
1912
|
-
// entirely when the landing isn't observable (SSR).
|
|
1913
|
-
...buildLandingPayloadFields(sessionId),
|
|
1914
|
-
first_page: firstPage,
|
|
1915
|
-
consent_state: consentSnapshot(),
|
|
1916
|
-
context
|
|
1917
|
-
};
|
|
1918
|
-
}
|
|
1919
|
-
function scheduleFlush(delayMs = flushIntervalMs) {
|
|
1920
|
-
if (flushTimer !== null || destroyed) return;
|
|
1921
|
-
flushTimer = setTimeout(() => {
|
|
1922
|
-
flushTimer = null;
|
|
1923
|
-
void flush();
|
|
1924
|
-
}, delayMs);
|
|
1925
|
-
}
|
|
1926
|
-
function clearScheduledFlush() {
|
|
1927
|
-
if (flushTimer !== null) {
|
|
1928
|
-
clearTimeout(flushTimer);
|
|
1929
|
-
flushTimer = null;
|
|
1930
|
-
}
|
|
1931
|
-
}
|
|
1932
|
-
function bufferQueued() {
|
|
1933
|
-
if (queue.length === 0) return;
|
|
1934
|
-
const events = queue.slice(0, HARD_MAX_BATCH);
|
|
1935
|
-
queue = queue.slice(events.length);
|
|
1936
|
-
pending = trimToBufferCap([...pending, { session: buildSessionPayload(), events }]);
|
|
1937
|
-
writePendingBatches(bufferKey, pending);
|
|
1938
|
-
}
|
|
1939
|
-
function flush() {
|
|
1940
|
-
flushChain = flushChain.then(runFlush).catch(() => {
|
|
1941
|
-
});
|
|
1942
|
-
return flushChain;
|
|
1943
|
-
}
|
|
1944
|
-
async function runFlush() {
|
|
1945
|
-
if (destroyed) return;
|
|
1946
|
-
clearScheduledFlush();
|
|
1947
|
-
bufferQueued();
|
|
1948
|
-
if (pending.length === 0) return;
|
|
1949
|
-
try {
|
|
1950
|
-
while (pending.length > 0) {
|
|
1951
|
-
const batch = pending[0];
|
|
1952
|
-
const body = { session: batch.session, events: batch.events };
|
|
1953
|
-
const outcome = await postWithFetch(
|
|
1954
|
-
eventsUrl,
|
|
1955
|
-
JSON.stringify(body),
|
|
1956
|
-
config.apiKey,
|
|
1957
|
-
identityHeaders2,
|
|
1958
|
-
false
|
|
1959
|
-
);
|
|
1960
|
-
if (outcome === "retry") {
|
|
1961
|
-
retryAttempt += 1;
|
|
1962
|
-
return;
|
|
1963
|
-
}
|
|
1964
|
-
pending = pending.slice(1);
|
|
1965
|
-
writePendingBatches(bufferKey, pending);
|
|
1966
|
-
retryAttempt = 0;
|
|
1967
|
-
}
|
|
1968
|
-
} finally {
|
|
1969
|
-
if (pending.length > 0) {
|
|
1970
|
-
const backoff = Math.min(flushIntervalMs * 2 ** retryAttempt, MAX_RETRY_BACKOFF_MS);
|
|
1971
|
-
scheduleFlush(backoff);
|
|
1972
|
-
} else if (queue.length > 0) {
|
|
1973
|
-
scheduleFlush();
|
|
1974
|
-
}
|
|
1975
|
-
}
|
|
1976
|
-
}
|
|
1977
|
-
function trackEvent(input) {
|
|
1978
|
-
if (destroyed) return;
|
|
1979
|
-
if (!input || typeof input.eventType !== "string" || input.eventType.length === 0) return;
|
|
1980
|
-
if (input.eventType === "form_submit" && getConsentState() !== "denied") {
|
|
1981
|
-
try {
|
|
1982
|
-
const fields = input.metadata?.form?.fields;
|
|
1983
|
-
if (fields) stashUserDataFromFormFields(fields, config.phone?.defaultCountry);
|
|
1984
|
-
} catch {
|
|
1985
|
-
}
|
|
1986
|
-
}
|
|
1987
|
-
const occurredAt = input.occurredAt instanceof Date ? input.occurredAt.toISOString() : typeof input.occurredAt === "string" ? input.occurredAt : (/* @__PURE__ */ new Date()).toISOString();
|
|
1988
|
-
queue.push({
|
|
1989
|
-
event_type: input.eventType,
|
|
1990
|
-
page_url: input.pageUrl ?? (typeof window === "undefined" ? null : window.location.href),
|
|
1991
|
-
metadata: input.metadata ?? null,
|
|
1992
|
-
occurred_at: occurredAt
|
|
1993
|
-
});
|
|
1994
|
-
if (queue.length >= maxQueueSize) {
|
|
1995
|
-
void flush();
|
|
1996
|
-
} else {
|
|
1997
|
-
scheduleFlush();
|
|
1998
|
-
}
|
|
1999
|
-
}
|
|
2000
|
-
function flushOnUnload() {
|
|
2001
|
-
bufferQueued();
|
|
2002
|
-
clearScheduledFlush();
|
|
2003
|
-
if (pending.length === 0) return;
|
|
2004
|
-
const batch = pending[0];
|
|
2005
|
-
pending = pending.slice(1);
|
|
2006
|
-
writePendingBatches(bufferKey, pending);
|
|
2007
|
-
const body = { session: batch.session, events: batch.events };
|
|
2008
|
-
void postWithFetch(eventsUrl, JSON.stringify(body), config.apiKey, identityHeaders2, true);
|
|
2009
|
-
}
|
|
2010
|
-
if (typeof window !== "undefined") {
|
|
2011
|
-
window.addEventListener("pagehide", flushOnUnload);
|
|
2012
|
-
window.addEventListener("visibilitychange", () => {
|
|
2013
|
-
if (document.visibilityState === "hidden") flushOnUnload();
|
|
2014
|
-
});
|
|
2015
|
-
}
|
|
2016
|
-
return {
|
|
2017
|
-
trackEvent,
|
|
2018
|
-
flush,
|
|
2019
|
-
flushBeacon: flushOnUnload,
|
|
2020
|
-
getSessionId: () => sessionId,
|
|
2021
|
-
getVisitorId: () => visitorId,
|
|
2022
|
-
destroy: () => {
|
|
2023
|
-
destroyed = true;
|
|
2024
|
-
if (queue.length > 0) {
|
|
2025
|
-
flushOnUnload();
|
|
2026
|
-
}
|
|
2027
|
-
clearScheduledFlush();
|
|
2028
|
-
queue = [];
|
|
2029
|
-
if (typeof window !== "undefined") {
|
|
2030
|
-
window.removeEventListener("pagehide", flushOnUnload);
|
|
2031
|
-
}
|
|
2032
|
-
}
|
|
2033
|
-
};
|
|
2034
|
-
}
|
|
2035
1286
|
|
|
2036
1287
|
// ../tracking-core/src/events/cta-click.ts
|
|
2037
1288
|
import { z as z2 } from "zod";
|
|
@@ -2360,506 +1611,6 @@ var EVENT_REGISTRY = {
|
|
|
2360
1611
|
var ALL_AUTOMATIC_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def]) => def.kind === "automatic").map(([name]) => name);
|
|
2361
1612
|
var ALL_MANUAL_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def]) => def.kind === "manual").map(([name]) => name);
|
|
2362
1613
|
var ALL_LEAD_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def]) => def.semantics.outcomeRole === "lead").map(([name]) => name);
|
|
2363
|
-
function getEventDefinition(name) {
|
|
2364
|
-
return EVENT_REGISTRY[name];
|
|
2365
|
-
}
|
|
2366
|
-
|
|
2367
|
-
// ../tracking-core/src/ingest-typed.ts
|
|
2368
|
-
function createTypedClient(raw, registry, options = {}) {
|
|
2369
|
-
const debug = options.debug ?? false;
|
|
2370
|
-
if (registry.manual?.form_submit) registerCapability("form_capture");
|
|
2371
|
-
return {
|
|
2372
|
-
trackEvent(eventType, metadata, opts) {
|
|
2373
|
-
if (debug) {
|
|
2374
|
-
const def = getEventDefinition(eventType);
|
|
2375
|
-
def.metadataSchema.parse(metadata);
|
|
2376
|
-
}
|
|
2377
|
-
raw.trackEvent({
|
|
2378
|
-
eventType,
|
|
2379
|
-
metadata,
|
|
2380
|
-
pageUrl: opts?.pageUrl ?? null,
|
|
2381
|
-
occurredAt: opts?.occurredAt ?? null
|
|
2382
|
-
});
|
|
2383
|
-
},
|
|
2384
|
-
flush: raw.flush.bind(raw),
|
|
2385
|
-
getSessionId: raw.getSessionId.bind(raw),
|
|
2386
|
-
getVisitorId: raw.getVisitorId.bind(raw)
|
|
2387
|
-
};
|
|
2388
|
-
}
|
|
2389
|
-
|
|
2390
|
-
// ../tracking-core/src/triggers/time-on-site.ts
|
|
2391
|
-
function attachTimeOnSite(client, config) {
|
|
2392
|
-
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
2393
|
-
return () => {
|
|
2394
|
-
};
|
|
2395
|
-
}
|
|
2396
|
-
const thresholdMs = config.thresholdSeconds * 1e3;
|
|
2397
|
-
let accumulatedMs = 0;
|
|
2398
|
-
let activeSince = document.visibilityState === "visible" ? Date.now() : null;
|
|
2399
|
-
let timer = null;
|
|
2400
|
-
let fired = false;
|
|
2401
|
-
function fire() {
|
|
2402
|
-
if (fired) return;
|
|
2403
|
-
fired = true;
|
|
2404
|
-
client.trackEvent({
|
|
2405
|
-
eventType: "time_on_site",
|
|
2406
|
-
metadata: {
|
|
2407
|
-
duration_ms: thresholdMs,
|
|
2408
|
-
page: { path: window.location.pathname }
|
|
2409
|
-
},
|
|
2410
|
-
pageUrl: window.location.href,
|
|
2411
|
-
occurredAt: null
|
|
2412
|
-
});
|
|
2413
|
-
}
|
|
2414
|
-
function scheduleNext() {
|
|
2415
|
-
if (fired || activeSince === null) return;
|
|
2416
|
-
const remaining = thresholdMs - accumulatedMs;
|
|
2417
|
-
if (remaining <= 0) {
|
|
2418
|
-
fire();
|
|
2419
|
-
return;
|
|
2420
|
-
}
|
|
2421
|
-
timer = setTimeout(fire, remaining);
|
|
2422
|
-
}
|
|
2423
|
-
function clearTimer() {
|
|
2424
|
-
if (timer !== null) {
|
|
2425
|
-
clearTimeout(timer);
|
|
2426
|
-
timer = null;
|
|
2427
|
-
}
|
|
2428
|
-
}
|
|
2429
|
-
function onVisibilityChange() {
|
|
2430
|
-
if (fired) return;
|
|
2431
|
-
if (document.visibilityState === "hidden") {
|
|
2432
|
-
if (activeSince !== null) {
|
|
2433
|
-
accumulatedMs += Date.now() - activeSince;
|
|
2434
|
-
activeSince = null;
|
|
2435
|
-
}
|
|
2436
|
-
clearTimer();
|
|
2437
|
-
} else {
|
|
2438
|
-
activeSince = Date.now();
|
|
2439
|
-
scheduleNext();
|
|
2440
|
-
}
|
|
2441
|
-
}
|
|
2442
|
-
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
2443
|
-
scheduleNext();
|
|
2444
|
-
return () => {
|
|
2445
|
-
clearTimer();
|
|
2446
|
-
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
2447
|
-
};
|
|
2448
|
-
}
|
|
2449
|
-
|
|
2450
|
-
// ../tracking-core/src/triggers/navigation.ts
|
|
2451
|
-
var listeners = /* @__PURE__ */ new Set();
|
|
2452
|
-
var restorePatch = null;
|
|
2453
|
-
function notify() {
|
|
2454
|
-
for (const listener of listeners) listener();
|
|
2455
|
-
}
|
|
2456
|
-
function notifyDeferred() {
|
|
2457
|
-
setTimeout(notify, 0);
|
|
2458
|
-
}
|
|
2459
|
-
function installPatch() {
|
|
2460
|
-
const originalPushState = history.pushState;
|
|
2461
|
-
const originalReplaceState = history.replaceState;
|
|
2462
|
-
function patchedPushState(...args) {
|
|
2463
|
-
originalPushState.apply(this, args);
|
|
2464
|
-
notifyDeferred();
|
|
2465
|
-
}
|
|
2466
|
-
function patchedReplaceState(...args) {
|
|
2467
|
-
originalReplaceState.apply(this, args);
|
|
2468
|
-
notifyDeferred();
|
|
2469
|
-
}
|
|
2470
|
-
history.pushState = patchedPushState;
|
|
2471
|
-
history.replaceState = patchedReplaceState;
|
|
2472
|
-
window.addEventListener("popstate", notify);
|
|
2473
|
-
restorePatch = () => {
|
|
2474
|
-
history.pushState = originalPushState;
|
|
2475
|
-
history.replaceState = originalReplaceState;
|
|
2476
|
-
window.removeEventListener("popstate", notify);
|
|
2477
|
-
restorePatch = null;
|
|
2478
|
-
};
|
|
2479
|
-
}
|
|
2480
|
-
function onHistoryChange(listener) {
|
|
2481
|
-
if (listeners.size === 0) installPatch();
|
|
2482
|
-
listeners.add(listener);
|
|
2483
|
-
return () => {
|
|
2484
|
-
if (!listeners.delete(listener)) return;
|
|
2485
|
-
if (listeners.size === 0) restorePatch?.();
|
|
2486
|
-
};
|
|
2487
|
-
}
|
|
2488
|
-
|
|
2489
|
-
// ../tracking-core/src/triggers/scroll-measurement.ts
|
|
2490
|
-
var BOTTOM_EPSILON_PX = 2;
|
|
2491
|
-
function measureScrollPercent() {
|
|
2492
|
-
const root = document.scrollingElement ?? document.documentElement;
|
|
2493
|
-
const scrollHeight = root.scrollHeight;
|
|
2494
|
-
const clientHeight = root.clientHeight;
|
|
2495
|
-
if (scrollHeight <= 0 || clientHeight <= 0) return null;
|
|
2496
|
-
if (scrollHeight <= clientHeight + BOTTOM_EPSILON_PX) return null;
|
|
2497
|
-
const maxTop = scrollHeight - clientHeight;
|
|
2498
|
-
const scrollTop = Math.min(Math.max(root.scrollTop, 0), maxTop);
|
|
2499
|
-
if (scrollTop + clientHeight >= scrollHeight - BOTTOM_EPSILON_PX) return 100;
|
|
2500
|
-
return Math.max(1, Math.min(100, Math.round((scrollTop + clientHeight) / scrollHeight * 100)));
|
|
2501
|
-
}
|
|
2502
|
-
function scheduleBaselineSnapshot(onSnapshot) {
|
|
2503
|
-
let rafId = requestAnimationFrame(() => {
|
|
2504
|
-
rafId = requestAnimationFrame(() => {
|
|
2505
|
-
onSnapshot(measureScrollPercent());
|
|
2506
|
-
});
|
|
2507
|
-
});
|
|
2508
|
-
return () => cancelAnimationFrame(rafId);
|
|
2509
|
-
}
|
|
2510
|
-
function createBaselineGate() {
|
|
2511
|
-
let baselinePercent = null;
|
|
2512
|
-
let ready = false;
|
|
2513
|
-
let cancelSnapshot = null;
|
|
2514
|
-
return {
|
|
2515
|
-
rebaseline() {
|
|
2516
|
-
cancelSnapshot?.();
|
|
2517
|
-
ready = false;
|
|
2518
|
-
baselinePercent = null;
|
|
2519
|
-
cancelSnapshot = scheduleBaselineSnapshot((b) => {
|
|
2520
|
-
baselinePercent = b;
|
|
2521
|
-
ready = true;
|
|
2522
|
-
});
|
|
2523
|
-
},
|
|
2524
|
-
cancel() {
|
|
2525
|
-
cancelSnapshot?.();
|
|
2526
|
-
},
|
|
2527
|
-
baseline() {
|
|
2528
|
-
return ready ? baselinePercent : null;
|
|
2529
|
-
},
|
|
2530
|
-
sample() {
|
|
2531
|
-
if (!ready) return null;
|
|
2532
|
-
if (baselinePercent === null) {
|
|
2533
|
-
baselinePercent = measureScrollPercent();
|
|
2534
|
-
return null;
|
|
2535
|
-
}
|
|
2536
|
-
return measureScrollPercent();
|
|
2537
|
-
}
|
|
2538
|
-
};
|
|
2539
|
-
}
|
|
2540
|
-
|
|
2541
|
-
// ../tracking-core/src/triggers/scroll-depth.ts
|
|
2542
|
-
function attachScrollDepth(client, config) {
|
|
2543
|
-
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
2544
|
-
return () => {
|
|
2545
|
-
};
|
|
2546
|
-
}
|
|
2547
|
-
const thresholds = new Set(config.thresholds);
|
|
2548
|
-
let firedForPath = /* @__PURE__ */ new Set();
|
|
2549
|
-
let currentPath2 = window.location.pathname;
|
|
2550
|
-
let rafId = null;
|
|
2551
|
-
const gate = createBaselineGate();
|
|
2552
|
-
function checkThresholds() {
|
|
2553
|
-
const percent = gate.sample();
|
|
2554
|
-
if (percent === null) return;
|
|
2555
|
-
const baseline = gate.baseline();
|
|
2556
|
-
if (baseline === null) return;
|
|
2557
|
-
for (const threshold of thresholds) {
|
|
2558
|
-
if (threshold <= baseline) continue;
|
|
2559
|
-
if (percent >= threshold && !firedForPath.has(threshold)) {
|
|
2560
|
-
firedForPath.add(threshold);
|
|
2561
|
-
client.trackEvent({
|
|
2562
|
-
eventType: "scroll_depth",
|
|
2563
|
-
metadata: {
|
|
2564
|
-
depth_percent: threshold,
|
|
2565
|
-
page: { path: currentPath2 }
|
|
2566
|
-
},
|
|
2567
|
-
pageUrl: window.location.href,
|
|
2568
|
-
occurredAt: null
|
|
2569
|
-
});
|
|
2570
|
-
}
|
|
2571
|
-
}
|
|
2572
|
-
}
|
|
2573
|
-
function onScroll() {
|
|
2574
|
-
if (rafId !== null) return;
|
|
2575
|
-
rafId = requestAnimationFrame(() => {
|
|
2576
|
-
rafId = null;
|
|
2577
|
-
checkThresholds();
|
|
2578
|
-
});
|
|
2579
|
-
}
|
|
2580
|
-
function resetIfPathChanged() {
|
|
2581
|
-
const newPath = window.location.pathname;
|
|
2582
|
-
if (newPath === currentPath2) return;
|
|
2583
|
-
currentPath2 = newPath;
|
|
2584
|
-
firedForPath = /* @__PURE__ */ new Set();
|
|
2585
|
-
gate.rebaseline();
|
|
2586
|
-
}
|
|
2587
|
-
const unsubscribeNav = onHistoryChange(resetIfPathChanged);
|
|
2588
|
-
window.addEventListener("scroll", onScroll, { passive: true });
|
|
2589
|
-
gate.rebaseline();
|
|
2590
|
-
return () => {
|
|
2591
|
-
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
2592
|
-
gate.cancel();
|
|
2593
|
-
unsubscribeNav();
|
|
2594
|
-
window.removeEventListener("scroll", onScroll);
|
|
2595
|
-
};
|
|
2596
|
-
}
|
|
2597
|
-
|
|
2598
|
-
// ../tracking-core/src/triggers/form-start.ts
|
|
2599
|
-
function attachFormStart(client, config) {
|
|
2600
|
-
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
2601
|
-
return () => {
|
|
2602
|
-
};
|
|
2603
|
-
}
|
|
2604
|
-
const selector = config.selector ?? "form";
|
|
2605
|
-
let firedForms = /* @__PURE__ */ new Set();
|
|
2606
|
-
let currentPath2 = window.location.pathname;
|
|
2607
|
-
function getFormKey(form) {
|
|
2608
|
-
if (form.id) return `id:${form.id}`;
|
|
2609
|
-
const explicitAction = form.getAttribute("action");
|
|
2610
|
-
if (explicitAction) return `action:${explicitAction}`;
|
|
2611
|
-
const forms = Array.from(document.querySelectorAll(selector));
|
|
2612
|
-
return `index:${forms.indexOf(form)}`;
|
|
2613
|
-
}
|
|
2614
|
-
function onFocusIn(event) {
|
|
2615
|
-
const target = event.target;
|
|
2616
|
-
if (!(target instanceof HTMLElement)) return;
|
|
2617
|
-
const form = target.closest(selector);
|
|
2618
|
-
if (!form || form.tagName !== "FORM") return;
|
|
2619
|
-
const key = getFormKey(form);
|
|
2620
|
-
if (firedForms.has(key)) return;
|
|
2621
|
-
firedForms.add(key);
|
|
2622
|
-
client.trackEvent({
|
|
2623
|
-
eventType: "form_start",
|
|
2624
|
-
metadata: {
|
|
2625
|
-
form: {
|
|
2626
|
-
id: form.id || "",
|
|
2627
|
-
action: form.getAttribute("action") ?? null
|
|
2628
|
-
},
|
|
2629
|
-
page: { path: window.location.pathname }
|
|
2630
|
-
},
|
|
2631
|
-
pageUrl: window.location.href,
|
|
2632
|
-
occurredAt: null
|
|
2633
|
-
});
|
|
2634
|
-
}
|
|
2635
|
-
function resetIfPathChanged() {
|
|
2636
|
-
const newPath = window.location.pathname;
|
|
2637
|
-
if (newPath === currentPath2) return;
|
|
2638
|
-
currentPath2 = newPath;
|
|
2639
|
-
firedForms = /* @__PURE__ */ new Set();
|
|
2640
|
-
}
|
|
2641
|
-
const originalPushState = history.pushState.bind(history);
|
|
2642
|
-
const originalReplaceState = history.replaceState.bind(history);
|
|
2643
|
-
function patchedPushState(...args) {
|
|
2644
|
-
originalPushState(...args);
|
|
2645
|
-
setTimeout(resetIfPathChanged, 0);
|
|
2646
|
-
}
|
|
2647
|
-
function patchedReplaceState(...args) {
|
|
2648
|
-
originalReplaceState(...args);
|
|
2649
|
-
setTimeout(resetIfPathChanged, 0);
|
|
2650
|
-
}
|
|
2651
|
-
history.pushState = patchedPushState;
|
|
2652
|
-
history.replaceState = patchedReplaceState;
|
|
2653
|
-
window.addEventListener("popstate", resetIfPathChanged);
|
|
2654
|
-
document.addEventListener("focusin", onFocusIn);
|
|
2655
|
-
return () => {
|
|
2656
|
-
history.pushState = originalPushState;
|
|
2657
|
-
history.replaceState = originalReplaceState;
|
|
2658
|
-
window.removeEventListener("popstate", resetIfPathChanged);
|
|
2659
|
-
document.removeEventListener("focusin", onFocusIn);
|
|
2660
|
-
};
|
|
2661
|
-
}
|
|
2662
|
-
|
|
2663
|
-
// ../tracking-core/src/triggers/page-exit.ts
|
|
2664
|
-
var MIN_SEGMENT_MS = 50;
|
|
2665
|
-
function attachPageExit(client) {
|
|
2666
|
-
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
2667
|
-
return () => {
|
|
2668
|
-
};
|
|
2669
|
-
}
|
|
2670
|
-
let currentPath2 = window.location.pathname;
|
|
2671
|
-
let activeSince = document.visibilityState === "visible" ? Date.now() : null;
|
|
2672
|
-
let accumulatedMs = 0;
|
|
2673
|
-
let maxScrollPercent = null;
|
|
2674
|
-
let rafId = null;
|
|
2675
|
-
const gate = createBaselineGate();
|
|
2676
|
-
function onScroll() {
|
|
2677
|
-
if (rafId !== null) return;
|
|
2678
|
-
rafId = requestAnimationFrame(() => {
|
|
2679
|
-
rafId = null;
|
|
2680
|
-
const percent = gate.sample();
|
|
2681
|
-
if (percent !== null && (maxScrollPercent === null || percent > maxScrollPercent)) {
|
|
2682
|
-
maxScrollPercent = percent;
|
|
2683
|
-
}
|
|
2684
|
-
});
|
|
2685
|
-
}
|
|
2686
|
-
function settledDwellMs() {
|
|
2687
|
-
let total = accumulatedMs;
|
|
2688
|
-
if (activeSince !== null) {
|
|
2689
|
-
total += Date.now() - activeSince;
|
|
2690
|
-
}
|
|
2691
|
-
return Math.max(0, Math.round(total));
|
|
2692
|
-
}
|
|
2693
|
-
function emitSegment(path, flush) {
|
|
2694
|
-
const dwell = settledDwellMs();
|
|
2695
|
-
if (dwell < MIN_SEGMENT_MS) return;
|
|
2696
|
-
client.trackEvent({
|
|
2697
|
-
eventType: "page_exit",
|
|
2698
|
-
metadata: {
|
|
2699
|
-
dwell_ms: dwell,
|
|
2700
|
-
max_scroll_percent: maxScrollPercent,
|
|
2701
|
-
// Lets the backend tell "scrolled to the bottom" apart from "the page
|
|
2702
|
-
// was barely scrollable". null = unscrollable page or the segment
|
|
2703
|
-
// ended before the post-paint snapshot landed. For pages that grew
|
|
2704
|
-
// after the snapshot this is the first-scroll position, not the
|
|
2705
|
-
// at-load fraction (see BaselineGate.baseline).
|
|
2706
|
-
scroll_baseline_percent: gate.baseline(),
|
|
2707
|
-
page: { path }
|
|
2708
|
-
},
|
|
2709
|
-
pageUrl: window.location.href,
|
|
2710
|
-
occurredAt: null
|
|
2711
|
-
});
|
|
2712
|
-
if (flush) {
|
|
2713
|
-
client.flushBeacon();
|
|
2714
|
-
}
|
|
2715
|
-
accumulatedMs = 0;
|
|
2716
|
-
activeSince = null;
|
|
2717
|
-
}
|
|
2718
|
-
function onNavigate() {
|
|
2719
|
-
const newPath = window.location.pathname;
|
|
2720
|
-
if (newPath === currentPath2) return;
|
|
2721
|
-
emitSegment(currentPath2, false);
|
|
2722
|
-
currentPath2 = newPath;
|
|
2723
|
-
maxScrollPercent = null;
|
|
2724
|
-
gate.rebaseline();
|
|
2725
|
-
accumulatedMs = 0;
|
|
2726
|
-
activeSince = document.visibilityState === "visible" ? Date.now() : null;
|
|
2727
|
-
}
|
|
2728
|
-
function onVisibilityChange() {
|
|
2729
|
-
if (document.visibilityState === "hidden") {
|
|
2730
|
-
emitSegment(currentPath2, true);
|
|
2731
|
-
} else {
|
|
2732
|
-
activeSince = Date.now();
|
|
2733
|
-
}
|
|
2734
|
-
}
|
|
2735
|
-
function onPageHide() {
|
|
2736
|
-
emitSegment(currentPath2, true);
|
|
2737
|
-
}
|
|
2738
|
-
const unsubscribeNav = onHistoryChange(onNavigate);
|
|
2739
|
-
window.addEventListener("scroll", onScroll, { passive: true });
|
|
2740
|
-
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
2741
|
-
window.addEventListener("pagehide", onPageHide);
|
|
2742
|
-
gate.rebaseline();
|
|
2743
|
-
return () => {
|
|
2744
|
-
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
2745
|
-
gate.cancel();
|
|
2746
|
-
unsubscribeNav();
|
|
2747
|
-
window.removeEventListener("scroll", onScroll);
|
|
2748
|
-
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
2749
|
-
window.removeEventListener("pagehide", onPageHide);
|
|
2750
|
-
};
|
|
2751
|
-
}
|
|
2752
|
-
|
|
2753
|
-
// ../tracking-core/src/triggers/cta-click-capture.ts
|
|
2754
|
-
var DEFAULT_CTA_SELECTOR = "[data-aranova-cta]";
|
|
2755
|
-
var CTA_NAME_MAX_LENGTH = 120;
|
|
2756
|
-
function describeElement(el) {
|
|
2757
|
-
const tag = el.tagName.toLowerCase();
|
|
2758
|
-
return el.id ? `${tag}#${el.id}` : tag;
|
|
2759
|
-
}
|
|
2760
|
-
function resolveCtaName(el) {
|
|
2761
|
-
const explicit = el.getAttribute("data-aranova-cta");
|
|
2762
|
-
if (explicit && explicit.trim().length > 0) return explicit.trim();
|
|
2763
|
-
const text = (el.textContent ?? "").trim().replaceAll(/\s+/g, " ");
|
|
2764
|
-
if (text.length > 0) return text.slice(0, CTA_NAME_MAX_LENGTH);
|
|
2765
|
-
return describeElement(el);
|
|
2766
|
-
}
|
|
2767
|
-
function attachCtaClickCapture(client, config) {
|
|
2768
|
-
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
2769
|
-
return () => {
|
|
2770
|
-
};
|
|
2771
|
-
}
|
|
2772
|
-
const autoCapture = config.autoCapture;
|
|
2773
|
-
if (!autoCapture) {
|
|
2774
|
-
return () => {
|
|
2775
|
-
};
|
|
2776
|
-
}
|
|
2777
|
-
registerCapability("cta_click_capture");
|
|
2778
|
-
const selector = autoCapture.selector ?? DEFAULT_CTA_SELECTOR;
|
|
2779
|
-
function onClick(event) {
|
|
2780
|
-
const target = event.target;
|
|
2781
|
-
if (!(target instanceof Element)) return;
|
|
2782
|
-
let matched = null;
|
|
2783
|
-
try {
|
|
2784
|
-
matched = target.closest(selector);
|
|
2785
|
-
} catch {
|
|
2786
|
-
return;
|
|
2787
|
-
}
|
|
2788
|
-
if (matched === null) return;
|
|
2789
|
-
const href = matched instanceof HTMLAnchorElement ? matched.href || null : matched.getAttribute("href");
|
|
2790
|
-
client.trackEvent({
|
|
2791
|
-
eventType: "cta_click",
|
|
2792
|
-
metadata: {
|
|
2793
|
-
cta_name: resolveCtaName(matched),
|
|
2794
|
-
page: { path: window.location.pathname },
|
|
2795
|
-
section: matched.getAttribute("data-aranova-section"),
|
|
2796
|
-
destination_url: href,
|
|
2797
|
-
href,
|
|
2798
|
-
element: describeElement(matched)
|
|
2799
|
-
},
|
|
2800
|
-
pageUrl: window.location.href,
|
|
2801
|
-
occurredAt: null
|
|
2802
|
-
});
|
|
2803
|
-
}
|
|
2804
|
-
document.addEventListener("click", onClick, true);
|
|
2805
|
-
return () => {
|
|
2806
|
-
document.removeEventListener("click", onClick, true);
|
|
2807
|
-
};
|
|
2808
|
-
}
|
|
2809
|
-
|
|
2810
|
-
// ../tracking-core/src/triggers/phone-click-capture.ts
|
|
2811
|
-
var DEFAULT_TEL_SELECTOR = 'a[href^="tel:"]';
|
|
2812
|
-
function safeDecodeURIComponent(value) {
|
|
2813
|
-
try {
|
|
2814
|
-
return decodeURIComponent(value);
|
|
2815
|
-
} catch {
|
|
2816
|
-
return value;
|
|
2817
|
-
}
|
|
2818
|
-
}
|
|
2819
|
-
function resolvePhoneNumber(el) {
|
|
2820
|
-
const href = el instanceof HTMLAnchorElement ? el.href : el.getAttribute("href") ?? "";
|
|
2821
|
-
const raw = safeDecodeURIComponent(href.replace(/^tel:/i, "").split(";")[0]).trim();
|
|
2822
|
-
return toE164(raw) ?? raw;
|
|
2823
|
-
}
|
|
2824
|
-
function attachPhoneClickCapture(client, config) {
|
|
2825
|
-
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
2826
|
-
return () => {
|
|
2827
|
-
};
|
|
2828
|
-
}
|
|
2829
|
-
const autoCapture = config.autoCapture;
|
|
2830
|
-
if (!autoCapture) {
|
|
2831
|
-
return () => {
|
|
2832
|
-
};
|
|
2833
|
-
}
|
|
2834
|
-
registerCapability("phone_click_capture");
|
|
2835
|
-
const selector = autoCapture.selector ?? DEFAULT_TEL_SELECTOR;
|
|
2836
|
-
function onClick(event) {
|
|
2837
|
-
const target = event.target;
|
|
2838
|
-
if (!(target instanceof Element)) return;
|
|
2839
|
-
let matched = null;
|
|
2840
|
-
try {
|
|
2841
|
-
matched = target.closest(selector);
|
|
2842
|
-
} catch {
|
|
2843
|
-
return;
|
|
2844
|
-
}
|
|
2845
|
-
if (matched === null) return;
|
|
2846
|
-
const metadata = {
|
|
2847
|
-
phone_number: resolvePhoneNumber(matched),
|
|
2848
|
-
page: { path: window.location.pathname },
|
|
2849
|
-
section: matched.getAttribute("data-aranova-section")
|
|
2850
|
-
};
|
|
2851
|
-
client.trackEvent({
|
|
2852
|
-
eventType: "phone_click",
|
|
2853
|
-
metadata,
|
|
2854
|
-
pageUrl: window.location.href,
|
|
2855
|
-
occurredAt: null
|
|
2856
|
-
});
|
|
2857
|
-
}
|
|
2858
|
-
document.addEventListener("click", onClick, true);
|
|
2859
|
-
return () => {
|
|
2860
|
-
document.removeEventListener("click", onClick, true);
|
|
2861
|
-
};
|
|
2862
|
-
}
|
|
2863
1614
|
|
|
2864
1615
|
// ../tracking-core/src/resources/http/errors.ts
|
|
2865
1616
|
var AranovaApiError = class extends Error {
|
|
@@ -3230,649 +1981,18 @@ function phoneField(name, raw, country) {
|
|
|
3230
1981
|
return { name, type: "phone", value: toE164(raw, country) };
|
|
3231
1982
|
}
|
|
3232
1983
|
|
|
3233
|
-
// src/
|
|
3234
|
-
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
3235
|
-
|
|
3236
|
-
// src/hooks.ts
|
|
3237
|
-
import { useCallback, useEffect, useState } from "react";
|
|
3238
|
-
function useGclid() {
|
|
3239
|
-
const [gclid, setGclid] = useState(null);
|
|
3240
|
-
useEffect(() => {
|
|
3241
|
-
setGclid(getCookieValueFromDocument("gclid"));
|
|
3242
|
-
}, []);
|
|
3243
|
-
return gclid;
|
|
3244
|
-
}
|
|
3245
|
-
function useTrackingParams() {
|
|
3246
|
-
const [trackingParams, setTrackingParams] = useState(createEmptyTrackingParams());
|
|
3247
|
-
useEffect(() => {
|
|
3248
|
-
setTrackingParams(getTrackingParamsFromCookieReader(getCookieValueFromDocument));
|
|
3249
|
-
}, []);
|
|
3250
|
-
return trackingParams;
|
|
3251
|
-
}
|
|
3252
|
-
var DEFAULT_CHOICE2 = {
|
|
3253
|
-
state: "granted",
|
|
3254
|
-
source: "default",
|
|
3255
|
-
updatedAt: null,
|
|
3256
|
-
expiresAt: null
|
|
3257
|
-
};
|
|
3258
|
-
function useCookiePreferences(options) {
|
|
3259
|
-
registerCapability("consent_controls");
|
|
3260
|
-
const [choice, setChoice] = useState(DEFAULT_CHOICE2);
|
|
3261
|
-
const ttlDays = options?.declineTtlDays;
|
|
3262
|
-
useEffect(() => {
|
|
3263
|
-
const sync = () => setChoice(getConsentChoice());
|
|
3264
|
-
sync();
|
|
3265
|
-
const handleStorage = (event) => {
|
|
3266
|
-
if (event.key === null || event.key === CONSENT_STATE_KEY || event.key === CONSENT_EXPIRES_AT_KEY || event.key === CONSENT_TIMESTAMP_KEY)
|
|
3267
|
-
sync();
|
|
3268
|
-
};
|
|
3269
|
-
window.addEventListener("storage", handleStorage);
|
|
3270
|
-
const unsubscribe = onConsentChange(sync);
|
|
3271
|
-
return () => {
|
|
3272
|
-
window.removeEventListener("storage", handleStorage);
|
|
3273
|
-
unsubscribe();
|
|
3274
|
-
};
|
|
3275
|
-
}, []);
|
|
3276
|
-
const optOutAction = useCallback(() => {
|
|
3277
|
-
optOut(ttlDays != null ? { declineTtlDays: ttlDays } : void 0);
|
|
3278
|
-
}, [ttlDays]);
|
|
3279
|
-
const optInAction = useCallback(() => {
|
|
3280
|
-
optIn();
|
|
3281
|
-
}, []);
|
|
3282
|
-
const reset = useCallback(() => {
|
|
3283
|
-
resetConsent();
|
|
3284
|
-
}, []);
|
|
3285
|
-
return {
|
|
3286
|
-
state: choice.state,
|
|
3287
|
-
source: choice.source,
|
|
3288
|
-
isDefault: choice.source === "default",
|
|
3289
|
-
isGranted: choice.state === "granted",
|
|
3290
|
-
isDenied: choice.state === "denied",
|
|
3291
|
-
updatedAt: choice.updatedAt,
|
|
3292
|
-
expiresAt: choice.expiresAt,
|
|
3293
|
-
optOut: optOutAction,
|
|
3294
|
-
optIn: optInAction,
|
|
3295
|
-
reset
|
|
3296
|
-
};
|
|
3297
|
-
}
|
|
3298
|
-
function useConsentState() {
|
|
3299
|
-
return useConsent().state;
|
|
3300
|
-
}
|
|
3301
|
-
function useConsent() {
|
|
3302
|
-
const {
|
|
3303
|
-
state,
|
|
3304
|
-
isGranted,
|
|
3305
|
-
isDenied,
|
|
3306
|
-
optIn: accept,
|
|
3307
|
-
optOut: decline,
|
|
3308
|
-
reset
|
|
3309
|
-
} = useCookiePreferences();
|
|
3310
|
-
return {
|
|
3311
|
-
state,
|
|
3312
|
-
isPending: false,
|
|
3313
|
-
isGranted,
|
|
3314
|
-
isDenied,
|
|
3315
|
-
accept,
|
|
3316
|
-
decline,
|
|
3317
|
-
reset
|
|
3318
|
-
};
|
|
3319
|
-
}
|
|
3320
|
-
|
|
3321
|
-
// src/ConsentBanner.tsx
|
|
3322
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3323
|
-
var LIGHT_THEME = {
|
|
3324
|
-
background: "#ffffff",
|
|
3325
|
-
border: "#e5e7eb",
|
|
3326
|
-
text: "#111827",
|
|
3327
|
-
mutedText: "#4b5563",
|
|
3328
|
-
acceptBg: "#111827",
|
|
3329
|
-
acceptText: "#ffffff",
|
|
3330
|
-
declineBg: "transparent",
|
|
3331
|
-
declineText: "#111827",
|
|
3332
|
-
declineBorder: "#d1d5db",
|
|
3333
|
-
shadow: "0 -4px 16px -2px rgba(15, 23, 42, 0.08), 0 -2px 6px -1px rgba(15, 23, 42, 0.04)",
|
|
3334
|
-
linkColor: "#1f2937"
|
|
3335
|
-
};
|
|
3336
|
-
var DARK_THEME = {
|
|
3337
|
-
background: "#0f172a",
|
|
3338
|
-
border: "#1e293b",
|
|
3339
|
-
text: "#f1f5f9",
|
|
3340
|
-
mutedText: "#cbd5e1",
|
|
3341
|
-
acceptBg: "#f1f5f9",
|
|
3342
|
-
acceptText: "#0f172a",
|
|
3343
|
-
declineBg: "transparent",
|
|
3344
|
-
declineText: "#f1f5f9",
|
|
3345
|
-
declineBorder: "#334155",
|
|
3346
|
-
shadow: "0 -4px 16px -2px rgba(0, 0, 0, 0.5), 0 -2px 6px -1px rgba(0, 0, 0, 0.3)",
|
|
3347
|
-
linkColor: "#e2e8f0"
|
|
3348
|
-
};
|
|
3349
|
-
function useResolvedTheme(theme) {
|
|
3350
|
-
const [prefersDark, setPrefersDark] = useState2(false);
|
|
3351
|
-
useEffect2(() => {
|
|
3352
|
-
if (theme !== "auto" || typeof window === "undefined" || !window.matchMedia) return;
|
|
3353
|
-
const mql = window.matchMedia("(prefers-color-scheme: dark)");
|
|
3354
|
-
setPrefersDark(mql.matches);
|
|
3355
|
-
const onChange = (e) => setPrefersDark(e.matches);
|
|
3356
|
-
mql.addEventListener("change", onChange);
|
|
3357
|
-
return () => mql.removeEventListener("change", onChange);
|
|
3358
|
-
}, [theme]);
|
|
3359
|
-
if (theme === "dark") return DARK_THEME;
|
|
3360
|
-
if (theme === "auto" && prefersDark) return DARK_THEME;
|
|
3361
|
-
return LIGHT_THEME;
|
|
3362
|
-
}
|
|
3363
|
-
var DEFAULT_MESSAGE = "We use cookies to understand ad performance and improve how our marketing works across visits. You can accept or decline this tracking.";
|
|
3364
|
-
function ConsentBanner({
|
|
3365
|
-
message,
|
|
3366
|
-
title,
|
|
3367
|
-
acceptLabel = "Accept",
|
|
3368
|
-
declineLabel = "Decline",
|
|
3369
|
-
policyHref,
|
|
3370
|
-
policyLabel = "Learn more",
|
|
3371
|
-
onAccept,
|
|
3372
|
-
onDecline,
|
|
3373
|
-
position = "bottom",
|
|
3374
|
-
theme = "light",
|
|
3375
|
-
className,
|
|
3376
|
-
style
|
|
3377
|
-
} = {}) {
|
|
3378
|
-
const { isPending, accept, decline } = useConsent();
|
|
3379
|
-
const tokens = useResolvedTheme(theme);
|
|
3380
|
-
const [hasMounted, setHasMounted] = useState2(false);
|
|
3381
|
-
useEffect2(() => {
|
|
3382
|
-
setHasMounted(true);
|
|
3383
|
-
}, []);
|
|
3384
|
-
if (!hasMounted || !isPending) return null;
|
|
3385
|
-
const wrapperStyle = {
|
|
3386
|
-
position: "fixed",
|
|
3387
|
-
left: 0,
|
|
3388
|
-
right: 0,
|
|
3389
|
-
[position]: 0,
|
|
3390
|
-
zIndex: 2147483640,
|
|
3391
|
-
background: tokens.background,
|
|
3392
|
-
color: tokens.text,
|
|
3393
|
-
borderTop: position === "bottom" ? `1px solid ${tokens.border}` : "none",
|
|
3394
|
-
borderBottom: position === "top" ? `1px solid ${tokens.border}` : "none",
|
|
3395
|
-
boxShadow: tokens.shadow,
|
|
3396
|
-
padding: "16px 20px",
|
|
3397
|
-
boxSizing: "border-box",
|
|
3398
|
-
animation: `${ANIMATION_NAME}-${position} 200ms ease-out`,
|
|
3399
|
-
fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
3400
|
-
...style
|
|
3401
|
-
};
|
|
3402
|
-
const innerStyle = {
|
|
3403
|
-
maxWidth: 1100,
|
|
3404
|
-
margin: "0 auto",
|
|
3405
|
-
display: "flex",
|
|
3406
|
-
flexWrap: "wrap",
|
|
3407
|
-
gap: 16,
|
|
3408
|
-
alignItems: "center",
|
|
3409
|
-
justifyContent: "space-between"
|
|
3410
|
-
};
|
|
3411
|
-
const messageStyle = {
|
|
3412
|
-
flex: "1 1 320px",
|
|
3413
|
-
margin: 0,
|
|
3414
|
-
fontSize: 14,
|
|
3415
|
-
lineHeight: 1.5,
|
|
3416
|
-
color: tokens.mutedText
|
|
3417
|
-
};
|
|
3418
|
-
const titleStyle = {
|
|
3419
|
-
margin: "0 0 4px 0",
|
|
3420
|
-
fontSize: 14,
|
|
3421
|
-
fontWeight: 600,
|
|
3422
|
-
color: tokens.text
|
|
3423
|
-
};
|
|
3424
|
-
const actionsStyle = {
|
|
3425
|
-
display: "flex",
|
|
3426
|
-
gap: 8,
|
|
3427
|
-
flexShrink: 0
|
|
3428
|
-
};
|
|
3429
|
-
const buttonBase = {
|
|
3430
|
-
appearance: "none",
|
|
3431
|
-
fontFamily: "inherit",
|
|
3432
|
-
fontSize: 14,
|
|
3433
|
-
fontWeight: 500,
|
|
3434
|
-
padding: "8px 16px",
|
|
3435
|
-
borderRadius: 6,
|
|
3436
|
-
cursor: "pointer",
|
|
3437
|
-
border: "1px solid transparent",
|
|
3438
|
-
transition: "opacity 120ms ease"
|
|
3439
|
-
};
|
|
3440
|
-
const declineStyle = {
|
|
3441
|
-
...buttonBase,
|
|
3442
|
-
background: tokens.declineBg,
|
|
3443
|
-
color: tokens.declineText,
|
|
3444
|
-
borderColor: tokens.declineBorder
|
|
3445
|
-
};
|
|
3446
|
-
const acceptStyle = {
|
|
3447
|
-
...buttonBase,
|
|
3448
|
-
background: tokens.acceptBg,
|
|
3449
|
-
color: tokens.acceptText
|
|
3450
|
-
};
|
|
3451
|
-
const linkStyle = {
|
|
3452
|
-
color: tokens.linkColor,
|
|
3453
|
-
textDecoration: "underline",
|
|
3454
|
-
textUnderlineOffset: 2
|
|
3455
|
-
};
|
|
3456
|
-
const handleAccept = () => {
|
|
3457
|
-
accept();
|
|
3458
|
-
onAccept?.();
|
|
3459
|
-
};
|
|
3460
|
-
const handleDecline = () => {
|
|
3461
|
-
decline();
|
|
3462
|
-
onDecline?.();
|
|
3463
|
-
};
|
|
3464
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3465
|
-
/* @__PURE__ */ jsx("style", { children: ANIMATION_KEYFRAMES }),
|
|
3466
|
-
/* @__PURE__ */ jsx(
|
|
3467
|
-
"div",
|
|
3468
|
-
{
|
|
3469
|
-
role: "dialog",
|
|
3470
|
-
"aria-live": "polite",
|
|
3471
|
-
"aria-label": "Cookie consent",
|
|
3472
|
-
className,
|
|
3473
|
-
style: wrapperStyle,
|
|
3474
|
-
children: /* @__PURE__ */ jsxs("div", { style: innerStyle, children: [
|
|
3475
|
-
/* @__PURE__ */ jsxs("div", { style: { flex: "1 1 320px" }, children: [
|
|
3476
|
-
title ? /* @__PURE__ */ jsx("p", { style: titleStyle, children: title }) : null,
|
|
3477
|
-
/* @__PURE__ */ jsxs("p", { style: messageStyle, children: [
|
|
3478
|
-
message ?? DEFAULT_MESSAGE,
|
|
3479
|
-
policyHref ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3480
|
-
" ",
|
|
3481
|
-
/* @__PURE__ */ jsx("a", { href: policyHref, style: linkStyle, children: policyLabel })
|
|
3482
|
-
] }) : null
|
|
3483
|
-
] })
|
|
3484
|
-
] }),
|
|
3485
|
-
/* @__PURE__ */ jsxs("div", { style: actionsStyle, children: [
|
|
3486
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: handleDecline, style: declineStyle, children: declineLabel }),
|
|
3487
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: handleAccept, style: acceptStyle, children: acceptLabel })
|
|
3488
|
-
] })
|
|
3489
|
-
] })
|
|
3490
|
-
}
|
|
3491
|
-
)
|
|
3492
|
-
] });
|
|
3493
|
-
}
|
|
3494
|
-
var ANIMATION_NAME = "aranova-consent-banner";
|
|
3495
|
-
var ANIMATION_KEYFRAMES = `
|
|
3496
|
-
@keyframes ${ANIMATION_NAME}-bottom {
|
|
3497
|
-
from { transform: translateY(100%); opacity: 0; }
|
|
3498
|
-
to { transform: translateY(0); opacity: 1; }
|
|
3499
|
-
}
|
|
3500
|
-
@keyframes ${ANIMATION_NAME}-top {
|
|
3501
|
-
from { transform: translateY(-100%); opacity: 0; }
|
|
3502
|
-
to { transform: translateY(0); opacity: 1; }
|
|
3503
|
-
}
|
|
3504
|
-
`;
|
|
3505
|
-
|
|
3506
|
-
// src/AdPlatformTracking.tsx
|
|
3507
|
-
import Script from "next/script";
|
|
3508
|
-
import { useEffect as useEffect3 } from "react";
|
|
3509
|
-
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
3510
|
-
function AdPlatformTracking({
|
|
3511
|
-
gtagId,
|
|
3512
|
-
gtagIds,
|
|
3513
|
-
trackingConfig,
|
|
3514
|
-
standalonePageView = false,
|
|
3515
|
-
metaPixelId,
|
|
3516
|
-
metaPixelIds
|
|
3517
|
-
}) {
|
|
3518
|
-
const trackingConfigKey2 = trackingConfig ? `${resolveTrackingConfigUrl(trackingConfig)}:${trackingConfig.businessId}:${trackingConfig.environment}` : "";
|
|
3519
|
-
useEffect3(() => {
|
|
3520
|
-
if (!trackingConfig) return;
|
|
3521
|
-
const runtime = getTrackingConfigRuntime(trackingConfig);
|
|
3522
|
-
if (standalonePageView) runtime.queuePageView();
|
|
3523
|
-
else runtime.start();
|
|
3524
|
-
}, [trackingConfigKey2, standalonePageView]);
|
|
3525
|
-
const gtagAll = trackingConfig ? [] : gtagIds ? Object.values(gtagIds).filter((id) => id != null) : gtagId ? [gtagId] : [];
|
|
3526
|
-
const metaAll = metaPixelIds ? Object.values(metaPixelIds).filter((id) => id != null) : metaPixelId ? [metaPixelId] : [];
|
|
3527
|
-
if (trackingConfig || gtagAll.length > 0) registerCapability("ad_tags_google");
|
|
3528
|
-
if (metaAll.length > 0) registerCapability("ad_tags_meta");
|
|
3529
|
-
const gtagLoaderId = gtagAll[0];
|
|
3530
|
-
const gtagInitScript = gtagAll.length === 1 ? createGtagInitScript(gtagAll[0]) : createGtagInitScriptMulti(gtagAll);
|
|
3531
|
-
const metaInitScript = metaAll.length === 1 ? createMetaPixelInitScript(metaAll[0]) : createMetaPixelInitScriptMulti(metaAll);
|
|
3532
|
-
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
3533
|
-
gtagLoaderId ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
3534
|
-
/* @__PURE__ */ jsx2(Script, { id: "consent-default", strategy: "beforeInteractive", children: createConsentDefaultScript() }),
|
|
3535
|
-
/* @__PURE__ */ jsx2(
|
|
3536
|
-
Script,
|
|
3537
|
-
{
|
|
3538
|
-
src: `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(gtagLoaderId)}`,
|
|
3539
|
-
strategy: "afterInteractive"
|
|
3540
|
-
}
|
|
3541
|
-
),
|
|
3542
|
-
/* @__PURE__ */ jsx2(Script, { id: "gtag-init", strategy: "afterInteractive", children: gtagInitScript })
|
|
3543
|
-
] }) : null,
|
|
3544
|
-
metaAll.length > 0 ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
3545
|
-
/* @__PURE__ */ jsx2(Script, { id: "meta-pixel-base", strategy: "afterInteractive", children: createMetaConsentDefaultScript() }),
|
|
3546
|
-
/* @__PURE__ */ jsx2(Script, { id: "meta-pixel-init", strategy: "afterInteractive", children: metaInitScript })
|
|
3547
|
-
] }) : null
|
|
3548
|
-
] });
|
|
3549
|
-
}
|
|
3550
|
-
|
|
3551
|
-
// src/GoogleAdsTracking.tsx
|
|
3552
|
-
import Script2 from "next/script";
|
|
3553
|
-
import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
3554
|
-
function GoogleAdsTracking(props) {
|
|
3555
|
-
const { gtagId, gtagIds } = props;
|
|
3556
|
-
const allIds = gtagIds ? Object.values(gtagIds).filter((id) => id != null) : gtagId ? [gtagId] : [];
|
|
3557
|
-
if (allIds.length === 0) return null;
|
|
3558
|
-
const loaderId = allIds[0];
|
|
3559
|
-
const initScript = allIds.length === 1 ? createGtagInitScript(loaderId) : createGtagInitScriptMulti(allIds);
|
|
3560
|
-
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
3561
|
-
/* @__PURE__ */ jsx3(Script2, { id: "consent-default", strategy: "beforeInteractive", children: createConsentDefaultScript() }),
|
|
3562
|
-
/* @__PURE__ */ jsx3(
|
|
3563
|
-
Script2,
|
|
3564
|
-
{
|
|
3565
|
-
src: `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(loaderId)}`,
|
|
3566
|
-
strategy: "afterInteractive"
|
|
3567
|
-
}
|
|
3568
|
-
),
|
|
3569
|
-
/* @__PURE__ */ jsx3(Script2, { id: "gtag-init", strategy: "afterInteractive", children: initScript })
|
|
3570
|
-
] });
|
|
3571
|
-
}
|
|
3572
|
-
|
|
3573
|
-
// src/factory.tsx
|
|
3574
|
-
import { usePathname, useSearchParams } from "next/navigation";
|
|
3575
|
-
|
|
3576
|
-
// package.json
|
|
3577
|
-
var version = "0.24.0";
|
|
3578
|
-
|
|
3579
|
-
// src/factory.tsx
|
|
3580
|
-
import {
|
|
3581
|
-
createContext as createContext2,
|
|
3582
|
-
Suspense,
|
|
3583
|
-
useCallback as useCallback3,
|
|
3584
|
-
useContext as useContext2,
|
|
3585
|
-
useEffect as useEffect4,
|
|
3586
|
-
useMemo as useMemo2,
|
|
3587
|
-
useRef
|
|
3588
|
-
} from "react";
|
|
3589
|
-
|
|
3590
|
-
// ../tracking-core/src/phone-react.tsx
|
|
1984
|
+
// src/index.ts
|
|
3591
1985
|
import {
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
return _phoneConfigContext ?? (_phoneConfigContext = createContext(null));
|
|
3603
|
-
}
|
|
3604
|
-
function PhoneConfigProvider({
|
|
3605
|
-
value,
|
|
3606
|
-
children
|
|
3607
|
-
}) {
|
|
3608
|
-
const Ctx = phoneConfigContext();
|
|
3609
|
-
return /* @__PURE__ */ jsx4(Ctx.Provider, { value, children });
|
|
3610
|
-
}
|
|
3611
|
-
function usePhoneConfig() {
|
|
3612
|
-
const ctx = useContext(phoneConfigContext());
|
|
3613
|
-
return {
|
|
3614
|
-
defaultCountry: ctx?.defaultCountry ?? DEFAULT_PHONE_COUNTRY,
|
|
3615
|
-
display: ctx?.display ?? "national"
|
|
3616
|
-
};
|
|
3617
|
-
}
|
|
3618
|
-
function usePhoneField(opts = {}) {
|
|
3619
|
-
registerCapability("phone_fields");
|
|
3620
|
-
const cfg = usePhoneConfig();
|
|
3621
|
-
const country = opts.country ?? cfg.defaultCountry;
|
|
3622
|
-
const display = opts.display ?? cfg.display;
|
|
3623
|
-
const { onValueChange } = opts;
|
|
3624
|
-
const [value, setValue] = useState3(() => formatPhoneAsTyped(opts.defaultValue ?? "", country));
|
|
3625
|
-
const [touched, setTouched] = useState3(false);
|
|
3626
|
-
const parsed = useMemo(() => parsePhone(value, country), [value, country]);
|
|
3627
|
-
const onChange = useCallback2(
|
|
3628
|
-
(event) => {
|
|
3629
|
-
const next = formatPhoneAsTyped(event.target.value, country);
|
|
3630
|
-
setValue(next);
|
|
3631
|
-
onValueChange?.(parsePhone(next, country).e164);
|
|
3632
|
-
},
|
|
3633
|
-
[country, onValueChange]
|
|
3634
|
-
);
|
|
3635
|
-
const onBlur = useCallback2(
|
|
3636
|
-
(_event) => {
|
|
3637
|
-
setTouched(true);
|
|
3638
|
-
setValue((current) => {
|
|
3639
|
-
const p = parsePhone(current, country);
|
|
3640
|
-
return p.isValid ? formatPhone(current, display, country) : current;
|
|
3641
|
-
});
|
|
3642
|
-
},
|
|
3643
|
-
[country, display]
|
|
3644
|
-
);
|
|
3645
|
-
const error = touched && value.length > 0 && !parsed.isValid ? "Enter a valid phone number" : null;
|
|
3646
|
-
return {
|
|
3647
|
-
value,
|
|
3648
|
-
e164: parsed.e164,
|
|
3649
|
-
isValid: parsed.isValid,
|
|
3650
|
-
error,
|
|
3651
|
-
parsed,
|
|
3652
|
-
inputProps: { value, onChange, onBlur, type: "tel", inputMode: "tel", autoComplete: "tel" }
|
|
3653
|
-
};
|
|
3654
|
-
}
|
|
3655
|
-
var PhoneField = forwardRef(function PhoneField2({ country, value, defaultValue, onChange, onE164Change, ...rest }, ref) {
|
|
3656
|
-
const cfg = usePhoneConfig();
|
|
3657
|
-
const resolvedCountry = country ?? cfg.defaultCountry;
|
|
3658
|
-
const isControlled = value !== void 0;
|
|
3659
|
-
const [internal, setInternal] = useState3(
|
|
3660
|
-
() => formatPhoneAsTyped(defaultValue ?? "", resolvedCountry)
|
|
3661
|
-
);
|
|
3662
|
-
const handleChange = (event) => {
|
|
3663
|
-
const formatted = formatPhoneAsTyped(event.target.value, resolvedCountry);
|
|
3664
|
-
event.target.value = formatted;
|
|
3665
|
-
onE164Change?.(parsePhone(formatted, resolvedCountry).e164);
|
|
3666
|
-
if (!isControlled) setInternal(formatted);
|
|
3667
|
-
onChange?.(event);
|
|
3668
|
-
};
|
|
3669
|
-
const shown = isControlled ? formatPhoneAsTyped(value, resolvedCountry) : internal;
|
|
3670
|
-
return /* @__PURE__ */ jsx4(
|
|
3671
|
-
"input",
|
|
3672
|
-
{
|
|
3673
|
-
...rest,
|
|
3674
|
-
ref,
|
|
3675
|
-
type: "tel",
|
|
3676
|
-
inputMode: "tel",
|
|
3677
|
-
autoComplete: "tel",
|
|
3678
|
-
value: shown,
|
|
3679
|
-
onChange: handleChange
|
|
3680
|
-
}
|
|
3681
|
-
);
|
|
3682
|
-
});
|
|
3683
|
-
|
|
3684
|
-
// src/factory.tsx
|
|
3685
|
-
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
3686
|
-
function PageViewTracker({ fire }) {
|
|
3687
|
-
const pathname = usePathname();
|
|
3688
|
-
const searchParams = useSearchParams();
|
|
3689
|
-
useEffect4(() => {
|
|
3690
|
-
fire();
|
|
3691
|
-
}, [pathname, searchParams, fire]);
|
|
3692
|
-
return null;
|
|
3693
|
-
}
|
|
3694
|
-
function createTracking(options) {
|
|
3695
|
-
const {
|
|
3696
|
-
apiKey,
|
|
3697
|
-
endpoint,
|
|
3698
|
-
triggers,
|
|
3699
|
-
environment,
|
|
3700
|
-
gtagIds,
|
|
3701
|
-
debug,
|
|
3702
|
-
phone,
|
|
3703
|
-
conversionConfig,
|
|
3704
|
-
trackingConfig
|
|
3705
|
-
} = options;
|
|
3706
|
-
registerCapability("base_tracking");
|
|
3707
|
-
if (trackingConfig) registerCapability("conversion_goals_auto");
|
|
3708
|
-
if (!apiKey || !endpoint) {
|
|
3709
|
-
if (apiKey || endpoint) {
|
|
3710
|
-
console.warn(
|
|
3711
|
-
"[AranovaTracking] createTracking() requires both `apiKey` and `endpoint`. Tracking is disabled for this session."
|
|
3712
|
-
);
|
|
3713
|
-
}
|
|
3714
|
-
const noopClient = {
|
|
3715
|
-
trackEvent: () => {
|
|
3716
|
-
},
|
|
3717
|
-
flush: async () => {
|
|
3718
|
-
},
|
|
3719
|
-
getSessionId: () => "",
|
|
3720
|
-
getVisitorId: () => ""
|
|
3721
|
-
};
|
|
3722
|
-
return {
|
|
3723
|
-
TrackingProvider: ({ children }) => /* @__PURE__ */ jsx5(PhoneConfigProvider, { value: phone ?? null, children }),
|
|
3724
|
-
useTracking: () => noopClient
|
|
3725
|
-
};
|
|
3726
|
-
}
|
|
3727
|
-
const TrackingContext = createContext2(null);
|
|
3728
|
-
const specificPageVisitConfig = triggers.automatic.specific_page_visit ?? null;
|
|
3729
|
-
const timeOnSiteConfig = triggers.automatic.time_on_site ?? null;
|
|
3730
|
-
function TrackingProvider({ children }) {
|
|
3731
|
-
const pathname = usePathname();
|
|
3732
|
-
const rawClient = useMemo2(
|
|
3733
|
-
() => getOrCreateTrackingClient({
|
|
3734
|
-
apiKey,
|
|
3735
|
-
endpoint,
|
|
3736
|
-
surface: "next",
|
|
3737
|
-
packageName: "@aranova/tracking-next",
|
|
3738
|
-
sdkVersion: version,
|
|
3739
|
-
triggers,
|
|
3740
|
-
environment,
|
|
3741
|
-
activeGtagIds: gtagIds,
|
|
3742
|
-
debug
|
|
3743
|
-
}),
|
|
3744
|
-
[]
|
|
3745
|
-
);
|
|
3746
|
-
const conversionStore = useMemo2(
|
|
3747
|
-
() => trackingConfig ? getTrackingConfigRuntime(trackingConfig) : conversionConfig ? resolveConversionConfig({
|
|
3748
|
-
cdnUrl: conversionConfig.cdnUrl,
|
|
3749
|
-
baked: conversionConfig.baked
|
|
3750
|
-
}) : null,
|
|
3751
|
-
[]
|
|
3752
|
-
);
|
|
3753
|
-
const wrapClient = useMemo2(() => {
|
|
3754
|
-
const autoFire = conversionStore ? createConversionAutoFire(conversionStore) : null;
|
|
3755
|
-
return (c) => autoFire ? withConversionAutoFire(c, autoFire) : c;
|
|
3756
|
-
}, [conversionStore]);
|
|
3757
|
-
const client = useMemo2(
|
|
3758
|
-
() => createTypedClient(wrapClient(rawClient), triggers, { debug }),
|
|
3759
|
-
[rawClient, wrapClient]
|
|
3760
|
-
);
|
|
3761
|
-
useEffect4(() => {
|
|
3762
|
-
if (trackingConfig && conversionStore && "start" in conversionStore) {
|
|
3763
|
-
conversionStore.start();
|
|
3764
|
-
}
|
|
3765
|
-
}, [conversionStore]);
|
|
3766
|
-
const firePageView = useCallback3(() => {
|
|
3767
|
-
fireManualPageView(wrapClient(rawClient));
|
|
3768
|
-
if (trackingConfig) getTrackingConfigRuntime(trackingConfig).queuePageView();
|
|
3769
|
-
}, [rawClient, wrapClient]);
|
|
3770
|
-
const firedPagesRef = useRef(/* @__PURE__ */ new Set());
|
|
3771
|
-
useEffect4(() => {
|
|
3772
|
-
if (!specificPageVisitConfig || pathname === null) return;
|
|
3773
|
-
const detectorClient = wrapClient(rawClient);
|
|
3774
|
-
for (const { name, pathPattern } of specificPageVisitConfig.pages) {
|
|
3775
|
-
if (!pathPattern.test(pathname)) continue;
|
|
3776
|
-
const key = `${name}:${pathname}`;
|
|
3777
|
-
if (firedPagesRef.current.has(key)) continue;
|
|
3778
|
-
firedPagesRef.current.add(key);
|
|
3779
|
-
detectorClient.trackEvent({
|
|
3780
|
-
eventType: "specific_page_visit",
|
|
3781
|
-
metadata: {
|
|
3782
|
-
page_name: name,
|
|
3783
|
-
page: { path: pathname }
|
|
3784
|
-
},
|
|
3785
|
-
pageUrl: null,
|
|
3786
|
-
occurredAt: null
|
|
3787
|
-
});
|
|
3788
|
-
}
|
|
3789
|
-
}, [pathname, rawClient, wrapClient]);
|
|
3790
|
-
const multiPageSessionConfig = triggers.automatic.multi_page_session ?? null;
|
|
3791
|
-
const mpsLastPathRef = useRef(null);
|
|
3792
|
-
useEffect4(() => {
|
|
3793
|
-
if (!multiPageSessionConfig || pathname === null) return;
|
|
3794
|
-
if (pathname === mpsLastPathRef.current) return;
|
|
3795
|
-
mpsLastPathRef.current = pathname;
|
|
3796
|
-
const MPS_PATHS_KEY = "aranova_tracking_mps_paths";
|
|
3797
|
-
const MPS_SESSION_KEY = "aranova_tracking_mps_session";
|
|
3798
|
-
const MPS_FIRED_KEY = "aranova_tracking_mps_fired";
|
|
3799
|
-
try {
|
|
3800
|
-
const store = window.sessionStorage;
|
|
3801
|
-
const currentSession = getOrRotateSessionId().id;
|
|
3802
|
-
const storedSession = store.getItem(MPS_SESSION_KEY);
|
|
3803
|
-
if (storedSession !== currentSession) {
|
|
3804
|
-
store.setItem(MPS_SESSION_KEY, currentSession);
|
|
3805
|
-
store.removeItem(MPS_PATHS_KEY);
|
|
3806
|
-
store.removeItem(MPS_FIRED_KEY);
|
|
3807
|
-
}
|
|
3808
|
-
if (store.getItem(MPS_FIRED_KEY) === "1") return;
|
|
3809
|
-
const raw = store.getItem(MPS_PATHS_KEY);
|
|
3810
|
-
const paths = raw ? new Set(JSON.parse(raw)) : /* @__PURE__ */ new Set();
|
|
3811
|
-
paths.add(pathname);
|
|
3812
|
-
store.setItem(MPS_PATHS_KEY, JSON.stringify([...paths]));
|
|
3813
|
-
if (paths.size >= multiPageSessionConfig.pageThreshold) {
|
|
3814
|
-
store.setItem(MPS_FIRED_KEY, "1");
|
|
3815
|
-
wrapClient(rawClient).trackEvent({
|
|
3816
|
-
eventType: "multi_page_session",
|
|
3817
|
-
metadata: {
|
|
3818
|
-
page_count: paths.size,
|
|
3819
|
-
page: { path: pathname }
|
|
3820
|
-
},
|
|
3821
|
-
pageUrl: null,
|
|
3822
|
-
occurredAt: null
|
|
3823
|
-
});
|
|
3824
|
-
}
|
|
3825
|
-
} catch {
|
|
3826
|
-
}
|
|
3827
|
-
}, [multiPageSessionConfig, pathname, rawClient, wrapClient]);
|
|
3828
|
-
useEffect4(() => {
|
|
3829
|
-
return attachClientCapturesOnce(rawClient, () => {
|
|
3830
|
-
const detachers = [];
|
|
3831
|
-
const detectorClient = wrapClient(rawClient);
|
|
3832
|
-
detachers.push(attachPageExit(detectorClient));
|
|
3833
|
-
detachers.push(attachBfcacheRestore(detectorClient));
|
|
3834
|
-
if (timeOnSiteConfig) {
|
|
3835
|
-
detachers.push(attachTimeOnSite(detectorClient, timeOnSiteConfig));
|
|
3836
|
-
}
|
|
3837
|
-
const scrollDepth = triggers.automatic.scroll_depth;
|
|
3838
|
-
if (scrollDepth) {
|
|
3839
|
-
detachers.push(attachScrollDepth(detectorClient, scrollDepth));
|
|
3840
|
-
}
|
|
3841
|
-
const formStart = triggers.automatic.form_start;
|
|
3842
|
-
if (formStart) {
|
|
3843
|
-
detachers.push(attachFormStart(detectorClient, formStart));
|
|
3844
|
-
}
|
|
3845
|
-
const ctaClick = triggers.manual?.cta_click;
|
|
3846
|
-
if (ctaClick) {
|
|
3847
|
-
detachers.push(attachCtaClickCapture(detectorClient, ctaClick));
|
|
3848
|
-
}
|
|
3849
|
-
const phoneClick = triggers.manual?.phone_click;
|
|
3850
|
-
if (phoneClick) {
|
|
3851
|
-
detachers.push(attachPhoneClickCapture(detectorClient, phoneClick));
|
|
3852
|
-
}
|
|
3853
|
-
return () => {
|
|
3854
|
-
for (let i = detachers.length - 1; i >= 0; i--) {
|
|
3855
|
-
detachers[i]();
|
|
3856
|
-
}
|
|
3857
|
-
};
|
|
3858
|
-
});
|
|
3859
|
-
}, [rawClient, wrapClient]);
|
|
3860
|
-
return /* @__PURE__ */ jsxs4(TrackingContext.Provider, { value: client, children: [
|
|
3861
|
-
/* @__PURE__ */ jsx5(Suspense, { fallback: null, children: /* @__PURE__ */ jsx5(PageViewTracker, { fire: firePageView }) }),
|
|
3862
|
-
/* @__PURE__ */ jsx5(PhoneConfigProvider, { value: phone ?? null, children })
|
|
3863
|
-
] });
|
|
3864
|
-
}
|
|
3865
|
-
function useTracking() {
|
|
3866
|
-
const client = useContext2(TrackingContext);
|
|
3867
|
-
if (client === null) {
|
|
3868
|
-
throw new Error(
|
|
3869
|
-
"useTracking must be called inside a <TrackingProvider> returned by createTracking()"
|
|
3870
|
-
);
|
|
3871
|
-
}
|
|
3872
|
-
return client;
|
|
3873
|
-
}
|
|
3874
|
-
return { TrackingProvider, useTracking };
|
|
3875
|
-
}
|
|
1986
|
+
AdPlatformTracking,
|
|
1987
|
+
ConsentBanner,
|
|
1988
|
+
createTracking,
|
|
1989
|
+
GoogleAdsTracking,
|
|
1990
|
+
useConsent,
|
|
1991
|
+
useConsentState,
|
|
1992
|
+
useCookiePreferences,
|
|
1993
|
+
useGclid,
|
|
1994
|
+
useTrackingParams
|
|
1995
|
+
} from "@aranova/tracking-next/client";
|
|
3876
1996
|
|
|
3877
1997
|
// ../tracking-core/src/resources/calendar/transport.ts
|
|
3878
1998
|
async function calendarRequest(config, method, path, body) {
|
|
@@ -4196,21 +2316,21 @@ function groupSlotsByDay(slots, timeZone) {
|
|
|
4196
2316
|
}
|
|
4197
2317
|
|
|
4198
2318
|
// ../tracking-core/src/calendar-react.tsx
|
|
4199
|
-
import { createContext
|
|
4200
|
-
import { jsx
|
|
2319
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
|
|
2320
|
+
import { jsx } from "react/jsx-runtime";
|
|
4201
2321
|
var _calendarClientContext;
|
|
4202
2322
|
function calendarClientContext() {
|
|
4203
|
-
return _calendarClientContext ?? (_calendarClientContext =
|
|
2323
|
+
return _calendarClientContext ?? (_calendarClientContext = createContext(null));
|
|
4204
2324
|
}
|
|
4205
2325
|
function CalendarClientProvider({
|
|
4206
2326
|
value,
|
|
4207
2327
|
children
|
|
4208
2328
|
}) {
|
|
4209
2329
|
const Ctx = calendarClientContext();
|
|
4210
|
-
return /* @__PURE__ */
|
|
2330
|
+
return /* @__PURE__ */ jsx(Ctx.Provider, { value, children });
|
|
4211
2331
|
}
|
|
4212
2332
|
function useCalendarClient() {
|
|
4213
|
-
const client =
|
|
2333
|
+
const client = useContext(calendarClientContext());
|
|
4214
2334
|
if (!client) {
|
|
4215
2335
|
throw new Error(
|
|
4216
2336
|
"useCalendarClient requires <CalendarClientProvider>. Wire it via createTracking({ calendar })."
|
|
@@ -4220,12 +2340,12 @@ function useCalendarClient() {
|
|
|
4220
2340
|
}
|
|
4221
2341
|
function useCalendarBusy(calendarKey, window2) {
|
|
4222
2342
|
const client = useCalendarClient();
|
|
4223
|
-
const [busy, setBusy] =
|
|
4224
|
-
const [timeZone, setTimeZone] =
|
|
4225
|
-
const [isLoading, setIsLoading] =
|
|
4226
|
-
const [error, setError] =
|
|
4227
|
-
const [nonce, setNonce] =
|
|
4228
|
-
|
|
2343
|
+
const [busy, setBusy] = useState([]);
|
|
2344
|
+
const [timeZone, setTimeZone] = useState(resolveBrowserTimeZone());
|
|
2345
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
2346
|
+
const [error, setError] = useState(null);
|
|
2347
|
+
const [nonce, setNonce] = useState(0);
|
|
2348
|
+
useEffect(() => {
|
|
4229
2349
|
const controller = new AbortController();
|
|
4230
2350
|
setIsLoading(true);
|
|
4231
2351
|
client.busy(calendarKey, { since: window2.since, until: window2.until }).then((response) => {
|
|
@@ -4241,22 +2361,22 @@ function useCalendarBusy(calendarKey, window2) {
|
|
|
4241
2361
|
});
|
|
4242
2362
|
return () => controller.abort();
|
|
4243
2363
|
}, [client, calendarKey, window2.since, window2.until, nonce]);
|
|
4244
|
-
const refetch =
|
|
2364
|
+
const refetch = useCallback(() => setNonce((value) => value + 1), []);
|
|
4245
2365
|
return { busy, timeZone, isLoading, error, refetch };
|
|
4246
2366
|
}
|
|
4247
2367
|
function useSlots(busy, timeZone, options) {
|
|
4248
2368
|
const zone = options.timeZone ?? timeZone;
|
|
4249
|
-
return
|
|
2369
|
+
return useMemo(() => {
|
|
4250
2370
|
const { slots, nextAvailableAt } = computeSlots({ ...options, busy, timeZone: zone });
|
|
4251
2371
|
return { slots, days: groupSlotsByDay(slots, zone), nextAvailableAt };
|
|
4252
2372
|
}, [busy, zone, options]);
|
|
4253
2373
|
}
|
|
4254
2374
|
function useBookingForm(options = {}) {
|
|
4255
2375
|
const endpoint = options.endpoint ?? "/api/aranova/calendar/bookings";
|
|
4256
|
-
const [status, setStatus] =
|
|
4257
|
-
const [error, setError] =
|
|
4258
|
-
const [booking, setBooking] =
|
|
4259
|
-
const submit =
|
|
2376
|
+
const [status, setStatus] = useState("idle");
|
|
2377
|
+
const [error, setError] = useState(null);
|
|
2378
|
+
const [booking, setBooking] = useState(null);
|
|
2379
|
+
const submit = useCallback(
|
|
4260
2380
|
async (input) => {
|
|
4261
2381
|
setStatus("submitting");
|
|
4262
2382
|
setError(null);
|
|
@@ -4281,13 +2401,20 @@ function useBookingForm(options = {}) {
|
|
|
4281
2401
|
},
|
|
4282
2402
|
[endpoint, options]
|
|
4283
2403
|
);
|
|
4284
|
-
const reset =
|
|
2404
|
+
const reset = useCallback(() => {
|
|
4285
2405
|
setStatus("idle");
|
|
4286
2406
|
setError(null);
|
|
4287
2407
|
setBooking(null);
|
|
4288
2408
|
}, []);
|
|
4289
2409
|
return { status, error, booking, submit, reset };
|
|
4290
2410
|
}
|
|
2411
|
+
|
|
2412
|
+
// src/index.ts
|
|
2413
|
+
import {
|
|
2414
|
+
PhoneField,
|
|
2415
|
+
usePhoneConfig,
|
|
2416
|
+
usePhoneField
|
|
2417
|
+
} from "@aranova/tracking-next/client";
|
|
4291
2418
|
export {
|
|
4292
2419
|
AdPlatformTracking,
|
|
4293
2420
|
AranovaApiError,
|