@aranova/tracking-next 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/dist/index.js CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
+ AdPlatformTracking: () => AdPlatformTracking,
33
34
  AranovaApiError: () => AranovaApiError,
34
35
  ConsentBanner: () => ConsentBanner,
35
36
  DEFAULT_PHONE_COUNTRY: () => DEFAULT_PHONE_COUNTRY,
@@ -55,6 +56,7 @@ __export(src_exports, {
55
56
  parsePhone: () => parsePhone,
56
57
  phoneField: () => phoneField,
57
58
  resetConsent: () => resetConsent,
59
+ resolveConversionConfig: () => resolveConversionConfig,
58
60
  saleCreateSchema: () => saleCreateSchema,
59
61
  saleItemSchema: () => saleItemSchema,
60
62
  saleServiceSchema: () => saleServiceSchema,
@@ -75,6 +77,13 @@ module.exports = __toCommonJS(src_exports);
75
77
  // ../tracking-core/src/consent.ts
76
78
  var CONSENT_STATE_KEY = "consent_state";
77
79
  var CONSENT_TIMESTAMP_KEY = "consent_timestamp";
80
+ var grantedListeners = /* @__PURE__ */ new Set();
81
+ function onConsentGranted(listener) {
82
+ grantedListeners.add(listener);
83
+ return () => {
84
+ grantedListeners.delete(listener);
85
+ };
86
+ }
78
87
  function buildConsentPayload(state) {
79
88
  return {
80
89
  ad_storage: state,
@@ -85,62 +94,142 @@ function buildConsentPayload(state) {
85
94
  }
86
95
  function getConsentState() {
87
96
  if (typeof window === "undefined") return "pending";
88
- const storedState = window.localStorage.getItem(CONSENT_STATE_KEY);
89
- if (storedState === "granted" || storedState === "denied") return storedState;
97
+ try {
98
+ const storedState = window.localStorage.getItem(CONSENT_STATE_KEY);
99
+ if (storedState === "granted" || storedState === "denied") return storedState;
100
+ } catch {
101
+ }
90
102
  return "pending";
91
103
  }
92
104
  function setConsentState(state) {
93
105
  if (typeof window === "undefined") return;
94
- window.localStorage.setItem(CONSENT_STATE_KEY, state);
95
- window.localStorage.setItem(CONSENT_TIMESTAMP_KEY, (/* @__PURE__ */ new Date()).toISOString());
106
+ try {
107
+ window.localStorage.setItem(CONSENT_STATE_KEY, state);
108
+ window.localStorage.setItem(CONSENT_TIMESTAMP_KEY, (/* @__PURE__ */ new Date()).toISOString());
109
+ } catch {
110
+ }
96
111
  if (typeof window.gtag === "function")
97
112
  window.gtag("consent", "update", buildConsentPayload(state));
113
+ if (typeof window.fbq === "function")
114
+ window.fbq("consent", state === "granted" ? "grant" : "revoke");
115
+ if (state === "granted") {
116
+ for (const listener of grantedListeners) {
117
+ try {
118
+ listener();
119
+ } catch {
120
+ }
121
+ }
122
+ }
98
123
  }
99
124
  function resetConsent() {
100
125
  if (typeof window === "undefined") return;
101
- window.localStorage.removeItem(CONSENT_STATE_KEY);
102
- window.localStorage.removeItem(CONSENT_TIMESTAMP_KEY);
126
+ try {
127
+ window.localStorage.removeItem(CONSENT_STATE_KEY);
128
+ window.localStorage.removeItem(CONSENT_TIMESTAMP_KEY);
129
+ } catch {
130
+ }
103
131
  }
104
132
 
105
- // ../tracking-core/src/payloads.ts
106
- function createTrackingClientContext(surface, input = {}) {
133
+ // ../tracking-core/src/tracking.ts
134
+ var TRACKING_COOKIE_MAX_AGE_SECONDS = 7776e3;
135
+ var TRACKING_PARAM_KEYS = [
136
+ "gclid",
137
+ "fbclid",
138
+ "utm_source",
139
+ "utm_medium",
140
+ "utm_campaign",
141
+ "utm_term",
142
+ "utm_content"
143
+ ];
144
+ function createEmptyTrackingParams() {
107
145
  return {
108
- surface,
109
- sdk_version: input.sdkVersion ?? null,
110
- package_name: input.packageName ?? null,
111
- site_origin: input.siteOrigin ?? (typeof window === "undefined" ? null : window.location.origin),
112
- page_title: input.pageTitle ?? (typeof document === "undefined" ? null : document.title || null),
113
- referrer: input.referrer ?? (typeof document === "undefined" ? null : document.referrer || null),
114
- environment: input.environment ?? "production",
115
- active_gtag_ids: input.activeGtagIds ?? null
146
+ gclid: null,
147
+ fbclid: null,
148
+ utm_source: null,
149
+ utm_medium: null,
150
+ utm_campaign: null,
151
+ utm_term: null,
152
+ utm_content: null
116
153
  };
117
154
  }
118
- function createTrackingSessionUpsertPayload(trackingParams, input, context) {
119
- return {
120
- session_id: input.sessionId,
121
- visitor_id: input.visitorId ?? null,
122
- gclid: trackingParams.gclid,
123
- fbclid: trackingParams.fbclid,
124
- utm_source: trackingParams.utm_source,
125
- utm_medium: trackingParams.utm_medium,
126
- utm_campaign: trackingParams.utm_campaign,
127
- utm_term: trackingParams.utm_term,
128
- utm_content: trackingParams.utm_content,
129
- first_page: input.firstPage ?? null,
130
- consent_state: input.consentState ?? null,
131
- context
132
- };
155
+ function normalizeTrackingCookieValue(value) {
156
+ return typeof value === "string" && value.length > 0 ? value : null;
133
157
  }
134
- function createTrackingEventCreatePayload(trackingParams, input, context) {
135
- return {
136
- session_id: input.sessionId,
137
- event_type: input.eventType,
138
- gclid: trackingParams.gclid,
139
- fbclid: trackingParams.fbclid,
140
- page_url: input.pageUrl ?? (typeof window === "undefined" ? null : window.location.href),
141
- metadata: input.metadata ?? null,
142
- context
143
- };
158
+ function getTrackingParamsFromCookieReader(readCookie) {
159
+ return TRACKING_PARAM_KEYS.reduce((params, key) => {
160
+ params[key] = normalizeTrackingCookieValue(readCookie(key));
161
+ return params;
162
+ }, createEmptyTrackingParams());
163
+ }
164
+ function getTrackingQueryValues(searchParams) {
165
+ return TRACKING_PARAM_KEYS.reduce((params, key) => {
166
+ const value = searchParams.get(key);
167
+ if (typeof value === "string" && value.trim().length > 0) {
168
+ params[key] = value;
169
+ }
170
+ return params;
171
+ }, {});
172
+ }
173
+ var FALLBACK_STORAGE_PREFIX = "_aranova_track_";
174
+ function fallbackKey(name) {
175
+ return `${FALLBACK_STORAGE_PREFIX}${name}`;
176
+ }
177
+ function persistCookieValue(name, value, maxAgeSeconds = TRACKING_COOKIE_MAX_AGE_SECONDS) {
178
+ const encoded = encodeURIComponent(value);
179
+ if (typeof document !== "undefined") {
180
+ try {
181
+ document.cookie = `${name}=${encoded}; Max-Age=${maxAgeSeconds}; Path=/; SameSite=Lax`;
182
+ } catch {
183
+ }
184
+ }
185
+ if (typeof window !== "undefined") {
186
+ try {
187
+ window.localStorage.setItem(fallbackKey(name), encoded);
188
+ } catch {
189
+ }
190
+ }
191
+ }
192
+ function readCookieValue(name) {
193
+ if (typeof document !== "undefined") {
194
+ const cookies = document.cookie ? document.cookie.split("; ") : [];
195
+ const match = cookies.find((cookie) => cookie.startsWith(`${name}=`));
196
+ if (match) {
197
+ const [, rawValue = ""] = match.split("=");
198
+ return normalizeTrackingCookieValue(decodeURIComponent(rawValue));
199
+ }
200
+ }
201
+ if (typeof window !== "undefined") {
202
+ try {
203
+ const stored = window.localStorage.getItem(fallbackKey(name));
204
+ if (stored) return normalizeTrackingCookieValue(decodeURIComponent(stored));
205
+ } catch {
206
+ }
207
+ }
208
+ return null;
209
+ }
210
+ function getCookieValueFromDocument(key) {
211
+ return readCookieValue(key);
212
+ }
213
+ function setTrackingCookie(key, value, maxAgeSeconds = TRACKING_COOKIE_MAX_AGE_SECONDS) {
214
+ persistCookieValue(key, value, maxAgeSeconds);
215
+ }
216
+ function mergeTrackingParams(primary, fallback) {
217
+ return TRACKING_PARAM_KEYS.reduce((merged, key) => {
218
+ merged[key] = primary[key] ?? fallback[key];
219
+ return merged;
220
+ }, createEmptyTrackingParams());
221
+ }
222
+ function persistTrackingParamsFromSearchParams(searchParams, maxAgeSeconds = TRACKING_COOKIE_MAX_AGE_SECONDS) {
223
+ const trackingValues = getTrackingQueryValues(searchParams);
224
+ Object.entries(trackingValues).forEach(([key, value]) => {
225
+ setTrackingCookie(key, value, maxAgeSeconds);
226
+ });
227
+ return trackingValues;
228
+ }
229
+ function captureTrackingParamsFromLocation(url = typeof window === "undefined" ? "" : window.location.href, maxAgeSeconds = TRACKING_COOKIE_MAX_AGE_SECONDS) {
230
+ const resolvedUrl = typeof window === "undefined" ? new URL(url || "https://example.invalid") : new URL(url, window.location.origin);
231
+ persistTrackingParamsFromSearchParams(resolvedUrl.searchParams, maxAgeSeconds);
232
+ return getTrackingParamsFromCookieReader(getCookieValueFromDocument);
144
233
  }
145
234
 
146
235
  // ../tracking-core/src/gtag.ts
@@ -174,17 +263,37 @@ gtag('config', '${gtagId}');
174
263
  }
175
264
  function createConsentRestoreScript() {
176
265
  return `
177
- const consentState = window.localStorage.getItem('consent_state');
178
- if (window.gtag && (consentState === 'granted' || consentState === 'denied')) {
179
- window.gtag('consent', 'update', {
180
- ad_storage: consentState,
181
- ad_user_data: consentState,
182
- ad_personalization: consentState,
183
- analytics_storage: consentState,
184
- });
185
- }
266
+ try {
267
+ var consentState = window.localStorage.getItem('consent_state');
268
+ if (window.gtag && (consentState === 'granted' || consentState === 'denied')) {
269
+ window.gtag('consent', 'update', {
270
+ ad_storage: consentState,
271
+ ad_user_data: consentState,
272
+ ad_personalization: consentState,
273
+ analytics_storage: consentState,
274
+ });
275
+ }
276
+ } catch (e) {}
186
277
  `.trim();
187
278
  }
279
+ var SEND_TO_RE = /^AW-[A-Za-z0-9]+\/[A-Za-z0-9_-]+$/;
280
+ function isValidSendTo(sendTo) {
281
+ return SEND_TO_RE.test(sendTo);
282
+ }
283
+ function fireGtagConversion(input) {
284
+ if (typeof window === "undefined" || typeof window.gtag !== "function") return false;
285
+ if (!isValidSendTo(input.sendTo)) return false;
286
+ const params = { send_to: input.sendTo };
287
+ if (input.value != null) params.value = input.value;
288
+ if (input.currency) params.currency = input.currency;
289
+ if (input.transactionId) params.transaction_id = input.transactionId;
290
+ try {
291
+ window.gtag("event", "conversion", params);
292
+ return true;
293
+ } catch {
294
+ return false;
295
+ }
296
+ }
188
297
  function createGtagInitScriptMulti(gtagIds) {
189
298
  const safeIds = gtagIds.filter(isValidGtagId);
190
299
  const configs = safeIds.map((id) => `gtag('config', '${id}');`).join("\n");
@@ -197,70 +306,403 @@ ${configs}
197
306
  `.trim();
198
307
  }
199
308
 
200
- // ../tracking-core/src/tracking.ts
201
- var TRACKING_COOKIE_MAX_AGE_SECONDS = 7776e3;
202
- var TRACKING_PARAM_KEYS = [
203
- "gclid",
204
- "fbclid",
205
- "utm_source",
206
- "utm_medium",
207
- "utm_campaign",
208
- "utm_term",
209
- "utm_content"
210
- ];
211
- function createEmptyTrackingParams() {
309
+ // ../tracking-core/src/fbq.ts
310
+ var FB_EVENTS_SCRIPT_HOST = "https://connect.facebook.net/en_US/fbevents.js";
311
+ var FBC_COOKIE = "_fbc";
312
+ var FBP_COOKIE = "_fbp";
313
+ var META_PIXEL_ID_PATTERN = /^\d{15,16}$/;
314
+ function isValidMetaPixelId(id) {
315
+ return META_PIXEL_ID_PATTERN.test(id);
316
+ }
317
+ function computeFbSubdomainIndex(hostname) {
318
+ const labels = hostname.split(".").filter(Boolean);
319
+ return Math.max(0, labels.length - 1);
320
+ }
321
+ function buildFbc(fbclid, now, hostname) {
322
+ const host = hostname ?? (typeof window === "undefined" ? "" : window.location.hostname);
323
+ return `fb.${computeFbSubdomainIndex(host)}.${now}.${fbclid}`;
324
+ }
325
+ function getFbcCookie() {
326
+ return readCookieValue(FBC_COOKIE);
327
+ }
328
+ function getFbpCookie() {
329
+ return readCookieValue(FBP_COOKIE);
330
+ }
331
+ function readFbclidFromUrl() {
332
+ if (typeof window === "undefined") return null;
333
+ try {
334
+ const value = new URL(window.location.href).searchParams.get("fbclid");
335
+ return value && value.trim().length > 0 ? value : null;
336
+ } catch {
337
+ return null;
338
+ }
339
+ }
340
+ function captureFbc(now = typeof Date === "undefined" ? 0 : Date.now()) {
341
+ if (typeof window === "undefined") return;
342
+ if (getFbcCookie()) return;
343
+ const fbclid = readFbclidFromUrl() ?? readCookieValue("fbclid");
344
+ if (!fbclid) return;
345
+ persistCookieValue(FBC_COOKIE, buildFbc(fbclid, now), TRACKING_COOKIE_MAX_AGE_SECONDS);
346
+ }
347
+ function fbqStubScript() {
348
+ return `
349
+ !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
350
+ n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
351
+ n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
352
+ t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
353
+ document,'script','${FB_EVENTS_SCRIPT_HOST}');`.trim();
354
+ }
355
+ function createMetaConsentDefaultScript() {
356
+ return `${fbqStubScript()}
357
+ fbq('consent', 'revoke');`;
358
+ }
359
+ function createMetaPixelInitScript(pixelId) {
360
+ if (!isValidMetaPixelId(pixelId)) return "";
361
+ return `fbq('init', '${pixelId}');
362
+ fbq('track', 'PageView');`;
363
+ }
364
+ function createMetaPixelInitScriptMulti(pixelIds) {
365
+ const inits = pixelIds.filter(isValidMetaPixelId).map((id) => `fbq('init', '${id}');`);
366
+ if (inits.length === 0) return "";
367
+ return `${inits.join("\n")}
368
+ fbq('track', 'PageView');`;
369
+ }
370
+ function createMetaConsentRestoreScript() {
371
+ return `
372
+ try {
373
+ var consentState = window.localStorage.getItem('consent_state');
374
+ if (window.fbq && (consentState === 'granted' || consentState === 'denied')) {
375
+ window.fbq('consent', consentState === 'granted' ? 'grant' : 'revoke');
376
+ }
377
+ } catch (e) {}`.trim();
378
+ }
379
+
380
+ // ../tracking-core/src/payloads.ts
381
+ function createTrackingClientContext(surface, input = {}) {
212
382
  return {
213
- gclid: null,
214
- fbclid: null,
215
- utm_source: null,
216
- utm_medium: null,
217
- utm_campaign: null,
218
- utm_term: null,
219
- utm_content: null
383
+ surface,
384
+ sdk_version: input.sdkVersion ?? null,
385
+ package_name: input.packageName ?? null,
386
+ site_origin: input.siteOrigin ?? (typeof window === "undefined" ? null : window.location.origin),
387
+ page_title: input.pageTitle ?? (typeof document === "undefined" ? null : document.title || null),
388
+ referrer: input.referrer ?? (typeof document === "undefined" ? null : document.referrer || null),
389
+ environment: input.environment ?? "production",
390
+ active_gtag_ids: input.activeGtagIds ?? null
220
391
  };
221
392
  }
222
- function normalizeTrackingCookieValue(value) {
223
- return typeof value === "string" && value.length > 0 ? value : null;
393
+ function createTrackingSessionUpsertPayload(trackingParams, input, context) {
394
+ return {
395
+ session_id: input.sessionId,
396
+ visitor_id: input.visitorId ?? null,
397
+ gclid: trackingParams.gclid,
398
+ fbclid: trackingParams.fbclid,
399
+ fbc: getFbcCookie(),
400
+ fbp: getFbpCookie(),
401
+ utm_source: trackingParams.utm_source,
402
+ utm_medium: trackingParams.utm_medium,
403
+ utm_campaign: trackingParams.utm_campaign,
404
+ utm_term: trackingParams.utm_term,
405
+ utm_content: trackingParams.utm_content,
406
+ first_page: input.firstPage ?? null,
407
+ consent_state: input.consentState ?? null,
408
+ context
409
+ };
224
410
  }
225
- function getTrackingParamsFromCookieReader(readCookie) {
226
- return TRACKING_PARAM_KEYS.reduce((params, key) => {
227
- params[key] = normalizeTrackingCookieValue(readCookie(key));
228
- return params;
229
- }, createEmptyTrackingParams());
411
+ function createTrackingEventCreatePayload(trackingParams, input, context) {
412
+ return {
413
+ session_id: input.sessionId,
414
+ event_type: input.eventType,
415
+ gclid: trackingParams.gclid,
416
+ fbclid: trackingParams.fbclid,
417
+ fbc: getFbcCookie(),
418
+ fbp: getFbpCookie(),
419
+ page_url: input.pageUrl ?? (typeof window === "undefined" ? null : window.location.href),
420
+ metadata: input.metadata ?? null,
421
+ context
422
+ };
230
423
  }
231
- function getTrackingQueryValues(searchParams) {
232
- return TRACKING_PARAM_KEYS.reduce((params, key) => {
233
- const value = searchParams.get(key);
234
- if (typeof value === "string" && value.trim().length > 0) {
235
- params[key] = value;
236
- }
237
- return params;
238
- }, {});
424
+
425
+ // ../tracking-core/src/resources/conversion-firing.ts
426
+ var DEDUP_PREFIX = "_aranova_conv_";
427
+ var MAX_PENDING = 100;
428
+ var pendingQueue = [];
429
+ function dedupKey(input) {
430
+ return `${DEDUP_PREFIX}${input.transactionId ?? ""}:${input.sendTo}`;
431
+ }
432
+ function alreadyFired(input) {
433
+ if (!input.transactionId || typeof window === "undefined") return false;
434
+ try {
435
+ return window.sessionStorage.getItem(dedupKey(input)) !== null;
436
+ } catch {
437
+ return false;
438
+ }
239
439
  }
240
- function getCookieValueFromDocument(key) {
241
- if (typeof document === "undefined") return null;
242
- const cookies = document.cookie ? document.cookie.split("; ") : [];
243
- const match = cookies.find((cookie) => cookie.startsWith(`${key}=`));
244
- if (!match) return null;
245
- const [, rawValue = ""] = match.split("=");
246
- return normalizeTrackingCookieValue(decodeURIComponent(rawValue));
440
+ function markFired(input) {
441
+ if (!input.transactionId || typeof window === "undefined") return;
442
+ try {
443
+ window.sessionStorage.setItem(dedupKey(input), "1");
444
+ } catch {
445
+ }
247
446
  }
248
- function setTrackingCookie(key, value, maxAgeSeconds = TRACKING_COOKIE_MAX_AGE_SECONDS) {
249
- if (typeof document === "undefined") return;
250
- const encodedValue = encodeURIComponent(value);
251
- document.cookie = `${key}=${encodedValue}; Max-Age=${maxAgeSeconds}; Path=/; SameSite=Lax`;
447
+ function fireOnce(input) {
448
+ if (alreadyFired(input)) return;
449
+ if (fireGtagConversion(input)) markFired(input);
450
+ }
451
+ function fireConversionWithConsent(input) {
452
+ const state = getConsentState();
453
+ if (state === "denied") return;
454
+ if (state === "pending") {
455
+ if (pendingQueue.length >= MAX_PENDING) pendingQueue.shift();
456
+ pendingQueue.push(input);
457
+ return;
458
+ }
459
+ fireOnce(input);
252
460
  }
253
- function persistTrackingParamsFromSearchParams(searchParams, maxAgeSeconds = TRACKING_COOKIE_MAX_AGE_SECONDS) {
254
- const trackingValues = getTrackingQueryValues(searchParams);
255
- Object.entries(trackingValues).forEach(([key, value]) => {
256
- setTrackingCookie(key, value, maxAgeSeconds);
461
+ function flushPendingConversions() {
462
+ if (getConsentState() !== "granted") return;
463
+ while (pendingQueue.length > 0) {
464
+ const input = pendingQueue.shift();
465
+ if (input) fireOnce(input);
466
+ }
467
+ }
468
+ if (typeof window !== "undefined") onConsentGranted(flushPendingConversions);
469
+
470
+ // ../tracking-core/src/resources/conversion-config.ts
471
+ function isStringMap(value) {
472
+ return typeof value === "object" && value !== null && Object.values(value).every((v) => typeof v === "string");
473
+ }
474
+ function parseFiring(value) {
475
+ if (!value || typeof value !== "object") return null;
476
+ const f = value;
477
+ if (typeof f.send_to !== "string") return null;
478
+ return {
479
+ send_to: f.send_to,
480
+ value_cents: typeof f.value_cents === "number" ? f.value_cents : null,
481
+ currency: typeof f.currency === "string" ? f.currency : null
482
+ };
483
+ }
484
+ function parseTrigger(value) {
485
+ if (!value || typeof value !== "object") return null;
486
+ const t = value;
487
+ if (typeof t.event_type !== "string") return null;
488
+ const spec = { event_type: t.event_type };
489
+ if (typeof t.threshold_percent === "number") spec.threshold_percent = t.threshold_percent;
490
+ if (typeof t.threshold_seconds === "number") spec.threshold_seconds = t.threshold_seconds;
491
+ if (typeof t.page_threshold === "number") spec.page_threshold = t.page_threshold;
492
+ if (typeof t.page_name === "string") spec.page_name = t.page_name;
493
+ return spec;
494
+ }
495
+ function parseConversionConfig(raw) {
496
+ if (!raw || typeof raw !== "object") return null;
497
+ const obj = raw;
498
+ const servicesRaw = Array.isArray(obj.services) ? obj.services : [];
499
+ const services = servicesRaw.flatMap((entry) => {
500
+ if (!entry || typeof entry !== "object") return [];
501
+ const s = entry;
502
+ if (typeof s.key !== "string") return [];
503
+ return [
504
+ {
505
+ key: s.key,
506
+ label: typeof s.label === "string" ? s.label : void 0,
507
+ firing: parseFiring(s.firing)
508
+ }
509
+ ];
257
510
  });
258
- return trackingValues;
511
+ const goalsRaw = Array.isArray(obj.goals) ? obj.goals : null;
512
+ const goals = goalsRaw ? goalsRaw.flatMap((entry) => {
513
+ if (!entry || typeof entry !== "object") return [];
514
+ const g = entry;
515
+ if (typeof g.key !== "string") return [];
516
+ return [
517
+ {
518
+ key: g.key,
519
+ label: typeof g.label === "string" ? g.label : void 0,
520
+ kind: g.kind === "event" ? "event" : "sale",
521
+ trigger: parseTrigger(g.trigger),
522
+ firing: parseFiring(g.firing)
523
+ }
524
+ ];
525
+ }) : services.map((s) => ({
526
+ key: s.key,
527
+ label: s.label,
528
+ kind: "sale",
529
+ trigger: null,
530
+ firing: s.firing
531
+ }));
532
+ return {
533
+ schema_version: typeof obj.schema_version === "number" ? obj.schema_version : 1,
534
+ config_version: typeof obj.config_version === "number" ? obj.config_version : 0,
535
+ business_id: typeof obj.business_id === "string" ? obj.business_id : void 0,
536
+ customer_id: typeof obj.customer_id === "string" ? obj.customer_id : null,
537
+ environment: typeof obj.environment === "string" ? obj.environment : void 0,
538
+ gtag_ids: isStringMap(obj.gtag_ids) ? obj.gtag_ids : {},
539
+ meta_pixel_ids: isStringMap(obj.meta_pixel_ids) ? obj.meta_pixel_ids : {},
540
+ services,
541
+ goals
542
+ };
259
543
  }
260
- function captureTrackingParamsFromLocation(url = typeof window === "undefined" ? "" : window.location.href, maxAgeSeconds = TRACKING_COOKIE_MAX_AGE_SECONDS) {
261
- const resolvedUrl = typeof window === "undefined" ? new URL(url || "https://example.invalid") : new URL(url, window.location.origin);
262
- persistTrackingParamsFromSearchParams(resolvedUrl.searchParams, maxAgeSeconds);
263
- return getTrackingParamsFromCookieReader(getCookieValueFromDocument);
544
+ var CACHE_PREFIX = "_aranova_cfg_";
545
+ function cacheKey(url) {
546
+ return `${CACHE_PREFIX}${url}`;
547
+ }
548
+ function readCache(url) {
549
+ if (typeof window === "undefined") return null;
550
+ try {
551
+ const raw = window.sessionStorage.getItem(cacheKey(url));
552
+ if (!raw) return null;
553
+ const parsed = JSON.parse(raw);
554
+ const config = parseConversionConfig(parsed.config);
555
+ if (!config) return null;
556
+ return {
557
+ etag: typeof parsed.etag === "string" ? parsed.etag : null,
558
+ config
559
+ };
560
+ } catch {
561
+ return null;
562
+ }
563
+ }
564
+ function writeCache(url, entry) {
565
+ if (typeof window === "undefined") return;
566
+ try {
567
+ window.sessionStorage.setItem(cacheKey(url), JSON.stringify(entry));
568
+ } catch {
569
+ }
570
+ }
571
+ function resolveConversionConfig(options) {
572
+ const cached = readCache(options.cdnUrl);
573
+ let current = cached?.config ?? options.baked ?? null;
574
+ let etag = cached?.etag ?? null;
575
+ const goalsByKey = /* @__PURE__ */ new Map();
576
+ function rebuildIndex() {
577
+ goalsByKey.clear();
578
+ for (const goal of current?.goals ?? []) {
579
+ goalsByKey.set(goal.key, goal);
580
+ }
581
+ }
582
+ function adopt(next, nextEtag) {
583
+ if (!next) return;
584
+ if (current && next.config_version <= current.config_version) return;
585
+ current = next;
586
+ etag = nextEtag;
587
+ rebuildIndex();
588
+ writeCache(options.cdnUrl, { etag, config: next });
589
+ }
590
+ async function revalidate() {
591
+ if (typeof window === "undefined") return;
592
+ try {
593
+ const doFetch = options.fetchImpl ?? globalThis.fetch;
594
+ if (!doFetch) return;
595
+ const headers = {};
596
+ if (etag) headers["If-None-Match"] = etag;
597
+ const response = await doFetch(options.cdnUrl, {
598
+ method: "GET",
599
+ headers
600
+ });
601
+ if (response.status === 304 || !response.ok) return;
602
+ adopt(parseConversionConfig(await response.json()), response.headers.get("ETag"));
603
+ } catch {
604
+ }
605
+ }
606
+ rebuildIndex();
607
+ void revalidate();
608
+ return {
609
+ getFiring: (key) => goalsByKey.get(key)?.firing ?? null,
610
+ getGoal: (key) => goalsByKey.get(key) ?? null,
611
+ listGoals: () => [...goalsByKey.values()],
612
+ current: () => current,
613
+ revalidate
614
+ };
615
+ }
616
+
617
+ // ../tracking-core/src/resources/sales/money.ts
618
+ var MINOR_UNIT_EXPONENT = {
619
+ USD: 2,
620
+ CAD: 2
621
+ };
622
+ function exponentFor(currency) {
623
+ return MINOR_UNIT_EXPONENT[currency] ?? 2;
624
+ }
625
+ function toMinor(amount, currency) {
626
+ return Math.round(amount * 10 ** exponentFor(currency));
627
+ }
628
+ function fromMinor(cents, currency) {
629
+ return cents / 10 ** exponentFor(currency);
630
+ }
631
+ function formatMoney(cents, currency, locale) {
632
+ return new Intl.NumberFormat(locale, { style: "currency", currency }).format(
633
+ fromMinor(cents, currency)
634
+ );
635
+ }
636
+ function formatDateInTz(iso, timeZone, opts, locale) {
637
+ const date = new Date(iso);
638
+ if (Number.isNaN(date.getTime())) return iso;
639
+ return new Intl.DateTimeFormat(locale, {
640
+ year: "numeric",
641
+ month: "short",
642
+ day: "2-digit",
643
+ hour: "2-digit",
644
+ minute: "2-digit",
645
+ ...opts,
646
+ timeZone
647
+ }).format(date);
648
+ }
649
+
650
+ // ../tracking-core/src/resources/conversion-autofire.ts
651
+ function thresholdMet(goal, eventType, metadata) {
652
+ const t = goal.trigger;
653
+ if (!t || t.event_type !== eventType) return false;
654
+ switch (eventType) {
655
+ case "scroll_depth":
656
+ return typeof metadata.depth_percent === "number" && t.threshold_percent != null && metadata.depth_percent >= t.threshold_percent;
657
+ case "time_on_site":
658
+ return typeof metadata.duration_ms === "number" && t.threshold_seconds != null && metadata.duration_ms >= t.threshold_seconds * 1e3;
659
+ case "multi_page_session":
660
+ return typeof metadata.page_count === "number" && t.page_threshold != null && metadata.page_count >= t.page_threshold;
661
+ case "specific_page_visit":
662
+ return typeof metadata.page_name === "string" && metadata.page_name === t.page_name;
663
+ case "page_view":
664
+ case "form_start":
665
+ return true;
666
+ // no threshold — fire whenever the detector emits
667
+ default:
668
+ return false;
669
+ }
670
+ }
671
+ function currentPath() {
672
+ return typeof window === "undefined" ? "" : window.location.pathname;
673
+ }
674
+ function createConversionAutoFire(store) {
675
+ return {
676
+ onAutomaticEvent(eventType, metadata) {
677
+ for (const goal of store.listGoals()) {
678
+ if (goal.kind !== "event" || !goal.firing) continue;
679
+ if (!thresholdMet(goal, eventType, metadata)) continue;
680
+ const firing = goal.firing;
681
+ const cents = firing.value_cents ?? null;
682
+ const currency = firing.currency ?? null;
683
+ fireConversionWithConsent({
684
+ sendTo: firing.send_to,
685
+ value: cents != null && currency ? fromMinor(cents, currency) : null,
686
+ currency,
687
+ // Page-scoped txn id → fire once per (goal, path) per session; engagement conversions
688
+ // shouldn't re-fire as the visitor scrolls back and forth or re-enters a page.
689
+ transactionId: `auto:${goal.key}:${currentPath()}`
690
+ });
691
+ }
692
+ }
693
+ };
694
+ }
695
+ function withConversionAutoFire(client, autoFire) {
696
+ return {
697
+ ...client,
698
+ trackEvent: (input) => {
699
+ client.trackEvent(input);
700
+ try {
701
+ autoFire.onAutomaticEvent(input.eventType, input.metadata ?? {});
702
+ } catch {
703
+ }
704
+ }
705
+ };
264
706
  }
265
707
 
266
708
  // ../tracking-core/src/session.ts
@@ -553,11 +995,22 @@ function createTrackingClient(config) {
553
995
  let queue = [];
554
996
  let flushTimer = null;
555
997
  let firstPage = null;
998
+ let initialParams = createEmptyTrackingParams();
556
999
  let destroyed = false;
557
1000
  const visitorId = getVisitorId();
558
1001
  const initialSession = getOrRotateSessionId();
559
1002
  let sessionId = initialSession.id;
560
- if (typeof window !== "undefined") firstPage = window.location.href;
1003
+ if (typeof window !== "undefined") {
1004
+ firstPage = window.location.href;
1005
+ try {
1006
+ initialParams = captureTrackingParamsFromLocation();
1007
+ } catch {
1008
+ }
1009
+ try {
1010
+ captureFbc();
1011
+ } catch {
1012
+ }
1013
+ }
561
1014
  function enqueueHeartbeat() {
562
1015
  const metadata = buildHeartbeatMetadata(
563
1016
  config.surface,
@@ -582,7 +1035,7 @@ function createTrackingClient(config) {
582
1035
  enqueueHeartbeat();
583
1036
  }
584
1037
  sessionId = rotated.id;
585
- const params = readTrackingParams();
1038
+ const params = mergeTrackingParams(readTrackingParams(), initialParams);
586
1039
  const context = buildContext(
587
1040
  config.surface,
588
1041
  sdkVersion,
@@ -595,6 +1048,8 @@ function createTrackingClient(config) {
595
1048
  visitor_id: visitorId,
596
1049
  gclid: params.gclid,
597
1050
  fbclid: params.fbclid,
1051
+ fbc: getFbcCookie(),
1052
+ fbp: getFbpCookie(),
598
1053
  utm_source: params.utm_source,
599
1054
  utm_medium: params.utm_medium,
600
1055
  utm_campaign: params.utm_campaign,
@@ -986,7 +1441,7 @@ function attachScrollDepth(client, config) {
986
1441
  }
987
1442
  const thresholds = new Set(config.thresholds);
988
1443
  let firedForPath = /* @__PURE__ */ new Set();
989
- let currentPath = window.location.pathname;
1444
+ let currentPath2 = window.location.pathname;
990
1445
  let rafId = null;
991
1446
  function getScrollPercent() {
992
1447
  const doc = document.documentElement;
@@ -1005,7 +1460,7 @@ function attachScrollDepth(client, config) {
1005
1460
  eventType: "scroll_depth",
1006
1461
  metadata: {
1007
1462
  depth_percent: threshold,
1008
- page: { path: currentPath }
1463
+ page: { path: currentPath2 }
1009
1464
  },
1010
1465
  pageUrl: window.location.href,
1011
1466
  occurredAt: null
@@ -1022,8 +1477,8 @@ function attachScrollDepth(client, config) {
1022
1477
  }
1023
1478
  function resetIfPathChanged() {
1024
1479
  const newPath = window.location.pathname;
1025
- if (newPath === currentPath) return;
1026
- currentPath = newPath;
1480
+ if (newPath === currentPath2) return;
1481
+ currentPath2 = newPath;
1027
1482
  firedForPath = /* @__PURE__ */ new Set();
1028
1483
  setTimeout(checkThresholds, 0);
1029
1484
  }
@@ -1059,7 +1514,7 @@ function attachFormStart(client, config) {
1059
1514
  }
1060
1515
  const selector = config.selector ?? "form";
1061
1516
  let firedForms = /* @__PURE__ */ new Set();
1062
- let currentPath = window.location.pathname;
1517
+ let currentPath2 = window.location.pathname;
1063
1518
  function getFormKey(form) {
1064
1519
  if (form.id) return `id:${form.id}`;
1065
1520
  const explicitAction = form.getAttribute("action");
@@ -1090,8 +1545,8 @@ function attachFormStart(client, config) {
1090
1545
  }
1091
1546
  function resetIfPathChanged() {
1092
1547
  const newPath = window.location.pathname;
1093
- if (newPath === currentPath) return;
1094
- currentPath = newPath;
1548
+ if (newPath === currentPath2) return;
1549
+ currentPath2 = newPath;
1095
1550
  firedForms = /* @__PURE__ */ new Set();
1096
1551
  }
1097
1552
  const originalPushState = history.pushState.bind(history);
@@ -1170,21 +1625,64 @@ async function salesRequest(config, method, path, body) {
1170
1625
  }
1171
1626
 
1172
1627
  // ../tracking-core/src/resources/sales/client.ts
1628
+ function fireRecordedConversions(firing, input, recorded, sale, currency) {
1629
+ if (!firing) return;
1630
+ const txnBase = input.external_id ?? sale.id;
1631
+ for (const item of recorded) {
1632
+ if (!item.service) continue;
1633
+ const config = firing.getFiring(item.service);
1634
+ if (!config) continue;
1635
+ const cents = item.amount_cents ?? config.value_cents ?? null;
1636
+ fireConversionWithConsent({
1637
+ sendTo: config.send_to,
1638
+ value: cents != null ? fromMinor(cents, currency) : null,
1639
+ currency: config.currency ?? currency,
1640
+ transactionId: `${txnBase}:${item.service}`
1641
+ });
1642
+ }
1643
+ }
1173
1644
  function createSalesClient(config) {
1174
- return {
1175
- async record(input) {
1176
- const currency = input.currency ?? config.defaultCurrency;
1177
- if (!currency) {
1178
- throw new Error(
1179
- "record: `currency` is required (pass it on the sale or set config.defaultCurrency)"
1180
- );
1645
+ async function record(input) {
1646
+ const currency = input.currency ?? config.defaultCurrency;
1647
+ if (!currency) {
1648
+ throw new Error(
1649
+ "record: `currency` is required (pass it on the sale or set config.defaultCurrency)"
1650
+ );
1651
+ }
1652
+ const body = {
1653
+ ...input,
1654
+ currency,
1655
+ occurred_at: input.occurred_at ?? (/* @__PURE__ */ new Date()).toISOString()
1656
+ };
1657
+ const sale = await salesRequest(config, "POST", "/sales", body);
1658
+ const recorded = input.services?.length ? input.services.map((s) => ({
1659
+ service: s.service,
1660
+ amount_cents: s.amount_cents
1661
+ })) : [
1662
+ {
1663
+ service: input.service,
1664
+ amount_cents: input.amount_total_cents ?? null
1181
1665
  }
1182
- const body = {
1183
- ...input,
1666
+ ];
1667
+ fireRecordedConversions(config.firing, input, recorded, sale, currency);
1668
+ return sale;
1669
+ }
1670
+ return {
1671
+ record,
1672
+ // recordSale is the intent-revealing alias — same behavior, clearer call site.
1673
+ recordSale: record,
1674
+ trackConversion(key, options) {
1675
+ const firing = config.firing?.getFiring(key);
1676
+ if (!firing) return;
1677
+ const currency = firing.currency ?? options?.currency ?? config.defaultCurrency ?? null;
1678
+ const cents = firing.value_cents ?? null;
1679
+ const value = options?.value ?? (cents != null && currency ? fromMinor(cents, currency) : null);
1680
+ fireConversionWithConsent({
1681
+ sendTo: firing.send_to,
1682
+ value,
1184
1683
  currency,
1185
- occurred_at: input.occurred_at ?? (/* @__PURE__ */ new Date()).toISOString()
1186
- };
1187
- return salesRequest(config, "POST", "/sales", body);
1684
+ transactionId: options?.transactionId ?? null
1685
+ });
1188
1686
  },
1189
1687
  async list(query) {
1190
1688
  const { cursor, limit, sort, order, want_total, ...filters } = query ?? {};
@@ -1278,39 +1776,6 @@ function createSalesClient(config) {
1278
1776
  };
1279
1777
  }
1280
1778
 
1281
- // ../tracking-core/src/resources/sales/money.ts
1282
- var MINOR_UNIT_EXPONENT = {
1283
- USD: 2,
1284
- CAD: 2
1285
- };
1286
- function exponentFor(currency) {
1287
- return MINOR_UNIT_EXPONENT[currency] ?? 2;
1288
- }
1289
- function toMinor(amount, currency) {
1290
- return Math.round(amount * 10 ** exponentFor(currency));
1291
- }
1292
- function fromMinor(cents, currency) {
1293
- return cents / 10 ** exponentFor(currency);
1294
- }
1295
- function formatMoney(cents, currency, locale) {
1296
- return new Intl.NumberFormat(locale, { style: "currency", currency }).format(
1297
- fromMinor(cents, currency)
1298
- );
1299
- }
1300
- function formatDateInTz(iso, timeZone, opts, locale) {
1301
- const date = new Date(iso);
1302
- if (Number.isNaN(date.getTime())) return iso;
1303
- return new Intl.DateTimeFormat(locale, {
1304
- year: "numeric",
1305
- month: "short",
1306
- day: "2-digit",
1307
- hour: "2-digit",
1308
- minute: "2-digit",
1309
- ...opts,
1310
- timeZone
1311
- }).format(date);
1312
- }
1313
-
1314
1779
  // ../tracking-core/src/resources/sales/schema.ts
1315
1780
  var import_zod11 = require("zod");
1316
1781
  var SUPPORTED_CURRENCIES = ["USD", "CAD"];
@@ -1713,26 +2178,61 @@ var ANIMATION_KEYFRAMES = `
1713
2178
  }
1714
2179
  `;
1715
2180
 
1716
- // src/GoogleAdsTracking.tsx
2181
+ // src/AdPlatformTracking.tsx
1717
2182
  var import_script = __toESM(require("next/script"));
1718
2183
  var import_jsx_runtime2 = require("react/jsx-runtime");
2184
+ function AdPlatformTracking({
2185
+ gtagId,
2186
+ gtagIds,
2187
+ metaPixelId,
2188
+ metaPixelIds
2189
+ }) {
2190
+ const gtagAll = gtagIds ? Object.values(gtagIds).filter((id) => id != null) : gtagId ? [gtagId] : [];
2191
+ const metaAll = metaPixelIds ? Object.values(metaPixelIds).filter((id) => id != null) : metaPixelId ? [metaPixelId] : [];
2192
+ const gtagLoaderId = gtagAll[0];
2193
+ const gtagInitScript = gtagAll.length === 1 ? createGtagInitScript(gtagAll[0]) : createGtagInitScriptMulti(gtagAll);
2194
+ const metaInitScript = metaAll.length === 1 ? createMetaPixelInitScript(metaAll[0]) : createMetaPixelInitScriptMulti(metaAll);
2195
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2196
+ gtagLoaderId ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2197
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_script.default, { id: "consent-default", strategy: "beforeInteractive", children: createConsentDefaultScript() }),
2198
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2199
+ import_script.default,
2200
+ {
2201
+ src: `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(gtagLoaderId)}`,
2202
+ strategy: "afterInteractive"
2203
+ }
2204
+ ),
2205
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_script.default, { id: "gtag-init", strategy: "afterInteractive", children: gtagInitScript }),
2206
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_script.default, { id: "consent-restore", strategy: "afterInteractive", children: createConsentRestoreScript() })
2207
+ ] }) : null,
2208
+ metaAll.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2209
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_script.default, { id: "meta-pixel-base", strategy: "afterInteractive", children: createMetaConsentDefaultScript() }),
2210
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_script.default, { id: "meta-pixel-init", strategy: "afterInteractive", children: metaInitScript }),
2211
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_script.default, { id: "meta-pixel-consent-restore", strategy: "afterInteractive", children: createMetaConsentRestoreScript() })
2212
+ ] }) : null
2213
+ ] });
2214
+ }
2215
+
2216
+ // src/GoogleAdsTracking.tsx
2217
+ var import_script2 = __toESM(require("next/script"));
2218
+ var import_jsx_runtime3 = require("react/jsx-runtime");
1719
2219
  function GoogleAdsTracking(props) {
1720
2220
  const { gtagId, gtagIds } = props;
1721
2221
  const allIds = gtagIds ? Object.values(gtagIds).filter((id) => id != null) : gtagId ? [gtagId] : [];
1722
2222
  if (allIds.length === 0) return null;
1723
2223
  const loaderId = allIds[0];
1724
2224
  const initScript = allIds.length === 1 ? createGtagInitScript(loaderId) : createGtagInitScriptMulti(allIds);
1725
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1726
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_script.default, { id: "consent-default", strategy: "beforeInteractive", children: createConsentDefaultScript() }),
1727
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1728
- import_script.default,
2225
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
2226
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_script2.default, { id: "consent-default", strategy: "beforeInteractive", children: createConsentDefaultScript() }),
2227
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2228
+ import_script2.default,
1729
2229
  {
1730
2230
  src: `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(loaderId)}`,
1731
2231
  strategy: "afterInteractive"
1732
2232
  }
1733
2233
  ),
1734
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_script.default, { id: "gtag-init", strategy: "afterInteractive", children: initScript }),
1735
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_script.default, { id: "consent-restore", strategy: "afterInteractive", children: createConsentRestoreScript() })
2234
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_script2.default, { id: "gtag-init", strategy: "afterInteractive", children: initScript }),
2235
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_script2.default, { id: "consent-restore", strategy: "afterInteractive", children: createConsentRestoreScript() })
1736
2236
  ] });
1737
2237
  }
1738
2238
 
@@ -1740,14 +2240,14 @@ function GoogleAdsTracking(props) {
1740
2240
  var import_navigation = require("next/navigation");
1741
2241
 
1742
2242
  // package.json
1743
- var version = "0.12.2";
2243
+ var version = "0.14.0";
1744
2244
 
1745
2245
  // src/factory.tsx
1746
2246
  var import_react4 = require("react");
1747
2247
 
1748
2248
  // ../tracking-core/src/phone-react.tsx
1749
2249
  var import_react3 = require("react");
1750
- var import_jsx_runtime3 = require("react/jsx-runtime");
2250
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1751
2251
  var _phoneConfigContext;
1752
2252
  function phoneConfigContext() {
1753
2253
  return _phoneConfigContext ?? (_phoneConfigContext = (0, import_react3.createContext)(null));
@@ -1757,7 +2257,7 @@ function PhoneConfigProvider({
1757
2257
  children
1758
2258
  }) {
1759
2259
  const Ctx = phoneConfigContext();
1760
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Ctx.Provider, { value, children });
2260
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Ctx.Provider, { value, children });
1761
2261
  }
1762
2262
  function usePhoneConfig() {
1763
2263
  const ctx = (0, import_react3.useContext)(phoneConfigContext());
@@ -1817,7 +2317,7 @@ var PhoneField = (0, import_react3.forwardRef)(function PhoneField2({ country, v
1817
2317
  onChange?.(event);
1818
2318
  };
1819
2319
  const shown = isControlled ? formatPhoneAsTyped(value, resolvedCountry) : internal;
1820
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2320
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1821
2321
  "input",
1822
2322
  {
1823
2323
  ...rest,
@@ -1832,9 +2332,9 @@ var PhoneField = (0, import_react3.forwardRef)(function PhoneField2({ country, v
1832
2332
  });
1833
2333
 
1834
2334
  // src/factory.tsx
1835
- var import_jsx_runtime4 = require("react/jsx-runtime");
2335
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1836
2336
  function createTracking(options) {
1837
- const { apiKey, endpoint, triggers, environment, gtagIds, debug, phone } = options;
2337
+ const { apiKey, endpoint, triggers, environment, gtagIds, debug, phone, conversionConfig } = options;
1838
2338
  if (!apiKey || !endpoint) {
1839
2339
  if (apiKey || endpoint) {
1840
2340
  console.warn(
@@ -1850,7 +2350,7 @@ function createTracking(options) {
1850
2350
  getVisitorId: () => ""
1851
2351
  };
1852
2352
  return {
1853
- TrackingProvider: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PhoneConfigProvider, { value: phone ?? null, children }),
2353
+ TrackingProvider: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PhoneConfigProvider, { value: phone ?? null, children }),
1854
2354
  useTracking: () => noopClient
1855
2355
  };
1856
2356
  }
@@ -1878,6 +2378,17 @@ function createTracking(options) {
1878
2378
  ),
1879
2379
  []
1880
2380
  );
2381
+ const conversionStore = (0, import_react4.useMemo)(
2382
+ () => conversionConfig ? resolveConversionConfig({
2383
+ cdnUrl: conversionConfig.cdnUrl,
2384
+ baked: conversionConfig.baked
2385
+ }) : null,
2386
+ []
2387
+ );
2388
+ const wrapClient = (0, import_react4.useMemo)(() => {
2389
+ const autoFire = conversionStore ? createConversionAutoFire(conversionStore) : null;
2390
+ return (c) => autoFire ? withConversionAutoFire(c, autoFire) : c;
2391
+ }, [conversionStore]);
1881
2392
  (0, import_react4.useEffect)(() => {
1882
2393
  const rawClient = getOrCreateTrackingClient({
1883
2394
  apiKey,
@@ -1889,7 +2400,7 @@ function createTracking(options) {
1889
2400
  activeGtagIds: gtagIds,
1890
2401
  debug
1891
2402
  });
1892
- fireManualPageView(rawClient);
2403
+ fireManualPageView(wrapClient(rawClient));
1893
2404
  }, [pathname, searchParams]);
1894
2405
  const firedPagesRef = (0, import_react4.useRef)(/* @__PURE__ */ new Set());
1895
2406
  (0, import_react4.useEffect)(() => {
@@ -1904,14 +2415,18 @@ function createTracking(options) {
1904
2415
  activeGtagIds: gtagIds,
1905
2416
  debug
1906
2417
  });
2418
+ const detectorClient = wrapClient(rawClient);
1907
2419
  for (const { name, pathPattern } of specificPageVisitConfig.pages) {
1908
2420
  if (!pathPattern.test(pathname)) continue;
1909
2421
  const key = `${name}:${pathname}`;
1910
2422
  if (firedPagesRef.current.has(key)) continue;
1911
2423
  firedPagesRef.current.add(key);
1912
- rawClient.trackEvent({
2424
+ detectorClient.trackEvent({
1913
2425
  eventType: "specific_page_visit",
1914
- metadata: { page_name: name, page: { path: pathname } },
2426
+ metadata: {
2427
+ page_name: name,
2428
+ page: { path: pathname }
2429
+ },
1915
2430
  pageUrl: null,
1916
2431
  occurredAt: null
1917
2432
  });
@@ -1928,7 +2443,7 @@ function createTracking(options) {
1928
2443
  activeGtagIds: gtagIds,
1929
2444
  debug
1930
2445
  });
1931
- return attachBfcacheRestore(rawClient);
2446
+ return attachBfcacheRestore(wrapClient(rawClient));
1932
2447
  }, []);
1933
2448
  (0, import_react4.useEffect)(() => {
1934
2449
  if (!timeOnSiteConfig) return;
@@ -1942,7 +2457,7 @@ function createTracking(options) {
1942
2457
  activeGtagIds: gtagIds,
1943
2458
  debug
1944
2459
  });
1945
- return attachTimeOnSite(rawClient, timeOnSiteConfig);
2460
+ return attachTimeOnSite(wrapClient(rawClient), timeOnSiteConfig);
1946
2461
  }, []);
1947
2462
  const multiPageSessionConfig = triggers.automatic.multi_page_session ?? null;
1948
2463
  const mpsLastPathRef = (0, import_react4.useRef)(null);
@@ -1980,7 +2495,7 @@ function createTracking(options) {
1980
2495
  activeGtagIds: gtagIds,
1981
2496
  debug
1982
2497
  });
1983
- rawClient.trackEvent({
2498
+ wrapClient(rawClient).trackEvent({
1984
2499
  eventType: "multi_page_session",
1985
2500
  metadata: {
1986
2501
  page_count: paths.size,
@@ -2005,13 +2520,14 @@ function createTracking(options) {
2005
2520
  activeGtagIds: gtagIds,
2006
2521
  debug
2007
2522
  });
2523
+ const detectorClient = wrapClient(rawClient);
2008
2524
  const scrollDepth = triggers.automatic.scroll_depth;
2009
2525
  if (scrollDepth) {
2010
- detachers.push(attachScrollDepth(rawClient, scrollDepth));
2526
+ detachers.push(attachScrollDepth(detectorClient, scrollDepth));
2011
2527
  }
2012
2528
  const formStart = triggers.automatic.form_start;
2013
2529
  if (formStart) {
2014
- detachers.push(attachFormStart(rawClient, formStart));
2530
+ detachers.push(attachFormStart(detectorClient, formStart));
2015
2531
  }
2016
2532
  return () => {
2017
2533
  for (let i = detachers.length - 1; i >= 0; i--) {
@@ -2019,7 +2535,7 @@ function createTracking(options) {
2019
2535
  }
2020
2536
  };
2021
2537
  }, []);
2022
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TrackingContext.Provider, { value: client, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PhoneConfigProvider, { value: phone ?? null, children }) });
2538
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TrackingContext.Provider, { value: client, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PhoneConfigProvider, { value: phone ?? null, children }) });
2023
2539
  }
2024
2540
  function useTracking() {
2025
2541
  const client = (0, import_react4.useContext)(TrackingContext);
@@ -2034,6 +2550,7 @@ function createTracking(options) {
2034
2550
  }
2035
2551
  // Annotate the CommonJS export names for ESM import in node:
2036
2552
  0 && (module.exports = {
2553
+ AdPlatformTracking,
2037
2554
  AranovaApiError,
2038
2555
  ConsentBanner,
2039
2556
  DEFAULT_PHONE_COUNTRY,
@@ -2059,6 +2576,7 @@ function createTracking(options) {
2059
2576
  parsePhone,
2060
2577
  phoneField,
2061
2578
  resetConsent,
2579
+ resolveConversionConfig,
2062
2580
  saleCreateSchema,
2063
2581
  saleItemSchema,
2064
2582
  saleServiceSchema,