@aranova/tracking-react 0.22.0 → 0.22.3

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
@@ -2,8 +2,8 @@ import * as react from 'react';
2
2
  import { ReactNode, CSSProperties, InputHTMLAttributes, ChangeEvent, FocusEvent } from 'react';
3
3
  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, G as GtagEnvironmentMap, M as MetaPixelEnvironmentMap, C as ConsentState, g as ConsentChoiceState, h as ConsentSource, P as PhoneConfig, i as ParsedPhone, j as PhoneDisplayFormat } from './phone-utils-BhWfNuPS.mjs';
4
4
  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-BhWfNuPS.mjs';
5
- import { T as TrackingConfigReference, C as ConversionConfig } from './sales-BhCYJqDy.mjs';
6
- 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-BhCYJqDy.mjs';
5
+ import { T as TrackingConfigReference, C as ConversionConfig } from './sales-ZTf8eSa3.mjs';
6
+ 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-ZTf8eSa3.mjs';
7
7
  import * as src from 'src';
8
8
  import { z } from 'zod';
9
9
  import { CountryCode } from 'libphonenumber-js';
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ import * as react from 'react';
2
2
  import { ReactNode, CSSProperties, InputHTMLAttributes, ChangeEvent, FocusEvent } from 'react';
3
3
  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, G as GtagEnvironmentMap, M as MetaPixelEnvironmentMap, C as ConsentState, g as ConsentChoiceState, h as ConsentSource, P as PhoneConfig, i as ParsedPhone, j as PhoneDisplayFormat } from './phone-utils-BhWfNuPS.js';
4
4
  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-BhWfNuPS.js';
5
- import { T as TrackingConfigReference, C as ConversionConfig } from './sales-BhCYJqDy.js';
6
- 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-BhCYJqDy.js';
5
+ import { T as TrackingConfigReference, C as ConversionConfig } from './sales-ZTf8eSa3.js';
6
+ 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-ZTf8eSa3.js';
7
7
  import * as src from 'src';
8
8
  import { z } from 'zod';
9
9
  import { CountryCode } from 'libphonenumber-js';
package/dist/index.js CHANGED
@@ -1756,6 +1756,9 @@ function buildHeartbeatMetadata(surface, sdkVersion, packageName, triggers, gtag
1756
1756
  var DEFAULT_FLUSH_INTERVAL_MS = 2e3;
1757
1757
  var DEFAULT_MAX_QUEUE_SIZE = 10;
1758
1758
  var HARD_MAX_BATCH = 50;
1759
+ var MAX_RETRY_BACKOFF_MS = 6e4;
1760
+ var MAX_BUFFERED_EVENTS2 = 200;
1761
+ var RETRY_BUFFER_KEY_PREFIX = "aranova_tracking_pending_v1";
1759
1762
  var API_KEY_HEADER = "X-Aranova-Api-Key";
1760
1763
  var SDK_VERSION_HEADER = "X-Aranova-Sdk-Version";
1761
1764
  var SDK_PACKAGE_HEADER = "X-Aranova-Sdk-Package";
@@ -1798,9 +1801,9 @@ function consentSnapshot() {
1798
1801
  }
1799
1802
  }
1800
1803
  async function postWithFetch(url, body, apiKey, identity, keepalive) {
1801
- if (typeof fetch !== "function") return;
1804
+ if (typeof fetch !== "function") return "drop";
1802
1805
  try {
1803
- await fetch(url, {
1806
+ const response = await fetch(url, {
1804
1807
  method: "POST",
1805
1808
  headers: {
1806
1809
  "Content-Type": "application/json",
@@ -1816,9 +1819,49 @@ async function postWithFetch(url, body, apiKey, identity, keepalive) {
1816
1819
  credentials: "omit",
1817
1820
  mode: "cors"
1818
1821
  });
1822
+ if (response.ok) return "ok";
1823
+ if (response.status === 408 || response.status === 429 || response.status >= 500) {
1824
+ return "retry";
1825
+ }
1826
+ return "drop";
1819
1827
  } catch {
1828
+ return "retry";
1820
1829
  }
1821
1830
  }
1831
+ function retryBufferKey(apiKey, endpoint) {
1832
+ return `${RETRY_BUFFER_KEY_PREFIX}:${apiKey}:${endpoint}`;
1833
+ }
1834
+ function readPendingBatches(key) {
1835
+ if (typeof window === "undefined") return [];
1836
+ try {
1837
+ const raw = window.localStorage.getItem(key);
1838
+ if (!raw) return [];
1839
+ const parsed = JSON.parse(raw);
1840
+ if (!Array.isArray(parsed)) return [];
1841
+ return parsed.filter(
1842
+ (entry) => typeof entry === "object" && entry !== null && "session" in entry && Array.isArray(entry.events)
1843
+ );
1844
+ } catch {
1845
+ return [];
1846
+ }
1847
+ }
1848
+ function writePendingBatches(key, batches) {
1849
+ if (typeof window === "undefined") return;
1850
+ try {
1851
+ if (batches.length === 0) window.localStorage.removeItem(key);
1852
+ else window.localStorage.setItem(key, JSON.stringify(batches));
1853
+ } catch {
1854
+ }
1855
+ }
1856
+ function trimToBufferCap(batches) {
1857
+ let total = batches.reduce((sum, batch) => sum + batch.events.length, 0);
1858
+ const trimmed = batches.slice();
1859
+ while (total > MAX_BUFFERED_EVENTS2 && trimmed.length > 1) {
1860
+ const dropped = trimmed.shift();
1861
+ total -= dropped ? dropped.events.length : 0;
1862
+ }
1863
+ return trimmed;
1864
+ }
1822
1865
  var globalClient = null;
1823
1866
  var globalClientKey = null;
1824
1867
  function clientConfigKey(config) {
@@ -1874,6 +1917,10 @@ function createTrackingClient(config) {
1874
1917
  };
1875
1918
  let queue = [];
1876
1919
  let flushTimer = null;
1920
+ const bufferKey = retryBufferKey(config.apiKey, endpointBase);
1921
+ let pending = readPendingBatches(bufferKey);
1922
+ let flushChain = Promise.resolve();
1923
+ let retryAttempt = 0;
1877
1924
  let firstPage = null;
1878
1925
  let initialParams = createEmptyTrackingParams();
1879
1926
  let destroyed = false;
@@ -1910,6 +1957,9 @@ function createTrackingClient(config) {
1910
1957
  if (initialSession.isNew) {
1911
1958
  enqueueHeartbeat();
1912
1959
  }
1960
+ if (pending.length > 0) {
1961
+ scheduleFlush();
1962
+ }
1913
1963
  function buildSessionPayload() {
1914
1964
  const rotated = getOrRotateSessionId();
1915
1965
  if (rotated.isNew && rotated.id !== sessionId) {
@@ -1948,12 +1998,12 @@ function createTrackingClient(config) {
1948
1998
  context
1949
1999
  };
1950
2000
  }
1951
- function scheduleFlush() {
2001
+ function scheduleFlush(delayMs = flushIntervalMs) {
1952
2002
  if (flushTimer !== null || destroyed) return;
1953
2003
  flushTimer = setTimeout(() => {
1954
2004
  flushTimer = null;
1955
2005
  void flush();
1956
- }, flushIntervalMs);
2006
+ }, delayMs);
1957
2007
  }
1958
2008
  function clearScheduledFlush() {
1959
2009
  if (flushTimer !== null) {
@@ -1961,17 +2011,50 @@ function createTrackingClient(config) {
1961
2011
  flushTimer = null;
1962
2012
  }
1963
2013
  }
1964
- async function flush() {
2014
+ function bufferQueued() {
1965
2015
  if (queue.length === 0) return;
1966
2016
  const events = queue.slice(0, HARD_MAX_BATCH);
1967
2017
  queue = queue.slice(events.length);
2018
+ pending = trimToBufferCap([...pending, { session: buildSessionPayload(), events }]);
2019
+ writePendingBatches(bufferKey, pending);
2020
+ }
2021
+ function flush() {
2022
+ flushChain = flushChain.then(runFlush).catch(() => {
2023
+ });
2024
+ return flushChain;
2025
+ }
2026
+ async function runFlush() {
2027
+ if (destroyed) return;
1968
2028
  clearScheduledFlush();
1969
- const body = {
1970
- session: buildSessionPayload(),
1971
- events
1972
- };
1973
- const serialized = JSON.stringify(body);
1974
- await postWithFetch(eventsUrl, serialized, config.apiKey, identityHeaders2, false);
2029
+ bufferQueued();
2030
+ if (pending.length === 0) return;
2031
+ try {
2032
+ while (pending.length > 0) {
2033
+ const batch = pending[0];
2034
+ const body = { session: batch.session, events: batch.events };
2035
+ const outcome = await postWithFetch(
2036
+ eventsUrl,
2037
+ JSON.stringify(body),
2038
+ config.apiKey,
2039
+ identityHeaders2,
2040
+ false
2041
+ );
2042
+ if (outcome === "retry") {
2043
+ retryAttempt += 1;
2044
+ return;
2045
+ }
2046
+ pending = pending.slice(1);
2047
+ writePendingBatches(bufferKey, pending);
2048
+ retryAttempt = 0;
2049
+ }
2050
+ } finally {
2051
+ if (pending.length > 0) {
2052
+ const backoff = Math.min(flushIntervalMs * 2 ** retryAttempt, MAX_RETRY_BACKOFF_MS);
2053
+ scheduleFlush(backoff);
2054
+ } else if (queue.length > 0) {
2055
+ scheduleFlush();
2056
+ }
2057
+ }
1975
2058
  }
1976
2059
  function trackEvent(input) {
1977
2060
  if (destroyed) return;
@@ -1997,16 +2080,14 @@ function createTrackingClient(config) {
1997
2080
  }
1998
2081
  }
1999
2082
  function flushOnUnload() {
2000
- if (queue.length === 0) return;
2001
- const events = queue.slice(0, HARD_MAX_BATCH);
2002
- queue = queue.slice(events.length);
2083
+ bufferQueued();
2003
2084
  clearScheduledFlush();
2004
- const body = {
2005
- session: buildSessionPayload(),
2006
- events
2007
- };
2008
- const serialized = JSON.stringify(body);
2009
- void postWithFetch(eventsUrl, serialized, config.apiKey, identityHeaders2, true);
2085
+ if (pending.length === 0) return;
2086
+ const batch = pending[0];
2087
+ pending = pending.slice(1);
2088
+ writePendingBatches(bufferKey, pending);
2089
+ const body = { session: batch.session, events: batch.events };
2090
+ void postWithFetch(eventsUrl, JSON.stringify(body), config.apiKey, identityHeaders2, true);
2010
2091
  }
2011
2092
  if (typeof window !== "undefined") {
2012
2093
  window.addEventListener("pagehide", flushOnUnload);
@@ -3316,7 +3397,12 @@ var saleCreateSchema = import_zod12.z.object({
3316
3397
  customer_email: customerEmailSchema.nullable().optional(),
3317
3398
  // CASL consent attestation: the customer agreed to receive SMS. Recorded
3318
3399
  // with a timestamp server-side; every SMS send path gates on it.
3319
- sms_consent: import_zod12.z.boolean().default(false)
3400
+ //
3401
+ // Tri-state: omit it (or send null) to let the server apply the business's
3402
+ // configured default-opt-in policy, honouring a returning customer's
3403
+ // remembered preference. Send an explicit boolean to assert consent state
3404
+ // yourself — `false` records a deliberate opt-out.
3405
+ sms_consent: import_zod12.z.boolean().nullable().optional()
3320
3406
  }).strict().superRefine((val, ctx) => refineServiceXor(val, ctx, { requireAmount: true }));
3321
3407
  var saleUpdateSchema = import_zod12.z.object({
3322
3408
  description: import_zod12.z.string().nullable().optional(),
@@ -3328,6 +3414,9 @@ var saleUpdateSchema = import_zod12.z.object({
3328
3414
  items: import_zod12.z.array(saleItemSchema).optional(),
3329
3415
  metadata: metadataSchema.nullable().optional(),
3330
3416
  customer_name: customerNameSchema.nullable().optional(),
3417
+ // Re-attest when changing a filler-looking name; the server clears the
3418
+ // prior attestation whenever `customer_name` changes.
3419
+ customer_name_placeholder_confirmed: import_zod12.z.boolean().optional(),
3331
3420
  customer_phone: customerPhoneSchema.nullable().optional(),
3332
3421
  customer_email: customerEmailSchema.nullable().optional(),
3333
3422
  // NOT NULL server-side: omit to leave unchanged (explicit null is rejected).
@@ -3689,7 +3778,7 @@ function GoogleAdsTracking(props) {
3689
3778
  var import_react6 = require("react");
3690
3779
 
3691
3780
  // package.json
3692
- var version = "0.22.0";
3781
+ var version = "0.22.3";
3693
3782
 
3694
3783
  // ../tracking-core/src/phone-react.tsx
3695
3784
  var import_react5 = require("react");