@aranova/tracking-next 0.19.0 → 0.19.1

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.mjs CHANGED
@@ -665,10 +665,17 @@ function markFired(input) {
665
665
  }
666
666
  }
667
667
  function fireConversionWithConsent(input, options) {
668
- if (getConsentState() === "denied") return;
669
- if (alreadyFired(input)) return;
670
- applyUserDataForConversion(options?.userData);
671
- if (fireGtagConversion(input)) markFired(input);
668
+ if (getConsentState() === "denied") return "denied";
669
+ if (alreadyFired(input)) return "duplicate";
670
+ if (!isValidSendTo(input.sendTo)) return "invalid";
671
+ try {
672
+ applyUserDataForConversion(options?.userData);
673
+ if (!fireGtagConversion(input)) return "retryable";
674
+ markFired(input);
675
+ return "fired";
676
+ } catch {
677
+ return "retryable";
678
+ }
672
679
  }
673
680
 
674
681
  // ../tracking-core/src/resources/conversion-config.ts
@@ -842,6 +849,103 @@ function resolveConversionConfig(options) {
842
849
  };
843
850
  }
844
851
 
852
+ // ../tracking-core/src/resources/automatic-transaction.ts
853
+ var STORAGE_KEY = "_aranova_auto_txn_map";
854
+ var transactionIds = /* @__PURE__ */ new Map();
855
+ var legacyCounter = 0;
856
+ function scopeKey(sessionId, goalKey, path) {
857
+ return JSON.stringify([sessionId, goalKey, path]);
858
+ }
859
+ function randomId() {
860
+ const cryptoApi = globalThis.crypto;
861
+ if (typeof cryptoApi?.randomUUID === "function") return cryptoApi.randomUUID();
862
+ if (typeof cryptoApi?.getRandomValues === "function") {
863
+ const bytes = cryptoApi.getRandomValues(new Uint8Array(16));
864
+ return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
865
+ }
866
+ legacyCounter = (legacyCounter + 1) % 4294967296;
867
+ const timestamp = Date.now().toString(16).padStart(12, "0");
868
+ const counter = legacyCounter.toString(16).padStart(8, "0");
869
+ const random = Math.floor(Math.random() * 281474976710655).toString(16).padStart(12, "0");
870
+ return `${timestamp}${counter}${random}`.slice(0, 32);
871
+ }
872
+ function isValidTransactionId(value) {
873
+ return typeof value === "string" && /^auto:(?:[0-9a-f]{32}|[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})$/i.test(
874
+ value
875
+ ) && value.length <= 64;
876
+ }
877
+ function readStoredMap(sessionId) {
878
+ if (typeof window === "undefined") return { sessionId, entries: {} };
879
+ try {
880
+ const raw = window.localStorage.getItem(STORAGE_KEY);
881
+ if (!raw) return { sessionId, entries: {} };
882
+ const parsed = JSON.parse(raw);
883
+ if (parsed.sessionId !== sessionId || !parsed.entries || typeof parsed.entries !== "object" || Array.isArray(parsed.entries)) {
884
+ return { sessionId, entries: {} };
885
+ }
886
+ return { sessionId, entries: parsed.entries };
887
+ } catch {
888
+ return { sessionId, entries: {} };
889
+ }
890
+ }
891
+ function writeStoredMap(stored) {
892
+ if (typeof window === "undefined") return;
893
+ try {
894
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(stored));
895
+ } catch {
896
+ }
897
+ }
898
+ function getAutomaticTransactionId(sessionId, goalKey, path) {
899
+ const key = scopeKey(sessionId, goalKey, path);
900
+ const existing = transactionIds.get(key);
901
+ if (existing) return existing;
902
+ const stored = readStoredMap(sessionId);
903
+ const storedId = stored.entries[key];
904
+ if (isValidTransactionId(storedId)) {
905
+ transactionIds.set(key, storedId);
906
+ return storedId;
907
+ }
908
+ const transactionId = `auto:${randomId()}`;
909
+ transactionIds.set(key, transactionId);
910
+ const latest = readStoredMap(sessionId);
911
+ const concurrentId = latest.entries[key];
912
+ if (isValidTransactionId(concurrentId)) {
913
+ transactionIds.set(key, concurrentId);
914
+ return concurrentId;
915
+ }
916
+ latest.entries[key] = transactionId;
917
+ writeStoredMap(latest);
918
+ return transactionId;
919
+ }
920
+
921
+ // ../tracking-core/src/resources/automatic-trigger.ts
922
+ function hasNumberField(metadata, key) {
923
+ return typeof metadata[key] === "number";
924
+ }
925
+ function hasStringField(metadata, key) {
926
+ return typeof metadata[key] === "string";
927
+ }
928
+ function automaticThresholdMet(goal, eventType, metadata) {
929
+ const trigger = goal.trigger;
930
+ if (!trigger || trigger.event_type !== eventType) return false;
931
+ switch (eventType) {
932
+ case "scroll_depth":
933
+ return hasNumberField(metadata, "depth_percent") && trigger.threshold_percent != null && metadata.depth_percent >= trigger.threshold_percent;
934
+ case "time_on_site":
935
+ return hasNumberField(metadata, "duration_ms") && trigger.threshold_seconds != null && metadata.duration_ms >= trigger.threshold_seconds * 1e3;
936
+ case "multi_page_session":
937
+ return hasNumberField(metadata, "page_count") && trigger.page_threshold != null && metadata.page_count >= trigger.page_threshold;
938
+ case "specific_page_visit":
939
+ return hasStringField(metadata, "page_name") && metadata.page_name === trigger.page_name;
940
+ case "page_view":
941
+ case "form_start":
942
+ case "phone_click":
943
+ return true;
944
+ default:
945
+ return false;
946
+ }
947
+ }
948
+
845
949
  // ../tracking-core/src/resources/sales/money.ts
846
950
  var MINOR_UNIT_EXPONENT = {
847
951
  USD: 2,
@@ -960,7 +1064,12 @@ var TrackingConfigRuntime = class {
960
1064
  this.etag = null;
961
1065
  this.stateValue = "unconfirmed";
962
1066
  this.confirmedAt = 0;
1067
+ this.authorityGeneration = 0;
963
1068
  this.inFlight = null;
1069
+ this.flushInFlight = null;
1070
+ this.flushRequested = false;
1071
+ this.retryTimer = null;
1072
+ this.started = false;
964
1073
  this.conversionQueue = [];
965
1074
  this.automaticQueue = [];
966
1075
  this.pageQueue = [];
@@ -968,6 +1077,20 @@ var TrackingConfigRuntime = class {
968
1077
  const cached = readCache2(ref.cdnUrl);
969
1078
  this.current = cached?.config ?? null;
970
1079
  this.etag = cached?.etag ?? null;
1080
+ this.start();
1081
+ }
1082
+ /**
1083
+ * Explicitly start authority resolution and Google-tag bootstrap.
1084
+ *
1085
+ * Idempotent so framework effects can call it after hydration without
1086
+ * depending on constructor timing.
1087
+ */
1088
+ start() {
1089
+ if (this.started) {
1090
+ void this.flush();
1091
+ return;
1092
+ }
1093
+ this.started = true;
971
1094
  void this.revalidate();
972
1095
  if (typeof window !== "undefined") {
973
1096
  window.addEventListener("visibilitychange", () => {
@@ -983,7 +1106,7 @@ var TrackingConfigRuntime = class {
983
1106
  return this.stateValue === "active" || this.stateValue === "tombstone" ? this.current : null;
984
1107
  }
985
1108
  __unsafeExpireAuthorityForTests() {
986
- this.confirmedAt = 0;
1109
+ this.confirmedAt = Number.NEGATIVE_INFINITY;
987
1110
  }
988
1111
  subscribe(listener) {
989
1112
  this.listeners.add(listener);
@@ -993,10 +1116,14 @@ var TrackingConfigRuntime = class {
993
1116
  if (this.stateValue !== "unconfirmed" && Date.now() - this.confirmedAt < AUTHORITY_TTL_MS) {
994
1117
  return true;
995
1118
  }
996
- await this.revalidate();
1119
+ await this.revalidateAuthority();
997
1120
  return this.stateValue !== "unconfirmed" && Date.now() - this.confirmedAt < AUTHORITY_TTL_MS;
998
1121
  }
999
1122
  async revalidate() {
1123
+ await this.revalidateAuthority();
1124
+ await this.flush();
1125
+ }
1126
+ async revalidateAuthority() {
1000
1127
  if (typeof window === "undefined" || !this.fetchImpl) return;
1001
1128
  if (this.inFlight) return this.inFlight;
1002
1129
  this.inFlight = this.revalidateNow().finally(() => {
@@ -1013,8 +1140,8 @@ var TrackingConfigRuntime = class {
1013
1140
  this.conversionQueue.push({ key, ...options });
1014
1141
  void this.flush();
1015
1142
  }
1016
- queueAutomaticEvent(eventType, metadata, transactionPath) {
1017
- this.automaticQueue.push({ eventType, metadata, transactionPath });
1143
+ queueAutomaticEvent(eventType, metadata, transactionPath, transactionScope) {
1144
+ this.automaticQueue.push({ eventType, metadata, transactionPath, transactionScope });
1018
1145
  void this.flush();
1019
1146
  }
1020
1147
  listGoals() {
@@ -1031,7 +1158,6 @@ var TrackingConfigRuntime = class {
1031
1158
  });
1032
1159
  if (response.status === 304 && this.current && validateConfig(this.current, this.ref)) {
1033
1160
  this.confirm(this.current, this.etag);
1034
- await this.flush();
1035
1161
  return;
1036
1162
  }
1037
1163
  if (!response.ok) {
@@ -1048,21 +1174,26 @@ var TrackingConfigRuntime = class {
1048
1174
  return;
1049
1175
  }
1050
1176
  this.confirm(next, response.headers.get("ETag"));
1051
- await this.flush();
1052
1177
  } catch {
1053
1178
  this.expireAuthority();
1054
1179
  }
1055
1180
  }
1056
1181
  expireAuthority() {
1182
+ this.authorityGeneration += 1;
1057
1183
  if (this.stateValue !== "unconfirmed") this.stateValue = "unconfirmed";
1058
1184
  }
1059
1185
  confirm(config, etag) {
1186
+ this.authorityGeneration += 1;
1060
1187
  this.current = config;
1061
1188
  this.etag = etag;
1062
1189
  this.confirmedAt = Date.now();
1063
1190
  this.stateValue = isTombstone(config) ? "tombstone" : "active";
1064
1191
  writeCache2(this.ref.cdnUrl, { etag, config });
1065
1192
  if (this.stateValue === "tombstone") {
1193
+ if (this.retryTimer !== null) {
1194
+ window.clearTimeout(this.retryTimer);
1195
+ this.retryTimer = null;
1196
+ }
1066
1197
  this.conversionQueue.length = 0;
1067
1198
  this.automaticQueue.length = 0;
1068
1199
  this.pageQueue.length = 0;
@@ -1070,80 +1201,107 @@ var TrackingConfigRuntime = class {
1070
1201
  for (const listener of this.listeners) listener();
1071
1202
  }
1072
1203
  async flush() {
1204
+ if (this.flushInFlight) {
1205
+ this.flushRequested = true;
1206
+ return this.flushInFlight;
1207
+ }
1208
+ this.flushRequested = false;
1209
+ this.flushInFlight = this.flushNow().finally(() => {
1210
+ this.flushInFlight = null;
1211
+ if (this.flushRequested && this.stateValue === "active") void this.flush();
1212
+ });
1213
+ return this.flushInFlight;
1214
+ }
1215
+ scheduleRetry() {
1216
+ if (this.retryTimer !== null || typeof window === "undefined") return;
1217
+ this.retryTimer = window.setTimeout(() => {
1218
+ this.retryTimer = null;
1219
+ void this.flush();
1220
+ }, 1e3);
1221
+ }
1222
+ async flushNow() {
1073
1223
  if (!await this.ensureAuthority()) return;
1074
1224
  if (this.stateValue !== "active" || !this.current) return;
1075
- const ids = Object.values(this.current.gtag_ids).filter(
1225
+ const config = this.current;
1226
+ const generation = this.authorityGeneration;
1227
+ const ids = Object.values(config.gtag_ids).filter(
1076
1228
  (id) => typeof id === "string" && isValidGtagId(id)
1077
1229
  );
1078
1230
  if (ids.length === 0) return;
1079
1231
  await ensureScript(ids[0]);
1232
+ if (this.authorityGeneration !== generation || this.stateValue !== "active" || this.current !== config) {
1233
+ return;
1234
+ }
1080
1235
  const gtag = window.gtag;
1081
1236
  if (typeof gtag !== "function") return;
1082
- if (!jsInitialized) {
1083
- gtag("js", /* @__PURE__ */ new Date());
1084
- jsInitialized = true;
1085
- }
1086
- for (const id of ids) {
1087
- if (configuredIds.has(id)) continue;
1088
- gtag("config", id, { send_page_view: false });
1089
- configuredIds.add(id);
1090
- }
1091
- while (this.pageQueue.length) {
1092
- const page = this.pageQueue.shift();
1093
- gtag("event", "page_view", {
1094
- page_location: page.href,
1095
- page_title: page.title ?? void 0,
1096
- page_referrer: page.referrer ?? void 0
1097
- });
1237
+ try {
1238
+ if (!jsInitialized) {
1239
+ gtag("js", /* @__PURE__ */ new Date());
1240
+ jsInitialized = true;
1241
+ }
1242
+ for (const id of ids) {
1243
+ if (configuredIds.has(id)) continue;
1244
+ gtag("config", id, { send_page_view: false });
1245
+ configuredIds.add(id);
1246
+ }
1247
+ } catch {
1248
+ this.scheduleRetry();
1249
+ return;
1098
1250
  }
1099
- while (this.automaticQueue.length) {
1100
- const event = this.automaticQueue.shift();
1101
- for (const goal of this.current.goals) {
1251
+ while (this.pageQueue.length > 0) {
1252
+ const page = this.pageQueue[0];
1253
+ try {
1254
+ gtag("event", "page_view", {
1255
+ page_location: page.href,
1256
+ page_title: page.title ?? void 0,
1257
+ page_referrer: page.referrer ?? void 0
1258
+ });
1259
+ this.pageQueue.shift();
1260
+ } catch {
1261
+ this.scheduleRetry();
1262
+ return;
1263
+ }
1264
+ }
1265
+ while (this.automaticQueue.length > 0) {
1266
+ const event = this.automaticQueue[0];
1267
+ for (const goal of config.goals) {
1102
1268
  if (goal.kind !== "event" || !goal.firing) continue;
1103
1269
  if (!automaticThresholdMet(goal, event.eventType, event.metadata)) continue;
1104
1270
  this.conversionQueue.push({
1105
1271
  key: goal.key,
1106
- transactionId: `auto:${goal.key}:${event.transactionPath}`
1272
+ transactionId: getAutomaticTransactionId(
1273
+ event.transactionScope,
1274
+ goal.key,
1275
+ event.transactionPath
1276
+ )
1107
1277
  });
1108
1278
  }
1279
+ this.automaticQueue.shift();
1109
1280
  }
1110
- while (this.conversionQueue.length) {
1111
- const item = this.conversionQueue.shift();
1112
- const goal = this.current.goals.find((g) => g.key === item.key);
1281
+ while (this.conversionQueue.length > 0) {
1282
+ const item = this.conversionQueue[0];
1283
+ const goal = config.goals.find((g) => g.key === item.key);
1113
1284
  const firing = goal?.firing;
1114
- if (!firing || getConsentState() === "denied") continue;
1285
+ if (!firing) {
1286
+ this.conversionQueue.shift();
1287
+ continue;
1288
+ }
1115
1289
  const currency = item.currency ?? firing.currency ?? null;
1116
1290
  const value = item.value ?? (firing.value_cents != null && currency ? fromMinor(firing.value_cents, currency) : null);
1117
- applyUserDataForConversion();
1118
- fireGtagConversion({
1291
+ const outcome = fireConversionWithConsent({
1119
1292
  sendTo: firing.send_to,
1120
1293
  value,
1121
1294
  currency,
1122
1295
  transactionId: item.transactionId ?? null
1123
1296
  });
1297
+ if (outcome === "retryable") {
1298
+ this.scheduleRetry();
1299
+ return;
1300
+ }
1301
+ this.conversionQueue.shift();
1124
1302
  }
1125
1303
  }
1126
1304
  };
1127
- function automaticThresholdMet(goal, eventType, metadata) {
1128
- const t = goal.trigger;
1129
- if (!t || t.event_type !== eventType) return false;
1130
- switch (eventType) {
1131
- case "scroll_depth":
1132
- return typeof metadata.depth_percent === "number" && t.threshold_percent != null && metadata.depth_percent >= t.threshold_percent;
1133
- case "time_on_site":
1134
- return typeof metadata.duration_ms === "number" && t.threshold_seconds != null && metadata.duration_ms >= t.threshold_seconds * 1e3;
1135
- case "multi_page_session":
1136
- return typeof metadata.page_count === "number" && t.page_threshold != null && metadata.page_count >= t.page_threshold;
1137
- case "specific_page_visit":
1138
- return typeof metadata.page_name === "string" && metadata.page_name === t.page_name;
1139
- case "page_view":
1140
- case "form_start":
1141
- case "phone_click":
1142
- return true;
1143
- default:
1144
- return false;
1145
- }
1146
- }
1147
1305
  function getTrackingConfigRuntime(ref, fetchImpl) {
1148
1306
  const key = `${ref.cdnUrl}|${ref.businessId}|${ref.environment}`;
1149
1307
  const existing = runtimes.get(key);
@@ -1154,26 +1312,6 @@ function getTrackingConfigRuntime(ref, fetchImpl) {
1154
1312
  }
1155
1313
 
1156
1314
  // ../tracking-core/src/resources/conversion-autofire.ts
1157
- function thresholdMet(goal, eventType, metadata) {
1158
- const t = goal.trigger;
1159
- if (!t || t.event_type !== eventType) return false;
1160
- switch (eventType) {
1161
- case "scroll_depth":
1162
- return typeof metadata.depth_percent === "number" && t.threshold_percent != null && metadata.depth_percent >= t.threshold_percent;
1163
- case "time_on_site":
1164
- return typeof metadata.duration_ms === "number" && t.threshold_seconds != null && metadata.duration_ms >= t.threshold_seconds * 1e3;
1165
- case "multi_page_session":
1166
- return typeof metadata.page_count === "number" && t.page_threshold != null && metadata.page_count >= t.page_threshold;
1167
- case "specific_page_visit":
1168
- return typeof metadata.page_name === "string" && metadata.page_name === t.page_name;
1169
- case "page_view":
1170
- case "form_start":
1171
- case "phone_click":
1172
- return true;
1173
- default:
1174
- return false;
1175
- }
1176
- }
1177
1315
  function currentPath() {
1178
1316
  return typeof window === "undefined" ? "" : window.location.pathname;
1179
1317
  }
@@ -1181,13 +1319,14 @@ var MAX_BUFFERED_EVENTS = 50;
1181
1319
  function createConversionAutoFire(store) {
1182
1320
  const pending = [];
1183
1321
  let subscribed = false;
1184
- function fireMatching(eventType, metadata) {
1322
+ function fireMatching(eventType, metadata, transactionScope) {
1185
1323
  for (const goal of store.listGoals()) {
1186
1324
  if (goal.kind !== "event" || !goal.firing) continue;
1187
- if (!thresholdMet(goal, eventType, metadata)) continue;
1325
+ if (!automaticThresholdMet(goal, eventType, metadata)) continue;
1326
+ const transactionId = getAutomaticTransactionId(transactionScope, goal.key, currentPath());
1188
1327
  if ("queueAutomaticEvent" in store) {
1189
1328
  store.fireConversion(goal.key, {
1190
- transactionId: `auto:${goal.key}:${currentPath()}`
1329
+ transactionId
1191
1330
  });
1192
1331
  continue;
1193
1332
  }
@@ -1198,28 +1337,30 @@ function createConversionAutoFire(store) {
1198
1337
  sendTo: firing.send_to,
1199
1338
  value: cents != null && currency ? fromMinor(cents, currency) : null,
1200
1339
  currency,
1201
- // Page-scoped txn id → fire once per (goal, path) per session; engagement conversions
1202
- // shouldn't re-fire as the visitor scrolls back and forth or re-enters a page.
1203
- transactionId: `auto:${goal.key}:${currentPath()}`
1340
+ transactionId
1204
1341
  });
1205
1342
  }
1206
1343
  }
1207
1344
  return {
1208
- onAutomaticEvent(eventType, metadata) {
1345
+ onAutomaticEvent(eventType, metadata, transactionScope) {
1209
1346
  if ("queueAutomaticEvent" in store) {
1210
- store.queueAutomaticEvent(eventType, metadata, currentPath());
1347
+ store.queueAutomaticEvent(eventType, metadata, currentPath(), transactionScope);
1211
1348
  return;
1212
1349
  }
1213
1350
  if (store.isReady()) {
1214
- fireMatching(eventType, metadata);
1351
+ fireMatching(eventType, metadata, transactionScope);
1215
1352
  return;
1216
1353
  }
1217
- if (pending.length < MAX_BUFFERED_EVENTS) pending.push({ eventType, metadata });
1354
+ if (pending.length < MAX_BUFFERED_EVENTS) {
1355
+ pending.push({ eventType, metadata, transactionScope });
1356
+ }
1218
1357
  if (!subscribed) {
1219
1358
  subscribed = true;
1220
1359
  store.onResolve(() => {
1221
1360
  const buffered = pending.splice(0);
1222
- for (const event of buffered) fireMatching(event.eventType, event.metadata);
1361
+ for (const event of buffered) {
1362
+ fireMatching(event.eventType, event.metadata, event.transactionScope);
1363
+ }
1223
1364
  });
1224
1365
  }
1225
1366
  }
@@ -1231,7 +1372,7 @@ function withConversionAutoFire(client, autoFire) {
1231
1372
  trackEvent: (input) => {
1232
1373
  client.trackEvent(input);
1233
1374
  try {
1234
- autoFire.onAutomaticEvent(input.eventType, input.metadata ?? {});
1375
+ autoFire.onAutomaticEvent(input.eventType, input.metadata ?? {}, client.getSessionId());
1235
1376
  } catch {
1236
1377
  }
1237
1378
  }
@@ -3190,7 +3331,7 @@ function AdPlatformTracking({
3190
3331
  if (!trackingConfig) return;
3191
3332
  const runtime = getTrackingConfigRuntime(trackingConfig);
3192
3333
  if (standalonePageView) runtime.queuePageView();
3193
- else void runtime.revalidate();
3334
+ else runtime.start();
3194
3335
  }, [trackingConfigKey, standalonePageView]);
3195
3336
  const gtagAll = trackingConfig ? [] : gtagIds ? Object.values(gtagIds).filter((id) => id != null) : gtagId ? [gtagId] : [];
3196
3337
  const metaAll = metaPixelIds ? Object.values(metaPixelIds).filter((id) => id != null) : metaPixelId ? [metaPixelId] : [];
@@ -3242,7 +3383,7 @@ function GoogleAdsTracking(props) {
3242
3383
  import { usePathname, useSearchParams } from "next/navigation";
3243
3384
 
3244
3385
  // package.json
3245
- var version = "0.19.0";
3386
+ var version = "0.19.1";
3246
3387
 
3247
3388
  // src/factory.tsx
3248
3389
  import {
@@ -3394,22 +3535,18 @@ function createTracking(options) {
3394
3535
  const timeOnSiteConfig = triggers.automatic.time_on_site ?? null;
3395
3536
  function TrackingProvider({ children }) {
3396
3537
  const pathname = usePathname();
3397
- const client = useMemo2(
3398
- () => createTypedClient(
3399
- getOrCreateTrackingClient({
3400
- apiKey,
3401
- endpoint,
3402
- surface: "next",
3403
- packageName: "@aranova/tracking-next",
3404
- sdkVersion: version,
3405
- triggers,
3406
- environment,
3407
- activeGtagIds: gtagIds,
3408
- debug
3409
- }),
3538
+ const rawClient = useMemo2(
3539
+ () => getOrCreateTrackingClient({
3540
+ apiKey,
3541
+ endpoint,
3542
+ surface: "next",
3543
+ packageName: "@aranova/tracking-next",
3544
+ sdkVersion: version,
3410
3545
  triggers,
3411
- { debug }
3412
- ),
3546
+ environment,
3547
+ activeGtagIds: gtagIds,
3548
+ debug
3549
+ }),
3413
3550
  []
3414
3551
  );
3415
3552
  const conversionStore = useMemo2(
@@ -3423,33 +3560,22 @@ function createTracking(options) {
3423
3560
  const autoFire = conversionStore ? createConversionAutoFire(conversionStore) : null;
3424
3561
  return (c) => autoFire ? withConversionAutoFire(c, autoFire) : c;
3425
3562
  }, [conversionStore]);
3563
+ const client = useMemo2(
3564
+ () => createTypedClient(wrapClient(rawClient), triggers, { debug }),
3565
+ [rawClient, wrapClient]
3566
+ );
3567
+ useEffect4(() => {
3568
+ if (trackingConfig && conversionStore && "start" in conversionStore) {
3569
+ conversionStore.start();
3570
+ }
3571
+ }, [conversionStore]);
3426
3572
  const firePageView = useCallback3(() => {
3427
- const rawClient = getOrCreateTrackingClient({
3428
- apiKey,
3429
- endpoint,
3430
- surface: "next",
3431
- packageName: "@aranova/tracking-next",
3432
- triggers,
3433
- environment,
3434
- activeGtagIds: gtagIds,
3435
- debug
3436
- });
3437
3573
  fireManualPageView(wrapClient(rawClient));
3438
3574
  if (trackingConfig) getTrackingConfigRuntime(trackingConfig).queuePageView();
3439
- }, [wrapClient]);
3575
+ }, [rawClient, wrapClient]);
3440
3576
  const firedPagesRef = useRef(/* @__PURE__ */ new Set());
3441
3577
  useEffect4(() => {
3442
3578
  if (!specificPageVisitConfig || pathname === null) return;
3443
- const rawClient = getOrCreateTrackingClient({
3444
- apiKey,
3445
- endpoint,
3446
- surface: "next",
3447
- packageName: "@aranova/tracking-next",
3448
- triggers,
3449
- environment,
3450
- activeGtagIds: gtagIds,
3451
- debug
3452
- });
3453
3579
  const detectorClient = wrapClient(rawClient);
3454
3580
  for (const { name, pathPattern } of specificPageVisitConfig.pages) {
3455
3581
  if (!pathPattern.test(pathname)) continue;
@@ -3466,7 +3592,7 @@ function createTracking(options) {
3466
3592
  occurredAt: null
3467
3593
  });
3468
3594
  }
3469
- }, [pathname]);
3595
+ }, [pathname, rawClient, wrapClient]);
3470
3596
  const multiPageSessionConfig = triggers.automatic.multi_page_session ?? null;
3471
3597
  const mpsLastPathRef = useRef(null);
3472
3598
  useEffect4(() => {
@@ -3492,17 +3618,6 @@ function createTracking(options) {
3492
3618
  store.setItem(MPS_PATHS_KEY, JSON.stringify([...paths]));
3493
3619
  if (paths.size >= multiPageSessionConfig.pageThreshold) {
3494
3620
  store.setItem(MPS_FIRED_KEY, "1");
3495
- const rawClient = getOrCreateTrackingClient({
3496
- apiKey,
3497
- endpoint,
3498
- surface: "next",
3499
- packageName: "@aranova/tracking-next",
3500
- sdkVersion: version,
3501
- triggers,
3502
- environment,
3503
- activeGtagIds: gtagIds,
3504
- debug
3505
- });
3506
3621
  wrapClient(rawClient).trackEvent({
3507
3622
  eventType: "multi_page_session",
3508
3623
  metadata: {
@@ -3515,18 +3630,8 @@ function createTracking(options) {
3515
3630
  }
3516
3631
  } catch {
3517
3632
  }
3518
- }, [pathname]);
3633
+ }, [multiPageSessionConfig, pathname, rawClient, wrapClient]);
3519
3634
  useEffect4(() => {
3520
- const rawClient = getOrCreateTrackingClient({
3521
- apiKey,
3522
- endpoint,
3523
- surface: "next",
3524
- packageName: "@aranova/tracking-next",
3525
- triggers,
3526
- environment,
3527
- activeGtagIds: gtagIds,
3528
- debug
3529
- });
3530
3635
  return attachClientCapturesOnce(rawClient, () => {
3531
3636
  const detachers = [];
3532
3637
  const detectorClient = wrapClient(rawClient);
@@ -3557,7 +3662,7 @@ function createTracking(options) {
3557
3662
  }
3558
3663
  };
3559
3664
  });
3560
- }, []);
3665
+ }, [rawClient, wrapClient]);
3561
3666
  return /* @__PURE__ */ jsxs4(TrackingContext.Provider, { value: client, children: [
3562
3667
  /* @__PURE__ */ jsx5(Suspense, { fallback: null, children: /* @__PURE__ */ jsx5(PageViewTracker, { fire: firePageView }) }),
3563
3668
  /* @__PURE__ */ jsx5(PhoneConfigProvider, { value: phone ?? null, children })