@aranova/tracking-react 0.19.0 → 0.19.2

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
@@ -686,10 +686,17 @@ function markFired(input) {
686
686
  }
687
687
  }
688
688
  function fireConversionWithConsent(input, options) {
689
- if (getConsentState() === "denied") return;
690
- if (alreadyFired(input)) return;
691
- applyUserDataForConversion(options?.userData);
692
- if (fireGtagConversion(input)) markFired(input);
689
+ if (getConsentState() === "denied") return "denied";
690
+ if (alreadyFired(input)) return "duplicate";
691
+ if (!isValidSendTo(input.sendTo)) return "invalid";
692
+ try {
693
+ applyUserDataForConversion(options?.userData);
694
+ if (!fireGtagConversion(input)) return "retryable";
695
+ markFired(input);
696
+ return "fired";
697
+ } catch {
698
+ return "retryable";
699
+ }
693
700
  }
694
701
 
695
702
  // ../tracking-core/src/resources/conversion-config.ts
@@ -863,6 +870,103 @@ function resolveConversionConfig(options) {
863
870
  };
864
871
  }
865
872
 
873
+ // ../tracking-core/src/resources/automatic-transaction.ts
874
+ var STORAGE_KEY = "_aranova_auto_txn_map";
875
+ var transactionIds = /* @__PURE__ */ new Map();
876
+ var legacyCounter = 0;
877
+ function scopeKey(sessionId, goalKey, path) {
878
+ return JSON.stringify([sessionId, goalKey, path]);
879
+ }
880
+ function randomId() {
881
+ const cryptoApi = globalThis.crypto;
882
+ if (typeof cryptoApi?.randomUUID === "function") return cryptoApi.randomUUID();
883
+ if (typeof cryptoApi?.getRandomValues === "function") {
884
+ const bytes = cryptoApi.getRandomValues(new Uint8Array(16));
885
+ return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
886
+ }
887
+ legacyCounter = (legacyCounter + 1) % 4294967296;
888
+ const timestamp = Date.now().toString(16).padStart(12, "0");
889
+ const counter = legacyCounter.toString(16).padStart(8, "0");
890
+ const random = Math.floor(Math.random() * 281474976710655).toString(16).padStart(12, "0");
891
+ return `${timestamp}${counter}${random}`.slice(0, 32);
892
+ }
893
+ function isValidTransactionId(value) {
894
+ 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(
895
+ value
896
+ ) && value.length <= 64;
897
+ }
898
+ function readStoredMap(sessionId) {
899
+ if (typeof window === "undefined") return { sessionId, entries: {} };
900
+ try {
901
+ const raw = window.localStorage.getItem(STORAGE_KEY);
902
+ if (!raw) return { sessionId, entries: {} };
903
+ const parsed = JSON.parse(raw);
904
+ if (parsed.sessionId !== sessionId || !parsed.entries || typeof parsed.entries !== "object" || Array.isArray(parsed.entries)) {
905
+ return { sessionId, entries: {} };
906
+ }
907
+ return { sessionId, entries: parsed.entries };
908
+ } catch {
909
+ return { sessionId, entries: {} };
910
+ }
911
+ }
912
+ function writeStoredMap(stored) {
913
+ if (typeof window === "undefined") return;
914
+ try {
915
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(stored));
916
+ } catch {
917
+ }
918
+ }
919
+ function getAutomaticTransactionId(sessionId, goalKey, path) {
920
+ const key = scopeKey(sessionId, goalKey, path);
921
+ const existing = transactionIds.get(key);
922
+ if (existing) return existing;
923
+ const stored = readStoredMap(sessionId);
924
+ const storedId = stored.entries[key];
925
+ if (isValidTransactionId(storedId)) {
926
+ transactionIds.set(key, storedId);
927
+ return storedId;
928
+ }
929
+ const transactionId = `auto:${randomId()}`;
930
+ transactionIds.set(key, transactionId);
931
+ const latest = readStoredMap(sessionId);
932
+ const concurrentId = latest.entries[key];
933
+ if (isValidTransactionId(concurrentId)) {
934
+ transactionIds.set(key, concurrentId);
935
+ return concurrentId;
936
+ }
937
+ latest.entries[key] = transactionId;
938
+ writeStoredMap(latest);
939
+ return transactionId;
940
+ }
941
+
942
+ // ../tracking-core/src/resources/automatic-trigger.ts
943
+ function hasNumberField(metadata, key) {
944
+ return typeof metadata[key] === "number";
945
+ }
946
+ function hasStringField(metadata, key) {
947
+ return typeof metadata[key] === "string";
948
+ }
949
+ function automaticThresholdMet(goal, eventType, metadata) {
950
+ const trigger = goal.trigger;
951
+ if (!trigger || trigger.event_type !== eventType) return false;
952
+ switch (eventType) {
953
+ case "scroll_depth":
954
+ return hasNumberField(metadata, "depth_percent") && trigger.threshold_percent != null && metadata.depth_percent >= trigger.threshold_percent;
955
+ case "time_on_site":
956
+ return hasNumberField(metadata, "duration_ms") && trigger.threshold_seconds != null && metadata.duration_ms >= trigger.threshold_seconds * 1e3;
957
+ case "multi_page_session":
958
+ return hasNumberField(metadata, "page_count") && trigger.page_threshold != null && metadata.page_count >= trigger.page_threshold;
959
+ case "specific_page_visit":
960
+ return hasStringField(metadata, "page_name") && metadata.page_name === trigger.page_name;
961
+ case "page_view":
962
+ case "form_start":
963
+ case "phone_click":
964
+ return true;
965
+ default:
966
+ return false;
967
+ }
968
+ }
969
+
866
970
  // ../tracking-core/src/resources/sales/money.ts
867
971
  var MINOR_UNIT_EXPONENT = {
868
972
  USD: 2,
@@ -976,19 +1080,38 @@ function ensureScript(gtagId) {
976
1080
  var TrackingConfigRuntime = class {
977
1081
  constructor(ref, fetchImpl = globalThis.fetch) {
978
1082
  this.ref = ref;
979
- this.fetchImpl = fetchImpl;
980
1083
  this.current = null;
981
1084
  this.etag = null;
982
1085
  this.stateValue = "unconfirmed";
983
1086
  this.confirmedAt = 0;
1087
+ this.authorityGeneration = 0;
984
1088
  this.inFlight = null;
1089
+ this.flushInFlight = null;
1090
+ this.flushRequested = false;
1091
+ this.retryTimer = null;
1092
+ this.started = false;
985
1093
  this.conversionQueue = [];
986
1094
  this.automaticQueue = [];
987
1095
  this.pageQueue = [];
988
1096
  this.listeners = /* @__PURE__ */ new Set();
1097
+ this.fetchImpl = fetchImpl.bind(globalThis);
989
1098
  const cached = readCache2(ref.cdnUrl);
990
1099
  this.current = cached?.config ?? null;
991
1100
  this.etag = cached?.etag ?? null;
1101
+ this.start();
1102
+ }
1103
+ /**
1104
+ * Explicitly start authority resolution and Google-tag bootstrap.
1105
+ *
1106
+ * Idempotent so framework effects can call it after hydration without
1107
+ * depending on constructor timing.
1108
+ */
1109
+ start() {
1110
+ if (this.started) {
1111
+ void this.flush();
1112
+ return;
1113
+ }
1114
+ this.started = true;
992
1115
  void this.revalidate();
993
1116
  if (typeof window !== "undefined") {
994
1117
  window.addEventListener("visibilitychange", () => {
@@ -1004,7 +1127,7 @@ var TrackingConfigRuntime = class {
1004
1127
  return this.stateValue === "active" || this.stateValue === "tombstone" ? this.current : null;
1005
1128
  }
1006
1129
  __unsafeExpireAuthorityForTests() {
1007
- this.confirmedAt = 0;
1130
+ this.confirmedAt = Number.NEGATIVE_INFINITY;
1008
1131
  }
1009
1132
  subscribe(listener) {
1010
1133
  this.listeners.add(listener);
@@ -1014,10 +1137,14 @@ var TrackingConfigRuntime = class {
1014
1137
  if (this.stateValue !== "unconfirmed" && Date.now() - this.confirmedAt < AUTHORITY_TTL_MS) {
1015
1138
  return true;
1016
1139
  }
1017
- await this.revalidate();
1140
+ await this.revalidateAuthority();
1018
1141
  return this.stateValue !== "unconfirmed" && Date.now() - this.confirmedAt < AUTHORITY_TTL_MS;
1019
1142
  }
1020
1143
  async revalidate() {
1144
+ await this.revalidateAuthority();
1145
+ await this.flush();
1146
+ }
1147
+ async revalidateAuthority() {
1021
1148
  if (typeof window === "undefined" || !this.fetchImpl) return;
1022
1149
  if (this.inFlight) return this.inFlight;
1023
1150
  this.inFlight = this.revalidateNow().finally(() => {
@@ -1034,8 +1161,8 @@ var TrackingConfigRuntime = class {
1034
1161
  this.conversionQueue.push({ key, ...options });
1035
1162
  void this.flush();
1036
1163
  }
1037
- queueAutomaticEvent(eventType, metadata, transactionPath) {
1038
- this.automaticQueue.push({ eventType, metadata, transactionPath });
1164
+ queueAutomaticEvent(eventType, metadata, transactionPath, transactionScope) {
1165
+ this.automaticQueue.push({ eventType, metadata, transactionPath, transactionScope });
1039
1166
  void this.flush();
1040
1167
  }
1041
1168
  listGoals() {
@@ -1052,7 +1179,6 @@ var TrackingConfigRuntime = class {
1052
1179
  });
1053
1180
  if (response.status === 304 && this.current && validateConfig(this.current, this.ref)) {
1054
1181
  this.confirm(this.current, this.etag);
1055
- await this.flush();
1056
1182
  return;
1057
1183
  }
1058
1184
  if (!response.ok) {
@@ -1069,21 +1195,26 @@ var TrackingConfigRuntime = class {
1069
1195
  return;
1070
1196
  }
1071
1197
  this.confirm(next, response.headers.get("ETag"));
1072
- await this.flush();
1073
1198
  } catch {
1074
1199
  this.expireAuthority();
1075
1200
  }
1076
1201
  }
1077
1202
  expireAuthority() {
1203
+ this.authorityGeneration += 1;
1078
1204
  if (this.stateValue !== "unconfirmed") this.stateValue = "unconfirmed";
1079
1205
  }
1080
1206
  confirm(config, etag) {
1207
+ this.authorityGeneration += 1;
1081
1208
  this.current = config;
1082
1209
  this.etag = etag;
1083
1210
  this.confirmedAt = Date.now();
1084
1211
  this.stateValue = isTombstone(config) ? "tombstone" : "active";
1085
1212
  writeCache2(this.ref.cdnUrl, { etag, config });
1086
1213
  if (this.stateValue === "tombstone") {
1214
+ if (this.retryTimer !== null) {
1215
+ window.clearTimeout(this.retryTimer);
1216
+ this.retryTimer = null;
1217
+ }
1087
1218
  this.conversionQueue.length = 0;
1088
1219
  this.automaticQueue.length = 0;
1089
1220
  this.pageQueue.length = 0;
@@ -1091,80 +1222,107 @@ var TrackingConfigRuntime = class {
1091
1222
  for (const listener of this.listeners) listener();
1092
1223
  }
1093
1224
  async flush() {
1225
+ if (this.flushInFlight) {
1226
+ this.flushRequested = true;
1227
+ return this.flushInFlight;
1228
+ }
1229
+ this.flushRequested = false;
1230
+ this.flushInFlight = this.flushNow().finally(() => {
1231
+ this.flushInFlight = null;
1232
+ if (this.flushRequested && this.stateValue === "active") void this.flush();
1233
+ });
1234
+ return this.flushInFlight;
1235
+ }
1236
+ scheduleRetry() {
1237
+ if (this.retryTimer !== null || typeof window === "undefined") return;
1238
+ this.retryTimer = window.setTimeout(() => {
1239
+ this.retryTimer = null;
1240
+ void this.flush();
1241
+ }, 1e3);
1242
+ }
1243
+ async flushNow() {
1094
1244
  if (!await this.ensureAuthority()) return;
1095
1245
  if (this.stateValue !== "active" || !this.current) return;
1096
- const ids = Object.values(this.current.gtag_ids).filter(
1246
+ const config = this.current;
1247
+ const generation = this.authorityGeneration;
1248
+ const ids = Object.values(config.gtag_ids).filter(
1097
1249
  (id) => typeof id === "string" && isValidGtagId(id)
1098
1250
  );
1099
1251
  if (ids.length === 0) return;
1100
1252
  await ensureScript(ids[0]);
1253
+ if (this.authorityGeneration !== generation || this.stateValue !== "active" || this.current !== config) {
1254
+ return;
1255
+ }
1101
1256
  const gtag = window.gtag;
1102
1257
  if (typeof gtag !== "function") return;
1103
- if (!jsInitialized) {
1104
- gtag("js", /* @__PURE__ */ new Date());
1105
- jsInitialized = true;
1106
- }
1107
- for (const id of ids) {
1108
- if (configuredIds.has(id)) continue;
1109
- gtag("config", id, { send_page_view: false });
1110
- configuredIds.add(id);
1111
- }
1112
- while (this.pageQueue.length) {
1113
- const page = this.pageQueue.shift();
1114
- gtag("event", "page_view", {
1115
- page_location: page.href,
1116
- page_title: page.title ?? void 0,
1117
- page_referrer: page.referrer ?? void 0
1118
- });
1258
+ try {
1259
+ if (!jsInitialized) {
1260
+ gtag("js", /* @__PURE__ */ new Date());
1261
+ jsInitialized = true;
1262
+ }
1263
+ for (const id of ids) {
1264
+ if (configuredIds.has(id)) continue;
1265
+ gtag("config", id, { send_page_view: false });
1266
+ configuredIds.add(id);
1267
+ }
1268
+ } catch {
1269
+ this.scheduleRetry();
1270
+ return;
1119
1271
  }
1120
- while (this.automaticQueue.length) {
1121
- const event = this.automaticQueue.shift();
1122
- for (const goal of this.current.goals) {
1272
+ while (this.pageQueue.length > 0) {
1273
+ const page = this.pageQueue[0];
1274
+ try {
1275
+ gtag("event", "page_view", {
1276
+ page_location: page.href,
1277
+ page_title: page.title ?? void 0,
1278
+ page_referrer: page.referrer ?? void 0
1279
+ });
1280
+ this.pageQueue.shift();
1281
+ } catch {
1282
+ this.scheduleRetry();
1283
+ return;
1284
+ }
1285
+ }
1286
+ while (this.automaticQueue.length > 0) {
1287
+ const event = this.automaticQueue[0];
1288
+ for (const goal of config.goals) {
1123
1289
  if (goal.kind !== "event" || !goal.firing) continue;
1124
1290
  if (!automaticThresholdMet(goal, event.eventType, event.metadata)) continue;
1125
1291
  this.conversionQueue.push({
1126
1292
  key: goal.key,
1127
- transactionId: `auto:${goal.key}:${event.transactionPath}`
1293
+ transactionId: getAutomaticTransactionId(
1294
+ event.transactionScope,
1295
+ goal.key,
1296
+ event.transactionPath
1297
+ )
1128
1298
  });
1129
1299
  }
1300
+ this.automaticQueue.shift();
1130
1301
  }
1131
- while (this.conversionQueue.length) {
1132
- const item = this.conversionQueue.shift();
1133
- const goal = this.current.goals.find((g) => g.key === item.key);
1302
+ while (this.conversionQueue.length > 0) {
1303
+ const item = this.conversionQueue[0];
1304
+ const goal = config.goals.find((g) => g.key === item.key);
1134
1305
  const firing = goal?.firing;
1135
- if (!firing || getConsentState() === "denied") continue;
1306
+ if (!firing) {
1307
+ this.conversionQueue.shift();
1308
+ continue;
1309
+ }
1136
1310
  const currency = item.currency ?? firing.currency ?? null;
1137
1311
  const value = item.value ?? (firing.value_cents != null && currency ? fromMinor(firing.value_cents, currency) : null);
1138
- applyUserDataForConversion();
1139
- fireGtagConversion({
1312
+ const outcome = fireConversionWithConsent({
1140
1313
  sendTo: firing.send_to,
1141
1314
  value,
1142
1315
  currency,
1143
1316
  transactionId: item.transactionId ?? null
1144
1317
  });
1318
+ if (outcome === "retryable") {
1319
+ this.scheduleRetry();
1320
+ return;
1321
+ }
1322
+ this.conversionQueue.shift();
1145
1323
  }
1146
1324
  }
1147
1325
  };
1148
- function automaticThresholdMet(goal, eventType, metadata) {
1149
- const t = goal.trigger;
1150
- if (!t || t.event_type !== eventType) return false;
1151
- switch (eventType) {
1152
- case "scroll_depth":
1153
- return typeof metadata.depth_percent === "number" && t.threshold_percent != null && metadata.depth_percent >= t.threshold_percent;
1154
- case "time_on_site":
1155
- return typeof metadata.duration_ms === "number" && t.threshold_seconds != null && metadata.duration_ms >= t.threshold_seconds * 1e3;
1156
- case "multi_page_session":
1157
- return typeof metadata.page_count === "number" && t.page_threshold != null && metadata.page_count >= t.page_threshold;
1158
- case "specific_page_visit":
1159
- return typeof metadata.page_name === "string" && metadata.page_name === t.page_name;
1160
- case "page_view":
1161
- case "form_start":
1162
- case "phone_click":
1163
- return true;
1164
- default:
1165
- return false;
1166
- }
1167
- }
1168
1326
  function getTrackingConfigRuntime(ref, fetchImpl) {
1169
1327
  const key = `${ref.cdnUrl}|${ref.businessId}|${ref.environment}`;
1170
1328
  const existing = runtimes.get(key);
@@ -1175,26 +1333,6 @@ function getTrackingConfigRuntime(ref, fetchImpl) {
1175
1333
  }
1176
1334
 
1177
1335
  // ../tracking-core/src/resources/conversion-autofire.ts
1178
- function thresholdMet(goal, eventType, metadata) {
1179
- const t = goal.trigger;
1180
- if (!t || t.event_type !== eventType) return false;
1181
- switch (eventType) {
1182
- case "scroll_depth":
1183
- return typeof metadata.depth_percent === "number" && t.threshold_percent != null && metadata.depth_percent >= t.threshold_percent;
1184
- case "time_on_site":
1185
- return typeof metadata.duration_ms === "number" && t.threshold_seconds != null && metadata.duration_ms >= t.threshold_seconds * 1e3;
1186
- case "multi_page_session":
1187
- return typeof metadata.page_count === "number" && t.page_threshold != null && metadata.page_count >= t.page_threshold;
1188
- case "specific_page_visit":
1189
- return typeof metadata.page_name === "string" && metadata.page_name === t.page_name;
1190
- case "page_view":
1191
- case "form_start":
1192
- case "phone_click":
1193
- return true;
1194
- default:
1195
- return false;
1196
- }
1197
- }
1198
1336
  function currentPath() {
1199
1337
  return typeof window === "undefined" ? "" : window.location.pathname;
1200
1338
  }
@@ -1202,13 +1340,14 @@ var MAX_BUFFERED_EVENTS = 50;
1202
1340
  function createConversionAutoFire(store) {
1203
1341
  const pending = [];
1204
1342
  let subscribed = false;
1205
- function fireMatching(eventType, metadata) {
1343
+ function fireMatching(eventType, metadata, transactionScope) {
1206
1344
  for (const goal of store.listGoals()) {
1207
1345
  if (goal.kind !== "event" || !goal.firing) continue;
1208
- if (!thresholdMet(goal, eventType, metadata)) continue;
1346
+ if (!automaticThresholdMet(goal, eventType, metadata)) continue;
1347
+ const transactionId = getAutomaticTransactionId(transactionScope, goal.key, currentPath());
1209
1348
  if ("queueAutomaticEvent" in store) {
1210
1349
  store.fireConversion(goal.key, {
1211
- transactionId: `auto:${goal.key}:${currentPath()}`
1350
+ transactionId
1212
1351
  });
1213
1352
  continue;
1214
1353
  }
@@ -1219,28 +1358,30 @@ function createConversionAutoFire(store) {
1219
1358
  sendTo: firing.send_to,
1220
1359
  value: cents != null && currency ? fromMinor(cents, currency) : null,
1221
1360
  currency,
1222
- // Page-scoped txn id → fire once per (goal, path) per session; engagement conversions
1223
- // shouldn't re-fire as the visitor scrolls back and forth or re-enters a page.
1224
- transactionId: `auto:${goal.key}:${currentPath()}`
1361
+ transactionId
1225
1362
  });
1226
1363
  }
1227
1364
  }
1228
1365
  return {
1229
- onAutomaticEvent(eventType, metadata) {
1366
+ onAutomaticEvent(eventType, metadata, transactionScope) {
1230
1367
  if ("queueAutomaticEvent" in store) {
1231
- store.queueAutomaticEvent(eventType, metadata, currentPath());
1368
+ store.queueAutomaticEvent(eventType, metadata, currentPath(), transactionScope);
1232
1369
  return;
1233
1370
  }
1234
1371
  if (store.isReady()) {
1235
- fireMatching(eventType, metadata);
1372
+ fireMatching(eventType, metadata, transactionScope);
1236
1373
  return;
1237
1374
  }
1238
- if (pending.length < MAX_BUFFERED_EVENTS) pending.push({ eventType, metadata });
1375
+ if (pending.length < MAX_BUFFERED_EVENTS) {
1376
+ pending.push({ eventType, metadata, transactionScope });
1377
+ }
1239
1378
  if (!subscribed) {
1240
1379
  subscribed = true;
1241
1380
  store.onResolve(() => {
1242
1381
  const buffered = pending.splice(0);
1243
- for (const event of buffered) fireMatching(event.eventType, event.metadata);
1382
+ for (const event of buffered) {
1383
+ fireMatching(event.eventType, event.metadata, event.transactionScope);
1384
+ }
1244
1385
  });
1245
1386
  }
1246
1387
  }
@@ -1252,7 +1393,7 @@ function withConversionAutoFire(client, autoFire) {
1252
1393
  trackEvent: (input) => {
1253
1394
  client.trackEvent(input);
1254
1395
  try {
1255
- autoFire.onAutomaticEvent(input.eventType, input.metadata ?? {});
1396
+ autoFire.onAutomaticEvent(input.eventType, input.metadata ?? {}, client.getSessionId());
1256
1397
  } catch {
1257
1398
  }
1258
1399
  }
@@ -2385,7 +2526,7 @@ function attachScrollDepth(client, config) {
2385
2526
  }
2386
2527
 
2387
2528
  // ../tracking-core/src/triggers/multi-page-session.ts
2388
- var STORAGE_KEY = "aranova_tracking_mps_paths";
2529
+ var STORAGE_KEY2 = "aranova_tracking_mps_paths";
2389
2530
  var SESSION_KEY = "aranova_tracking_mps_session";
2390
2531
  var FIRED_KEY = "aranova_tracking_mps_fired";
2391
2532
  function getSessionStorage() {
@@ -2407,7 +2548,7 @@ function attachMultiPageSession(client, config) {
2407
2548
  let lastCheckedPath = "";
2408
2549
  function getDistinctPaths() {
2409
2550
  try {
2410
- const raw = storage.getItem(STORAGE_KEY);
2551
+ const raw = storage.getItem(STORAGE_KEY2);
2411
2552
  return raw ? new Set(JSON.parse(raw)) : /* @__PURE__ */ new Set();
2412
2553
  } catch {
2413
2554
  return /* @__PURE__ */ new Set();
@@ -2415,7 +2556,7 @@ function attachMultiPageSession(client, config) {
2415
2556
  }
2416
2557
  function saveDistinctPaths(paths) {
2417
2558
  try {
2418
- storage.setItem(STORAGE_KEY, JSON.stringify([...paths]));
2559
+ storage.setItem(STORAGE_KEY2, JSON.stringify([...paths]));
2419
2560
  } catch {
2420
2561
  }
2421
2562
  }
@@ -2424,7 +2565,7 @@ function attachMultiPageSession(client, config) {
2424
2565
  const storedSession = storage.getItem(SESSION_KEY);
2425
2566
  if (storedSession !== currentSession) {
2426
2567
  storage.setItem(SESSION_KEY, currentSession);
2427
- storage.removeItem(STORAGE_KEY);
2568
+ storage.removeItem(STORAGE_KEY2);
2428
2569
  storage.removeItem(FIRED_KEY);
2429
2570
  }
2430
2571
  }
@@ -3419,7 +3560,7 @@ function GoogleAdsTracking(props) {
3419
3560
  import { createContext as createContext2, useContext as useContext2, useEffect as useEffect5, useMemo as useMemo4 } from "react";
3420
3561
 
3421
3562
  // package.json
3422
- var version = "0.19.0";
3563
+ var version = "0.19.2";
3423
3564
 
3424
3565
  // ../tracking-core/src/phone-react.tsx
3425
3566
  import {
@@ -3557,31 +3698,46 @@ function createTracking(options) {
3557
3698
  metaPixelIds,
3558
3699
  children
3559
3700
  }) {
3560
- const resolvedGtagIds = gtagIds ? Object.fromEntries(
3561
- Object.entries(gtagIds).filter((e) => e[1] != null)
3562
- ) : gtagId ? { default: gtagId } : void 0;
3563
- const client = useMemo4(
3564
- () => createTypedClient(
3565
- getOrCreateTrackingClient({
3566
- apiKey,
3567
- endpoint,
3568
- surface: "react",
3569
- packageName: "@aranova/tracking-react",
3570
- sdkVersion: version,
3571
- triggers,
3572
- environment,
3573
- activeGtagIds: resolvedGtagIds,
3574
- debug
3575
- }),
3701
+ const gtagIdsKey = useMemo4(() => gtagIds ? JSON.stringify(gtagIds) : "", [gtagIds]);
3702
+ const resolvedGtagIds = useMemo4(
3703
+ () => gtagIds ? Object.fromEntries(
3704
+ Object.entries(gtagIds).filter((e) => e[1] != null)
3705
+ ) : gtagId ? { default: gtagId } : void 0,
3706
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- gtagIdsKey is stable proxy
3707
+ [gtagId, gtagIdsKey]
3708
+ );
3709
+ const rawClient = useMemo4(
3710
+ () => getOrCreateTrackingClient({
3711
+ apiKey,
3712
+ endpoint,
3713
+ surface: "react",
3714
+ packageName: "@aranova/tracking-react",
3715
+ sdkVersion: version,
3576
3716
  triggers,
3577
- { debug }
3578
- ),
3717
+ environment,
3718
+ activeGtagIds: resolvedGtagIds,
3719
+ debug
3720
+ }),
3721
+ [resolvedGtagIds]
3722
+ );
3723
+ const conversionStore = useMemo4(
3724
+ () => trackingConfig ? getTrackingConfigRuntime(trackingConfig) : conversionConfig ? resolveConversionConfig({
3725
+ cdnUrl: conversionConfig.cdnUrl,
3726
+ baked: conversionConfig.baked
3727
+ }) : null,
3579
3728
  []
3580
3729
  );
3581
- const gtagIdsKey = useMemo4(() => gtagIds ? JSON.stringify(gtagIds) : "", [gtagIds]);
3730
+ const conversionClient = useMemo4(
3731
+ () => conversionStore ? withConversionAutoFire(rawClient, createConversionAutoFire(conversionStore)) : rawClient,
3732
+ [rawClient, conversionStore]
3733
+ );
3734
+ const client = useMemo4(
3735
+ () => createTypedClient(conversionClient, triggers, { debug }),
3736
+ [conversionClient]
3737
+ );
3582
3738
  useEffect5(() => {
3583
3739
  if (trackingConfig) {
3584
- void getTrackingConfigRuntime(trackingConfig).revalidate();
3740
+ getTrackingConfigRuntime(trackingConfig).start();
3585
3741
  } else if (gtagIds && Object.keys(gtagIds).length > 0) {
3586
3742
  bootstrapMultipleGtags(gtagIds);
3587
3743
  } else if (gtagId) {
@@ -3600,23 +3756,9 @@ function createTracking(options) {
3600
3756
  }
3601
3757
  }, [metaPixelId, metaPixelIdsKey]);
3602
3758
  useEffect5(() => {
3603
- const rawClient = getOrCreateTrackingClient({
3604
- apiKey,
3605
- endpoint,
3606
- surface: "react",
3607
- packageName: "@aranova/tracking-react",
3608
- triggers,
3609
- environment,
3610
- activeGtagIds: resolvedGtagIds,
3611
- debug
3612
- });
3613
3759
  return attachClientCapturesOnce(rawClient, () => {
3614
3760
  const detachers = [];
3615
- const conversionStore = trackingConfig ? getTrackingConfigRuntime(trackingConfig) : conversionConfig ? resolveConversionConfig({
3616
- cdnUrl: conversionConfig.cdnUrl,
3617
- baked: conversionConfig.baked
3618
- }) : null;
3619
- const detectorClient = conversionStore ? withConversionAutoFire(rawClient, createConversionAutoFire(conversionStore)) : rawClient;
3761
+ const detectorClient = conversionStore ? conversionClient : rawClient;
3620
3762
  const pageClient = trackingConfig && conversionStore && "queuePageView" in conversionStore ? {
3621
3763
  ...detectorClient,
3622
3764
  trackEvent: (input) => {
@@ -3661,7 +3803,7 @@ function createTracking(options) {
3661
3803
  }
3662
3804
  };
3663
3805
  });
3664
- }, []);
3806
+ }, [conversionClient, conversionStore, rawClient]);
3665
3807
  return /* @__PURE__ */ jsx3(TrackingContext.Provider, { value: client, children: /* @__PURE__ */ jsx3(PhoneConfigProvider, { value: phone ?? null, children }) });
3666
3808
  }
3667
3809
  function useTracking() {