@aranova/tracking-react 0.12.2 → 0.14.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 +38 -0
- package/dist/index.d.mts +64 -16
- package/dist/index.d.ts +64 -16
- package/dist/index.js +738 -183
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +726 -173
- package/dist/index.mjs.map +1 -1
- package/dist/{phone-utils-Du-alwyM.d.mts → phone-utils-Dyk0F14_.d.mts} +26 -1
- package/dist/{phone-utils-Du-alwyM.d.ts → phone-utils-Dyk0F14_.d.ts} +26 -1
- package/dist/phone.d.mts +1 -1
- package/dist/phone.d.ts +1 -1
- package/dist/phone.js +73 -0
- package/dist/phone.js.map +1 -1
- package/dist/phone.mjs +73 -0
- package/dist/phone.mjs.map +1 -1
- package/dist/sales-BsJodmh0.d.mts +887 -0
- package/dist/sales-BsJodmh0.d.ts +887 -0
- package/dist/sales.d.mts +2 -784
- package/dist/sales.d.ts +2 -784
- package/dist/sales.js +172 -45
- package/dist/sales.js.map +1 -1
- package/dist/sales.mjs +172 -45
- package/dist/sales.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -7,6 +7,13 @@ import { useCallback, useEffect, useState } from "react";
|
|
|
7
7
|
// ../tracking-core/src/consent.ts
|
|
8
8
|
var CONSENT_STATE_KEY = "consent_state";
|
|
9
9
|
var CONSENT_TIMESTAMP_KEY = "consent_timestamp";
|
|
10
|
+
var grantedListeners = /* @__PURE__ */ new Set();
|
|
11
|
+
function onConsentGranted(listener) {
|
|
12
|
+
grantedListeners.add(listener);
|
|
13
|
+
return () => {
|
|
14
|
+
grantedListeners.delete(listener);
|
|
15
|
+
};
|
|
16
|
+
}
|
|
10
17
|
function buildConsentPayload(state) {
|
|
11
18
|
return {
|
|
12
19
|
ad_storage: state,
|
|
@@ -17,21 +24,40 @@ function buildConsentPayload(state) {
|
|
|
17
24
|
}
|
|
18
25
|
function getConsentState() {
|
|
19
26
|
if (typeof window === "undefined") return "pending";
|
|
20
|
-
|
|
21
|
-
|
|
27
|
+
try {
|
|
28
|
+
const storedState = window.localStorage.getItem(CONSENT_STATE_KEY);
|
|
29
|
+
if (storedState === "granted" || storedState === "denied") return storedState;
|
|
30
|
+
} catch {
|
|
31
|
+
}
|
|
22
32
|
return "pending";
|
|
23
33
|
}
|
|
24
34
|
function setConsentState(state) {
|
|
25
35
|
if (typeof window === "undefined") return;
|
|
26
|
-
|
|
27
|
-
|
|
36
|
+
try {
|
|
37
|
+
window.localStorage.setItem(CONSENT_STATE_KEY, state);
|
|
38
|
+
window.localStorage.setItem(CONSENT_TIMESTAMP_KEY, (/* @__PURE__ */ new Date()).toISOString());
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
28
41
|
if (typeof window.gtag === "function")
|
|
29
42
|
window.gtag("consent", "update", buildConsentPayload(state));
|
|
43
|
+
if (typeof window.fbq === "function")
|
|
44
|
+
window.fbq("consent", state === "granted" ? "grant" : "revoke");
|
|
45
|
+
if (state === "granted") {
|
|
46
|
+
for (const listener of grantedListeners) {
|
|
47
|
+
try {
|
|
48
|
+
listener();
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
30
53
|
}
|
|
31
54
|
function resetConsent() {
|
|
32
55
|
if (typeof window === "undefined") return;
|
|
33
|
-
|
|
34
|
-
|
|
56
|
+
try {
|
|
57
|
+
window.localStorage.removeItem(CONSENT_STATE_KEY);
|
|
58
|
+
window.localStorage.removeItem(CONSENT_TIMESTAMP_KEY);
|
|
59
|
+
} catch {
|
|
60
|
+
}
|
|
35
61
|
}
|
|
36
62
|
function restoreStoredConsent() {
|
|
37
63
|
const consentState = getConsentState();
|
|
@@ -39,45 +65,106 @@ function restoreStoredConsent() {
|
|
|
39
65
|
return consentState;
|
|
40
66
|
}
|
|
41
67
|
|
|
42
|
-
// ../tracking-core/src/
|
|
43
|
-
|
|
68
|
+
// ../tracking-core/src/tracking.ts
|
|
69
|
+
var TRACKING_COOKIE_MAX_AGE_SECONDS = 7776e3;
|
|
70
|
+
var TRACKING_PARAM_KEYS = [
|
|
71
|
+
"gclid",
|
|
72
|
+
"fbclid",
|
|
73
|
+
"utm_source",
|
|
74
|
+
"utm_medium",
|
|
75
|
+
"utm_campaign",
|
|
76
|
+
"utm_term",
|
|
77
|
+
"utm_content"
|
|
78
|
+
];
|
|
79
|
+
function createEmptyTrackingParams() {
|
|
44
80
|
return {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
active_gtag_ids: input.activeGtagIds ?? null
|
|
81
|
+
gclid: null,
|
|
82
|
+
fbclid: null,
|
|
83
|
+
utm_source: null,
|
|
84
|
+
utm_medium: null,
|
|
85
|
+
utm_campaign: null,
|
|
86
|
+
utm_term: null,
|
|
87
|
+
utm_content: null
|
|
53
88
|
};
|
|
54
89
|
}
|
|
55
|
-
function
|
|
56
|
-
return
|
|
57
|
-
session_id: input.sessionId,
|
|
58
|
-
visitor_id: input.visitorId ?? null,
|
|
59
|
-
gclid: trackingParams.gclid,
|
|
60
|
-
fbclid: trackingParams.fbclid,
|
|
61
|
-
utm_source: trackingParams.utm_source,
|
|
62
|
-
utm_medium: trackingParams.utm_medium,
|
|
63
|
-
utm_campaign: trackingParams.utm_campaign,
|
|
64
|
-
utm_term: trackingParams.utm_term,
|
|
65
|
-
utm_content: trackingParams.utm_content,
|
|
66
|
-
first_page: input.firstPage ?? null,
|
|
67
|
-
consent_state: input.consentState ?? null,
|
|
68
|
-
context
|
|
69
|
-
};
|
|
90
|
+
function normalizeTrackingCookieValue(value) {
|
|
91
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
70
92
|
}
|
|
71
|
-
function
|
|
72
|
-
return {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
93
|
+
function getTrackingParamsFromCookieReader(readCookie) {
|
|
94
|
+
return TRACKING_PARAM_KEYS.reduce((params, key) => {
|
|
95
|
+
params[key] = normalizeTrackingCookieValue(readCookie(key));
|
|
96
|
+
return params;
|
|
97
|
+
}, createEmptyTrackingParams());
|
|
98
|
+
}
|
|
99
|
+
function getTrackingQueryValues(searchParams) {
|
|
100
|
+
return TRACKING_PARAM_KEYS.reduce((params, key) => {
|
|
101
|
+
const value = searchParams.get(key);
|
|
102
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
103
|
+
params[key] = value;
|
|
104
|
+
}
|
|
105
|
+
return params;
|
|
106
|
+
}, {});
|
|
107
|
+
}
|
|
108
|
+
var FALLBACK_STORAGE_PREFIX = "_aranova_track_";
|
|
109
|
+
function fallbackKey(name) {
|
|
110
|
+
return `${FALLBACK_STORAGE_PREFIX}${name}`;
|
|
111
|
+
}
|
|
112
|
+
function persistCookieValue(name, value, maxAgeSeconds = TRACKING_COOKIE_MAX_AGE_SECONDS) {
|
|
113
|
+
const encoded = encodeURIComponent(value);
|
|
114
|
+
if (typeof document !== "undefined") {
|
|
115
|
+
try {
|
|
116
|
+
document.cookie = `${name}=${encoded}; Max-Age=${maxAgeSeconds}; Path=/; SameSite=Lax`;
|
|
117
|
+
} catch {
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (typeof window !== "undefined") {
|
|
121
|
+
try {
|
|
122
|
+
window.localStorage.setItem(fallbackKey(name), encoded);
|
|
123
|
+
} catch {
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function readCookieValue(name) {
|
|
128
|
+
if (typeof document !== "undefined") {
|
|
129
|
+
const cookies = document.cookie ? document.cookie.split("; ") : [];
|
|
130
|
+
const match = cookies.find((cookie) => cookie.startsWith(`${name}=`));
|
|
131
|
+
if (match) {
|
|
132
|
+
const [, rawValue = ""] = match.split("=");
|
|
133
|
+
return normalizeTrackingCookieValue(decodeURIComponent(rawValue));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (typeof window !== "undefined") {
|
|
137
|
+
try {
|
|
138
|
+
const stored = window.localStorage.getItem(fallbackKey(name));
|
|
139
|
+
if (stored) return normalizeTrackingCookieValue(decodeURIComponent(stored));
|
|
140
|
+
} catch {
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
function getCookieValueFromDocument(key) {
|
|
146
|
+
return readCookieValue(key);
|
|
147
|
+
}
|
|
148
|
+
function setTrackingCookie(key, value, maxAgeSeconds = TRACKING_COOKIE_MAX_AGE_SECONDS) {
|
|
149
|
+
persistCookieValue(key, value, maxAgeSeconds);
|
|
150
|
+
}
|
|
151
|
+
function mergeTrackingParams(primary, fallback) {
|
|
152
|
+
return TRACKING_PARAM_KEYS.reduce((merged, key) => {
|
|
153
|
+
merged[key] = primary[key] ?? fallback[key];
|
|
154
|
+
return merged;
|
|
155
|
+
}, createEmptyTrackingParams());
|
|
156
|
+
}
|
|
157
|
+
function persistTrackingParamsFromSearchParams(searchParams, maxAgeSeconds = TRACKING_COOKIE_MAX_AGE_SECONDS) {
|
|
158
|
+
const trackingValues = getTrackingQueryValues(searchParams);
|
|
159
|
+
Object.entries(trackingValues).forEach(([key, value]) => {
|
|
160
|
+
setTrackingCookie(key, value, maxAgeSeconds);
|
|
161
|
+
});
|
|
162
|
+
return trackingValues;
|
|
163
|
+
}
|
|
164
|
+
function captureTrackingParamsFromLocation(url = typeof window === "undefined" ? "" : window.location.href, maxAgeSeconds = TRACKING_COOKIE_MAX_AGE_SECONDS) {
|
|
165
|
+
const resolvedUrl = typeof window === "undefined" ? new URL(url || "https://example.invalid") : new URL(url, window.location.origin);
|
|
166
|
+
persistTrackingParamsFromSearchParams(resolvedUrl.searchParams, maxAgeSeconds);
|
|
167
|
+
return getTrackingParamsFromCookieReader(getCookieValueFromDocument);
|
|
81
168
|
}
|
|
82
169
|
|
|
83
170
|
// ../tracking-core/src/gtag.ts
|
|
@@ -98,6 +185,24 @@ function ensureGtagFunction() {
|
|
|
98
185
|
};
|
|
99
186
|
return window.gtag;
|
|
100
187
|
}
|
|
188
|
+
var SEND_TO_RE = /^AW-[A-Za-z0-9]+\/[A-Za-z0-9_-]+$/;
|
|
189
|
+
function isValidSendTo(sendTo) {
|
|
190
|
+
return SEND_TO_RE.test(sendTo);
|
|
191
|
+
}
|
|
192
|
+
function fireGtagConversion(input) {
|
|
193
|
+
if (typeof window === "undefined" || typeof window.gtag !== "function") return false;
|
|
194
|
+
if (!isValidSendTo(input.sendTo)) return false;
|
|
195
|
+
const params = { send_to: input.sendTo };
|
|
196
|
+
if (input.value != null) params.value = input.value;
|
|
197
|
+
if (input.currency) params.currency = input.currency;
|
|
198
|
+
if (input.transactionId) params.transaction_id = input.transactionId;
|
|
199
|
+
try {
|
|
200
|
+
window.gtag("event", "conversion", params);
|
|
201
|
+
return true;
|
|
202
|
+
} catch {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
101
206
|
function applyDefaultConsentState() {
|
|
102
207
|
const gtag = ensureGtagFunction();
|
|
103
208
|
gtag("consent", "default", {
|
|
@@ -150,70 +255,441 @@ function bootstrapMultipleGtags(gtagIds) {
|
|
|
150
255
|
restoreStoredConsent();
|
|
151
256
|
}
|
|
152
257
|
|
|
153
|
-
// ../tracking-core/src/
|
|
154
|
-
var
|
|
155
|
-
var
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
"
|
|
163
|
-
|
|
164
|
-
|
|
258
|
+
// ../tracking-core/src/fbq.ts
|
|
259
|
+
var FB_EVENTS_SCRIPT_HOST = "https://connect.facebook.net/en_US/fbevents.js";
|
|
260
|
+
var FBC_COOKIE = "_fbc";
|
|
261
|
+
var FBP_COOKIE = "_fbp";
|
|
262
|
+
var META_PIXEL_ID_PATTERN = /^\d{15,16}$/;
|
|
263
|
+
function isValidMetaPixelId(id) {
|
|
264
|
+
return META_PIXEL_ID_PATTERN.test(id);
|
|
265
|
+
}
|
|
266
|
+
function computeFbSubdomainIndex(hostname) {
|
|
267
|
+
const labels = hostname.split(".").filter(Boolean);
|
|
268
|
+
return Math.max(0, labels.length - 1);
|
|
269
|
+
}
|
|
270
|
+
function buildFbc(fbclid, now, hostname) {
|
|
271
|
+
const host = hostname ?? (typeof window === "undefined" ? "" : window.location.hostname);
|
|
272
|
+
return `fb.${computeFbSubdomainIndex(host)}.${now}.${fbclid}`;
|
|
273
|
+
}
|
|
274
|
+
function getFbcCookie() {
|
|
275
|
+
return readCookieValue(FBC_COOKIE);
|
|
276
|
+
}
|
|
277
|
+
function getFbpCookie() {
|
|
278
|
+
return readCookieValue(FBP_COOKIE);
|
|
279
|
+
}
|
|
280
|
+
function readFbclidFromUrl() {
|
|
281
|
+
if (typeof window === "undefined") return null;
|
|
282
|
+
try {
|
|
283
|
+
const value = new URL(window.location.href).searchParams.get("fbclid");
|
|
284
|
+
return value && value.trim().length > 0 ? value : null;
|
|
285
|
+
} catch {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
function captureFbc(now = typeof Date === "undefined" ? 0 : Date.now()) {
|
|
290
|
+
if (typeof window === "undefined") return;
|
|
291
|
+
if (getFbcCookie()) return;
|
|
292
|
+
const fbclid = readFbclidFromUrl() ?? readCookieValue("fbclid");
|
|
293
|
+
if (!fbclid) return;
|
|
294
|
+
persistCookieValue(FBC_COOKIE, buildFbc(fbclid, now), TRACKING_COOKIE_MAX_AGE_SECONDS);
|
|
295
|
+
}
|
|
296
|
+
function getScriptMarker2(id) {
|
|
297
|
+
return `aranova-${id}`;
|
|
298
|
+
}
|
|
299
|
+
function ensureFbqFunction() {
|
|
300
|
+
const w = window;
|
|
301
|
+
if (typeof w.fbq === "function") return w.fbq;
|
|
302
|
+
const fbq = function(...args) {
|
|
303
|
+
if (fbq.callMethod) fbq.callMethod.apply(fbq, args);
|
|
304
|
+
else fbq.queue.push(args);
|
|
305
|
+
};
|
|
306
|
+
fbq.push = fbq;
|
|
307
|
+
fbq.loaded = true;
|
|
308
|
+
fbq.version = "2.0";
|
|
309
|
+
fbq.queue = [];
|
|
310
|
+
w.fbq = fbq;
|
|
311
|
+
if (!w._fbq) w._fbq = fbq;
|
|
312
|
+
return fbq;
|
|
313
|
+
}
|
|
314
|
+
function applyDefaultMetaConsentState() {
|
|
315
|
+
ensureFbqFunction()("consent", "revoke");
|
|
316
|
+
}
|
|
317
|
+
function loadFbeventsScript() {
|
|
318
|
+
if (typeof document === "undefined") return;
|
|
319
|
+
const marker = getScriptMarker2("fbq-loader");
|
|
320
|
+
const existing = document.querySelector(
|
|
321
|
+
`script[${TRACKING_SCRIPT_ATTRIBUTE}="${marker}"]`
|
|
322
|
+
);
|
|
323
|
+
if (existing) return;
|
|
324
|
+
const script = document.createElement("script");
|
|
325
|
+
script.async = true;
|
|
326
|
+
script.src = FB_EVENTS_SCRIPT_HOST;
|
|
327
|
+
script.setAttribute(TRACKING_SCRIPT_ATTRIBUTE, marker);
|
|
328
|
+
document.head.append(script);
|
|
329
|
+
}
|
|
330
|
+
function initializeMetaPixel(pixelId) {
|
|
331
|
+
const fbq = ensureFbqFunction();
|
|
332
|
+
fbq("init", pixelId);
|
|
333
|
+
fbq("track", "PageView");
|
|
334
|
+
}
|
|
335
|
+
function restoreMetaConsentState() {
|
|
336
|
+
if (typeof window === "undefined") return;
|
|
337
|
+
const state = getConsentState();
|
|
338
|
+
if (state === "granted") window.fbq?.("consent", "grant");
|
|
339
|
+
else if (state === "denied") window.fbq?.("consent", "revoke");
|
|
340
|
+
}
|
|
341
|
+
function bootstrapMetaPixel(pixelId) {
|
|
342
|
+
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
343
|
+
if (!isValidMetaPixelId(pixelId)) return;
|
|
344
|
+
applyDefaultMetaConsentState();
|
|
345
|
+
loadFbeventsScript();
|
|
346
|
+
initializeMetaPixel(pixelId);
|
|
347
|
+
restoreMetaConsentState();
|
|
348
|
+
captureFbc();
|
|
349
|
+
}
|
|
350
|
+
function bootstrapMultiplePixels(pixelIds) {
|
|
351
|
+
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
352
|
+
const ids = Object.values(pixelIds).filter(
|
|
353
|
+
(id) => typeof id === "string" && isValidMetaPixelId(id)
|
|
354
|
+
);
|
|
355
|
+
if (ids.length === 0) return;
|
|
356
|
+
applyDefaultMetaConsentState();
|
|
357
|
+
loadFbeventsScript();
|
|
358
|
+
const fbq = ensureFbqFunction();
|
|
359
|
+
for (const id of ids) {
|
|
360
|
+
fbq("init", id);
|
|
361
|
+
}
|
|
362
|
+
fbq("track", "PageView");
|
|
363
|
+
restoreMetaConsentState();
|
|
364
|
+
captureFbc();
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// ../tracking-core/src/payloads.ts
|
|
368
|
+
function createTrackingClientContext(surface, input = {}) {
|
|
165
369
|
return {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
370
|
+
surface,
|
|
371
|
+
sdk_version: input.sdkVersion ?? null,
|
|
372
|
+
package_name: input.packageName ?? null,
|
|
373
|
+
site_origin: input.siteOrigin ?? (typeof window === "undefined" ? null : window.location.origin),
|
|
374
|
+
page_title: input.pageTitle ?? (typeof document === "undefined" ? null : document.title || null),
|
|
375
|
+
referrer: input.referrer ?? (typeof document === "undefined" ? null : document.referrer || null),
|
|
376
|
+
environment: input.environment ?? "production",
|
|
377
|
+
active_gtag_ids: input.activeGtagIds ?? null
|
|
173
378
|
};
|
|
174
379
|
}
|
|
175
|
-
function
|
|
176
|
-
return
|
|
380
|
+
function createTrackingSessionUpsertPayload(trackingParams, input, context) {
|
|
381
|
+
return {
|
|
382
|
+
session_id: input.sessionId,
|
|
383
|
+
visitor_id: input.visitorId ?? null,
|
|
384
|
+
gclid: trackingParams.gclid,
|
|
385
|
+
fbclid: trackingParams.fbclid,
|
|
386
|
+
fbc: getFbcCookie(),
|
|
387
|
+
fbp: getFbpCookie(),
|
|
388
|
+
utm_source: trackingParams.utm_source,
|
|
389
|
+
utm_medium: trackingParams.utm_medium,
|
|
390
|
+
utm_campaign: trackingParams.utm_campaign,
|
|
391
|
+
utm_term: trackingParams.utm_term,
|
|
392
|
+
utm_content: trackingParams.utm_content,
|
|
393
|
+
first_page: input.firstPage ?? null,
|
|
394
|
+
consent_state: input.consentState ?? null,
|
|
395
|
+
context
|
|
396
|
+
};
|
|
177
397
|
}
|
|
178
|
-
function
|
|
179
|
-
return
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
398
|
+
function createTrackingEventCreatePayload(trackingParams, input, context) {
|
|
399
|
+
return {
|
|
400
|
+
session_id: input.sessionId,
|
|
401
|
+
event_type: input.eventType,
|
|
402
|
+
gclid: trackingParams.gclid,
|
|
403
|
+
fbclid: trackingParams.fbclid,
|
|
404
|
+
fbc: getFbcCookie(),
|
|
405
|
+
fbp: getFbpCookie(),
|
|
406
|
+
page_url: input.pageUrl ?? (typeof window === "undefined" ? null : window.location.href),
|
|
407
|
+
metadata: input.metadata ?? null,
|
|
408
|
+
context
|
|
409
|
+
};
|
|
183
410
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
411
|
+
|
|
412
|
+
// ../tracking-core/src/resources/conversion-firing.ts
|
|
413
|
+
var DEDUP_PREFIX = "_aranova_conv_";
|
|
414
|
+
var MAX_PENDING = 100;
|
|
415
|
+
var pendingQueue = [];
|
|
416
|
+
function dedupKey(input) {
|
|
417
|
+
return `${DEDUP_PREFIX}${input.transactionId ?? ""}:${input.sendTo}`;
|
|
418
|
+
}
|
|
419
|
+
function alreadyFired(input) {
|
|
420
|
+
if (!input.transactionId || typeof window === "undefined") return false;
|
|
421
|
+
try {
|
|
422
|
+
return window.sessionStorage.getItem(dedupKey(input)) !== null;
|
|
423
|
+
} catch {
|
|
424
|
+
return false;
|
|
425
|
+
}
|
|
192
426
|
}
|
|
193
|
-
function
|
|
194
|
-
if (typeof
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return normalizeTrackingCookieValue(decodeURIComponent(rawValue));
|
|
427
|
+
function markFired(input) {
|
|
428
|
+
if (!input.transactionId || typeof window === "undefined") return;
|
|
429
|
+
try {
|
|
430
|
+
window.sessionStorage.setItem(dedupKey(input), "1");
|
|
431
|
+
} catch {
|
|
432
|
+
}
|
|
200
433
|
}
|
|
201
|
-
function
|
|
202
|
-
if (
|
|
203
|
-
|
|
204
|
-
document.cookie = `${key}=${encodedValue}; Max-Age=${maxAgeSeconds}; Path=/; SameSite=Lax`;
|
|
434
|
+
function fireOnce(input) {
|
|
435
|
+
if (alreadyFired(input)) return;
|
|
436
|
+
if (fireGtagConversion(input)) markFired(input);
|
|
205
437
|
}
|
|
206
|
-
function
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
438
|
+
function fireConversionWithConsent(input) {
|
|
439
|
+
const state = getConsentState();
|
|
440
|
+
if (state === "denied") return;
|
|
441
|
+
if (state === "pending") {
|
|
442
|
+
if (pendingQueue.length >= MAX_PENDING) pendingQueue.shift();
|
|
443
|
+
pendingQueue.push(input);
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
fireOnce(input);
|
|
447
|
+
}
|
|
448
|
+
function flushPendingConversions() {
|
|
449
|
+
if (getConsentState() !== "granted") return;
|
|
450
|
+
while (pendingQueue.length > 0) {
|
|
451
|
+
const input = pendingQueue.shift();
|
|
452
|
+
if (input) fireOnce(input);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
if (typeof window !== "undefined") onConsentGranted(flushPendingConversions);
|
|
456
|
+
|
|
457
|
+
// ../tracking-core/src/resources/conversion-config.ts
|
|
458
|
+
function isStringMap(value) {
|
|
459
|
+
return typeof value === "object" && value !== null && Object.values(value).every((v) => typeof v === "string");
|
|
460
|
+
}
|
|
461
|
+
function parseFiring(value) {
|
|
462
|
+
if (!value || typeof value !== "object") return null;
|
|
463
|
+
const f = value;
|
|
464
|
+
if (typeof f.send_to !== "string") return null;
|
|
465
|
+
return {
|
|
466
|
+
send_to: f.send_to,
|
|
467
|
+
value_cents: typeof f.value_cents === "number" ? f.value_cents : null,
|
|
468
|
+
currency: typeof f.currency === "string" ? f.currency : null
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
function parseTrigger(value) {
|
|
472
|
+
if (!value || typeof value !== "object") return null;
|
|
473
|
+
const t = value;
|
|
474
|
+
if (typeof t.event_type !== "string") return null;
|
|
475
|
+
const spec = { event_type: t.event_type };
|
|
476
|
+
if (typeof t.threshold_percent === "number") spec.threshold_percent = t.threshold_percent;
|
|
477
|
+
if (typeof t.threshold_seconds === "number") spec.threshold_seconds = t.threshold_seconds;
|
|
478
|
+
if (typeof t.page_threshold === "number") spec.page_threshold = t.page_threshold;
|
|
479
|
+
if (typeof t.page_name === "string") spec.page_name = t.page_name;
|
|
480
|
+
return spec;
|
|
481
|
+
}
|
|
482
|
+
function parseConversionConfig(raw) {
|
|
483
|
+
if (!raw || typeof raw !== "object") return null;
|
|
484
|
+
const obj = raw;
|
|
485
|
+
const servicesRaw = Array.isArray(obj.services) ? obj.services : [];
|
|
486
|
+
const services = servicesRaw.flatMap((entry) => {
|
|
487
|
+
if (!entry || typeof entry !== "object") return [];
|
|
488
|
+
const s = entry;
|
|
489
|
+
if (typeof s.key !== "string") return [];
|
|
490
|
+
return [
|
|
491
|
+
{
|
|
492
|
+
key: s.key,
|
|
493
|
+
label: typeof s.label === "string" ? s.label : void 0,
|
|
494
|
+
firing: parseFiring(s.firing)
|
|
495
|
+
}
|
|
496
|
+
];
|
|
210
497
|
});
|
|
211
|
-
|
|
498
|
+
const goalsRaw = Array.isArray(obj.goals) ? obj.goals : null;
|
|
499
|
+
const goals = goalsRaw ? goalsRaw.flatMap((entry) => {
|
|
500
|
+
if (!entry || typeof entry !== "object") return [];
|
|
501
|
+
const g = entry;
|
|
502
|
+
if (typeof g.key !== "string") return [];
|
|
503
|
+
return [
|
|
504
|
+
{
|
|
505
|
+
key: g.key,
|
|
506
|
+
label: typeof g.label === "string" ? g.label : void 0,
|
|
507
|
+
kind: g.kind === "event" ? "event" : "sale",
|
|
508
|
+
trigger: parseTrigger(g.trigger),
|
|
509
|
+
firing: parseFiring(g.firing)
|
|
510
|
+
}
|
|
511
|
+
];
|
|
512
|
+
}) : services.map((s) => ({
|
|
513
|
+
key: s.key,
|
|
514
|
+
label: s.label,
|
|
515
|
+
kind: "sale",
|
|
516
|
+
trigger: null,
|
|
517
|
+
firing: s.firing
|
|
518
|
+
}));
|
|
519
|
+
return {
|
|
520
|
+
schema_version: typeof obj.schema_version === "number" ? obj.schema_version : 1,
|
|
521
|
+
config_version: typeof obj.config_version === "number" ? obj.config_version : 0,
|
|
522
|
+
business_id: typeof obj.business_id === "string" ? obj.business_id : void 0,
|
|
523
|
+
customer_id: typeof obj.customer_id === "string" ? obj.customer_id : null,
|
|
524
|
+
environment: typeof obj.environment === "string" ? obj.environment : void 0,
|
|
525
|
+
gtag_ids: isStringMap(obj.gtag_ids) ? obj.gtag_ids : {},
|
|
526
|
+
meta_pixel_ids: isStringMap(obj.meta_pixel_ids) ? obj.meta_pixel_ids : {},
|
|
527
|
+
services,
|
|
528
|
+
goals
|
|
529
|
+
};
|
|
212
530
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
531
|
+
var CACHE_PREFIX = "_aranova_cfg_";
|
|
532
|
+
function cacheKey(url) {
|
|
533
|
+
return `${CACHE_PREFIX}${url}`;
|
|
534
|
+
}
|
|
535
|
+
function readCache(url) {
|
|
536
|
+
if (typeof window === "undefined") return null;
|
|
537
|
+
try {
|
|
538
|
+
const raw = window.sessionStorage.getItem(cacheKey(url));
|
|
539
|
+
if (!raw) return null;
|
|
540
|
+
const parsed = JSON.parse(raw);
|
|
541
|
+
const config = parseConversionConfig(parsed.config);
|
|
542
|
+
if (!config) return null;
|
|
543
|
+
return {
|
|
544
|
+
etag: typeof parsed.etag === "string" ? parsed.etag : null,
|
|
545
|
+
config
|
|
546
|
+
};
|
|
547
|
+
} catch {
|
|
548
|
+
return null;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
function writeCache(url, entry) {
|
|
552
|
+
if (typeof window === "undefined") return;
|
|
553
|
+
try {
|
|
554
|
+
window.sessionStorage.setItem(cacheKey(url), JSON.stringify(entry));
|
|
555
|
+
} catch {
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
function resolveConversionConfig(options) {
|
|
559
|
+
const cached = readCache(options.cdnUrl);
|
|
560
|
+
let current = cached?.config ?? options.baked ?? null;
|
|
561
|
+
let etag = cached?.etag ?? null;
|
|
562
|
+
const goalsByKey = /* @__PURE__ */ new Map();
|
|
563
|
+
function rebuildIndex() {
|
|
564
|
+
goalsByKey.clear();
|
|
565
|
+
for (const goal of current?.goals ?? []) {
|
|
566
|
+
goalsByKey.set(goal.key, goal);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
function adopt(next, nextEtag) {
|
|
570
|
+
if (!next) return;
|
|
571
|
+
if (current && next.config_version <= current.config_version) return;
|
|
572
|
+
current = next;
|
|
573
|
+
etag = nextEtag;
|
|
574
|
+
rebuildIndex();
|
|
575
|
+
writeCache(options.cdnUrl, { etag, config: next });
|
|
576
|
+
}
|
|
577
|
+
async function revalidate() {
|
|
578
|
+
if (typeof window === "undefined") return;
|
|
579
|
+
try {
|
|
580
|
+
const doFetch = options.fetchImpl ?? globalThis.fetch;
|
|
581
|
+
if (!doFetch) return;
|
|
582
|
+
const headers = {};
|
|
583
|
+
if (etag) headers["If-None-Match"] = etag;
|
|
584
|
+
const response = await doFetch(options.cdnUrl, {
|
|
585
|
+
method: "GET",
|
|
586
|
+
headers
|
|
587
|
+
});
|
|
588
|
+
if (response.status === 304 || !response.ok) return;
|
|
589
|
+
adopt(parseConversionConfig(await response.json()), response.headers.get("ETag"));
|
|
590
|
+
} catch {
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
rebuildIndex();
|
|
594
|
+
void revalidate();
|
|
595
|
+
return {
|
|
596
|
+
getFiring: (key) => goalsByKey.get(key)?.firing ?? null,
|
|
597
|
+
getGoal: (key) => goalsByKey.get(key) ?? null,
|
|
598
|
+
listGoals: () => [...goalsByKey.values()],
|
|
599
|
+
current: () => current,
|
|
600
|
+
revalidate
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// ../tracking-core/src/resources/sales/money.ts
|
|
605
|
+
var MINOR_UNIT_EXPONENT = {
|
|
606
|
+
USD: 2,
|
|
607
|
+
CAD: 2
|
|
608
|
+
};
|
|
609
|
+
function exponentFor(currency) {
|
|
610
|
+
return MINOR_UNIT_EXPONENT[currency] ?? 2;
|
|
611
|
+
}
|
|
612
|
+
function toMinor(amount, currency) {
|
|
613
|
+
return Math.round(amount * 10 ** exponentFor(currency));
|
|
614
|
+
}
|
|
615
|
+
function fromMinor(cents, currency) {
|
|
616
|
+
return cents / 10 ** exponentFor(currency);
|
|
617
|
+
}
|
|
618
|
+
function formatMoney(cents, currency, locale) {
|
|
619
|
+
return new Intl.NumberFormat(locale, { style: "currency", currency }).format(
|
|
620
|
+
fromMinor(cents, currency)
|
|
621
|
+
);
|
|
622
|
+
}
|
|
623
|
+
function formatDateInTz(iso, timeZone, opts, locale) {
|
|
624
|
+
const date = new Date(iso);
|
|
625
|
+
if (Number.isNaN(date.getTime())) return iso;
|
|
626
|
+
return new Intl.DateTimeFormat(locale, {
|
|
627
|
+
year: "numeric",
|
|
628
|
+
month: "short",
|
|
629
|
+
day: "2-digit",
|
|
630
|
+
hour: "2-digit",
|
|
631
|
+
minute: "2-digit",
|
|
632
|
+
...opts,
|
|
633
|
+
timeZone
|
|
634
|
+
}).format(date);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// ../tracking-core/src/resources/conversion-autofire.ts
|
|
638
|
+
function thresholdMet(goal, eventType, metadata) {
|
|
639
|
+
const t = goal.trigger;
|
|
640
|
+
if (!t || t.event_type !== eventType) return false;
|
|
641
|
+
switch (eventType) {
|
|
642
|
+
case "scroll_depth":
|
|
643
|
+
return typeof metadata.depth_percent === "number" && t.threshold_percent != null && metadata.depth_percent >= t.threshold_percent;
|
|
644
|
+
case "time_on_site":
|
|
645
|
+
return typeof metadata.duration_ms === "number" && t.threshold_seconds != null && metadata.duration_ms >= t.threshold_seconds * 1e3;
|
|
646
|
+
case "multi_page_session":
|
|
647
|
+
return typeof metadata.page_count === "number" && t.page_threshold != null && metadata.page_count >= t.page_threshold;
|
|
648
|
+
case "specific_page_visit":
|
|
649
|
+
return typeof metadata.page_name === "string" && metadata.page_name === t.page_name;
|
|
650
|
+
case "page_view":
|
|
651
|
+
case "form_start":
|
|
652
|
+
return true;
|
|
653
|
+
// no threshold — fire whenever the detector emits
|
|
654
|
+
default:
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
function currentPath() {
|
|
659
|
+
return typeof window === "undefined" ? "" : window.location.pathname;
|
|
660
|
+
}
|
|
661
|
+
function createConversionAutoFire(store) {
|
|
662
|
+
return {
|
|
663
|
+
onAutomaticEvent(eventType, metadata) {
|
|
664
|
+
for (const goal of store.listGoals()) {
|
|
665
|
+
if (goal.kind !== "event" || !goal.firing) continue;
|
|
666
|
+
if (!thresholdMet(goal, eventType, metadata)) continue;
|
|
667
|
+
const firing = goal.firing;
|
|
668
|
+
const cents = firing.value_cents ?? null;
|
|
669
|
+
const currency = firing.currency ?? null;
|
|
670
|
+
fireConversionWithConsent({
|
|
671
|
+
sendTo: firing.send_to,
|
|
672
|
+
value: cents != null && currency ? fromMinor(cents, currency) : null,
|
|
673
|
+
currency,
|
|
674
|
+
// Page-scoped txn id → fire once per (goal, path) per session; engagement conversions
|
|
675
|
+
// shouldn't re-fire as the visitor scrolls back and forth or re-enters a page.
|
|
676
|
+
transactionId: `auto:${goal.key}:${currentPath()}`
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
function withConversionAutoFire(client, autoFire) {
|
|
683
|
+
return {
|
|
684
|
+
...client,
|
|
685
|
+
trackEvent: (input) => {
|
|
686
|
+
client.trackEvent(input);
|
|
687
|
+
try {
|
|
688
|
+
autoFire.onAutomaticEvent(input.eventType, input.metadata ?? {});
|
|
689
|
+
} catch {
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
};
|
|
217
693
|
}
|
|
218
694
|
|
|
219
695
|
// ../tracking-core/src/session.ts
|
|
@@ -544,11 +1020,22 @@ function createTrackingClient(config) {
|
|
|
544
1020
|
let queue = [];
|
|
545
1021
|
let flushTimer = null;
|
|
546
1022
|
let firstPage = null;
|
|
1023
|
+
let initialParams = createEmptyTrackingParams();
|
|
547
1024
|
let destroyed = false;
|
|
548
1025
|
const visitorId = getVisitorId();
|
|
549
1026
|
const initialSession = getOrRotateSessionId();
|
|
550
1027
|
let sessionId = initialSession.id;
|
|
551
|
-
if (typeof window !== "undefined")
|
|
1028
|
+
if (typeof window !== "undefined") {
|
|
1029
|
+
firstPage = window.location.href;
|
|
1030
|
+
try {
|
|
1031
|
+
initialParams = captureTrackingParamsFromLocation();
|
|
1032
|
+
} catch {
|
|
1033
|
+
}
|
|
1034
|
+
try {
|
|
1035
|
+
captureFbc();
|
|
1036
|
+
} catch {
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
552
1039
|
function enqueueHeartbeat() {
|
|
553
1040
|
const metadata = buildHeartbeatMetadata(
|
|
554
1041
|
config.surface,
|
|
@@ -573,7 +1060,7 @@ function createTrackingClient(config) {
|
|
|
573
1060
|
enqueueHeartbeat();
|
|
574
1061
|
}
|
|
575
1062
|
sessionId = rotated.id;
|
|
576
|
-
const params = readTrackingParams();
|
|
1063
|
+
const params = mergeTrackingParams(readTrackingParams(), initialParams);
|
|
577
1064
|
const context = buildContext(
|
|
578
1065
|
config.surface,
|
|
579
1066
|
sdkVersion,
|
|
@@ -586,6 +1073,8 @@ function createTrackingClient(config) {
|
|
|
586
1073
|
visitor_id: visitorId,
|
|
587
1074
|
gclid: params.gclid,
|
|
588
1075
|
fbclid: params.fbclid,
|
|
1076
|
+
fbc: getFbcCookie(),
|
|
1077
|
+
fbp: getFbpCookie(),
|
|
589
1078
|
utm_source: params.utm_source,
|
|
590
1079
|
utm_medium: params.utm_medium,
|
|
591
1080
|
utm_campaign: params.utm_campaign,
|
|
@@ -1022,7 +1511,7 @@ function attachScrollDepth(client, config) {
|
|
|
1022
1511
|
}
|
|
1023
1512
|
const thresholds = new Set(config.thresholds);
|
|
1024
1513
|
let firedForPath = /* @__PURE__ */ new Set();
|
|
1025
|
-
let
|
|
1514
|
+
let currentPath2 = window.location.pathname;
|
|
1026
1515
|
let rafId = null;
|
|
1027
1516
|
function getScrollPercent() {
|
|
1028
1517
|
const doc = document.documentElement;
|
|
@@ -1041,7 +1530,7 @@ function attachScrollDepth(client, config) {
|
|
|
1041
1530
|
eventType: "scroll_depth",
|
|
1042
1531
|
metadata: {
|
|
1043
1532
|
depth_percent: threshold,
|
|
1044
|
-
page: { path:
|
|
1533
|
+
page: { path: currentPath2 }
|
|
1045
1534
|
},
|
|
1046
1535
|
pageUrl: window.location.href,
|
|
1047
1536
|
occurredAt: null
|
|
@@ -1058,8 +1547,8 @@ function attachScrollDepth(client, config) {
|
|
|
1058
1547
|
}
|
|
1059
1548
|
function resetIfPathChanged() {
|
|
1060
1549
|
const newPath = window.location.pathname;
|
|
1061
|
-
if (newPath ===
|
|
1062
|
-
|
|
1550
|
+
if (newPath === currentPath2) return;
|
|
1551
|
+
currentPath2 = newPath;
|
|
1063
1552
|
firedForPath = /* @__PURE__ */ new Set();
|
|
1064
1553
|
setTimeout(checkThresholds, 0);
|
|
1065
1554
|
}
|
|
@@ -1135,13 +1624,13 @@ function attachMultiPageSession(client, config) {
|
|
|
1135
1624
|
return storage.getItem(FIRED_KEY) === "1";
|
|
1136
1625
|
}
|
|
1137
1626
|
function check() {
|
|
1138
|
-
const
|
|
1139
|
-
if (
|
|
1140
|
-
lastCheckedPath =
|
|
1627
|
+
const currentPath2 = window.location.pathname;
|
|
1628
|
+
if (currentPath2 === lastCheckedPath) return;
|
|
1629
|
+
lastCheckedPath = currentPath2;
|
|
1141
1630
|
resetIfSessionChanged();
|
|
1142
1631
|
if (hasFired()) return;
|
|
1143
1632
|
const paths = getDistinctPaths();
|
|
1144
|
-
paths.add(
|
|
1633
|
+
paths.add(currentPath2);
|
|
1145
1634
|
saveDistinctPaths(paths);
|
|
1146
1635
|
if (paths.size >= pageThreshold) {
|
|
1147
1636
|
storage.setItem(FIRED_KEY, "1");
|
|
@@ -1185,7 +1674,7 @@ function attachFormStart(client, config) {
|
|
|
1185
1674
|
}
|
|
1186
1675
|
const selector = config.selector ?? "form";
|
|
1187
1676
|
let firedForms = /* @__PURE__ */ new Set();
|
|
1188
|
-
let
|
|
1677
|
+
let currentPath2 = window.location.pathname;
|
|
1189
1678
|
function getFormKey(form) {
|
|
1190
1679
|
if (form.id) return `id:${form.id}`;
|
|
1191
1680
|
const explicitAction = form.getAttribute("action");
|
|
@@ -1216,8 +1705,8 @@ function attachFormStart(client, config) {
|
|
|
1216
1705
|
}
|
|
1217
1706
|
function resetIfPathChanged() {
|
|
1218
1707
|
const newPath = window.location.pathname;
|
|
1219
|
-
if (newPath ===
|
|
1220
|
-
|
|
1708
|
+
if (newPath === currentPath2) return;
|
|
1709
|
+
currentPath2 = newPath;
|
|
1221
1710
|
firedForms = /* @__PURE__ */ new Set();
|
|
1222
1711
|
}
|
|
1223
1712
|
const originalPushState = history.pushState.bind(history);
|
|
@@ -1296,21 +1785,64 @@ async function salesRequest(config, method, path, body) {
|
|
|
1296
1785
|
}
|
|
1297
1786
|
|
|
1298
1787
|
// ../tracking-core/src/resources/sales/client.ts
|
|
1788
|
+
function fireRecordedConversions(firing, input, recorded, sale, currency) {
|
|
1789
|
+
if (!firing) return;
|
|
1790
|
+
const txnBase = input.external_id ?? sale.id;
|
|
1791
|
+
for (const item of recorded) {
|
|
1792
|
+
if (!item.service) continue;
|
|
1793
|
+
const config = firing.getFiring(item.service);
|
|
1794
|
+
if (!config) continue;
|
|
1795
|
+
const cents = item.amount_cents ?? config.value_cents ?? null;
|
|
1796
|
+
fireConversionWithConsent({
|
|
1797
|
+
sendTo: config.send_to,
|
|
1798
|
+
value: cents != null ? fromMinor(cents, currency) : null,
|
|
1799
|
+
currency: config.currency ?? currency,
|
|
1800
|
+
transactionId: `${txnBase}:${item.service}`
|
|
1801
|
+
});
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1299
1804
|
function createSalesClient(config) {
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1805
|
+
async function record(input) {
|
|
1806
|
+
const currency = input.currency ?? config.defaultCurrency;
|
|
1807
|
+
if (!currency) {
|
|
1808
|
+
throw new Error(
|
|
1809
|
+
"record: `currency` is required (pass it on the sale or set config.defaultCurrency)"
|
|
1810
|
+
);
|
|
1811
|
+
}
|
|
1812
|
+
const body = {
|
|
1813
|
+
...input,
|
|
1814
|
+
currency,
|
|
1815
|
+
occurred_at: input.occurred_at ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
1816
|
+
};
|
|
1817
|
+
const sale = await salesRequest(config, "POST", "/sales", body);
|
|
1818
|
+
const recorded = input.services?.length ? input.services.map((s) => ({
|
|
1819
|
+
service: s.service,
|
|
1820
|
+
amount_cents: s.amount_cents
|
|
1821
|
+
})) : [
|
|
1822
|
+
{
|
|
1823
|
+
service: input.service,
|
|
1824
|
+
amount_cents: input.amount_total_cents ?? null
|
|
1307
1825
|
}
|
|
1308
|
-
|
|
1309
|
-
|
|
1826
|
+
];
|
|
1827
|
+
fireRecordedConversions(config.firing, input, recorded, sale, currency);
|
|
1828
|
+
return sale;
|
|
1829
|
+
}
|
|
1830
|
+
return {
|
|
1831
|
+
record,
|
|
1832
|
+
// recordSale is the intent-revealing alias — same behavior, clearer call site.
|
|
1833
|
+
recordSale: record,
|
|
1834
|
+
trackConversion(key, options) {
|
|
1835
|
+
const firing = config.firing?.getFiring(key);
|
|
1836
|
+
if (!firing) return;
|
|
1837
|
+
const currency = firing.currency ?? options?.currency ?? config.defaultCurrency ?? null;
|
|
1838
|
+
const cents = firing.value_cents ?? null;
|
|
1839
|
+
const value = options?.value ?? (cents != null && currency ? fromMinor(cents, currency) : null);
|
|
1840
|
+
fireConversionWithConsent({
|
|
1841
|
+
sendTo: firing.send_to,
|
|
1842
|
+
value,
|
|
1310
1843
|
currency,
|
|
1311
|
-
|
|
1312
|
-
};
|
|
1313
|
-
return salesRequest(config, "POST", "/sales", body);
|
|
1844
|
+
transactionId: options?.transactionId ?? null
|
|
1845
|
+
});
|
|
1314
1846
|
},
|
|
1315
1847
|
async list(query) {
|
|
1316
1848
|
const { cursor, limit, sort, order, want_total, ...filters } = query ?? {};
|
|
@@ -1404,39 +1936,6 @@ function createSalesClient(config) {
|
|
|
1404
1936
|
};
|
|
1405
1937
|
}
|
|
1406
1938
|
|
|
1407
|
-
// ../tracking-core/src/resources/sales/money.ts
|
|
1408
|
-
var MINOR_UNIT_EXPONENT = {
|
|
1409
|
-
USD: 2,
|
|
1410
|
-
CAD: 2
|
|
1411
|
-
};
|
|
1412
|
-
function exponentFor(currency) {
|
|
1413
|
-
return MINOR_UNIT_EXPONENT[currency] ?? 2;
|
|
1414
|
-
}
|
|
1415
|
-
function toMinor(amount, currency) {
|
|
1416
|
-
return Math.round(amount * 10 ** exponentFor(currency));
|
|
1417
|
-
}
|
|
1418
|
-
function fromMinor(cents, currency) {
|
|
1419
|
-
return cents / 10 ** exponentFor(currency);
|
|
1420
|
-
}
|
|
1421
|
-
function formatMoney(cents, currency, locale) {
|
|
1422
|
-
return new Intl.NumberFormat(locale, { style: "currency", currency }).format(
|
|
1423
|
-
fromMinor(cents, currency)
|
|
1424
|
-
);
|
|
1425
|
-
}
|
|
1426
|
-
function formatDateInTz(iso, timeZone, opts, locale) {
|
|
1427
|
-
const date = new Date(iso);
|
|
1428
|
-
if (Number.isNaN(date.getTime())) return iso;
|
|
1429
|
-
return new Intl.DateTimeFormat(locale, {
|
|
1430
|
-
year: "numeric",
|
|
1431
|
-
month: "short",
|
|
1432
|
-
day: "2-digit",
|
|
1433
|
-
hour: "2-digit",
|
|
1434
|
-
minute: "2-digit",
|
|
1435
|
-
...opts,
|
|
1436
|
-
timeZone
|
|
1437
|
-
}).format(date);
|
|
1438
|
-
}
|
|
1439
|
-
|
|
1440
1939
|
// ../tracking-core/src/resources/sales/schema.ts
|
|
1441
1940
|
import { z as z11 } from "zod";
|
|
1442
1941
|
var SUPPORTED_CURRENCIES = ["USD", "CAD"];
|
|
@@ -1835,11 +2334,19 @@ var ANIMATION_KEYFRAMES = `
|
|
|
1835
2334
|
}
|
|
1836
2335
|
`;
|
|
1837
2336
|
|
|
1838
|
-
// src/
|
|
2337
|
+
// src/AdPlatformTracking.tsx
|
|
1839
2338
|
import { useEffect as useEffect3, useMemo } from "react";
|
|
1840
|
-
function
|
|
1841
|
-
|
|
2339
|
+
function AdPlatformTracking({
|
|
2340
|
+
gtagId,
|
|
2341
|
+
gtagIds,
|
|
2342
|
+
metaPixelId,
|
|
2343
|
+
metaPixelIds
|
|
2344
|
+
}) {
|
|
1842
2345
|
const gtagIdsKey = useMemo(() => gtagIds ? JSON.stringify(gtagIds) : "", [gtagIds]);
|
|
2346
|
+
const metaPixelIdsKey = useMemo(
|
|
2347
|
+
() => metaPixelIds ? JSON.stringify(metaPixelIds) : "",
|
|
2348
|
+
[metaPixelIds]
|
|
2349
|
+
);
|
|
1843
2350
|
useEffect3(() => {
|
|
1844
2351
|
if (gtagIds && Object.keys(gtagIds).length > 0) {
|
|
1845
2352
|
bootstrapMultipleGtags(gtagIds);
|
|
@@ -1847,14 +2354,36 @@ function GoogleAdsTracking(props) {
|
|
|
1847
2354
|
bootstrapGoogleAdsTracking(gtagId);
|
|
1848
2355
|
}
|
|
1849
2356
|
}, [gtagId, gtagIdsKey]);
|
|
2357
|
+
useEffect3(() => {
|
|
2358
|
+
if (metaPixelIds && Object.keys(metaPixelIds).length > 0) {
|
|
2359
|
+
bootstrapMultiplePixels(metaPixelIds);
|
|
2360
|
+
} else if (metaPixelId) {
|
|
2361
|
+
bootstrapMetaPixel(metaPixelId);
|
|
2362
|
+
}
|
|
2363
|
+
}, [metaPixelId, metaPixelIdsKey]);
|
|
2364
|
+
return null;
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
// src/GoogleAdsTracking.tsx
|
|
2368
|
+
import { useEffect as useEffect4, useMemo as useMemo2 } from "react";
|
|
2369
|
+
function GoogleAdsTracking(props) {
|
|
2370
|
+
const { gtagId, gtagIds } = props;
|
|
2371
|
+
const gtagIdsKey = useMemo2(() => gtagIds ? JSON.stringify(gtagIds) : "", [gtagIds]);
|
|
2372
|
+
useEffect4(() => {
|
|
2373
|
+
if (gtagIds && Object.keys(gtagIds).length > 0) {
|
|
2374
|
+
bootstrapMultipleGtags(gtagIds);
|
|
2375
|
+
} else if (gtagId) {
|
|
2376
|
+
bootstrapGoogleAdsTracking(gtagId);
|
|
2377
|
+
}
|
|
2378
|
+
}, [gtagId, gtagIdsKey]);
|
|
1850
2379
|
return null;
|
|
1851
2380
|
}
|
|
1852
2381
|
|
|
1853
2382
|
// src/factory.tsx
|
|
1854
|
-
import { createContext as createContext2, useContext as useContext2, useEffect as
|
|
2383
|
+
import { createContext as createContext2, useContext as useContext2, useEffect as useEffect5, useMemo as useMemo4 } from "react";
|
|
1855
2384
|
|
|
1856
2385
|
// package.json
|
|
1857
|
-
var version = "0.
|
|
2386
|
+
var version = "0.14.0";
|
|
1858
2387
|
|
|
1859
2388
|
// ../tracking-core/src/phone-react.tsx
|
|
1860
2389
|
import {
|
|
@@ -1862,7 +2391,7 @@ import {
|
|
|
1862
2391
|
forwardRef,
|
|
1863
2392
|
useCallback as useCallback2,
|
|
1864
2393
|
useContext,
|
|
1865
|
-
useMemo as
|
|
2394
|
+
useMemo as useMemo3,
|
|
1866
2395
|
useState as useState3
|
|
1867
2396
|
} from "react";
|
|
1868
2397
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
@@ -1891,7 +2420,7 @@ function usePhoneField(opts = {}) {
|
|
|
1891
2420
|
const { onValueChange } = opts;
|
|
1892
2421
|
const [value, setValue] = useState3(() => formatPhoneAsTyped(opts.defaultValue ?? "", country));
|
|
1893
2422
|
const [touched, setTouched] = useState3(false);
|
|
1894
|
-
const parsed =
|
|
2423
|
+
const parsed = useMemo3(() => parsePhone(value, country), [value, country]);
|
|
1895
2424
|
const onChange = useCallback2(
|
|
1896
2425
|
(event) => {
|
|
1897
2426
|
const next = formatPhoneAsTyped(event.target.value, country);
|
|
@@ -1960,7 +2489,7 @@ var NOOP_CLIENT = {
|
|
|
1960
2489
|
getVisitorId: () => ""
|
|
1961
2490
|
};
|
|
1962
2491
|
function createTracking(options) {
|
|
1963
|
-
const { apiKey, endpoint, triggers, environment, debug, phone } = options;
|
|
2492
|
+
const { apiKey, endpoint, triggers, environment, debug, phone, conversionConfig } = options;
|
|
1964
2493
|
if (!apiKey || !endpoint) {
|
|
1965
2494
|
if (apiKey || endpoint) {
|
|
1966
2495
|
console.warn(
|
|
@@ -1976,11 +2505,17 @@ function createTracking(options) {
|
|
|
1976
2505
|
};
|
|
1977
2506
|
}
|
|
1978
2507
|
const TrackingContext = createContext2(null);
|
|
1979
|
-
function TrackingProvider({
|
|
2508
|
+
function TrackingProvider({
|
|
2509
|
+
gtagId,
|
|
2510
|
+
gtagIds,
|
|
2511
|
+
metaPixelId,
|
|
2512
|
+
metaPixelIds,
|
|
2513
|
+
children
|
|
2514
|
+
}) {
|
|
1980
2515
|
const resolvedGtagIds = gtagIds ? Object.fromEntries(
|
|
1981
2516
|
Object.entries(gtagIds).filter((e) => e[1] != null)
|
|
1982
2517
|
) : gtagId ? { default: gtagId } : void 0;
|
|
1983
|
-
const client =
|
|
2518
|
+
const client = useMemo4(
|
|
1984
2519
|
() => createTypedClient(
|
|
1985
2520
|
getOrCreateTrackingClient({
|
|
1986
2521
|
apiKey,
|
|
@@ -1998,15 +2533,26 @@ function createTracking(options) {
|
|
|
1998
2533
|
),
|
|
1999
2534
|
[]
|
|
2000
2535
|
);
|
|
2001
|
-
const gtagIdsKey =
|
|
2002
|
-
|
|
2536
|
+
const gtagIdsKey = useMemo4(() => gtagIds ? JSON.stringify(gtagIds) : "", [gtagIds]);
|
|
2537
|
+
useEffect5(() => {
|
|
2003
2538
|
if (gtagIds && Object.keys(gtagIds).length > 0) {
|
|
2004
2539
|
bootstrapMultipleGtags(gtagIds);
|
|
2005
2540
|
} else if (gtagId) {
|
|
2006
2541
|
bootstrapGoogleAdsTracking(gtagId);
|
|
2007
2542
|
}
|
|
2008
2543
|
}, [gtagId, gtagIdsKey]);
|
|
2009
|
-
|
|
2544
|
+
const metaPixelIdsKey = useMemo4(
|
|
2545
|
+
() => metaPixelIds ? JSON.stringify(metaPixelIds) : "",
|
|
2546
|
+
[metaPixelIds]
|
|
2547
|
+
);
|
|
2548
|
+
useEffect5(() => {
|
|
2549
|
+
if (metaPixelIds && Object.keys(metaPixelIds).length > 0) {
|
|
2550
|
+
bootstrapMultiplePixels(metaPixelIds);
|
|
2551
|
+
} else if (metaPixelId) {
|
|
2552
|
+
bootstrapMetaPixel(metaPixelId);
|
|
2553
|
+
}
|
|
2554
|
+
}, [metaPixelId, metaPixelIdsKey]);
|
|
2555
|
+
useEffect5(() => {
|
|
2010
2556
|
const detachers = [];
|
|
2011
2557
|
const rawClient = getOrCreateTrackingClient({
|
|
2012
2558
|
apiKey,
|
|
@@ -2018,27 +2564,32 @@ function createTracking(options) {
|
|
|
2018
2564
|
activeGtagIds: resolvedGtagIds,
|
|
2019
2565
|
debug
|
|
2020
2566
|
});
|
|
2021
|
-
|
|
2022
|
-
|
|
2567
|
+
const conversionStore = conversionConfig ? resolveConversionConfig({
|
|
2568
|
+
cdnUrl: conversionConfig.cdnUrl,
|
|
2569
|
+
baked: conversionConfig.baked
|
|
2570
|
+
}) : null;
|
|
2571
|
+
const detectorClient = conversionStore ? withConversionAutoFire(rawClient, createConversionAutoFire(conversionStore)) : rawClient;
|
|
2572
|
+
detachers.push(attachAutoPageView(detectorClient));
|
|
2573
|
+
detachers.push(attachBfcacheRestore(detectorClient));
|
|
2023
2574
|
const timeOnSite = triggers.automatic.time_on_site;
|
|
2024
2575
|
if (timeOnSite) {
|
|
2025
|
-
detachers.push(attachTimeOnSite(
|
|
2576
|
+
detachers.push(attachTimeOnSite(detectorClient, timeOnSite));
|
|
2026
2577
|
}
|
|
2027
2578
|
const specificPageVisit = triggers.automatic.specific_page_visit;
|
|
2028
2579
|
if (specificPageVisit) {
|
|
2029
|
-
detachers.push(attachSpecificPageVisit(
|
|
2580
|
+
detachers.push(attachSpecificPageVisit(detectorClient, specificPageVisit));
|
|
2030
2581
|
}
|
|
2031
2582
|
const scrollDepth = triggers.automatic.scroll_depth;
|
|
2032
2583
|
if (scrollDepth) {
|
|
2033
|
-
detachers.push(attachScrollDepth(
|
|
2584
|
+
detachers.push(attachScrollDepth(detectorClient, scrollDepth));
|
|
2034
2585
|
}
|
|
2035
2586
|
const multiPageSession = triggers.automatic.multi_page_session;
|
|
2036
2587
|
if (multiPageSession) {
|
|
2037
|
-
detachers.push(attachMultiPageSession(
|
|
2588
|
+
detachers.push(attachMultiPageSession(detectorClient, multiPageSession));
|
|
2038
2589
|
}
|
|
2039
2590
|
const formStart = triggers.automatic.form_start;
|
|
2040
2591
|
if (formStart) {
|
|
2041
|
-
detachers.push(attachFormStart(
|
|
2592
|
+
detachers.push(attachFormStart(detectorClient, formStart));
|
|
2042
2593
|
}
|
|
2043
2594
|
return () => {
|
|
2044
2595
|
for (let i = detachers.length - 1; i >= 0; i--) {
|
|
@@ -2060,6 +2611,7 @@ function createTracking(options) {
|
|
|
2060
2611
|
return { TrackingProvider, useTracking };
|
|
2061
2612
|
}
|
|
2062
2613
|
export {
|
|
2614
|
+
AdPlatformTracking,
|
|
2063
2615
|
AranovaApiError,
|
|
2064
2616
|
ConsentBanner,
|
|
2065
2617
|
DEFAULT_PHONE_COUNTRY,
|
|
@@ -2085,6 +2637,7 @@ export {
|
|
|
2085
2637
|
parsePhone,
|
|
2086
2638
|
phoneField,
|
|
2087
2639
|
resetConsent,
|
|
2640
|
+
resolveConversionConfig,
|
|
2088
2641
|
saleCreateSchema,
|
|
2089
2642
|
saleItemSchema,
|
|
2090
2643
|
saleServiceSchema,
|