@aranova/tracking-react 0.18.1 → 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/sales.mjs CHANGED
@@ -1,3 +1,76 @@
1
+ // ../tracking-core/src/phone.ts
2
+ import { AsYouType, parsePhoneNumberFromString } from "libphonenumber-js";
3
+ var DEFAULT_PHONE_COUNTRY = "CA";
4
+ function parsePhone(raw, country) {
5
+ const region = country ?? DEFAULT_PHONE_COUNTRY;
6
+ const parsed = parsePhoneNumberFromString(raw ?? "", region);
7
+ if (!parsed) {
8
+ return { e164: null, national: "", international: "", country: region, isValid: false };
9
+ }
10
+ const isValid = parsed.isValid();
11
+ return {
12
+ // E.164 is only surfaced for a *valid* number — a possible-but-invalid input
13
+ // (e.g. too few digits) still parses but must not be transmitted.
14
+ e164: isValid ? parsed.number : null,
15
+ national: parsed.formatNational(),
16
+ international: parsed.formatInternational(),
17
+ country: parsed.country ?? region,
18
+ isValid
19
+ };
20
+ }
21
+ function toE164(raw, country) {
22
+ return parsePhone(raw, country).e164;
23
+ }
24
+
25
+ // ../tracking-core/src/user-data.ts
26
+ var EMAIL_SHAPE = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
27
+ var stash = { email: null, phoneNumber: null };
28
+ function normalizeEmail(raw) {
29
+ if (typeof raw !== "string") return null;
30
+ const cleaned = raw.trim().toLowerCase();
31
+ return EMAIL_SHAPE.test(cleaned) ? cleaned : null;
32
+ }
33
+ function stashUserData(data, country) {
34
+ const email = normalizeEmail(data.email);
35
+ let phoneNumber = null;
36
+ if (typeof data.phone === "string" && data.phone.length > 0) {
37
+ try {
38
+ phoneNumber = toE164(data.phone, country);
39
+ } catch {
40
+ phoneNumber = null;
41
+ }
42
+ }
43
+ stash = {
44
+ email: email ?? stash.email,
45
+ phoneNumber: phoneNumber ?? stash.phoneNumber
46
+ };
47
+ }
48
+ function applyUserDataForConversion(explicit, country) {
49
+ if (typeof window === "undefined" || typeof window.gtag !== "function") return false;
50
+ let email = stash.email;
51
+ let phoneNumber = stash.phoneNumber;
52
+ if (explicit) {
53
+ const normalizedEmail = normalizeEmail(explicit.email);
54
+ if (normalizedEmail) email = normalizedEmail;
55
+ if (typeof explicit.phone === "string" && explicit.phone.length > 0) {
56
+ try {
57
+ phoneNumber = toE164(explicit.phone, country) ?? phoneNumber;
58
+ } catch {
59
+ }
60
+ }
61
+ }
62
+ if (email === null && phoneNumber === null) return false;
63
+ try {
64
+ window.gtag("set", "user_data", {
65
+ ...email !== null ? { email } : {},
66
+ ...phoneNumber !== null ? { phone_number: phoneNumber } : {}
67
+ });
68
+ return true;
69
+ } catch {
70
+ return false;
71
+ }
72
+ }
73
+
1
74
  // ../tracking-core/src/consent.ts
2
75
  var CONSENT_STATE_KEY = "consent_state";
3
76
  var CONSENT_TIMESTAMP_KEY = "consent_timestamp";
@@ -77,13 +150,18 @@ function markFired(input) {
77
150
  } catch {
78
151
  }
79
152
  }
80
- function fireOnce(input) {
81
- if (alreadyFired(input)) return;
82
- if (fireGtagConversion(input)) markFired(input);
83
- }
84
- function fireConversionWithConsent(input) {
85
- if (getConsentState() === "denied") return;
86
- fireOnce(input);
153
+ function fireConversionWithConsent(input, options) {
154
+ if (getConsentState() === "denied") return "denied";
155
+ if (alreadyFired(input)) return "duplicate";
156
+ if (!isValidSendTo(input.sendTo)) return "invalid";
157
+ try {
158
+ applyUserDataForConversion(options?.userData);
159
+ if (!fireGtagConversion(input)) return "retryable";
160
+ markFired(input);
161
+ return "fired";
162
+ } catch {
163
+ return "retryable";
164
+ }
87
165
  }
88
166
 
89
167
  // ../tracking-core/src/events/page-view.ts
@@ -205,6 +283,8 @@ function formatDateInTz(iso, timeZone, opts, locale) {
205
283
  // ../tracking-core/src/resources/sales/client.ts
206
284
  function fireRecordedConversions(firing, input, recorded, sale, currency) {
207
285
  if (!firing) return;
286
+ const userData = input.customer_email || input.customer_phone ? { email: input.customer_email ?? null, phone: input.customer_phone ?? null } : null;
287
+ if (userData && getConsentState() !== "denied") stashUserData(userData);
208
288
  const txnBase = input.external_id ?? sale.id;
209
289
  for (const item of recorded) {
210
290
  if (!item.service) continue;
@@ -219,12 +299,15 @@ function fireRecordedConversions(firing, input, recorded, sale, currency) {
219
299
  const config = firing.getFiring(item.service);
220
300
  if (!config) continue;
221
301
  const cents = item.amount_cents ?? config.value_cents ?? null;
222
- fireConversionWithConsent({
223
- sendTo: config.send_to,
224
- value: cents != null ? fromMinor(cents, currency) : null,
225
- currency: config.currency ?? currency,
226
- transactionId: `${txnBase}:${item.service}`
227
- });
302
+ fireConversionWithConsent(
303
+ {
304
+ sendTo: config.send_to,
305
+ value: cents != null ? fromMinor(cents, currency) : null,
306
+ currency: config.currency ?? currency,
307
+ transactionId: `${txnBase}:${item.service}`
308
+ },
309
+ { userData }
310
+ );
228
311
  }
229
312
  }
230
313
  function createSalesClient(config) {
@@ -259,6 +342,7 @@ function createSalesClient(config) {
259
342
  recordSale: record,
260
343
  trackConversion(key, options) {
261
344
  if (config.firing && "fireConversion" in config.firing) {
345
+ if (options?.userData && getConsentState() !== "denied") stashUserData(options.userData);
262
346
  config.firing.fireConversion(key, {
263
347
  value: options?.value ?? void 0,
264
348
  currency: options?.currency ?? config.defaultCurrency ?? void 0,
@@ -271,12 +355,15 @@ function createSalesClient(config) {
271
355
  const currency = firing.currency ?? options?.currency ?? config.defaultCurrency ?? null;
272
356
  const cents = firing.value_cents ?? null;
273
357
  const value = options?.value ?? (cents != null && currency ? fromMinor(cents, currency) : null);
274
- fireConversionWithConsent({
275
- sendTo: firing.send_to,
276
- value,
277
- currency,
278
- transactionId: options?.transactionId ?? null
279
- });
358
+ fireConversionWithConsent(
359
+ {
360
+ sendTo: firing.send_to,
361
+ value,
362
+ currency,
363
+ transactionId: options?.transactionId ?? null
364
+ },
365
+ { userData: options?.userData }
366
+ );
280
367
  },
281
368
  async list(query) {
282
369
  const { cursor, limit, sort, order, want_total, ...filters } = query ?? {};