@aranova/tracking-react 0.18.0 → 0.19.0

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,14 +150,12 @@ function markFired(input) {
77
150
  } catch {
78
151
  }
79
152
  }
80
- function fireOnce(input) {
153
+ function fireConversionWithConsent(input, options) {
154
+ if (getConsentState() === "denied") return;
81
155
  if (alreadyFired(input)) return;
156
+ applyUserDataForConversion(options?.userData);
82
157
  if (fireGtagConversion(input)) markFired(input);
83
158
  }
84
- function fireConversionWithConsent(input) {
85
- if (getConsentState() === "denied") return;
86
- fireOnce(input);
87
- }
88
159
 
89
160
  // ../tracking-core/src/events/page-view.ts
90
161
  import { z } from "zod";
@@ -205,6 +276,8 @@ function formatDateInTz(iso, timeZone, opts, locale) {
205
276
  // ../tracking-core/src/resources/sales/client.ts
206
277
  function fireRecordedConversions(firing, input, recorded, sale, currency) {
207
278
  if (!firing) return;
279
+ const userData = input.customer_email || input.customer_phone ? { email: input.customer_email ?? null, phone: input.customer_phone ?? null } : null;
280
+ if (userData && getConsentState() !== "denied") stashUserData(userData);
208
281
  const txnBase = input.external_id ?? sale.id;
209
282
  for (const item of recorded) {
210
283
  if (!item.service) continue;
@@ -219,12 +292,15 @@ function fireRecordedConversions(firing, input, recorded, sale, currency) {
219
292
  const config = firing.getFiring(item.service);
220
293
  if (!config) continue;
221
294
  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
- });
295
+ fireConversionWithConsent(
296
+ {
297
+ sendTo: config.send_to,
298
+ value: cents != null ? fromMinor(cents, currency) : null,
299
+ currency: config.currency ?? currency,
300
+ transactionId: `${txnBase}:${item.service}`
301
+ },
302
+ { userData }
303
+ );
228
304
  }
229
305
  }
230
306
  function createSalesClient(config) {
@@ -259,6 +335,7 @@ function createSalesClient(config) {
259
335
  recordSale: record,
260
336
  trackConversion(key, options) {
261
337
  if (config.firing && "fireConversion" in config.firing) {
338
+ if (options?.userData && getConsentState() !== "denied") stashUserData(options.userData);
262
339
  config.firing.fireConversion(key, {
263
340
  value: options?.value ?? void 0,
264
341
  currency: options?.currency ?? config.defaultCurrency ?? void 0,
@@ -271,12 +348,15 @@ function createSalesClient(config) {
271
348
  const currency = firing.currency ?? options?.currency ?? config.defaultCurrency ?? null;
272
349
  const cents = firing.value_cents ?? null;
273
350
  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
- });
351
+ fireConversionWithConsent(
352
+ {
353
+ sendTo: firing.send_to,
354
+ value,
355
+ currency,
356
+ transactionId: options?.transactionId ?? null
357
+ },
358
+ { userData: options?.userData }
359
+ );
280
360
  },
281
361
  async list(query) {
282
362
  const { cursor, limit, sort, order, want_total, ...filters } = query ?? {};