@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.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { T as TrackingParams, a as TrackingInstallSurface, b as TrackingEnvironment, c as TrackingClientContext, d as TrackingEventCreatePayload, e as TrackingSessionUpsertPayload, F as FormSubmitConfig, f as FormSubmitMetadata, C as ConsentState, g as ConsentChoiceState, h as ConsentSource, G as GtagEnvironmentMap, M as MetaPixelEnvironmentMap, P as PhoneConfig, i as ParsedPhone, j as PhoneDisplayFormat } from './phone-utils-B2vHJkNz.mjs';
2
2
  export { k as ConsentChoice, D as DEFAULT_DECLINE_TTL_DAYS, l as DEFAULT_PHONE_COUNTRY, J as JsonValue, S as SetConsentOptions, m as TrackedField, n as TrackingInitConfig, o as formSubmitConfigSchema, p as formSubmitMetadataSchema, q as formatPhone, r as formatPhoneAsTyped, s as getConsentChoice, t as getConsentState, u as jsonValueSchema, v as onConsentChange, w as optIn, x as optOut, y as parsePhone, z as phoneField, A as resetConsent, B as setConsentState, E as toE164 } from './phone-utils-B2vHJkNz.mjs';
3
- import { T as TrackingConfigReference, C as ConversionConfig } from './sales--WzOzyiO.mjs';
4
- export { A as AranovaApiError, B as BusinessConfig, a as BusinessConfigFeatures, b as BusinessConfigService, c as CompareTo, d as ConversionConfigStore, e as ConversionUserData, f as CurrencyRevenue, g as CustomerCurrencyDelta, h as CustomerCurrencyTotal, i as CustomerGetOptions, j as CustomerGetResult, k as CustomerKpis, l as CustomerKpisDeltas, m as CustomerKpisPrevious, n as CustomerListPage, o as CustomerListQuery, p as CustomerProfile, q as CustomerSegment, r as CustomerSegmentCount, s as CustomerSortField, t as CustomerSummary, u as CustomerSummaryQuery, D as DistinctCustomersByCurrency, G as Granularity, N as NAMED_RANGES, v as NamedRange, P as PublicServiceItem, S as SUPPORTED_CURRENCIES, w as Sale, x as SaleCursorPage, y as SaleFilters, z as SaleInput, E as SaleItem, F as SaleItemInput, H as SaleKeysetSortField, I as SaleListPage, J as SaleListQuery, K as SaleListQueryV2, L as SaleService, M as SaleServiceInput, O as SaleSortField, Q as SaleSortOrder, R as SaleSummary, U as SaleSummaryPrevious, V as SaleSummaryQuery, W as SaleSummaryQueryV2, X as SaleSummaryV2, Y as SaleUpdateInput, Z as SalesBusinessClient, _ as SalesCategoryBreakdown, $ as SalesClient, a0 as SalesClientConfig, a1 as SalesCustomersClient, a2 as SalesServiceBreakdown, a3 as SalesTransportConfig, a4 as SalesTrendPoint, a5 as SummaryCurrencyDelta, a6 as SummaryDeltas, a7 as SummaryWindow, a8 as SupportedCurrency, a9 as TRACKING_RANGES, aa as TrackingOverviewRange, ab as clearStashedUserData, ac as createSalesClient, ad as fetchServices, ae as formatDateInTz, af as formatMoney, ag as fromMinor, ah as getTrackingConfigRuntime, ai as resolveConversionConfig, aj as saleCreateSchema, ak as saleItemSchema, al as saleServiceSchema, am as saleUpdateSchema, an as salesRequest, ao as stashUserData, ap as toMinor } from './sales--WzOzyiO.mjs';
3
+ import { T as TrackingConfigReference, C as ConversionConfig } from './sales-DrH6dY5F.mjs';
4
+ export { A as AranovaApiError, B as BusinessConfig, a as BusinessConfigFeatures, b as BusinessConfigService, c as CompareTo, d as ConversionConfigStore, e as ConversionUserData, f as CurrencyRevenue, g as CustomerCurrencyDelta, h as CustomerCurrencyTotal, i as CustomerGetOptions, j as CustomerGetResult, k as CustomerKpis, l as CustomerKpisDeltas, m as CustomerKpisPrevious, n as CustomerListPage, o as CustomerListQuery, p as CustomerProfile, q as CustomerSegment, r as CustomerSegmentCount, s as CustomerSortField, t as CustomerSummary, u as CustomerSummaryQuery, D as DistinctCustomersByCurrency, G as Granularity, N as NAMED_RANGES, v as NamedRange, P as PublicServiceItem, S as SUPPORTED_CURRENCIES, w as Sale, x as SaleCursorPage, y as SaleFilters, z as SaleInput, E as SaleItem, F as SaleItemInput, H as SaleKeysetSortField, I as SaleListPage, J as SaleListQuery, K as SaleListQueryV2, L as SaleService, M as SaleServiceInput, O as SaleSortField, Q as SaleSortOrder, R as SaleSummary, U as SaleSummaryPrevious, V as SaleSummaryQuery, W as SaleSummaryQueryV2, X as SaleSummaryV2, Y as SaleUpdateInput, Z as SalesBusinessClient, _ as SalesCategoryBreakdown, $ as SalesClient, a0 as SalesClientConfig, a1 as SalesCustomersClient, a2 as SalesServiceBreakdown, a3 as SalesTransportConfig, a4 as SalesTrendPoint, a5 as SummaryCurrencyDelta, a6 as SummaryDeltas, a7 as SummaryWindow, a8 as SupportedCurrency, a9 as TRACKING_RANGES, aa as TrackingOverviewRange, ab as clearStashedUserData, ac as createSalesClient, ad as fetchServices, ae as formatDateInTz, af as formatMoney, ag as fromMinor, ah as getTrackingConfigRuntime, ai as resolveConversionConfig, aj as saleCreateSchema, ak as saleItemSchema, al as saleServiceSchema, am as saleUpdateSchema, an as salesRequest, ao as stashUserData, ap as toMinor } from './sales-DrH6dY5F.mjs';
5
5
  import { z } from 'zod';
6
6
  import * as src from 'src';
7
7
  import * as react from 'react';
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { T as TrackingParams, a as TrackingInstallSurface, b as TrackingEnvironment, c as TrackingClientContext, d as TrackingEventCreatePayload, e as TrackingSessionUpsertPayload, F as FormSubmitConfig, f as FormSubmitMetadata, C as ConsentState, g as ConsentChoiceState, h as ConsentSource, G as GtagEnvironmentMap, M as MetaPixelEnvironmentMap, P as PhoneConfig, i as ParsedPhone, j as PhoneDisplayFormat } from './phone-utils-B2vHJkNz.js';
2
2
  export { k as ConsentChoice, D as DEFAULT_DECLINE_TTL_DAYS, l as DEFAULT_PHONE_COUNTRY, J as JsonValue, S as SetConsentOptions, m as TrackedField, n as TrackingInitConfig, o as formSubmitConfigSchema, p as formSubmitMetadataSchema, q as formatPhone, r as formatPhoneAsTyped, s as getConsentChoice, t as getConsentState, u as jsonValueSchema, v as onConsentChange, w as optIn, x as optOut, y as parsePhone, z as phoneField, A as resetConsent, B as setConsentState, E as toE164 } from './phone-utils-B2vHJkNz.js';
3
- import { T as TrackingConfigReference, C as ConversionConfig } from './sales--WzOzyiO.js';
4
- export { A as AranovaApiError, B as BusinessConfig, a as BusinessConfigFeatures, b as BusinessConfigService, c as CompareTo, d as ConversionConfigStore, e as ConversionUserData, f as CurrencyRevenue, g as CustomerCurrencyDelta, h as CustomerCurrencyTotal, i as CustomerGetOptions, j as CustomerGetResult, k as CustomerKpis, l as CustomerKpisDeltas, m as CustomerKpisPrevious, n as CustomerListPage, o as CustomerListQuery, p as CustomerProfile, q as CustomerSegment, r as CustomerSegmentCount, s as CustomerSortField, t as CustomerSummary, u as CustomerSummaryQuery, D as DistinctCustomersByCurrency, G as Granularity, N as NAMED_RANGES, v as NamedRange, P as PublicServiceItem, S as SUPPORTED_CURRENCIES, w as Sale, x as SaleCursorPage, y as SaleFilters, z as SaleInput, E as SaleItem, F as SaleItemInput, H as SaleKeysetSortField, I as SaleListPage, J as SaleListQuery, K as SaleListQueryV2, L as SaleService, M as SaleServiceInput, O as SaleSortField, Q as SaleSortOrder, R as SaleSummary, U as SaleSummaryPrevious, V as SaleSummaryQuery, W as SaleSummaryQueryV2, X as SaleSummaryV2, Y as SaleUpdateInput, Z as SalesBusinessClient, _ as SalesCategoryBreakdown, $ as SalesClient, a0 as SalesClientConfig, a1 as SalesCustomersClient, a2 as SalesServiceBreakdown, a3 as SalesTransportConfig, a4 as SalesTrendPoint, a5 as SummaryCurrencyDelta, a6 as SummaryDeltas, a7 as SummaryWindow, a8 as SupportedCurrency, a9 as TRACKING_RANGES, aa as TrackingOverviewRange, ab as clearStashedUserData, ac as createSalesClient, ad as fetchServices, ae as formatDateInTz, af as formatMoney, ag as fromMinor, ah as getTrackingConfigRuntime, ai as resolveConversionConfig, aj as saleCreateSchema, ak as saleItemSchema, al as saleServiceSchema, am as saleUpdateSchema, an as salesRequest, ao as stashUserData, ap as toMinor } from './sales--WzOzyiO.js';
3
+ import { T as TrackingConfigReference, C as ConversionConfig } from './sales-DrH6dY5F.js';
4
+ export { A as AranovaApiError, B as BusinessConfig, a as BusinessConfigFeatures, b as BusinessConfigService, c as CompareTo, d as ConversionConfigStore, e as ConversionUserData, f as CurrencyRevenue, g as CustomerCurrencyDelta, h as CustomerCurrencyTotal, i as CustomerGetOptions, j as CustomerGetResult, k as CustomerKpis, l as CustomerKpisDeltas, m as CustomerKpisPrevious, n as CustomerListPage, o as CustomerListQuery, p as CustomerProfile, q as CustomerSegment, r as CustomerSegmentCount, s as CustomerSortField, t as CustomerSummary, u as CustomerSummaryQuery, D as DistinctCustomersByCurrency, G as Granularity, N as NAMED_RANGES, v as NamedRange, P as PublicServiceItem, S as SUPPORTED_CURRENCIES, w as Sale, x as SaleCursorPage, y as SaleFilters, z as SaleInput, E as SaleItem, F as SaleItemInput, H as SaleKeysetSortField, I as SaleListPage, J as SaleListQuery, K as SaleListQueryV2, L as SaleService, M as SaleServiceInput, O as SaleSortField, Q as SaleSortOrder, R as SaleSummary, U as SaleSummaryPrevious, V as SaleSummaryQuery, W as SaleSummaryQueryV2, X as SaleSummaryV2, Y as SaleUpdateInput, Z as SalesBusinessClient, _ as SalesCategoryBreakdown, $ as SalesClient, a0 as SalesClientConfig, a1 as SalesCustomersClient, a2 as SalesServiceBreakdown, a3 as SalesTransportConfig, a4 as SalesTrendPoint, a5 as SummaryCurrencyDelta, a6 as SummaryDeltas, a7 as SummaryWindow, a8 as SupportedCurrency, a9 as TRACKING_RANGES, aa as TrackingOverviewRange, ab as clearStashedUserData, ac as createSalesClient, ad as fetchServices, ae as formatDateInTz, af as formatMoney, ag as fromMinor, ah as getTrackingConfigRuntime, ai as resolveConversionConfig, aj as saleCreateSchema, ak as saleItemSchema, al as saleServiceSchema, am as saleUpdateSchema, an as salesRequest, ao as stashUserData, ap as toMinor } from './sales-DrH6dY5F.js';
5
5
  import { z } from 'zod';
6
6
  import * as src from 'src';
7
7
  import * as react from 'react';
package/dist/index.js CHANGED
@@ -752,10 +752,17 @@ function markFired(input) {
752
752
  }
753
753
  }
754
754
  function fireConversionWithConsent(input, options) {
755
- if (getConsentState() === "denied") return;
756
- if (alreadyFired(input)) return;
757
- applyUserDataForConversion(options?.userData);
758
- if (fireGtagConversion(input)) markFired(input);
755
+ if (getConsentState() === "denied") return "denied";
756
+ if (alreadyFired(input)) return "duplicate";
757
+ if (!isValidSendTo(input.sendTo)) return "invalid";
758
+ try {
759
+ applyUserDataForConversion(options?.userData);
760
+ if (!fireGtagConversion(input)) return "retryable";
761
+ markFired(input);
762
+ return "fired";
763
+ } catch {
764
+ return "retryable";
765
+ }
759
766
  }
760
767
 
761
768
  // ../tracking-core/src/resources/conversion-config.ts
@@ -929,6 +936,103 @@ function resolveConversionConfig(options) {
929
936
  };
930
937
  }
931
938
 
939
+ // ../tracking-core/src/resources/automatic-transaction.ts
940
+ var STORAGE_KEY = "_aranova_auto_txn_map";
941
+ var transactionIds = /* @__PURE__ */ new Map();
942
+ var legacyCounter = 0;
943
+ function scopeKey(sessionId, goalKey, path) {
944
+ return JSON.stringify([sessionId, goalKey, path]);
945
+ }
946
+ function randomId() {
947
+ const cryptoApi = globalThis.crypto;
948
+ if (typeof cryptoApi?.randomUUID === "function") return cryptoApi.randomUUID();
949
+ if (typeof cryptoApi?.getRandomValues === "function") {
950
+ const bytes = cryptoApi.getRandomValues(new Uint8Array(16));
951
+ return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
952
+ }
953
+ legacyCounter = (legacyCounter + 1) % 4294967296;
954
+ const timestamp = Date.now().toString(16).padStart(12, "0");
955
+ const counter = legacyCounter.toString(16).padStart(8, "0");
956
+ const random = Math.floor(Math.random() * 281474976710655).toString(16).padStart(12, "0");
957
+ return `${timestamp}${counter}${random}`.slice(0, 32);
958
+ }
959
+ function isValidTransactionId(value) {
960
+ 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(
961
+ value
962
+ ) && value.length <= 64;
963
+ }
964
+ function readStoredMap(sessionId) {
965
+ if (typeof window === "undefined") return { sessionId, entries: {} };
966
+ try {
967
+ const raw = window.localStorage.getItem(STORAGE_KEY);
968
+ if (!raw) return { sessionId, entries: {} };
969
+ const parsed = JSON.parse(raw);
970
+ if (parsed.sessionId !== sessionId || !parsed.entries || typeof parsed.entries !== "object" || Array.isArray(parsed.entries)) {
971
+ return { sessionId, entries: {} };
972
+ }
973
+ return { sessionId, entries: parsed.entries };
974
+ } catch {
975
+ return { sessionId, entries: {} };
976
+ }
977
+ }
978
+ function writeStoredMap(stored) {
979
+ if (typeof window === "undefined") return;
980
+ try {
981
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(stored));
982
+ } catch {
983
+ }
984
+ }
985
+ function getAutomaticTransactionId(sessionId, goalKey, path) {
986
+ const key = scopeKey(sessionId, goalKey, path);
987
+ const existing = transactionIds.get(key);
988
+ if (existing) return existing;
989
+ const stored = readStoredMap(sessionId);
990
+ const storedId = stored.entries[key];
991
+ if (isValidTransactionId(storedId)) {
992
+ transactionIds.set(key, storedId);
993
+ return storedId;
994
+ }
995
+ const transactionId = `auto:${randomId()}`;
996
+ transactionIds.set(key, transactionId);
997
+ const latest = readStoredMap(sessionId);
998
+ const concurrentId = latest.entries[key];
999
+ if (isValidTransactionId(concurrentId)) {
1000
+ transactionIds.set(key, concurrentId);
1001
+ return concurrentId;
1002
+ }
1003
+ latest.entries[key] = transactionId;
1004
+ writeStoredMap(latest);
1005
+ return transactionId;
1006
+ }
1007
+
1008
+ // ../tracking-core/src/resources/automatic-trigger.ts
1009
+ function hasNumberField(metadata, key) {
1010
+ return typeof metadata[key] === "number";
1011
+ }
1012
+ function hasStringField(metadata, key) {
1013
+ return typeof metadata[key] === "string";
1014
+ }
1015
+ function automaticThresholdMet(goal, eventType, metadata) {
1016
+ const trigger = goal.trigger;
1017
+ if (!trigger || trigger.event_type !== eventType) return false;
1018
+ switch (eventType) {
1019
+ case "scroll_depth":
1020
+ return hasNumberField(metadata, "depth_percent") && trigger.threshold_percent != null && metadata.depth_percent >= trigger.threshold_percent;
1021
+ case "time_on_site":
1022
+ return hasNumberField(metadata, "duration_ms") && trigger.threshold_seconds != null && metadata.duration_ms >= trigger.threshold_seconds * 1e3;
1023
+ case "multi_page_session":
1024
+ return hasNumberField(metadata, "page_count") && trigger.page_threshold != null && metadata.page_count >= trigger.page_threshold;
1025
+ case "specific_page_visit":
1026
+ return hasStringField(metadata, "page_name") && metadata.page_name === trigger.page_name;
1027
+ case "page_view":
1028
+ case "form_start":
1029
+ case "phone_click":
1030
+ return true;
1031
+ default:
1032
+ return false;
1033
+ }
1034
+ }
1035
+
932
1036
  // ../tracking-core/src/resources/sales/money.ts
933
1037
  var MINOR_UNIT_EXPONENT = {
934
1038
  USD: 2,
@@ -1047,7 +1151,12 @@ var TrackingConfigRuntime = class {
1047
1151
  this.etag = null;
1048
1152
  this.stateValue = "unconfirmed";
1049
1153
  this.confirmedAt = 0;
1154
+ this.authorityGeneration = 0;
1050
1155
  this.inFlight = null;
1156
+ this.flushInFlight = null;
1157
+ this.flushRequested = false;
1158
+ this.retryTimer = null;
1159
+ this.started = false;
1051
1160
  this.conversionQueue = [];
1052
1161
  this.automaticQueue = [];
1053
1162
  this.pageQueue = [];
@@ -1055,6 +1164,20 @@ var TrackingConfigRuntime = class {
1055
1164
  const cached = readCache2(ref.cdnUrl);
1056
1165
  this.current = cached?.config ?? null;
1057
1166
  this.etag = cached?.etag ?? null;
1167
+ this.start();
1168
+ }
1169
+ /**
1170
+ * Explicitly start authority resolution and Google-tag bootstrap.
1171
+ *
1172
+ * Idempotent so framework effects can call it after hydration without
1173
+ * depending on constructor timing.
1174
+ */
1175
+ start() {
1176
+ if (this.started) {
1177
+ void this.flush();
1178
+ return;
1179
+ }
1180
+ this.started = true;
1058
1181
  void this.revalidate();
1059
1182
  if (typeof window !== "undefined") {
1060
1183
  window.addEventListener("visibilitychange", () => {
@@ -1070,7 +1193,7 @@ var TrackingConfigRuntime = class {
1070
1193
  return this.stateValue === "active" || this.stateValue === "tombstone" ? this.current : null;
1071
1194
  }
1072
1195
  __unsafeExpireAuthorityForTests() {
1073
- this.confirmedAt = 0;
1196
+ this.confirmedAt = Number.NEGATIVE_INFINITY;
1074
1197
  }
1075
1198
  subscribe(listener) {
1076
1199
  this.listeners.add(listener);
@@ -1080,10 +1203,14 @@ var TrackingConfigRuntime = class {
1080
1203
  if (this.stateValue !== "unconfirmed" && Date.now() - this.confirmedAt < AUTHORITY_TTL_MS) {
1081
1204
  return true;
1082
1205
  }
1083
- await this.revalidate();
1206
+ await this.revalidateAuthority();
1084
1207
  return this.stateValue !== "unconfirmed" && Date.now() - this.confirmedAt < AUTHORITY_TTL_MS;
1085
1208
  }
1086
1209
  async revalidate() {
1210
+ await this.revalidateAuthority();
1211
+ await this.flush();
1212
+ }
1213
+ async revalidateAuthority() {
1087
1214
  if (typeof window === "undefined" || !this.fetchImpl) return;
1088
1215
  if (this.inFlight) return this.inFlight;
1089
1216
  this.inFlight = this.revalidateNow().finally(() => {
@@ -1100,8 +1227,8 @@ var TrackingConfigRuntime = class {
1100
1227
  this.conversionQueue.push({ key, ...options });
1101
1228
  void this.flush();
1102
1229
  }
1103
- queueAutomaticEvent(eventType, metadata, transactionPath) {
1104
- this.automaticQueue.push({ eventType, metadata, transactionPath });
1230
+ queueAutomaticEvent(eventType, metadata, transactionPath, transactionScope) {
1231
+ this.automaticQueue.push({ eventType, metadata, transactionPath, transactionScope });
1105
1232
  void this.flush();
1106
1233
  }
1107
1234
  listGoals() {
@@ -1118,7 +1245,6 @@ var TrackingConfigRuntime = class {
1118
1245
  });
1119
1246
  if (response.status === 304 && this.current && validateConfig(this.current, this.ref)) {
1120
1247
  this.confirm(this.current, this.etag);
1121
- await this.flush();
1122
1248
  return;
1123
1249
  }
1124
1250
  if (!response.ok) {
@@ -1135,21 +1261,26 @@ var TrackingConfigRuntime = class {
1135
1261
  return;
1136
1262
  }
1137
1263
  this.confirm(next, response.headers.get("ETag"));
1138
- await this.flush();
1139
1264
  } catch {
1140
1265
  this.expireAuthority();
1141
1266
  }
1142
1267
  }
1143
1268
  expireAuthority() {
1269
+ this.authorityGeneration += 1;
1144
1270
  if (this.stateValue !== "unconfirmed") this.stateValue = "unconfirmed";
1145
1271
  }
1146
1272
  confirm(config, etag) {
1273
+ this.authorityGeneration += 1;
1147
1274
  this.current = config;
1148
1275
  this.etag = etag;
1149
1276
  this.confirmedAt = Date.now();
1150
1277
  this.stateValue = isTombstone(config) ? "tombstone" : "active";
1151
1278
  writeCache2(this.ref.cdnUrl, { etag, config });
1152
1279
  if (this.stateValue === "tombstone") {
1280
+ if (this.retryTimer !== null) {
1281
+ window.clearTimeout(this.retryTimer);
1282
+ this.retryTimer = null;
1283
+ }
1153
1284
  this.conversionQueue.length = 0;
1154
1285
  this.automaticQueue.length = 0;
1155
1286
  this.pageQueue.length = 0;
@@ -1157,80 +1288,107 @@ var TrackingConfigRuntime = class {
1157
1288
  for (const listener of this.listeners) listener();
1158
1289
  }
1159
1290
  async flush() {
1291
+ if (this.flushInFlight) {
1292
+ this.flushRequested = true;
1293
+ return this.flushInFlight;
1294
+ }
1295
+ this.flushRequested = false;
1296
+ this.flushInFlight = this.flushNow().finally(() => {
1297
+ this.flushInFlight = null;
1298
+ if (this.flushRequested && this.stateValue === "active") void this.flush();
1299
+ });
1300
+ return this.flushInFlight;
1301
+ }
1302
+ scheduleRetry() {
1303
+ if (this.retryTimer !== null || typeof window === "undefined") return;
1304
+ this.retryTimer = window.setTimeout(() => {
1305
+ this.retryTimer = null;
1306
+ void this.flush();
1307
+ }, 1e3);
1308
+ }
1309
+ async flushNow() {
1160
1310
  if (!await this.ensureAuthority()) return;
1161
1311
  if (this.stateValue !== "active" || !this.current) return;
1162
- const ids = Object.values(this.current.gtag_ids).filter(
1312
+ const config = this.current;
1313
+ const generation = this.authorityGeneration;
1314
+ const ids = Object.values(config.gtag_ids).filter(
1163
1315
  (id) => typeof id === "string" && isValidGtagId(id)
1164
1316
  );
1165
1317
  if (ids.length === 0) return;
1166
1318
  await ensureScript(ids[0]);
1319
+ if (this.authorityGeneration !== generation || this.stateValue !== "active" || this.current !== config) {
1320
+ return;
1321
+ }
1167
1322
  const gtag = window.gtag;
1168
1323
  if (typeof gtag !== "function") return;
1169
- if (!jsInitialized) {
1170
- gtag("js", /* @__PURE__ */ new Date());
1171
- jsInitialized = true;
1172
- }
1173
- for (const id of ids) {
1174
- if (configuredIds.has(id)) continue;
1175
- gtag("config", id, { send_page_view: false });
1176
- configuredIds.add(id);
1177
- }
1178
- while (this.pageQueue.length) {
1179
- const page = this.pageQueue.shift();
1180
- gtag("event", "page_view", {
1181
- page_location: page.href,
1182
- page_title: page.title ?? void 0,
1183
- page_referrer: page.referrer ?? void 0
1184
- });
1324
+ try {
1325
+ if (!jsInitialized) {
1326
+ gtag("js", /* @__PURE__ */ new Date());
1327
+ jsInitialized = true;
1328
+ }
1329
+ for (const id of ids) {
1330
+ if (configuredIds.has(id)) continue;
1331
+ gtag("config", id, { send_page_view: false });
1332
+ configuredIds.add(id);
1333
+ }
1334
+ } catch {
1335
+ this.scheduleRetry();
1336
+ return;
1185
1337
  }
1186
- while (this.automaticQueue.length) {
1187
- const event = this.automaticQueue.shift();
1188
- for (const goal of this.current.goals) {
1338
+ while (this.pageQueue.length > 0) {
1339
+ const page = this.pageQueue[0];
1340
+ try {
1341
+ gtag("event", "page_view", {
1342
+ page_location: page.href,
1343
+ page_title: page.title ?? void 0,
1344
+ page_referrer: page.referrer ?? void 0
1345
+ });
1346
+ this.pageQueue.shift();
1347
+ } catch {
1348
+ this.scheduleRetry();
1349
+ return;
1350
+ }
1351
+ }
1352
+ while (this.automaticQueue.length > 0) {
1353
+ const event = this.automaticQueue[0];
1354
+ for (const goal of config.goals) {
1189
1355
  if (goal.kind !== "event" || !goal.firing) continue;
1190
1356
  if (!automaticThresholdMet(goal, event.eventType, event.metadata)) continue;
1191
1357
  this.conversionQueue.push({
1192
1358
  key: goal.key,
1193
- transactionId: `auto:${goal.key}:${event.transactionPath}`
1359
+ transactionId: getAutomaticTransactionId(
1360
+ event.transactionScope,
1361
+ goal.key,
1362
+ event.transactionPath
1363
+ )
1194
1364
  });
1195
1365
  }
1366
+ this.automaticQueue.shift();
1196
1367
  }
1197
- while (this.conversionQueue.length) {
1198
- const item = this.conversionQueue.shift();
1199
- const goal = this.current.goals.find((g) => g.key === item.key);
1368
+ while (this.conversionQueue.length > 0) {
1369
+ const item = this.conversionQueue[0];
1370
+ const goal = config.goals.find((g) => g.key === item.key);
1200
1371
  const firing = goal?.firing;
1201
- if (!firing || getConsentState() === "denied") continue;
1372
+ if (!firing) {
1373
+ this.conversionQueue.shift();
1374
+ continue;
1375
+ }
1202
1376
  const currency = item.currency ?? firing.currency ?? null;
1203
1377
  const value = item.value ?? (firing.value_cents != null && currency ? fromMinor(firing.value_cents, currency) : null);
1204
- applyUserDataForConversion();
1205
- fireGtagConversion({
1378
+ const outcome = fireConversionWithConsent({
1206
1379
  sendTo: firing.send_to,
1207
1380
  value,
1208
1381
  currency,
1209
1382
  transactionId: item.transactionId ?? null
1210
1383
  });
1384
+ if (outcome === "retryable") {
1385
+ this.scheduleRetry();
1386
+ return;
1387
+ }
1388
+ this.conversionQueue.shift();
1211
1389
  }
1212
1390
  }
1213
1391
  };
1214
- function automaticThresholdMet(goal, eventType, metadata) {
1215
- const t = goal.trigger;
1216
- if (!t || t.event_type !== eventType) return false;
1217
- switch (eventType) {
1218
- case "scroll_depth":
1219
- return typeof metadata.depth_percent === "number" && t.threshold_percent != null && metadata.depth_percent >= t.threshold_percent;
1220
- case "time_on_site":
1221
- return typeof metadata.duration_ms === "number" && t.threshold_seconds != null && metadata.duration_ms >= t.threshold_seconds * 1e3;
1222
- case "multi_page_session":
1223
- return typeof metadata.page_count === "number" && t.page_threshold != null && metadata.page_count >= t.page_threshold;
1224
- case "specific_page_visit":
1225
- return typeof metadata.page_name === "string" && metadata.page_name === t.page_name;
1226
- case "page_view":
1227
- case "form_start":
1228
- case "phone_click":
1229
- return true;
1230
- default:
1231
- return false;
1232
- }
1233
- }
1234
1392
  function getTrackingConfigRuntime(ref, fetchImpl) {
1235
1393
  const key = `${ref.cdnUrl}|${ref.businessId}|${ref.environment}`;
1236
1394
  const existing = runtimes.get(key);
@@ -1241,26 +1399,6 @@ function getTrackingConfigRuntime(ref, fetchImpl) {
1241
1399
  }
1242
1400
 
1243
1401
  // ../tracking-core/src/resources/conversion-autofire.ts
1244
- function thresholdMet(goal, eventType, metadata) {
1245
- const t = goal.trigger;
1246
- if (!t || t.event_type !== eventType) return false;
1247
- switch (eventType) {
1248
- case "scroll_depth":
1249
- return typeof metadata.depth_percent === "number" && t.threshold_percent != null && metadata.depth_percent >= t.threshold_percent;
1250
- case "time_on_site":
1251
- return typeof metadata.duration_ms === "number" && t.threshold_seconds != null && metadata.duration_ms >= t.threshold_seconds * 1e3;
1252
- case "multi_page_session":
1253
- return typeof metadata.page_count === "number" && t.page_threshold != null && metadata.page_count >= t.page_threshold;
1254
- case "specific_page_visit":
1255
- return typeof metadata.page_name === "string" && metadata.page_name === t.page_name;
1256
- case "page_view":
1257
- case "form_start":
1258
- case "phone_click":
1259
- return true;
1260
- default:
1261
- return false;
1262
- }
1263
- }
1264
1402
  function currentPath() {
1265
1403
  return typeof window === "undefined" ? "" : window.location.pathname;
1266
1404
  }
@@ -1268,13 +1406,14 @@ var MAX_BUFFERED_EVENTS = 50;
1268
1406
  function createConversionAutoFire(store) {
1269
1407
  const pending = [];
1270
1408
  let subscribed = false;
1271
- function fireMatching(eventType, metadata) {
1409
+ function fireMatching(eventType, metadata, transactionScope) {
1272
1410
  for (const goal of store.listGoals()) {
1273
1411
  if (goal.kind !== "event" || !goal.firing) continue;
1274
- if (!thresholdMet(goal, eventType, metadata)) continue;
1412
+ if (!automaticThresholdMet(goal, eventType, metadata)) continue;
1413
+ const transactionId = getAutomaticTransactionId(transactionScope, goal.key, currentPath());
1275
1414
  if ("queueAutomaticEvent" in store) {
1276
1415
  store.fireConversion(goal.key, {
1277
- transactionId: `auto:${goal.key}:${currentPath()}`
1416
+ transactionId
1278
1417
  });
1279
1418
  continue;
1280
1419
  }
@@ -1285,28 +1424,30 @@ function createConversionAutoFire(store) {
1285
1424
  sendTo: firing.send_to,
1286
1425
  value: cents != null && currency ? fromMinor(cents, currency) : null,
1287
1426
  currency,
1288
- // Page-scoped txn id → fire once per (goal, path) per session; engagement conversions
1289
- // shouldn't re-fire as the visitor scrolls back and forth or re-enters a page.
1290
- transactionId: `auto:${goal.key}:${currentPath()}`
1427
+ transactionId
1291
1428
  });
1292
1429
  }
1293
1430
  }
1294
1431
  return {
1295
- onAutomaticEvent(eventType, metadata) {
1432
+ onAutomaticEvent(eventType, metadata, transactionScope) {
1296
1433
  if ("queueAutomaticEvent" in store) {
1297
- store.queueAutomaticEvent(eventType, metadata, currentPath());
1434
+ store.queueAutomaticEvent(eventType, metadata, currentPath(), transactionScope);
1298
1435
  return;
1299
1436
  }
1300
1437
  if (store.isReady()) {
1301
- fireMatching(eventType, metadata);
1438
+ fireMatching(eventType, metadata, transactionScope);
1302
1439
  return;
1303
1440
  }
1304
- if (pending.length < MAX_BUFFERED_EVENTS) pending.push({ eventType, metadata });
1441
+ if (pending.length < MAX_BUFFERED_EVENTS) {
1442
+ pending.push({ eventType, metadata, transactionScope });
1443
+ }
1305
1444
  if (!subscribed) {
1306
1445
  subscribed = true;
1307
1446
  store.onResolve(() => {
1308
1447
  const buffered = pending.splice(0);
1309
- for (const event of buffered) fireMatching(event.eventType, event.metadata);
1448
+ for (const event of buffered) {
1449
+ fireMatching(event.eventType, event.metadata, event.transactionScope);
1450
+ }
1310
1451
  });
1311
1452
  }
1312
1453
  }
@@ -1318,7 +1459,7 @@ function withConversionAutoFire(client, autoFire) {
1318
1459
  trackEvent: (input) => {
1319
1460
  client.trackEvent(input);
1320
1461
  try {
1321
- autoFire.onAutomaticEvent(input.eventType, input.metadata ?? {});
1462
+ autoFire.onAutomaticEvent(input.eventType, input.metadata ?? {}, client.getSessionId());
1322
1463
  } catch {
1323
1464
  }
1324
1465
  }
@@ -3277,7 +3418,7 @@ function AdPlatformTracking({
3277
3418
  if (!trackingConfig) return;
3278
3419
  const runtime = getTrackingConfigRuntime(trackingConfig);
3279
3420
  if (standalonePageView) runtime.queuePageView();
3280
- else void runtime.revalidate();
3421
+ else runtime.start();
3281
3422
  }, [trackingConfigKey, standalonePageView]);
3282
3423
  const gtagAll = trackingConfig ? [] : gtagIds ? Object.values(gtagIds).filter((id) => id != null) : gtagId ? [gtagId] : [];
3283
3424
  const metaAll = metaPixelIds ? Object.values(metaPixelIds).filter((id) => id != null) : metaPixelId ? [metaPixelId] : [];
@@ -3329,7 +3470,7 @@ function GoogleAdsTracking(props) {
3329
3470
  var import_navigation3 = require("next/navigation");
3330
3471
 
3331
3472
  // package.json
3332
- var version = "0.19.0";
3473
+ var version = "0.19.1";
3333
3474
 
3334
3475
  // src/factory.tsx
3335
3476
  var import_react5 = require("react");
@@ -3466,22 +3607,18 @@ function createTracking(options) {
3466
3607
  const timeOnSiteConfig = triggers.automatic.time_on_site ?? null;
3467
3608
  function TrackingProvider({ children }) {
3468
3609
  const pathname = (0, import_navigation3.usePathname)();
3469
- const client = (0, import_react5.useMemo)(
3470
- () => createTypedClient(
3471
- getOrCreateTrackingClient({
3472
- apiKey,
3473
- endpoint,
3474
- surface: "next",
3475
- packageName: "@aranova/tracking-next",
3476
- sdkVersion: version,
3477
- triggers,
3478
- environment,
3479
- activeGtagIds: gtagIds,
3480
- debug
3481
- }),
3610
+ const rawClient = (0, import_react5.useMemo)(
3611
+ () => getOrCreateTrackingClient({
3612
+ apiKey,
3613
+ endpoint,
3614
+ surface: "next",
3615
+ packageName: "@aranova/tracking-next",
3616
+ sdkVersion: version,
3482
3617
  triggers,
3483
- { debug }
3484
- ),
3618
+ environment,
3619
+ activeGtagIds: gtagIds,
3620
+ debug
3621
+ }),
3485
3622
  []
3486
3623
  );
3487
3624
  const conversionStore = (0, import_react5.useMemo)(
@@ -3495,33 +3632,22 @@ function createTracking(options) {
3495
3632
  const autoFire = conversionStore ? createConversionAutoFire(conversionStore) : null;
3496
3633
  return (c) => autoFire ? withConversionAutoFire(c, autoFire) : c;
3497
3634
  }, [conversionStore]);
3635
+ const client = (0, import_react5.useMemo)(
3636
+ () => createTypedClient(wrapClient(rawClient), triggers, { debug }),
3637
+ [rawClient, wrapClient]
3638
+ );
3639
+ (0, import_react5.useEffect)(() => {
3640
+ if (trackingConfig && conversionStore && "start" in conversionStore) {
3641
+ conversionStore.start();
3642
+ }
3643
+ }, [conversionStore]);
3498
3644
  const firePageView = (0, import_react5.useCallback)(() => {
3499
- const rawClient = getOrCreateTrackingClient({
3500
- apiKey,
3501
- endpoint,
3502
- surface: "next",
3503
- packageName: "@aranova/tracking-next",
3504
- triggers,
3505
- environment,
3506
- activeGtagIds: gtagIds,
3507
- debug
3508
- });
3509
3645
  fireManualPageView(wrapClient(rawClient));
3510
3646
  if (trackingConfig) getTrackingConfigRuntime(trackingConfig).queuePageView();
3511
- }, [wrapClient]);
3647
+ }, [rawClient, wrapClient]);
3512
3648
  const firedPagesRef = (0, import_react5.useRef)(/* @__PURE__ */ new Set());
3513
3649
  (0, import_react5.useEffect)(() => {
3514
3650
  if (!specificPageVisitConfig || pathname === null) return;
3515
- const rawClient = getOrCreateTrackingClient({
3516
- apiKey,
3517
- endpoint,
3518
- surface: "next",
3519
- packageName: "@aranova/tracking-next",
3520
- triggers,
3521
- environment,
3522
- activeGtagIds: gtagIds,
3523
- debug
3524
- });
3525
3651
  const detectorClient = wrapClient(rawClient);
3526
3652
  for (const { name, pathPattern } of specificPageVisitConfig.pages) {
3527
3653
  if (!pathPattern.test(pathname)) continue;
@@ -3538,7 +3664,7 @@ function createTracking(options) {
3538
3664
  occurredAt: null
3539
3665
  });
3540
3666
  }
3541
- }, [pathname]);
3667
+ }, [pathname, rawClient, wrapClient]);
3542
3668
  const multiPageSessionConfig = triggers.automatic.multi_page_session ?? null;
3543
3669
  const mpsLastPathRef = (0, import_react5.useRef)(null);
3544
3670
  (0, import_react5.useEffect)(() => {
@@ -3564,17 +3690,6 @@ function createTracking(options) {
3564
3690
  store.setItem(MPS_PATHS_KEY, JSON.stringify([...paths]));
3565
3691
  if (paths.size >= multiPageSessionConfig.pageThreshold) {
3566
3692
  store.setItem(MPS_FIRED_KEY, "1");
3567
- const rawClient = getOrCreateTrackingClient({
3568
- apiKey,
3569
- endpoint,
3570
- surface: "next",
3571
- packageName: "@aranova/tracking-next",
3572
- sdkVersion: version,
3573
- triggers,
3574
- environment,
3575
- activeGtagIds: gtagIds,
3576
- debug
3577
- });
3578
3693
  wrapClient(rawClient).trackEvent({
3579
3694
  eventType: "multi_page_session",
3580
3695
  metadata: {
@@ -3587,18 +3702,8 @@ function createTracking(options) {
3587
3702
  }
3588
3703
  } catch {
3589
3704
  }
3590
- }, [pathname]);
3705
+ }, [multiPageSessionConfig, pathname, rawClient, wrapClient]);
3591
3706
  (0, import_react5.useEffect)(() => {
3592
- const rawClient = getOrCreateTrackingClient({
3593
- apiKey,
3594
- endpoint,
3595
- surface: "next",
3596
- packageName: "@aranova/tracking-next",
3597
- triggers,
3598
- environment,
3599
- activeGtagIds: gtagIds,
3600
- debug
3601
- });
3602
3707
  return attachClientCapturesOnce(rawClient, () => {
3603
3708
  const detachers = [];
3604
3709
  const detectorClient = wrapClient(rawClient);
@@ -3629,7 +3734,7 @@ function createTracking(options) {
3629
3734
  }
3630
3735
  };
3631
3736
  });
3632
- }, []);
3737
+ }, [rawClient, wrapClient]);
3633
3738
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(TrackingContext.Provider, { value: client, children: [
3634
3739
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react5.Suspense, { fallback: null, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PageViewTracker, { fire: firePageView }) }),
3635
3740
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PhoneConfigProvider, { value: phone ?? null, children })