@aranova/tracking-react 0.21.0 → 0.22.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.d.mts CHANGED
@@ -1,9 +1,9 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, CSSProperties, InputHTMLAttributes, ChangeEvent, FocusEvent } from 'react';
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-B2vHJkNz.mjs';
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-B2vHJkNz.mjs';
5
- import { T as TrackingConfigReference, C as ConversionConfig } from './sales-CBQJ2SBT.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-CBQJ2SBT.mjs';
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
+ 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-BfmXpXem.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-BfmXpXem.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
@@ -1,9 +1,9 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, CSSProperties, InputHTMLAttributes, ChangeEvent, FocusEvent } from 'react';
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-B2vHJkNz.js';
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-B2vHJkNz.js';
5
- import { T as TrackingConfigReference, C as ConversionConfig } from './sales-CBQJ2SBT.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-CBQJ2SBT.js';
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
+ 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-BfmXpXem.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-BfmXpXem.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
@@ -327,6 +327,43 @@ function resetConsent() {
327
327
  notifyConsentChanged(DEFAULT_CHOICE);
328
328
  }
329
329
 
330
+ // ../tracking-core/src/capabilities.ts
331
+ var TRACKING_CAPABILITIES = [
332
+ "ad_tags_google",
333
+ "ad_tags_meta",
334
+ "base_tracking",
335
+ "blog_rendering",
336
+ "calendar_read",
337
+ "calendar_write",
338
+ "consent_controls",
339
+ "conversion_goals_auto",
340
+ "conversion_goals_manual",
341
+ "cta_click_capture",
342
+ "form_capture",
343
+ "phone_click_capture",
344
+ "phone_fields"
345
+ ];
346
+ var CAPABILITY_DOM_ATTRIBUTE = "data-aranova-capability";
347
+ var registered = /* @__PURE__ */ new Set();
348
+ function registerCapability(capability) {
349
+ registered.add(capability);
350
+ }
351
+ function getRegisteredCapabilities() {
352
+ const all = new Set(registered);
353
+ for (const marker of readDomMarkers()) all.add(marker);
354
+ return Array.from(all).sort();
355
+ }
356
+ function readDomMarkers() {
357
+ if (typeof document === "undefined") return [];
358
+ const known = new Set(TRACKING_CAPABILITIES);
359
+ const found = [];
360
+ for (const node of document.querySelectorAll(`[${CAPABILITY_DOM_ATTRIBUTE}]`)) {
361
+ const value = node.getAttribute(CAPABILITY_DOM_ATTRIBUTE);
362
+ if (value && known.has(value)) found.push(value);
363
+ }
364
+ return found;
365
+ }
366
+
330
367
  // ../tracking-core/src/tracking.ts
331
368
  var TRACKING_COOKIE_MAX_AGE_SECONDS = 7776e3;
332
369
  var TRACKING_PARAM_KEYS = [
@@ -700,7 +737,8 @@ function createTrackingClientContext(surface, input = {}) {
700
737
  page_title: input.pageTitle ?? (typeof document === "undefined" ? null : document.title || null),
701
738
  referrer: input.referrer ?? (typeof document === "undefined" ? null : document.referrer || null),
702
739
  environment: input.environment ?? "production",
703
- active_gtag_ids: input.activeGtagIds ?? null
740
+ active_gtag_ids: input.activeGtagIds ?? null,
741
+ capabilities: getRegisteredCapabilities()
704
742
  };
705
743
  }
706
744
  function createTrackingSessionUpsertPayload(trackingParams, input, context) {
@@ -1718,6 +1756,9 @@ function buildHeartbeatMetadata(surface, sdkVersion, packageName, triggers, gtag
1718
1756
  var DEFAULT_FLUSH_INTERVAL_MS = 2e3;
1719
1757
  var DEFAULT_MAX_QUEUE_SIZE = 10;
1720
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";
1721
1762
  var API_KEY_HEADER = "X-Aranova-Api-Key";
1722
1763
  var SDK_VERSION_HEADER = "X-Aranova-Sdk-Version";
1723
1764
  var SDK_PACKAGE_HEADER = "X-Aranova-Sdk-Package";
@@ -1732,7 +1773,10 @@ function buildContext(surface, sdkVersion, packageName, environment, activeGtagI
1732
1773
  page_title: typeof document === "undefined" ? null : document.title || null,
1733
1774
  referrer: typeof document === "undefined" ? null : document.referrer || null,
1734
1775
  environment,
1735
- active_gtag_ids: activeGtagIds
1776
+ active_gtag_ids: activeGtagIds,
1777
+ // Rebuilt per flush (this runs inside the payload builder), so a client
1778
+ // constructed later on a deeper route still gets reported.
1779
+ capabilities: getRegisteredCapabilities()
1736
1780
  };
1737
1781
  }
1738
1782
  function readTrackingParams() {
@@ -1757,9 +1801,9 @@ function consentSnapshot() {
1757
1801
  }
1758
1802
  }
1759
1803
  async function postWithFetch(url, body, apiKey, identity, keepalive) {
1760
- if (typeof fetch !== "function") return;
1804
+ if (typeof fetch !== "function") return "drop";
1761
1805
  try {
1762
- await fetch(url, {
1806
+ const response = await fetch(url, {
1763
1807
  method: "POST",
1764
1808
  headers: {
1765
1809
  "Content-Type": "application/json",
@@ -1775,9 +1819,49 @@ async function postWithFetch(url, body, apiKey, identity, keepalive) {
1775
1819
  credentials: "omit",
1776
1820
  mode: "cors"
1777
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";
1778
1827
  } catch {
1828
+ return "retry";
1779
1829
  }
1780
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
+ }
1781
1865
  var globalClient = null;
1782
1866
  var globalClientKey = null;
1783
1867
  function clientConfigKey(config) {
@@ -1833,6 +1917,10 @@ function createTrackingClient(config) {
1833
1917
  };
1834
1918
  let queue = [];
1835
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;
1836
1924
  let firstPage = null;
1837
1925
  let initialParams = createEmptyTrackingParams();
1838
1926
  let destroyed = false;
@@ -1869,6 +1957,9 @@ function createTrackingClient(config) {
1869
1957
  if (initialSession.isNew) {
1870
1958
  enqueueHeartbeat();
1871
1959
  }
1960
+ if (pending.length > 0) {
1961
+ scheduleFlush();
1962
+ }
1872
1963
  function buildSessionPayload() {
1873
1964
  const rotated = getOrRotateSessionId();
1874
1965
  if (rotated.isNew && rotated.id !== sessionId) {
@@ -1907,12 +1998,12 @@ function createTrackingClient(config) {
1907
1998
  context
1908
1999
  };
1909
2000
  }
1910
- function scheduleFlush() {
2001
+ function scheduleFlush(delayMs = flushIntervalMs) {
1911
2002
  if (flushTimer !== null || destroyed) return;
1912
2003
  flushTimer = setTimeout(() => {
1913
2004
  flushTimer = null;
1914
2005
  void flush();
1915
- }, flushIntervalMs);
2006
+ }, delayMs);
1916
2007
  }
1917
2008
  function clearScheduledFlush() {
1918
2009
  if (flushTimer !== null) {
@@ -1920,17 +2011,50 @@ function createTrackingClient(config) {
1920
2011
  flushTimer = null;
1921
2012
  }
1922
2013
  }
1923
- async function flush() {
2014
+ function bufferQueued() {
1924
2015
  if (queue.length === 0) return;
1925
2016
  const events = queue.slice(0, HARD_MAX_BATCH);
1926
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;
1927
2028
  clearScheduledFlush();
1928
- const body = {
1929
- session: buildSessionPayload(),
1930
- events
1931
- };
1932
- const serialized = JSON.stringify(body);
1933
- 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
+ }
1934
2058
  }
1935
2059
  function trackEvent(input) {
1936
2060
  if (destroyed) return;
@@ -1956,16 +2080,14 @@ function createTrackingClient(config) {
1956
2080
  }
1957
2081
  }
1958
2082
  function flushOnUnload() {
1959
- if (queue.length === 0) return;
1960
- const events = queue.slice(0, HARD_MAX_BATCH);
1961
- queue = queue.slice(events.length);
2083
+ bufferQueued();
1962
2084
  clearScheduledFlush();
1963
- const body = {
1964
- session: buildSessionPayload(),
1965
- events
1966
- };
1967
- const serialized = JSON.stringify(body);
1968
- 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);
1969
2091
  }
1970
2092
  if (typeof window !== "undefined") {
1971
2093
  window.addEventListener("pagehide", flushOnUnload);
@@ -2325,8 +2447,9 @@ function getEventDefinition(name) {
2325
2447
  }
2326
2448
 
2327
2449
  // ../tracking-core/src/ingest-typed.ts
2328
- function createTypedClient(raw, _registry, options = {}) {
2450
+ function createTypedClient(raw, registry, options = {}) {
2329
2451
  const debug = options.debug ?? false;
2452
+ if (registry.manual?.form_submit) registerCapability("form_capture");
2330
2453
  return {
2331
2454
  trackEvent(eventType, metadata, opts) {
2332
2455
  if (debug) {
@@ -2868,6 +2991,7 @@ function attachCtaClickCapture(client, config) {
2868
2991
  return () => {
2869
2992
  };
2870
2993
  }
2994
+ registerCapability("cta_click_capture");
2871
2995
  const selector = autoCapture.selector ?? DEFAULT_CTA_SELECTOR;
2872
2996
  function onClick(event) {
2873
2997
  const target = event.target;
@@ -2924,6 +3048,7 @@ function attachPhoneClickCapture(client, config) {
2924
3048
  return () => {
2925
3049
  };
2926
3050
  }
3051
+ registerCapability("phone_click_capture");
2927
3052
  const selector = autoCapture.selector ?? DEFAULT_TEL_SELECTOR;
2928
3053
  function onClick(event) {
2929
3054
  const target = event.target;
@@ -3040,6 +3165,7 @@ function fireRecordedConversions(firing, input, recorded, sale, currency) {
3040
3165
  }
3041
3166
  }
3042
3167
  function createSalesClient(config) {
3168
+ if (config.firing) registerCapability("conversion_goals_manual");
3043
3169
  async function record(input) {
3044
3170
  const currency = input.currency ?? config.defaultCurrency;
3045
3171
  if (!currency) {
@@ -3283,6 +3409,9 @@ var saleUpdateSchema = import_zod12.z.object({
3283
3409
  items: import_zod12.z.array(saleItemSchema).optional(),
3284
3410
  metadata: metadataSchema.nullable().optional(),
3285
3411
  customer_name: customerNameSchema.nullable().optional(),
3412
+ // Re-attest when changing a filler-looking name; the server clears the
3413
+ // prior attestation whenever `customer_name` changes.
3414
+ customer_name_placeholder_confirmed: import_zod12.z.boolean().optional(),
3286
3415
  customer_phone: customerPhoneSchema.nullable().optional(),
3287
3416
  customer_email: customerEmailSchema.nullable().optional(),
3288
3417
  // NOT NULL server-side: omit to leave unchanged (explicit null is rejected).
@@ -3335,6 +3464,7 @@ var DEFAULT_CHOICE2 = {
3335
3464
  expiresAt: null
3336
3465
  };
3337
3466
  function useCookiePreferences(options) {
3467
+ registerCapability("consent_controls");
3338
3468
  const [choice, setChoice] = (0, import_react.useState)(DEFAULT_CHOICE2);
3339
3469
  const ttlDays = options?.declineTtlDays;
3340
3470
  (0, import_react.useEffect)(() => {
@@ -3597,6 +3727,12 @@ function AdPlatformTracking({
3597
3727
  () => metaPixelIds ? JSON.stringify(metaPixelIds) : "",
3598
3728
  [metaPixelIds]
3599
3729
  );
3730
+ if (trackingConfig || gtagId || gtagIds && Object.keys(gtagIds).length > 0) {
3731
+ registerCapability("ad_tags_google");
3732
+ }
3733
+ if (metaPixelId || metaPixelIds && Object.keys(metaPixelIds).length > 0) {
3734
+ registerCapability("ad_tags_meta");
3735
+ }
3600
3736
  (0, import_react3.useEffect)(() => {
3601
3737
  if (trackingConfig) {
3602
3738
  const runtime = getTrackingConfigRuntime(trackingConfig);
@@ -3637,7 +3773,7 @@ function GoogleAdsTracking(props) {
3637
3773
  var import_react6 = require("react");
3638
3774
 
3639
3775
  // package.json
3640
- var version = "0.21.0";
3776
+ var version = "0.22.2";
3641
3777
 
3642
3778
  // ../tracking-core/src/phone-react.tsx
3643
3779
  var import_react5 = require("react");
@@ -3661,6 +3797,7 @@ function usePhoneConfig() {
3661
3797
  };
3662
3798
  }
3663
3799
  function usePhoneField(opts = {}) {
3800
+ registerCapability("phone_fields");
3664
3801
  const cfg = usePhoneConfig();
3665
3802
  const country = opts.country ?? cfg.defaultCountry;
3666
3803
  const display = opts.display ?? cfg.display;
@@ -3746,6 +3883,8 @@ function createTracking(options) {
3746
3883
  conversionConfig,
3747
3884
  trackingConfig
3748
3885
  } = options;
3886
+ registerCapability("base_tracking");
3887
+ if (trackingConfig) registerCapability("conversion_goals_auto");
3749
3888
  if (!apiKey || !endpoint) {
3750
3889
  if (apiKey || endpoint) {
3751
3890
  console.warn(