@aranova/tracking-react 0.14.2 → 0.16.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 +63 -46
- package/dist/index.d.mts +225 -103
- package/dist/index.d.ts +225 -103
- package/dist/index.js +474 -144
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +468 -144
- package/dist/index.mjs.map +1 -1
- package/dist/{phone-utils-Dyk0F14_.d.mts → phone-utils-DlAQK-gU.d.mts} +127 -6
- package/dist/{phone-utils-Dyk0F14_.d.ts → phone-utils-DlAQK-gU.d.ts} +127 -6
- package/dist/phone.d.mts +1 -1
- package/dist/phone.d.ts +1 -1
- package/dist/phone.js +88 -135
- package/dist/phone.js.map +1 -1
- package/dist/phone.mjs +88 -135
- package/dist/phone.mjs.map +1 -1
- package/dist/sales.js +33 -29
- package/dist/sales.js.map +1 -1
- package/dist/sales.mjs +33 -29
- package/dist/sales.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23,6 +23,7 @@ __export(src_exports, {
|
|
|
23
23
|
AdPlatformTracking: () => AdPlatformTracking,
|
|
24
24
|
AranovaApiError: () => AranovaApiError,
|
|
25
25
|
ConsentBanner: () => ConsentBanner,
|
|
26
|
+
DEFAULT_DECLINE_TTL_DAYS: () => DEFAULT_DECLINE_TTL_DAYS,
|
|
26
27
|
DEFAULT_PHONE_COUNTRY: () => DEFAULT_PHONE_COUNTRY,
|
|
27
28
|
GoogleAdsTracking: () => GoogleAdsTracking,
|
|
28
29
|
NAMED_RANGES: () => NAMED_RANGES,
|
|
@@ -42,7 +43,11 @@ __export(src_exports, {
|
|
|
42
43
|
formatPhone: () => formatPhone,
|
|
43
44
|
formatPhoneAsTyped: () => formatPhoneAsTyped,
|
|
44
45
|
fromMinor: () => fromMinor,
|
|
46
|
+
getConsentChoice: () => getConsentChoice,
|
|
45
47
|
getConsentState: () => getConsentState,
|
|
48
|
+
onConsentChange: () => onConsentChange,
|
|
49
|
+
optIn: () => optIn,
|
|
50
|
+
optOut: () => optOut,
|
|
46
51
|
parsePhone: () => parsePhone,
|
|
47
52
|
phoneField: () => phoneField,
|
|
48
53
|
resetConsent: () => resetConsent,
|
|
@@ -57,6 +62,7 @@ __export(src_exports, {
|
|
|
57
62
|
toMinor: () => toMinor,
|
|
58
63
|
useConsent: () => useConsent,
|
|
59
64
|
useConsentState: () => useConsentState,
|
|
65
|
+
useCookiePreferences: () => useCookiePreferences,
|
|
60
66
|
useGclid: () => useGclid,
|
|
61
67
|
usePhoneConfig: () => usePhoneConfig,
|
|
62
68
|
usePhoneField: () => usePhoneField,
|
|
@@ -73,13 +79,30 @@ var import_react = require("react");
|
|
|
73
79
|
// ../tracking-core/src/consent.ts
|
|
74
80
|
var CONSENT_STATE_KEY = "consent_state";
|
|
75
81
|
var CONSENT_TIMESTAMP_KEY = "consent_timestamp";
|
|
76
|
-
var
|
|
77
|
-
|
|
78
|
-
|
|
82
|
+
var CONSENT_EXPIRES_AT_KEY = "consent_expires_at";
|
|
83
|
+
var DEFAULT_DECLINE_TTL_DAYS = 90;
|
|
84
|
+
var DAY_MS = 864e5;
|
|
85
|
+
var DEFAULT_CHOICE = {
|
|
86
|
+
state: "granted",
|
|
87
|
+
source: "default",
|
|
88
|
+
updatedAt: null,
|
|
89
|
+
expiresAt: null
|
|
90
|
+
};
|
|
91
|
+
var changeListeners = /* @__PURE__ */ new Set();
|
|
92
|
+
function onConsentChange(listener) {
|
|
93
|
+
changeListeners.add(listener);
|
|
79
94
|
return () => {
|
|
80
|
-
|
|
95
|
+
changeListeners.delete(listener);
|
|
81
96
|
};
|
|
82
97
|
}
|
|
98
|
+
function notifyConsentChanged(choice) {
|
|
99
|
+
for (const listener of changeListeners) {
|
|
100
|
+
try {
|
|
101
|
+
listener(choice);
|
|
102
|
+
} catch {
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
83
106
|
function buildConsentPayload(state) {
|
|
84
107
|
return {
|
|
85
108
|
ad_storage: state,
|
|
@@ -88,47 +111,74 @@ function buildConsentPayload(state) {
|
|
|
88
111
|
analytics_storage: state
|
|
89
112
|
};
|
|
90
113
|
}
|
|
91
|
-
function
|
|
92
|
-
if (typeof window === "undefined") return
|
|
114
|
+
function getConsentChoice() {
|
|
115
|
+
if (typeof window === "undefined") return DEFAULT_CHOICE;
|
|
93
116
|
try {
|
|
94
|
-
const
|
|
95
|
-
|
|
117
|
+
const stored = window.localStorage.getItem(CONSENT_STATE_KEY);
|
|
118
|
+
const updatedAt = window.localStorage.getItem(CONSENT_TIMESTAMP_KEY);
|
|
119
|
+
if (stored === "granted")
|
|
120
|
+
return { state: "granted", source: "explicit", updatedAt, expiresAt: null };
|
|
121
|
+
if (stored === "denied") {
|
|
122
|
+
let expiresAt = window.localStorage.getItem(CONSENT_EXPIRES_AT_KEY);
|
|
123
|
+
if (!expiresAt) {
|
|
124
|
+
expiresAt = new Date(Date.now() + DEFAULT_DECLINE_TTL_DAYS * DAY_MS).toISOString();
|
|
125
|
+
try {
|
|
126
|
+
window.localStorage.setItem(CONSENT_EXPIRES_AT_KEY, expiresAt);
|
|
127
|
+
} catch {
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (!(Date.parse(expiresAt) <= Date.now()))
|
|
131
|
+
return { state: "denied", source: "explicit", updatedAt, expiresAt };
|
|
132
|
+
}
|
|
96
133
|
} catch {
|
|
97
134
|
}
|
|
98
|
-
return
|
|
135
|
+
return DEFAULT_CHOICE;
|
|
99
136
|
}
|
|
100
|
-
function
|
|
137
|
+
function getConsentState() {
|
|
138
|
+
return getConsentChoice().state;
|
|
139
|
+
}
|
|
140
|
+
function pushConsentToPlatforms(state) {
|
|
101
141
|
if (typeof window === "undefined") return;
|
|
102
|
-
try {
|
|
103
|
-
window.localStorage.setItem(CONSENT_STATE_KEY, state);
|
|
104
|
-
window.localStorage.setItem(CONSENT_TIMESTAMP_KEY, (/* @__PURE__ */ new Date()).toISOString());
|
|
105
|
-
} catch {
|
|
106
|
-
}
|
|
107
142
|
if (typeof window.gtag === "function")
|
|
108
143
|
window.gtag("consent", "update", buildConsentPayload(state));
|
|
109
144
|
if (typeof window.fbq === "function")
|
|
110
145
|
window.fbq("consent", state === "granted" ? "grant" : "revoke");
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
146
|
+
}
|
|
147
|
+
function setConsentState(state, options) {
|
|
148
|
+
if (typeof window === "undefined") return;
|
|
149
|
+
const requestedTtl = options?.declineTtlDays;
|
|
150
|
+
const ttlDays = typeof requestedTtl === "number" && Number.isFinite(requestedTtl) && requestedTtl > 0 ? requestedTtl : DEFAULT_DECLINE_TTL_DAYS;
|
|
151
|
+
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
152
|
+
const expiresAt = state === "denied" ? new Date(Date.now() + ttlDays * DAY_MS).toISOString() : null;
|
|
153
|
+
try {
|
|
154
|
+
window.localStorage.setItem(CONSENT_STATE_KEY, state);
|
|
155
|
+
window.localStorage.setItem(CONSENT_TIMESTAMP_KEY, updatedAt);
|
|
156
|
+
if (expiresAt !== null) {
|
|
157
|
+
window.localStorage.setItem(CONSENT_EXPIRES_AT_KEY, expiresAt);
|
|
158
|
+
} else {
|
|
159
|
+
window.localStorage.removeItem(CONSENT_EXPIRES_AT_KEY);
|
|
117
160
|
}
|
|
161
|
+
} catch {
|
|
118
162
|
}
|
|
163
|
+
pushConsentToPlatforms(state);
|
|
164
|
+
notifyConsentChanged({ state, source: "explicit", updatedAt, expiresAt });
|
|
165
|
+
}
|
|
166
|
+
function optIn() {
|
|
167
|
+
setConsentState("granted");
|
|
168
|
+
}
|
|
169
|
+
function optOut(options) {
|
|
170
|
+
setConsentState("denied", options);
|
|
119
171
|
}
|
|
120
172
|
function resetConsent() {
|
|
121
173
|
if (typeof window === "undefined") return;
|
|
122
174
|
try {
|
|
123
175
|
window.localStorage.removeItem(CONSENT_STATE_KEY);
|
|
124
176
|
window.localStorage.removeItem(CONSENT_TIMESTAMP_KEY);
|
|
177
|
+
window.localStorage.removeItem(CONSENT_EXPIRES_AT_KEY);
|
|
125
178
|
} catch {
|
|
126
179
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const consentState = getConsentState();
|
|
130
|
-
if (consentState === "granted" || consentState === "denied") setConsentState(consentState);
|
|
131
|
-
return consentState;
|
|
180
|
+
pushConsentToPlatforms("granted");
|
|
181
|
+
notifyConsentChanged(DEFAULT_CHOICE);
|
|
132
182
|
}
|
|
133
183
|
|
|
134
184
|
// ../tracking-core/src/tracking.ts
|
|
@@ -272,13 +322,11 @@ function fireGtagConversion(input) {
|
|
|
272
322
|
}
|
|
273
323
|
function applyDefaultConsentState() {
|
|
274
324
|
const gtag = ensureGtagFunction();
|
|
275
|
-
gtag(
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
wait_for_update: 500
|
|
281
|
-
});
|
|
325
|
+
gtag(
|
|
326
|
+
"consent",
|
|
327
|
+
"default",
|
|
328
|
+
buildConsentPayload(getConsentState() === "denied" ? "denied" : "granted")
|
|
329
|
+
);
|
|
282
330
|
}
|
|
283
331
|
function loadGtagScript(gtagId) {
|
|
284
332
|
if (typeof document === "undefined") return;
|
|
@@ -304,7 +352,6 @@ function bootstrapGoogleAdsTracking(gtagId) {
|
|
|
304
352
|
applyDefaultConsentState();
|
|
305
353
|
loadGtagScript(gtagId);
|
|
306
354
|
initializeGtag(gtagId);
|
|
307
|
-
restoreStoredConsent();
|
|
308
355
|
}
|
|
309
356
|
function bootstrapMultipleGtags(gtagIds) {
|
|
310
357
|
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
@@ -319,7 +366,6 @@ function bootstrapMultipleGtags(gtagIds) {
|
|
|
319
366
|
for (const id of ids) {
|
|
320
367
|
gtag("config", id);
|
|
321
368
|
}
|
|
322
|
-
restoreStoredConsent();
|
|
323
369
|
}
|
|
324
370
|
|
|
325
371
|
// ../tracking-core/src/fbq.ts
|
|
@@ -379,7 +425,7 @@ function ensureFbqFunction() {
|
|
|
379
425
|
return fbq;
|
|
380
426
|
}
|
|
381
427
|
function applyDefaultMetaConsentState() {
|
|
382
|
-
ensureFbqFunction()("consent", "revoke");
|
|
428
|
+
ensureFbqFunction()("consent", getConsentState() === "denied" ? "revoke" : "grant");
|
|
383
429
|
}
|
|
384
430
|
function loadFbeventsScript() {
|
|
385
431
|
if (typeof document === "undefined") return;
|
|
@@ -399,19 +445,12 @@ function initializeMetaPixel(pixelId) {
|
|
|
399
445
|
fbq("init", pixelId);
|
|
400
446
|
fbq("track", "PageView");
|
|
401
447
|
}
|
|
402
|
-
function restoreMetaConsentState() {
|
|
403
|
-
if (typeof window === "undefined") return;
|
|
404
|
-
const state = getConsentState();
|
|
405
|
-
if (state === "granted") window.fbq?.("consent", "grant");
|
|
406
|
-
else if (state === "denied") window.fbq?.("consent", "revoke");
|
|
407
|
-
}
|
|
408
448
|
function bootstrapMetaPixel(pixelId) {
|
|
409
449
|
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
410
450
|
if (!isValidMetaPixelId(pixelId)) return;
|
|
411
451
|
applyDefaultMetaConsentState();
|
|
412
452
|
loadFbeventsScript();
|
|
413
453
|
initializeMetaPixel(pixelId);
|
|
414
|
-
restoreMetaConsentState();
|
|
415
454
|
captureFbc();
|
|
416
455
|
}
|
|
417
456
|
function bootstrapMultiplePixels(pixelIds) {
|
|
@@ -427,10 +466,75 @@ function bootstrapMultiplePixels(pixelIds) {
|
|
|
427
466
|
fbq("init", id);
|
|
428
467
|
}
|
|
429
468
|
fbq("track", "PageView");
|
|
430
|
-
restoreMetaConsentState();
|
|
431
469
|
captureFbc();
|
|
432
470
|
}
|
|
433
471
|
|
|
472
|
+
// ../tracking-core/src/landing.ts
|
|
473
|
+
var LANDING_STORAGE_KEY = "_aranova_track_landing";
|
|
474
|
+
var memoryRecord = null;
|
|
475
|
+
function sanitizeParams(value) {
|
|
476
|
+
if (typeof value !== "object" || value === null) return {};
|
|
477
|
+
const source = value;
|
|
478
|
+
return TRACKING_PARAM_KEYS.reduce((params, key) => {
|
|
479
|
+
const entry = source[key];
|
|
480
|
+
if (typeof entry === "string" && entry.length > 0) params[key] = entry;
|
|
481
|
+
return params;
|
|
482
|
+
}, {});
|
|
483
|
+
}
|
|
484
|
+
function readStoredRecord() {
|
|
485
|
+
try {
|
|
486
|
+
const raw = window.localStorage.getItem(LANDING_STORAGE_KEY);
|
|
487
|
+
if (!raw) return null;
|
|
488
|
+
const parsed = JSON.parse(raw);
|
|
489
|
+
if (typeof parsed.session_id !== "string" || parsed.session_id.length === 0) return null;
|
|
490
|
+
return { session_id: parsed.session_id, params: sanitizeParams(parsed.params) };
|
|
491
|
+
} catch {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
function writeRecord(record) {
|
|
496
|
+
memoryRecord = record;
|
|
497
|
+
try {
|
|
498
|
+
window.localStorage.setItem(LANDING_STORAGE_KEY, JSON.stringify(record));
|
|
499
|
+
} catch {
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
function captureFromUrl(url) {
|
|
503
|
+
try {
|
|
504
|
+
const resolved = new URL(url ?? window.location.href, window.location.origin);
|
|
505
|
+
return getTrackingQueryValues(resolved.searchParams);
|
|
506
|
+
} catch {
|
|
507
|
+
return {};
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
function getOrCaptureLandingParams(sessionId, url) {
|
|
511
|
+
if (typeof window === "undefined") return {};
|
|
512
|
+
const stored = readStoredRecord();
|
|
513
|
+
if (stored && stored.session_id === sessionId) {
|
|
514
|
+
memoryRecord = stored;
|
|
515
|
+
return stored.params;
|
|
516
|
+
}
|
|
517
|
+
if (memoryRecord && memoryRecord.session_id === sessionId) {
|
|
518
|
+
return memoryRecord.params;
|
|
519
|
+
}
|
|
520
|
+
const record = { session_id: sessionId, params: captureFromUrl(url) };
|
|
521
|
+
writeRecord(record);
|
|
522
|
+
return record.params;
|
|
523
|
+
}
|
|
524
|
+
function buildLandingPayloadFields(sessionId, override) {
|
|
525
|
+
const params = override ?? (typeof window === "undefined" ? null : getOrCaptureLandingParams(sessionId));
|
|
526
|
+
if (params === null) return {};
|
|
527
|
+
return {
|
|
528
|
+
landing_gclid: params.gclid ?? null,
|
|
529
|
+
landing_fbclid: params.fbclid ?? null,
|
|
530
|
+
landing_utm_source: params.utm_source ?? null,
|
|
531
|
+
landing_utm_medium: params.utm_medium ?? null,
|
|
532
|
+
landing_utm_campaign: params.utm_campaign ?? null,
|
|
533
|
+
landing_utm_term: params.utm_term ?? null,
|
|
534
|
+
landing_utm_content: params.utm_content ?? null
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
|
|
434
538
|
// ../tracking-core/src/payloads.ts
|
|
435
539
|
function createTrackingClientContext(surface, input = {}) {
|
|
436
540
|
return {
|
|
@@ -457,6 +561,9 @@ function createTrackingSessionUpsertPayload(trackingParams, input, context) {
|
|
|
457
561
|
utm_campaign: trackingParams.utm_campaign,
|
|
458
562
|
utm_term: trackingParams.utm_term,
|
|
459
563
|
utm_content: trackingParams.utm_content,
|
|
564
|
+
// Omitted entirely when the landing isn't observable (SSR, no override) —
|
|
565
|
+
// present-as-null would wrongly tell the backend "landed with no params".
|
|
566
|
+
...buildLandingPayloadFields(input.sessionId, input.landingParams),
|
|
460
567
|
first_page: input.firstPage ?? null,
|
|
461
568
|
consent_state: input.consentState ?? null,
|
|
462
569
|
context
|
|
@@ -478,8 +585,6 @@ function createTrackingEventCreatePayload(trackingParams, input, context) {
|
|
|
478
585
|
|
|
479
586
|
// ../tracking-core/src/resources/conversion-firing.ts
|
|
480
587
|
var DEDUP_PREFIX = "_aranova_conv_";
|
|
481
|
-
var MAX_PENDING = 100;
|
|
482
|
-
var pendingQueue = [];
|
|
483
588
|
function dedupKey(input) {
|
|
484
589
|
return `${DEDUP_PREFIX}${input.transactionId ?? ""}:${input.sendTo}`;
|
|
485
590
|
}
|
|
@@ -503,23 +608,9 @@ function fireOnce(input) {
|
|
|
503
608
|
if (fireGtagConversion(input)) markFired(input);
|
|
504
609
|
}
|
|
505
610
|
function fireConversionWithConsent(input) {
|
|
506
|
-
|
|
507
|
-
if (state === "denied") return;
|
|
508
|
-
if (state === "pending") {
|
|
509
|
-
if (pendingQueue.length >= MAX_PENDING) pendingQueue.shift();
|
|
510
|
-
pendingQueue.push(input);
|
|
511
|
-
return;
|
|
512
|
-
}
|
|
611
|
+
if (getConsentState() === "denied") return;
|
|
513
612
|
fireOnce(input);
|
|
514
613
|
}
|
|
515
|
-
function flushPendingConversions() {
|
|
516
|
-
if (getConsentState() !== "granted") return;
|
|
517
|
-
while (pendingQueue.length > 0) {
|
|
518
|
-
const input = pendingQueue.shift();
|
|
519
|
-
if (input) fireOnce(input);
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
if (typeof window !== "undefined") onConsentGranted(flushPendingConversions);
|
|
523
614
|
|
|
524
615
|
// ../tracking-core/src/resources/conversion-config.ts
|
|
525
616
|
function isStringMap(value) {
|
|
@@ -1065,7 +1156,13 @@ function readTrackingParams() {
|
|
|
1065
1156
|
}
|
|
1066
1157
|
function consentSnapshot() {
|
|
1067
1158
|
try {
|
|
1068
|
-
|
|
1159
|
+
const choice = getConsentChoice();
|
|
1160
|
+
return {
|
|
1161
|
+
state: choice.state,
|
|
1162
|
+
source: choice.source,
|
|
1163
|
+
updated_at: choice.updatedAt,
|
|
1164
|
+
expires_at: choice.expiresAt
|
|
1165
|
+
};
|
|
1069
1166
|
} catch {
|
|
1070
1167
|
return null;
|
|
1071
1168
|
}
|
|
@@ -1138,6 +1235,7 @@ function createTrackingClient(config) {
|
|
|
1138
1235
|
initialParams = captureTrackingParamsFromLocation();
|
|
1139
1236
|
} catch {
|
|
1140
1237
|
}
|
|
1238
|
+
getOrCaptureLandingParams(sessionId);
|
|
1141
1239
|
try {
|
|
1142
1240
|
captureFbc();
|
|
1143
1241
|
} catch {
|
|
@@ -1187,6 +1285,11 @@ function createTrackingClient(config) {
|
|
|
1187
1285
|
utm_campaign: params.utm_campaign,
|
|
1188
1286
|
utm_term: params.utm_term,
|
|
1189
1287
|
utm_content: params.utm_content,
|
|
1288
|
+
// Landing params for the CURRENT session id — captured on the spot when
|
|
1289
|
+
// the session just rotated (the current URL is the rotated session's
|
|
1290
|
+
// landing), reused from the stored record otherwise. Keys are omitted
|
|
1291
|
+
// entirely when the landing isn't observable (SSR).
|
|
1292
|
+
...buildLandingPayloadFields(sessionId),
|
|
1190
1293
|
first_page: firstPage,
|
|
1191
1294
|
consent_state: consentSnapshot(),
|
|
1192
1295
|
context
|
|
@@ -1254,6 +1357,7 @@ function createTrackingClient(config) {
|
|
|
1254
1357
|
return {
|
|
1255
1358
|
trackEvent,
|
|
1256
1359
|
flush,
|
|
1360
|
+
flushBeacon: flushOnUnload,
|
|
1257
1361
|
getSessionId: () => sessionId,
|
|
1258
1362
|
getVisitorId: () => visitorId,
|
|
1259
1363
|
destroy: () => {
|
|
@@ -1278,9 +1382,17 @@ var ctaClickMetadataSchema = import_zod2.z.object({
|
|
|
1278
1382
|
path: import_zod2.z.string()
|
|
1279
1383
|
}).strict(),
|
|
1280
1384
|
section: import_zod2.z.string().nullable().optional(),
|
|
1281
|
-
destination_url: import_zod2.z.string().nullable().optional()
|
|
1385
|
+
destination_url: import_zod2.z.string().nullable().optional(),
|
|
1386
|
+
// Set by auto-capture (and available to manual callers): the link target
|
|
1387
|
+
// and a short element descriptor (tag#id) for tying clicks to specific UI.
|
|
1388
|
+
href: import_zod2.z.string().nullable().optional(),
|
|
1389
|
+
element: import_zod2.z.string().nullable().optional()
|
|
1390
|
+
}).strict();
|
|
1391
|
+
var ctaClickConfigSchema = import_zod2.z.object({
|
|
1392
|
+
autoCapture: import_zod2.z.object({
|
|
1393
|
+
selector: import_zod2.z.string().optional()
|
|
1394
|
+
}).strict().optional()
|
|
1282
1395
|
}).strict();
|
|
1283
|
-
var ctaClickConfigSchema = import_zod2.z.object({}).strict();
|
|
1284
1396
|
|
|
1285
1397
|
// ../tracking-core/src/events/sdk-heartbeat.ts
|
|
1286
1398
|
var import_zod3 = require("zod");
|
|
@@ -1356,31 +1468,44 @@ var multiPageSessionConfigSchema = import_zod6.z.object({
|
|
|
1356
1468
|
pageThreshold: import_zod6.z.number().int().min(2)
|
|
1357
1469
|
}).strict();
|
|
1358
1470
|
|
|
1359
|
-
// ../tracking-core/src/events/
|
|
1471
|
+
// ../tracking-core/src/events/page-exit.ts
|
|
1360
1472
|
var import_zod7 = require("zod");
|
|
1361
|
-
var
|
|
1362
|
-
|
|
1473
|
+
var pageExitMetadataSchema = import_zod7.z.object({
|
|
1474
|
+
dwell_ms: import_zod7.z.number().int().min(0),
|
|
1475
|
+
// null = left without any scroll signal; floor is 0 so a valid 0% is never
|
|
1476
|
+
// rejected (a single bad field 422s the whole keepalive beacon batch).
|
|
1477
|
+
max_scroll_percent: import_zod7.z.number().int().min(0).max(100).nullable(),
|
|
1363
1478
|
page: import_zod7.z.object({
|
|
1364
1479
|
path: import_zod7.z.string()
|
|
1365
|
-
}).strict()
|
|
1366
|
-
section: import_zod7.z.string().nullable().optional()
|
|
1480
|
+
}).strict()
|
|
1367
1481
|
}).strict();
|
|
1368
|
-
var
|
|
1482
|
+
var pageExitConfigSchema = import_zod7.z.object({}).strict();
|
|
1369
1483
|
|
|
1370
|
-
// ../tracking-core/src/events/
|
|
1484
|
+
// ../tracking-core/src/events/phone-click.ts
|
|
1371
1485
|
var import_zod8 = require("zod");
|
|
1372
|
-
var
|
|
1373
|
-
|
|
1486
|
+
var phoneClickMetadataSchema = import_zod8.z.object({
|
|
1487
|
+
phone_number: import_zod8.z.string(),
|
|
1374
1488
|
page: import_zod8.z.object({
|
|
1375
1489
|
path: import_zod8.z.string()
|
|
1490
|
+
}).strict(),
|
|
1491
|
+
section: import_zod8.z.string().nullable().optional()
|
|
1492
|
+
}).strict();
|
|
1493
|
+
var phoneClickConfigSchema = import_zod8.z.object({}).strict();
|
|
1494
|
+
|
|
1495
|
+
// ../tracking-core/src/events/scroll-depth.ts
|
|
1496
|
+
var import_zod9 = require("zod");
|
|
1497
|
+
var scrollDepthMetadataSchema = import_zod9.z.object({
|
|
1498
|
+
depth_percent: import_zod9.z.number().int().min(1).max(100),
|
|
1499
|
+
page: import_zod9.z.object({
|
|
1500
|
+
path: import_zod9.z.string()
|
|
1376
1501
|
}).strict()
|
|
1377
1502
|
}).strict();
|
|
1378
|
-
var scrollDepthConfigSchema =
|
|
1379
|
-
thresholds:
|
|
1503
|
+
var scrollDepthConfigSchema = import_zod9.z.object({
|
|
1504
|
+
thresholds: import_zod9.z.array(import_zod9.z.number().int().min(1).max(100)).min(1)
|
|
1380
1505
|
}).strict();
|
|
1381
1506
|
|
|
1382
1507
|
// ../tracking-core/src/events/specific-page-visit.ts
|
|
1383
|
-
var
|
|
1508
|
+
var import_zod10 = require("zod");
|
|
1384
1509
|
var SPECIFIC_PAGE_NAMES = [
|
|
1385
1510
|
"contact_page",
|
|
1386
1511
|
"about_page",
|
|
@@ -1391,18 +1516,18 @@ var SPECIFIC_PAGE_NAMES = [
|
|
|
1391
1516
|
"faq_page",
|
|
1392
1517
|
"testimonials_page"
|
|
1393
1518
|
];
|
|
1394
|
-
var specificPageNameSchema =
|
|
1395
|
-
var specificPageVisitMetadataSchema =
|
|
1519
|
+
var specificPageNameSchema = import_zod10.z.enum(SPECIFIC_PAGE_NAMES);
|
|
1520
|
+
var specificPageVisitMetadataSchema = import_zod10.z.object({
|
|
1396
1521
|
page_name: specificPageNameSchema,
|
|
1397
|
-
page:
|
|
1398
|
-
path:
|
|
1522
|
+
page: import_zod10.z.object({
|
|
1523
|
+
path: import_zod10.z.string()
|
|
1399
1524
|
}).strict()
|
|
1400
1525
|
}).strict();
|
|
1401
|
-
var specificPageVisitConfigSchema =
|
|
1402
|
-
pages:
|
|
1403
|
-
|
|
1526
|
+
var specificPageVisitConfigSchema = import_zod10.z.object({
|
|
1527
|
+
pages: import_zod10.z.array(
|
|
1528
|
+
import_zod10.z.object({
|
|
1404
1529
|
name: specificPageNameSchema,
|
|
1405
|
-
pathPattern:
|
|
1530
|
+
pathPattern: import_zod10.z.custom((value) => value instanceof RegExp, {
|
|
1406
1531
|
message: "pathPattern must be a RegExp"
|
|
1407
1532
|
})
|
|
1408
1533
|
}).strict()
|
|
@@ -1410,15 +1535,15 @@ var specificPageVisitConfigSchema = import_zod9.z.object({
|
|
|
1410
1535
|
}).strict();
|
|
1411
1536
|
|
|
1412
1537
|
// ../tracking-core/src/events/time-on-site.ts
|
|
1413
|
-
var
|
|
1414
|
-
var timeOnSiteMetadataSchema =
|
|
1415
|
-
duration_ms:
|
|
1416
|
-
page:
|
|
1417
|
-
path:
|
|
1538
|
+
var import_zod11 = require("zod");
|
|
1539
|
+
var timeOnSiteMetadataSchema = import_zod11.z.object({
|
|
1540
|
+
duration_ms: import_zod11.z.number().int().nonnegative(),
|
|
1541
|
+
page: import_zod11.z.object({
|
|
1542
|
+
path: import_zod11.z.string()
|
|
1418
1543
|
}).strict()
|
|
1419
1544
|
}).strict();
|
|
1420
|
-
var timeOnSiteConfigSchema =
|
|
1421
|
-
thresholdSeconds:
|
|
1545
|
+
var timeOnSiteConfigSchema = import_zod11.z.object({
|
|
1546
|
+
thresholdSeconds: import_zod11.z.number().int().positive()
|
|
1422
1547
|
}).strict();
|
|
1423
1548
|
|
|
1424
1549
|
// ../tracking-core/src/events/registry.ts
|
|
@@ -1460,6 +1585,11 @@ var EVENT_REGISTRY = {
|
|
|
1460
1585
|
metadataSchema: sdkHeartbeatMetadataSchema,
|
|
1461
1586
|
configSchema: sdkHeartbeatConfigSchema
|
|
1462
1587
|
},
|
|
1588
|
+
page_exit: {
|
|
1589
|
+
kind: "automatic",
|
|
1590
|
+
metadataSchema: pageExitMetadataSchema,
|
|
1591
|
+
configSchema: pageExitConfigSchema
|
|
1592
|
+
},
|
|
1463
1593
|
// --- manual triggers ---
|
|
1464
1594
|
form_submit: {
|
|
1465
1595
|
kind: "manual",
|
|
@@ -1838,6 +1968,163 @@ function attachFormStart(client, config) {
|
|
|
1838
1968
|
};
|
|
1839
1969
|
}
|
|
1840
1970
|
|
|
1971
|
+
// ../tracking-core/src/triggers/page-exit.ts
|
|
1972
|
+
function attachPageExit(client) {
|
|
1973
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
1974
|
+
return () => {
|
|
1975
|
+
};
|
|
1976
|
+
}
|
|
1977
|
+
let currentPath2 = window.location.pathname;
|
|
1978
|
+
let activeSince = document.visibilityState === "visible" ? Date.now() : null;
|
|
1979
|
+
let accumulatedMs = 0;
|
|
1980
|
+
let maxScrollPercent = null;
|
|
1981
|
+
let rafId = null;
|
|
1982
|
+
function getScrollPercent() {
|
|
1983
|
+
const doc = document.documentElement;
|
|
1984
|
+
const scrollTop = window.scrollY || doc.scrollTop;
|
|
1985
|
+
const scrollHeight = doc.scrollHeight;
|
|
1986
|
+
const clientHeight = doc.clientHeight;
|
|
1987
|
+
if (scrollHeight <= clientHeight) return 100;
|
|
1988
|
+
return Math.round((scrollTop + clientHeight) / scrollHeight * 100);
|
|
1989
|
+
}
|
|
1990
|
+
function onScroll() {
|
|
1991
|
+
if (rafId !== null) return;
|
|
1992
|
+
rafId = requestAnimationFrame(() => {
|
|
1993
|
+
rafId = null;
|
|
1994
|
+
const percent = getScrollPercent();
|
|
1995
|
+
if (percent >= 1 && (maxScrollPercent === null || percent > maxScrollPercent)) {
|
|
1996
|
+
maxScrollPercent = Math.min(percent, 100);
|
|
1997
|
+
}
|
|
1998
|
+
});
|
|
1999
|
+
}
|
|
2000
|
+
function settledDwellMs() {
|
|
2001
|
+
let total = accumulatedMs;
|
|
2002
|
+
if (activeSince !== null) {
|
|
2003
|
+
total += Date.now() - activeSince;
|
|
2004
|
+
}
|
|
2005
|
+
return Math.max(0, Math.round(total));
|
|
2006
|
+
}
|
|
2007
|
+
function emitSegment(path, flush) {
|
|
2008
|
+
const dwell = settledDwellMs();
|
|
2009
|
+
if (dwell === 0) return;
|
|
2010
|
+
client.trackEvent({
|
|
2011
|
+
eventType: "page_exit",
|
|
2012
|
+
metadata: {
|
|
2013
|
+
dwell_ms: dwell,
|
|
2014
|
+
max_scroll_percent: maxScrollPercent,
|
|
2015
|
+
page: { path }
|
|
2016
|
+
},
|
|
2017
|
+
pageUrl: window.location.href,
|
|
2018
|
+
occurredAt: null
|
|
2019
|
+
});
|
|
2020
|
+
if (flush) {
|
|
2021
|
+
client.flushBeacon();
|
|
2022
|
+
}
|
|
2023
|
+
accumulatedMs = 0;
|
|
2024
|
+
activeSince = document.visibilityState === "visible" ? Date.now() : null;
|
|
2025
|
+
}
|
|
2026
|
+
function onNavigate() {
|
|
2027
|
+
const newPath = window.location.pathname;
|
|
2028
|
+
if (newPath === currentPath2) return;
|
|
2029
|
+
emitSegment(currentPath2, false);
|
|
2030
|
+
currentPath2 = newPath;
|
|
2031
|
+
maxScrollPercent = null;
|
|
2032
|
+
accumulatedMs = 0;
|
|
2033
|
+
activeSince = document.visibilityState === "visible" ? Date.now() : null;
|
|
2034
|
+
}
|
|
2035
|
+
function onVisibilityChange() {
|
|
2036
|
+
if (document.visibilityState === "hidden") {
|
|
2037
|
+
emitSegment(currentPath2, true);
|
|
2038
|
+
} else {
|
|
2039
|
+
activeSince = Date.now();
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
function onPageHide() {
|
|
2043
|
+
emitSegment(currentPath2, true);
|
|
2044
|
+
}
|
|
2045
|
+
const originalPushState = history.pushState.bind(history);
|
|
2046
|
+
const originalReplaceState = history.replaceState.bind(history);
|
|
2047
|
+
function patchedPushState(...args) {
|
|
2048
|
+
originalPushState(...args);
|
|
2049
|
+
setTimeout(onNavigate, 0);
|
|
2050
|
+
}
|
|
2051
|
+
function patchedReplaceState(...args) {
|
|
2052
|
+
originalReplaceState(...args);
|
|
2053
|
+
setTimeout(onNavigate, 0);
|
|
2054
|
+
}
|
|
2055
|
+
history.pushState = patchedPushState;
|
|
2056
|
+
history.replaceState = patchedReplaceState;
|
|
2057
|
+
window.addEventListener("popstate", onNavigate);
|
|
2058
|
+
window.addEventListener("scroll", onScroll, { passive: true });
|
|
2059
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
2060
|
+
window.addEventListener("pagehide", onPageHide);
|
|
2061
|
+
return () => {
|
|
2062
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
2063
|
+
history.pushState = originalPushState;
|
|
2064
|
+
history.replaceState = originalReplaceState;
|
|
2065
|
+
window.removeEventListener("popstate", onNavigate);
|
|
2066
|
+
window.removeEventListener("scroll", onScroll);
|
|
2067
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
2068
|
+
window.removeEventListener("pagehide", onPageHide);
|
|
2069
|
+
};
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
// ../tracking-core/src/triggers/cta-click-capture.ts
|
|
2073
|
+
var DEFAULT_CTA_SELECTOR = "[data-aranova-cta]";
|
|
2074
|
+
var CTA_NAME_MAX_LENGTH = 120;
|
|
2075
|
+
function describeElement(el) {
|
|
2076
|
+
const tag = el.tagName.toLowerCase();
|
|
2077
|
+
return el.id ? `${tag}#${el.id}` : tag;
|
|
2078
|
+
}
|
|
2079
|
+
function resolveCtaName(el) {
|
|
2080
|
+
const explicit = el.getAttribute("data-aranova-cta");
|
|
2081
|
+
if (explicit && explicit.trim().length > 0) return explicit.trim();
|
|
2082
|
+
const text = (el.textContent ?? "").trim().replace(/\s+/g, " ");
|
|
2083
|
+
if (text.length > 0) return text.slice(0, CTA_NAME_MAX_LENGTH);
|
|
2084
|
+
return describeElement(el);
|
|
2085
|
+
}
|
|
2086
|
+
function attachCtaClickCapture(client, config) {
|
|
2087
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
2088
|
+
return () => {
|
|
2089
|
+
};
|
|
2090
|
+
}
|
|
2091
|
+
const autoCapture = config.autoCapture;
|
|
2092
|
+
if (!autoCapture) {
|
|
2093
|
+
return () => {
|
|
2094
|
+
};
|
|
2095
|
+
}
|
|
2096
|
+
const selector = autoCapture.selector ?? DEFAULT_CTA_SELECTOR;
|
|
2097
|
+
function onClick(event) {
|
|
2098
|
+
const target = event.target;
|
|
2099
|
+
if (!(target instanceof Element)) return;
|
|
2100
|
+
let matched = null;
|
|
2101
|
+
try {
|
|
2102
|
+
matched = target.closest(selector);
|
|
2103
|
+
} catch {
|
|
2104
|
+
return;
|
|
2105
|
+
}
|
|
2106
|
+
if (matched === null) return;
|
|
2107
|
+
const href = matched instanceof HTMLAnchorElement ? matched.href || null : matched.getAttribute("href");
|
|
2108
|
+
client.trackEvent({
|
|
2109
|
+
eventType: "cta_click",
|
|
2110
|
+
metadata: {
|
|
2111
|
+
cta_name: resolveCtaName(matched),
|
|
2112
|
+
page: { path: window.location.pathname },
|
|
2113
|
+
section: matched.getAttribute("data-aranova-section"),
|
|
2114
|
+
destination_url: href,
|
|
2115
|
+
href,
|
|
2116
|
+
element: describeElement(matched)
|
|
2117
|
+
},
|
|
2118
|
+
pageUrl: window.location.href,
|
|
2119
|
+
occurredAt: null
|
|
2120
|
+
});
|
|
2121
|
+
}
|
|
2122
|
+
document.addEventListener("click", onClick, true);
|
|
2123
|
+
return () => {
|
|
2124
|
+
document.removeEventListener("click", onClick, true);
|
|
2125
|
+
};
|
|
2126
|
+
}
|
|
2127
|
+
|
|
1841
2128
|
// ../tracking-core/src/resources/sales/errors.ts
|
|
1842
2129
|
var AranovaApiError = class extends Error {
|
|
1843
2130
|
constructor(message, options) {
|
|
@@ -2044,42 +2331,42 @@ function createSalesClient(config) {
|
|
|
2044
2331
|
}
|
|
2045
2332
|
|
|
2046
2333
|
// ../tracking-core/src/resources/sales/schema.ts
|
|
2047
|
-
var
|
|
2334
|
+
var import_zod12 = require("zod");
|
|
2048
2335
|
var SUPPORTED_CURRENCIES = ["USD", "CAD"];
|
|
2049
2336
|
var TRACKING_ENVIRONMENTS = ["production", "development"];
|
|
2050
|
-
var currencySchema =
|
|
2051
|
-
var centsSchema =
|
|
2052
|
-
var quantitySchema =
|
|
2053
|
-
var metadataSchema =
|
|
2054
|
-
var saleItemSchema =
|
|
2055
|
-
external_item_id:
|
|
2056
|
-
name:
|
|
2057
|
-
category:
|
|
2337
|
+
var currencySchema = import_zod12.z.enum(SUPPORTED_CURRENCIES);
|
|
2338
|
+
var centsSchema = import_zod12.z.number().int().nonnegative();
|
|
2339
|
+
var quantitySchema = import_zod12.z.string().regex(/^\d+(\.\d{1,3})?$/);
|
|
2340
|
+
var metadataSchema = import_zod12.z.record(import_zod12.z.unknown());
|
|
2341
|
+
var saleItemSchema = import_zod12.z.object({
|
|
2342
|
+
external_item_id: import_zod12.z.string().nullable().optional(),
|
|
2343
|
+
name: import_zod12.z.string().nullable().optional(),
|
|
2344
|
+
category: import_zod12.z.string().nullable().optional(),
|
|
2058
2345
|
quantity: quantitySchema,
|
|
2059
2346
|
unit_price_cents: centsSchema,
|
|
2060
2347
|
// Non-negativity validated on the wire — same contract as the other cents
|
|
2061
2348
|
// fields — and backstopped by the DB CHECK.
|
|
2062
2349
|
unit_cost_cents: centsSchema.nullable().optional()
|
|
2063
2350
|
}).strict();
|
|
2064
|
-
var saleServiceSchema =
|
|
2065
|
-
service:
|
|
2351
|
+
var saleServiceSchema = import_zod12.z.object({
|
|
2352
|
+
service: import_zod12.z.string(),
|
|
2066
2353
|
amount_cents: centsSchema
|
|
2067
2354
|
}).strict();
|
|
2068
|
-
var customerNameSchema =
|
|
2069
|
-
var customerPhoneSchema =
|
|
2070
|
-
var customerEmailSchema =
|
|
2355
|
+
var customerNameSchema = import_zod12.z.string().max(200);
|
|
2356
|
+
var customerPhoneSchema = import_zod12.z.string().max(64);
|
|
2357
|
+
var customerEmailSchema = import_zod12.z.string().max(320).email();
|
|
2071
2358
|
function refineServiceXor(val, ctx, { requireAmount }) {
|
|
2072
2359
|
if (val.services != null) {
|
|
2073
2360
|
if (val.service != null) {
|
|
2074
2361
|
ctx.addIssue({
|
|
2075
|
-
code:
|
|
2362
|
+
code: import_zod12.z.ZodIssueCode.custom,
|
|
2076
2363
|
message: "pass either `service` or `services`, not both",
|
|
2077
2364
|
path: ["services"]
|
|
2078
2365
|
});
|
|
2079
2366
|
}
|
|
2080
2367
|
if (val.services.length === 0) {
|
|
2081
2368
|
ctx.addIssue({
|
|
2082
|
-
code:
|
|
2369
|
+
code: import_zod12.z.ZodIssueCode.custom,
|
|
2083
2370
|
message: "`services` must not be empty",
|
|
2084
2371
|
path: ["services"]
|
|
2085
2372
|
});
|
|
@@ -2087,7 +2374,7 @@ function refineServiceXor(val, ctx, { requireAmount }) {
|
|
|
2087
2374
|
const keys = val.services.map((s) => s.service);
|
|
2088
2375
|
if (new Set(keys).size !== keys.length) {
|
|
2089
2376
|
ctx.addIssue({
|
|
2090
|
-
code:
|
|
2377
|
+
code: import_zod12.z.ZodIssueCode.custom,
|
|
2091
2378
|
message: "`services` must not list the same service more than once",
|
|
2092
2379
|
path: ["services"]
|
|
2093
2380
|
});
|
|
@@ -2096,7 +2383,7 @@ function refineServiceXor(val, ctx, { requireAmount }) {
|
|
|
2096
2383
|
const sum = val.services.reduce((acc, s) => acc + s.amount_cents, 0);
|
|
2097
2384
|
if (val.amount_total_cents !== sum) {
|
|
2098
2385
|
ctx.addIssue({
|
|
2099
|
-
code:
|
|
2386
|
+
code: import_zod12.z.ZodIssueCode.custom,
|
|
2100
2387
|
message: "amount_total_cents must equal the sum of the services amounts (omit it to derive it automatically)",
|
|
2101
2388
|
path: ["amount_total_cents"]
|
|
2102
2389
|
});
|
|
@@ -2104,37 +2391,37 @@ function refineServiceXor(val, ctx, { requireAmount }) {
|
|
|
2104
2391
|
}
|
|
2105
2392
|
} else if (requireAmount && val.amount_total_cents == null) {
|
|
2106
2393
|
ctx.addIssue({
|
|
2107
|
-
code:
|
|
2394
|
+
code: import_zod12.z.ZodIssueCode.custom,
|
|
2108
2395
|
message: "amount_total_cents is required unless `services` is provided",
|
|
2109
2396
|
path: ["amount_total_cents"]
|
|
2110
2397
|
});
|
|
2111
2398
|
}
|
|
2112
2399
|
}
|
|
2113
|
-
var saleCreateSchema =
|
|
2114
|
-
external_id:
|
|
2115
|
-
description:
|
|
2116
|
-
service:
|
|
2117
|
-
services:
|
|
2400
|
+
var saleCreateSchema = import_zod12.z.object({
|
|
2401
|
+
external_id: import_zod12.z.string().nullable().optional(),
|
|
2402
|
+
description: import_zod12.z.string().nullable().optional(),
|
|
2403
|
+
service: import_zod12.z.string().nullable().optional(),
|
|
2404
|
+
services: import_zod12.z.array(saleServiceSchema).nullable().optional(),
|
|
2118
2405
|
currency: currencySchema,
|
|
2119
2406
|
// Optional only because the plural `services` form derives it from the sum
|
|
2120
2407
|
// (see refineServiceXor); the singular/serviceless path still requires it.
|
|
2121
2408
|
amount_total_cents: centsSchema.nullable().optional(),
|
|
2122
|
-
occurred_at:
|
|
2123
|
-
environment:
|
|
2124
|
-
items:
|
|
2409
|
+
occurred_at: import_zod12.z.string().datetime(),
|
|
2410
|
+
environment: import_zod12.z.enum(TRACKING_ENVIRONMENTS).default("production"),
|
|
2411
|
+
items: import_zod12.z.array(saleItemSchema).default([]),
|
|
2125
2412
|
metadata: metadataSchema.nullable().optional(),
|
|
2126
2413
|
customer_name: customerNameSchema.nullable().optional(),
|
|
2127
2414
|
customer_phone: customerPhoneSchema.nullable().optional(),
|
|
2128
2415
|
customer_email: customerEmailSchema.nullable().optional()
|
|
2129
2416
|
}).strict().superRefine((val, ctx) => refineServiceXor(val, ctx, { requireAmount: true }));
|
|
2130
|
-
var saleUpdateSchema =
|
|
2131
|
-
description:
|
|
2132
|
-
service:
|
|
2133
|
-
services:
|
|
2417
|
+
var saleUpdateSchema = import_zod12.z.object({
|
|
2418
|
+
description: import_zod12.z.string().nullable().optional(),
|
|
2419
|
+
service: import_zod12.z.string().nullable().optional(),
|
|
2420
|
+
services: import_zod12.z.array(saleServiceSchema).nullable().optional(),
|
|
2134
2421
|
currency: currencySchema.optional(),
|
|
2135
2422
|
amount_total_cents: centsSchema.optional(),
|
|
2136
|
-
occurred_at:
|
|
2137
|
-
items:
|
|
2423
|
+
occurred_at: import_zod12.z.string().datetime().optional(),
|
|
2424
|
+
items: import_zod12.z.array(saleItemSchema).optional(),
|
|
2138
2425
|
metadata: metadataSchema.nullable().optional(),
|
|
2139
2426
|
customer_name: customerNameSchema.nullable().optional(),
|
|
2140
2427
|
customer_phone: customerPhoneSchema.nullable().optional(),
|
|
@@ -2220,36 +2507,68 @@ function useTrackingParams() {
|
|
|
2220
2507
|
}, []);
|
|
2221
2508
|
return trackingParams;
|
|
2222
2509
|
}
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2510
|
+
var DEFAULT_CHOICE2 = {
|
|
2511
|
+
state: "granted",
|
|
2512
|
+
source: "default",
|
|
2513
|
+
updatedAt: null,
|
|
2514
|
+
expiresAt: null
|
|
2515
|
+
};
|
|
2516
|
+
function useCookiePreferences(options) {
|
|
2517
|
+
const [choice, setChoice] = (0, import_react.useState)(DEFAULT_CHOICE2);
|
|
2518
|
+
const ttlDays = options?.declineTtlDays;
|
|
2228
2519
|
(0, import_react.useEffect)(() => {
|
|
2229
|
-
|
|
2520
|
+
const sync = () => setChoice(getConsentChoice());
|
|
2521
|
+
sync();
|
|
2230
2522
|
const handleStorage = (event) => {
|
|
2231
|
-
if (event.key === CONSENT_STATE_KEY
|
|
2523
|
+
if (event.key === null || event.key === CONSENT_STATE_KEY || event.key === CONSENT_EXPIRES_AT_KEY || event.key === CONSENT_TIMESTAMP_KEY)
|
|
2524
|
+
sync();
|
|
2232
2525
|
};
|
|
2233
2526
|
window.addEventListener("storage", handleStorage);
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2527
|
+
const unsubscribe = onConsentChange(sync);
|
|
2528
|
+
return () => {
|
|
2529
|
+
window.removeEventListener("storage", handleStorage);
|
|
2530
|
+
unsubscribe();
|
|
2531
|
+
};
|
|
2239
2532
|
}, []);
|
|
2240
|
-
const
|
|
2241
|
-
|
|
2242
|
-
|
|
2533
|
+
const optOutAction = (0, import_react.useCallback)(() => {
|
|
2534
|
+
optOut(ttlDays != null ? { declineTtlDays: ttlDays } : void 0);
|
|
2535
|
+
}, [ttlDays]);
|
|
2536
|
+
const optInAction = (0, import_react.useCallback)(() => {
|
|
2537
|
+
optIn();
|
|
2243
2538
|
}, []);
|
|
2244
2539
|
const reset = (0, import_react.useCallback)(() => {
|
|
2245
2540
|
resetConsent();
|
|
2246
|
-
setState("pending");
|
|
2247
2541
|
}, []);
|
|
2542
|
+
return {
|
|
2543
|
+
state: choice.state,
|
|
2544
|
+
source: choice.source,
|
|
2545
|
+
isDefault: choice.source === "default",
|
|
2546
|
+
isGranted: choice.state === "granted",
|
|
2547
|
+
isDenied: choice.state === "denied",
|
|
2548
|
+
updatedAt: choice.updatedAt,
|
|
2549
|
+
expiresAt: choice.expiresAt,
|
|
2550
|
+
optOut: optOutAction,
|
|
2551
|
+
optIn: optInAction,
|
|
2552
|
+
reset
|
|
2553
|
+
};
|
|
2554
|
+
}
|
|
2555
|
+
function useConsentState() {
|
|
2556
|
+
return useConsent().state;
|
|
2557
|
+
}
|
|
2558
|
+
function useConsent() {
|
|
2559
|
+
const {
|
|
2560
|
+
state,
|
|
2561
|
+
isGranted,
|
|
2562
|
+
isDenied,
|
|
2563
|
+
optIn: accept,
|
|
2564
|
+
optOut: decline,
|
|
2565
|
+
reset
|
|
2566
|
+
} = useCookiePreferences();
|
|
2248
2567
|
return {
|
|
2249
2568
|
state,
|
|
2250
|
-
isPending:
|
|
2251
|
-
isGranted
|
|
2252
|
-
isDenied
|
|
2569
|
+
isPending: false,
|
|
2570
|
+
isGranted,
|
|
2571
|
+
isDenied,
|
|
2253
2572
|
accept,
|
|
2254
2573
|
decline,
|
|
2255
2574
|
reset
|
|
@@ -2490,7 +2809,7 @@ function GoogleAdsTracking(props) {
|
|
|
2490
2809
|
var import_react6 = require("react");
|
|
2491
2810
|
|
|
2492
2811
|
// package.json
|
|
2493
|
-
var version = "0.
|
|
2812
|
+
var version = "0.16.0";
|
|
2494
2813
|
|
|
2495
2814
|
// ../tracking-core/src/phone-react.tsx
|
|
2496
2815
|
var import_react5 = require("react");
|
|
@@ -2671,6 +2990,7 @@ function createTracking(options) {
|
|
|
2671
2990
|
const detectorClient = conversionStore ? withConversionAutoFire(rawClient, createConversionAutoFire(conversionStore)) : rawClient;
|
|
2672
2991
|
detachers.push(attachAutoPageView(detectorClient));
|
|
2673
2992
|
detachers.push(attachBfcacheRestore(detectorClient));
|
|
2993
|
+
detachers.push(attachPageExit(detectorClient));
|
|
2674
2994
|
const timeOnSite = triggers.automatic.time_on_site;
|
|
2675
2995
|
if (timeOnSite) {
|
|
2676
2996
|
detachers.push(attachTimeOnSite(detectorClient, timeOnSite));
|
|
@@ -2691,6 +3011,10 @@ function createTracking(options) {
|
|
|
2691
3011
|
if (formStart) {
|
|
2692
3012
|
detachers.push(attachFormStart(detectorClient, formStart));
|
|
2693
3013
|
}
|
|
3014
|
+
const ctaClick = triggers.manual?.cta_click;
|
|
3015
|
+
if (ctaClick) {
|
|
3016
|
+
detachers.push(attachCtaClickCapture(detectorClient, ctaClick));
|
|
3017
|
+
}
|
|
2694
3018
|
return () => {
|
|
2695
3019
|
for (let i = detachers.length - 1; i >= 0; i--) {
|
|
2696
3020
|
detachers[i]();
|
|
@@ -2715,6 +3039,7 @@ function createTracking(options) {
|
|
|
2715
3039
|
AdPlatformTracking,
|
|
2716
3040
|
AranovaApiError,
|
|
2717
3041
|
ConsentBanner,
|
|
3042
|
+
DEFAULT_DECLINE_TTL_DAYS,
|
|
2718
3043
|
DEFAULT_PHONE_COUNTRY,
|
|
2719
3044
|
GoogleAdsTracking,
|
|
2720
3045
|
NAMED_RANGES,
|
|
@@ -2734,7 +3059,11 @@ function createTracking(options) {
|
|
|
2734
3059
|
formatPhone,
|
|
2735
3060
|
formatPhoneAsTyped,
|
|
2736
3061
|
fromMinor,
|
|
3062
|
+
getConsentChoice,
|
|
2737
3063
|
getConsentState,
|
|
3064
|
+
onConsentChange,
|
|
3065
|
+
optIn,
|
|
3066
|
+
optOut,
|
|
2738
3067
|
parsePhone,
|
|
2739
3068
|
phoneField,
|
|
2740
3069
|
resetConsent,
|
|
@@ -2749,6 +3078,7 @@ function createTracking(options) {
|
|
|
2749
3078
|
toMinor,
|
|
2750
3079
|
useConsent,
|
|
2751
3080
|
useConsentState,
|
|
3081
|
+
useCookiePreferences,
|
|
2752
3082
|
useGclid,
|
|
2753
3083
|
usePhoneConfig,
|
|
2754
3084
|
usePhoneField,
|