@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/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +461 -184
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +459 -184
- package/dist/index.mjs.map +1 -1
- package/dist/{phone-utils-CVCzW04Z.d.mts → phone-utils-B2vHJkNz.d.mts} +10 -0
- package/dist/{phone-utils-CVCzW04Z.d.ts → phone-utils-B2vHJkNz.d.ts} +10 -0
- package/dist/phone.d.mts +1 -1
- package/dist/phone.d.ts +1 -1
- package/dist/phone.js +40 -40
- package/dist/phone.js.map +1 -1
- package/dist/phone.mjs +40 -40
- package/dist/phone.mjs.map +1 -1
- package/dist/{sales-QqKh6_iy.d.mts → sales-DrH6dY5F.d.mts} +34 -2
- package/dist/{sales-QqKh6_iy.d.ts → sales-DrH6dY5F.d.ts} +34 -2
- package/dist/sales.d.mts +2 -1
- package/dist/sales.d.ts +2 -1
- package/dist/sales.js +106 -19
- package/dist/sales.js.map +1 -1
- package/dist/sales.mjs +106 -19
- package/dist/sales.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ __export(src_exports, {
|
|
|
33
33
|
TRACKING_PARAM_KEYS: () => TRACKING_PARAM_KEYS,
|
|
34
34
|
TRACKING_RANGES: () => TRACKING_RANGES,
|
|
35
35
|
captureTrackingParamsFromLocation: () => captureTrackingParamsFromLocation,
|
|
36
|
+
clearStashedUserData: () => clearStashedUserData,
|
|
36
37
|
createSalesClient: () => createSalesClient,
|
|
37
38
|
createTracking: () => createTracking,
|
|
38
39
|
createTrackingClientContext: () => createTrackingClientContext,
|
|
@@ -61,6 +62,7 @@ __export(src_exports, {
|
|
|
61
62
|
saleUpdateSchema: () => saleUpdateSchema,
|
|
62
63
|
salesRequest: () => salesRequest,
|
|
63
64
|
setConsentState: () => setConsentState,
|
|
65
|
+
stashUserData: () => stashUserData,
|
|
64
66
|
toE164: () => toE164,
|
|
65
67
|
toMinor: () => toMinor,
|
|
66
68
|
useConsent: () => useConsent,
|
|
@@ -79,6 +81,140 @@ var import_react2 = require("react");
|
|
|
79
81
|
// src/hooks.ts
|
|
80
82
|
var import_react = require("react");
|
|
81
83
|
|
|
84
|
+
// ../tracking-core/src/phone.ts
|
|
85
|
+
var import_libphonenumber_js = require("libphonenumber-js");
|
|
86
|
+
var DEFAULT_PHONE_COUNTRY = "CA";
|
|
87
|
+
function parsePhone(raw, country) {
|
|
88
|
+
const region = country ?? DEFAULT_PHONE_COUNTRY;
|
|
89
|
+
const parsed = (0, import_libphonenumber_js.parsePhoneNumberFromString)(raw ?? "", region);
|
|
90
|
+
if (!parsed) {
|
|
91
|
+
return { e164: null, national: "", international: "", country: region, isValid: false };
|
|
92
|
+
}
|
|
93
|
+
const isValid = parsed.isValid();
|
|
94
|
+
return {
|
|
95
|
+
// E.164 is only surfaced for a *valid* number — a possible-but-invalid input
|
|
96
|
+
// (e.g. too few digits) still parses but must not be transmitted.
|
|
97
|
+
e164: isValid ? parsed.number : null,
|
|
98
|
+
national: parsed.formatNational(),
|
|
99
|
+
international: parsed.formatInternational(),
|
|
100
|
+
country: parsed.country ?? region,
|
|
101
|
+
isValid
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function toE164(raw, country) {
|
|
105
|
+
return parsePhone(raw, country).e164;
|
|
106
|
+
}
|
|
107
|
+
function formatPhone(value, format = "national", country) {
|
|
108
|
+
const parsed = parsePhone(value, country);
|
|
109
|
+
if (typeof format === "function") return format(parsed);
|
|
110
|
+
switch (format) {
|
|
111
|
+
case "international":
|
|
112
|
+
return parsed.international || value;
|
|
113
|
+
case "e164":
|
|
114
|
+
return parsed.e164 ?? value;
|
|
115
|
+
case "national":
|
|
116
|
+
default:
|
|
117
|
+
return parsed.national || value;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function formatPhoneAsTyped(raw, country) {
|
|
121
|
+
return new import_libphonenumber_js.AsYouType(country ?? DEFAULT_PHONE_COUNTRY).input(raw ?? "");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ../tracking-core/src/user-data.ts
|
|
125
|
+
var EMAIL_SHAPE = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
|
|
126
|
+
var EMAIL_NAME_HINT = /e[-_]?mail/i;
|
|
127
|
+
var PHONE_NAME_HINT = /(^|[^a-z])(phone|tel|mobile|cell)/i;
|
|
128
|
+
var stash = { email: null, phoneNumber: null };
|
|
129
|
+
function normalizeEmail(raw) {
|
|
130
|
+
if (typeof raw !== "string") return null;
|
|
131
|
+
const cleaned = raw.trim().toLowerCase();
|
|
132
|
+
return EMAIL_SHAPE.test(cleaned) ? cleaned : null;
|
|
133
|
+
}
|
|
134
|
+
function fieldText(field, key) {
|
|
135
|
+
const value = field[key];
|
|
136
|
+
return typeof value === "string" ? value : "";
|
|
137
|
+
}
|
|
138
|
+
function extractUserDataFromFormFields(fields, country) {
|
|
139
|
+
const result = { email: null, phoneNumber: null };
|
|
140
|
+
if (!Array.isArray(fields)) return result;
|
|
141
|
+
const passes = [
|
|
142
|
+
(field, _hint, type) => fieldText(field, "type").toLowerCase() === type,
|
|
143
|
+
(field, hint) => hint.test(fieldText(field, "name")) || hint.test(fieldText(field, "label"))
|
|
144
|
+
];
|
|
145
|
+
for (const matches of passes) {
|
|
146
|
+
for (const raw of fields) {
|
|
147
|
+
if (raw === null || typeof raw !== "object") continue;
|
|
148
|
+
const field = raw;
|
|
149
|
+
if (typeof field.value !== "string" || field.value.length === 0) continue;
|
|
150
|
+
if (result.email === null && matches(field, EMAIL_NAME_HINT, "email")) {
|
|
151
|
+
result.email = normalizeEmail(field.value);
|
|
152
|
+
}
|
|
153
|
+
if (result.phoneNumber === null && matches(field, PHONE_NAME_HINT, "tel")) {
|
|
154
|
+
try {
|
|
155
|
+
result.phoneNumber = toE164(field.value, country);
|
|
156
|
+
} catch {
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (result.email !== null && result.phoneNumber !== null) break;
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
function stashUserData(data, country) {
|
|
165
|
+
const email = normalizeEmail(data.email);
|
|
166
|
+
let phoneNumber = null;
|
|
167
|
+
if (typeof data.phone === "string" && data.phone.length > 0) {
|
|
168
|
+
try {
|
|
169
|
+
phoneNumber = toE164(data.phone, country);
|
|
170
|
+
} catch {
|
|
171
|
+
phoneNumber = null;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
stash = {
|
|
175
|
+
email: email ?? stash.email,
|
|
176
|
+
phoneNumber: phoneNumber ?? stash.phoneNumber
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function stashUserDataFromFormFields(fields, country) {
|
|
180
|
+
try {
|
|
181
|
+
const extracted = extractUserDataFromFormFields(fields, country);
|
|
182
|
+
stash = {
|
|
183
|
+
email: extracted.email ?? stash.email,
|
|
184
|
+
phoneNumber: extracted.phoneNumber ?? stash.phoneNumber
|
|
185
|
+
};
|
|
186
|
+
} catch {
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function clearStashedUserData() {
|
|
190
|
+
stash = { email: null, phoneNumber: null };
|
|
191
|
+
}
|
|
192
|
+
function applyUserDataForConversion(explicit, country) {
|
|
193
|
+
if (typeof window === "undefined" || typeof window.gtag !== "function") return false;
|
|
194
|
+
let email = stash.email;
|
|
195
|
+
let phoneNumber = stash.phoneNumber;
|
|
196
|
+
if (explicit) {
|
|
197
|
+
const normalizedEmail = normalizeEmail(explicit.email);
|
|
198
|
+
if (normalizedEmail) email = normalizedEmail;
|
|
199
|
+
if (typeof explicit.phone === "string" && explicit.phone.length > 0) {
|
|
200
|
+
try {
|
|
201
|
+
phoneNumber = toE164(explicit.phone, country) ?? phoneNumber;
|
|
202
|
+
} catch {
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (email === null && phoneNumber === null) return false;
|
|
207
|
+
try {
|
|
208
|
+
window.gtag("set", "user_data", {
|
|
209
|
+
...email !== null ? { email } : {},
|
|
210
|
+
...phoneNumber !== null ? { phone_number: phoneNumber } : {}
|
|
211
|
+
});
|
|
212
|
+
return true;
|
|
213
|
+
} catch {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
82
218
|
// ../tracking-core/src/consent.ts
|
|
83
219
|
var CONSENT_STATE_KEY = "consent_state";
|
|
84
220
|
var CONSENT_TIMESTAMP_KEY = "consent_timestamp";
|
|
@@ -164,6 +300,13 @@ function setConsentState(state, options) {
|
|
|
164
300
|
} catch {
|
|
165
301
|
}
|
|
166
302
|
pushConsentToPlatforms(state);
|
|
303
|
+
if (state === "denied") {
|
|
304
|
+
clearStashedUserData();
|
|
305
|
+
try {
|
|
306
|
+
if (typeof window.gtag === "function") window.gtag("set", "user_data", null);
|
|
307
|
+
} catch {
|
|
308
|
+
}
|
|
309
|
+
}
|
|
167
310
|
notifyConsentChanged({ state, source: "explicit", updatedAt, expiresAt });
|
|
168
311
|
}
|
|
169
312
|
function optIn() {
|
|
@@ -188,6 +331,11 @@ function resetConsent() {
|
|
|
188
331
|
var TRACKING_COOKIE_MAX_AGE_SECONDS = 7776e3;
|
|
189
332
|
var TRACKING_PARAM_KEYS = [
|
|
190
333
|
"gclid",
|
|
334
|
+
// Google's iOS/Safari replacement click IDs — issued when privacy features
|
|
335
|
+
// withhold gclid (wbraid: web-to-web, gbraid: app-to-web). First-class
|
|
336
|
+
// citizens: captured, persisted, and attributed exactly like gclid.
|
|
337
|
+
"wbraid",
|
|
338
|
+
"gbraid",
|
|
191
339
|
"fbclid",
|
|
192
340
|
"utm_source",
|
|
193
341
|
"utm_medium",
|
|
@@ -198,6 +346,8 @@ var TRACKING_PARAM_KEYS = [
|
|
|
198
346
|
function createEmptyTrackingParams() {
|
|
199
347
|
return {
|
|
200
348
|
gclid: null,
|
|
349
|
+
wbraid: null,
|
|
350
|
+
gbraid: null,
|
|
201
351
|
fbclid: null,
|
|
202
352
|
utm_source: null,
|
|
203
353
|
utm_medium: null,
|
|
@@ -529,6 +679,8 @@ function buildLandingPayloadFields(sessionId, override) {
|
|
|
529
679
|
if (params === null) return {};
|
|
530
680
|
return {
|
|
531
681
|
landing_gclid: params.gclid ?? null,
|
|
682
|
+
landing_wbraid: params.wbraid ?? null,
|
|
683
|
+
landing_gbraid: params.gbraid ?? null,
|
|
532
684
|
landing_fbclid: params.fbclid ?? null,
|
|
533
685
|
landing_utm_source: params.utm_source ?? null,
|
|
534
686
|
landing_utm_medium: params.utm_medium ?? null,
|
|
@@ -556,6 +708,8 @@ function createTrackingSessionUpsertPayload(trackingParams, input, context) {
|
|
|
556
708
|
session_id: input.sessionId,
|
|
557
709
|
visitor_id: input.visitorId ?? null,
|
|
558
710
|
gclid: trackingParams.gclid,
|
|
711
|
+
wbraid: trackingParams.wbraid,
|
|
712
|
+
gbraid: trackingParams.gbraid,
|
|
559
713
|
fbclid: trackingParams.fbclid,
|
|
560
714
|
fbc: getFbcCookie(),
|
|
561
715
|
fbp: getFbpCookie(),
|
|
@@ -577,6 +731,8 @@ function createTrackingEventCreatePayload(trackingParams, input, context) {
|
|
|
577
731
|
session_id: input.sessionId,
|
|
578
732
|
event_type: input.eventType,
|
|
579
733
|
gclid: trackingParams.gclid,
|
|
734
|
+
wbraid: trackingParams.wbraid,
|
|
735
|
+
gbraid: trackingParams.gbraid,
|
|
580
736
|
fbclid: trackingParams.fbclid,
|
|
581
737
|
fbc: getFbcCookie(),
|
|
582
738
|
fbp: getFbpCookie(),
|
|
@@ -606,13 +762,18 @@ function markFired(input) {
|
|
|
606
762
|
} catch {
|
|
607
763
|
}
|
|
608
764
|
}
|
|
609
|
-
function
|
|
610
|
-
if (
|
|
611
|
-
if (
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
765
|
+
function fireConversionWithConsent(input, options) {
|
|
766
|
+
if (getConsentState() === "denied") return "denied";
|
|
767
|
+
if (alreadyFired(input)) return "duplicate";
|
|
768
|
+
if (!isValidSendTo(input.sendTo)) return "invalid";
|
|
769
|
+
try {
|
|
770
|
+
applyUserDataForConversion(options?.userData);
|
|
771
|
+
if (!fireGtagConversion(input)) return "retryable";
|
|
772
|
+
markFired(input);
|
|
773
|
+
return "fired";
|
|
774
|
+
} catch {
|
|
775
|
+
return "retryable";
|
|
776
|
+
}
|
|
616
777
|
}
|
|
617
778
|
|
|
618
779
|
// ../tracking-core/src/resources/conversion-config.ts
|
|
@@ -786,6 +947,103 @@ function resolveConversionConfig(options) {
|
|
|
786
947
|
};
|
|
787
948
|
}
|
|
788
949
|
|
|
950
|
+
// ../tracking-core/src/resources/automatic-transaction.ts
|
|
951
|
+
var STORAGE_KEY = "_aranova_auto_txn_map";
|
|
952
|
+
var transactionIds = /* @__PURE__ */ new Map();
|
|
953
|
+
var legacyCounter = 0;
|
|
954
|
+
function scopeKey(sessionId, goalKey, path) {
|
|
955
|
+
return JSON.stringify([sessionId, goalKey, path]);
|
|
956
|
+
}
|
|
957
|
+
function randomId() {
|
|
958
|
+
const cryptoApi = globalThis.crypto;
|
|
959
|
+
if (typeof cryptoApi?.randomUUID === "function") return cryptoApi.randomUUID();
|
|
960
|
+
if (typeof cryptoApi?.getRandomValues === "function") {
|
|
961
|
+
const bytes = cryptoApi.getRandomValues(new Uint8Array(16));
|
|
962
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
963
|
+
}
|
|
964
|
+
legacyCounter = (legacyCounter + 1) % 4294967296;
|
|
965
|
+
const timestamp = Date.now().toString(16).padStart(12, "0");
|
|
966
|
+
const counter = legacyCounter.toString(16).padStart(8, "0");
|
|
967
|
+
const random = Math.floor(Math.random() * 281474976710655).toString(16).padStart(12, "0");
|
|
968
|
+
return `${timestamp}${counter}${random}`.slice(0, 32);
|
|
969
|
+
}
|
|
970
|
+
function isValidTransactionId(value) {
|
|
971
|
+
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(
|
|
972
|
+
value
|
|
973
|
+
) && value.length <= 64;
|
|
974
|
+
}
|
|
975
|
+
function readStoredMap(sessionId) {
|
|
976
|
+
if (typeof window === "undefined") return { sessionId, entries: {} };
|
|
977
|
+
try {
|
|
978
|
+
const raw = window.localStorage.getItem(STORAGE_KEY);
|
|
979
|
+
if (!raw) return { sessionId, entries: {} };
|
|
980
|
+
const parsed = JSON.parse(raw);
|
|
981
|
+
if (parsed.sessionId !== sessionId || !parsed.entries || typeof parsed.entries !== "object" || Array.isArray(parsed.entries)) {
|
|
982
|
+
return { sessionId, entries: {} };
|
|
983
|
+
}
|
|
984
|
+
return { sessionId, entries: parsed.entries };
|
|
985
|
+
} catch {
|
|
986
|
+
return { sessionId, entries: {} };
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
function writeStoredMap(stored) {
|
|
990
|
+
if (typeof window === "undefined") return;
|
|
991
|
+
try {
|
|
992
|
+
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(stored));
|
|
993
|
+
} catch {
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
function getAutomaticTransactionId(sessionId, goalKey, path) {
|
|
997
|
+
const key = scopeKey(sessionId, goalKey, path);
|
|
998
|
+
const existing = transactionIds.get(key);
|
|
999
|
+
if (existing) return existing;
|
|
1000
|
+
const stored = readStoredMap(sessionId);
|
|
1001
|
+
const storedId = stored.entries[key];
|
|
1002
|
+
if (isValidTransactionId(storedId)) {
|
|
1003
|
+
transactionIds.set(key, storedId);
|
|
1004
|
+
return storedId;
|
|
1005
|
+
}
|
|
1006
|
+
const transactionId = `auto:${randomId()}`;
|
|
1007
|
+
transactionIds.set(key, transactionId);
|
|
1008
|
+
const latest = readStoredMap(sessionId);
|
|
1009
|
+
const concurrentId = latest.entries[key];
|
|
1010
|
+
if (isValidTransactionId(concurrentId)) {
|
|
1011
|
+
transactionIds.set(key, concurrentId);
|
|
1012
|
+
return concurrentId;
|
|
1013
|
+
}
|
|
1014
|
+
latest.entries[key] = transactionId;
|
|
1015
|
+
writeStoredMap(latest);
|
|
1016
|
+
return transactionId;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
// ../tracking-core/src/resources/automatic-trigger.ts
|
|
1020
|
+
function hasNumberField(metadata, key) {
|
|
1021
|
+
return typeof metadata[key] === "number";
|
|
1022
|
+
}
|
|
1023
|
+
function hasStringField(metadata, key) {
|
|
1024
|
+
return typeof metadata[key] === "string";
|
|
1025
|
+
}
|
|
1026
|
+
function automaticThresholdMet(goal, eventType, metadata) {
|
|
1027
|
+
const trigger = goal.trigger;
|
|
1028
|
+
if (!trigger || trigger.event_type !== eventType) return false;
|
|
1029
|
+
switch (eventType) {
|
|
1030
|
+
case "scroll_depth":
|
|
1031
|
+
return hasNumberField(metadata, "depth_percent") && trigger.threshold_percent != null && metadata.depth_percent >= trigger.threshold_percent;
|
|
1032
|
+
case "time_on_site":
|
|
1033
|
+
return hasNumberField(metadata, "duration_ms") && trigger.threshold_seconds != null && metadata.duration_ms >= trigger.threshold_seconds * 1e3;
|
|
1034
|
+
case "multi_page_session":
|
|
1035
|
+
return hasNumberField(metadata, "page_count") && trigger.page_threshold != null && metadata.page_count >= trigger.page_threshold;
|
|
1036
|
+
case "specific_page_visit":
|
|
1037
|
+
return hasStringField(metadata, "page_name") && metadata.page_name === trigger.page_name;
|
|
1038
|
+
case "page_view":
|
|
1039
|
+
case "form_start":
|
|
1040
|
+
case "phone_click":
|
|
1041
|
+
return true;
|
|
1042
|
+
default:
|
|
1043
|
+
return false;
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
|
|
789
1047
|
// ../tracking-core/src/resources/sales/money.ts
|
|
790
1048
|
var MINOR_UNIT_EXPONENT = {
|
|
791
1049
|
USD: 2,
|
|
@@ -904,7 +1162,12 @@ var TrackingConfigRuntime = class {
|
|
|
904
1162
|
this.etag = null;
|
|
905
1163
|
this.stateValue = "unconfirmed";
|
|
906
1164
|
this.confirmedAt = 0;
|
|
1165
|
+
this.authorityGeneration = 0;
|
|
907
1166
|
this.inFlight = null;
|
|
1167
|
+
this.flushInFlight = null;
|
|
1168
|
+
this.flushRequested = false;
|
|
1169
|
+
this.retryTimer = null;
|
|
1170
|
+
this.started = false;
|
|
908
1171
|
this.conversionQueue = [];
|
|
909
1172
|
this.automaticQueue = [];
|
|
910
1173
|
this.pageQueue = [];
|
|
@@ -912,6 +1175,20 @@ var TrackingConfigRuntime = class {
|
|
|
912
1175
|
const cached = readCache2(ref.cdnUrl);
|
|
913
1176
|
this.current = cached?.config ?? null;
|
|
914
1177
|
this.etag = cached?.etag ?? null;
|
|
1178
|
+
this.start();
|
|
1179
|
+
}
|
|
1180
|
+
/**
|
|
1181
|
+
* Explicitly start authority resolution and Google-tag bootstrap.
|
|
1182
|
+
*
|
|
1183
|
+
* Idempotent so framework effects can call it after hydration without
|
|
1184
|
+
* depending on constructor timing.
|
|
1185
|
+
*/
|
|
1186
|
+
start() {
|
|
1187
|
+
if (this.started) {
|
|
1188
|
+
void this.flush();
|
|
1189
|
+
return;
|
|
1190
|
+
}
|
|
1191
|
+
this.started = true;
|
|
915
1192
|
void this.revalidate();
|
|
916
1193
|
if (typeof window !== "undefined") {
|
|
917
1194
|
window.addEventListener("visibilitychange", () => {
|
|
@@ -927,7 +1204,7 @@ var TrackingConfigRuntime = class {
|
|
|
927
1204
|
return this.stateValue === "active" || this.stateValue === "tombstone" ? this.current : null;
|
|
928
1205
|
}
|
|
929
1206
|
__unsafeExpireAuthorityForTests() {
|
|
930
|
-
this.confirmedAt =
|
|
1207
|
+
this.confirmedAt = Number.NEGATIVE_INFINITY;
|
|
931
1208
|
}
|
|
932
1209
|
subscribe(listener) {
|
|
933
1210
|
this.listeners.add(listener);
|
|
@@ -937,10 +1214,14 @@ var TrackingConfigRuntime = class {
|
|
|
937
1214
|
if (this.stateValue !== "unconfirmed" && Date.now() - this.confirmedAt < AUTHORITY_TTL_MS) {
|
|
938
1215
|
return true;
|
|
939
1216
|
}
|
|
940
|
-
await this.
|
|
1217
|
+
await this.revalidateAuthority();
|
|
941
1218
|
return this.stateValue !== "unconfirmed" && Date.now() - this.confirmedAt < AUTHORITY_TTL_MS;
|
|
942
1219
|
}
|
|
943
1220
|
async revalidate() {
|
|
1221
|
+
await this.revalidateAuthority();
|
|
1222
|
+
await this.flush();
|
|
1223
|
+
}
|
|
1224
|
+
async revalidateAuthority() {
|
|
944
1225
|
if (typeof window === "undefined" || !this.fetchImpl) return;
|
|
945
1226
|
if (this.inFlight) return this.inFlight;
|
|
946
1227
|
this.inFlight = this.revalidateNow().finally(() => {
|
|
@@ -957,8 +1238,8 @@ var TrackingConfigRuntime = class {
|
|
|
957
1238
|
this.conversionQueue.push({ key, ...options });
|
|
958
1239
|
void this.flush();
|
|
959
1240
|
}
|
|
960
|
-
queueAutomaticEvent(eventType, metadata, transactionPath) {
|
|
961
|
-
this.automaticQueue.push({ eventType, metadata, transactionPath });
|
|
1241
|
+
queueAutomaticEvent(eventType, metadata, transactionPath, transactionScope) {
|
|
1242
|
+
this.automaticQueue.push({ eventType, metadata, transactionPath, transactionScope });
|
|
962
1243
|
void this.flush();
|
|
963
1244
|
}
|
|
964
1245
|
listGoals() {
|
|
@@ -975,7 +1256,6 @@ var TrackingConfigRuntime = class {
|
|
|
975
1256
|
});
|
|
976
1257
|
if (response.status === 304 && this.current && validateConfig(this.current, this.ref)) {
|
|
977
1258
|
this.confirm(this.current, this.etag);
|
|
978
|
-
await this.flush();
|
|
979
1259
|
return;
|
|
980
1260
|
}
|
|
981
1261
|
if (!response.ok) {
|
|
@@ -992,21 +1272,26 @@ var TrackingConfigRuntime = class {
|
|
|
992
1272
|
return;
|
|
993
1273
|
}
|
|
994
1274
|
this.confirm(next, response.headers.get("ETag"));
|
|
995
|
-
await this.flush();
|
|
996
1275
|
} catch {
|
|
997
1276
|
this.expireAuthority();
|
|
998
1277
|
}
|
|
999
1278
|
}
|
|
1000
1279
|
expireAuthority() {
|
|
1280
|
+
this.authorityGeneration += 1;
|
|
1001
1281
|
if (this.stateValue !== "unconfirmed") this.stateValue = "unconfirmed";
|
|
1002
1282
|
}
|
|
1003
1283
|
confirm(config, etag) {
|
|
1284
|
+
this.authorityGeneration += 1;
|
|
1004
1285
|
this.current = config;
|
|
1005
1286
|
this.etag = etag;
|
|
1006
1287
|
this.confirmedAt = Date.now();
|
|
1007
1288
|
this.stateValue = isTombstone(config) ? "tombstone" : "active";
|
|
1008
1289
|
writeCache2(this.ref.cdnUrl, { etag, config });
|
|
1009
1290
|
if (this.stateValue === "tombstone") {
|
|
1291
|
+
if (this.retryTimer !== null) {
|
|
1292
|
+
window.clearTimeout(this.retryTimer);
|
|
1293
|
+
this.retryTimer = null;
|
|
1294
|
+
}
|
|
1010
1295
|
this.conversionQueue.length = 0;
|
|
1011
1296
|
this.automaticQueue.length = 0;
|
|
1012
1297
|
this.pageQueue.length = 0;
|
|
@@ -1014,79 +1299,107 @@ var TrackingConfigRuntime = class {
|
|
|
1014
1299
|
for (const listener of this.listeners) listener();
|
|
1015
1300
|
}
|
|
1016
1301
|
async flush() {
|
|
1302
|
+
if (this.flushInFlight) {
|
|
1303
|
+
this.flushRequested = true;
|
|
1304
|
+
return this.flushInFlight;
|
|
1305
|
+
}
|
|
1306
|
+
this.flushRequested = false;
|
|
1307
|
+
this.flushInFlight = this.flushNow().finally(() => {
|
|
1308
|
+
this.flushInFlight = null;
|
|
1309
|
+
if (this.flushRequested && this.stateValue === "active") void this.flush();
|
|
1310
|
+
});
|
|
1311
|
+
return this.flushInFlight;
|
|
1312
|
+
}
|
|
1313
|
+
scheduleRetry() {
|
|
1314
|
+
if (this.retryTimer !== null || typeof window === "undefined") return;
|
|
1315
|
+
this.retryTimer = window.setTimeout(() => {
|
|
1316
|
+
this.retryTimer = null;
|
|
1317
|
+
void this.flush();
|
|
1318
|
+
}, 1e3);
|
|
1319
|
+
}
|
|
1320
|
+
async flushNow() {
|
|
1017
1321
|
if (!await this.ensureAuthority()) return;
|
|
1018
1322
|
if (this.stateValue !== "active" || !this.current) return;
|
|
1019
|
-
const
|
|
1323
|
+
const config = this.current;
|
|
1324
|
+
const generation = this.authorityGeneration;
|
|
1325
|
+
const ids = Object.values(config.gtag_ids).filter(
|
|
1020
1326
|
(id) => typeof id === "string" && isValidGtagId(id)
|
|
1021
1327
|
);
|
|
1022
1328
|
if (ids.length === 0) return;
|
|
1023
1329
|
await ensureScript(ids[0]);
|
|
1330
|
+
if (this.authorityGeneration !== generation || this.stateValue !== "active" || this.current !== config) {
|
|
1331
|
+
return;
|
|
1332
|
+
}
|
|
1024
1333
|
const gtag = window.gtag;
|
|
1025
1334
|
if (typeof gtag !== "function") return;
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1335
|
+
try {
|
|
1336
|
+
if (!jsInitialized) {
|
|
1337
|
+
gtag("js", /* @__PURE__ */ new Date());
|
|
1338
|
+
jsInitialized = true;
|
|
1339
|
+
}
|
|
1340
|
+
for (const id of ids) {
|
|
1341
|
+
if (configuredIds.has(id)) continue;
|
|
1342
|
+
gtag("config", id, { send_page_view: false });
|
|
1343
|
+
configuredIds.add(id);
|
|
1344
|
+
}
|
|
1345
|
+
} catch {
|
|
1346
|
+
this.scheduleRetry();
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
while (this.pageQueue.length > 0) {
|
|
1350
|
+
const page = this.pageQueue[0];
|
|
1351
|
+
try {
|
|
1352
|
+
gtag("event", "page_view", {
|
|
1353
|
+
page_location: page.href,
|
|
1354
|
+
page_title: page.title ?? void 0,
|
|
1355
|
+
page_referrer: page.referrer ?? void 0
|
|
1356
|
+
});
|
|
1357
|
+
this.pageQueue.shift();
|
|
1358
|
+
} catch {
|
|
1359
|
+
this.scheduleRetry();
|
|
1360
|
+
return;
|
|
1361
|
+
}
|
|
1042
1362
|
}
|
|
1043
|
-
while (this.automaticQueue.length) {
|
|
1044
|
-
const event = this.automaticQueue
|
|
1045
|
-
for (const goal of
|
|
1363
|
+
while (this.automaticQueue.length > 0) {
|
|
1364
|
+
const event = this.automaticQueue[0];
|
|
1365
|
+
for (const goal of config.goals) {
|
|
1046
1366
|
if (goal.kind !== "event" || !goal.firing) continue;
|
|
1047
1367
|
if (!automaticThresholdMet(goal, event.eventType, event.metadata)) continue;
|
|
1048
1368
|
this.conversionQueue.push({
|
|
1049
1369
|
key: goal.key,
|
|
1050
|
-
transactionId:
|
|
1370
|
+
transactionId: getAutomaticTransactionId(
|
|
1371
|
+
event.transactionScope,
|
|
1372
|
+
goal.key,
|
|
1373
|
+
event.transactionPath
|
|
1374
|
+
)
|
|
1051
1375
|
});
|
|
1052
1376
|
}
|
|
1377
|
+
this.automaticQueue.shift();
|
|
1053
1378
|
}
|
|
1054
|
-
while (this.conversionQueue.length) {
|
|
1055
|
-
const item = this.conversionQueue
|
|
1056
|
-
const goal =
|
|
1379
|
+
while (this.conversionQueue.length > 0) {
|
|
1380
|
+
const item = this.conversionQueue[0];
|
|
1381
|
+
const goal = config.goals.find((g) => g.key === item.key);
|
|
1057
1382
|
const firing = goal?.firing;
|
|
1058
|
-
if (!firing
|
|
1383
|
+
if (!firing) {
|
|
1384
|
+
this.conversionQueue.shift();
|
|
1385
|
+
continue;
|
|
1386
|
+
}
|
|
1059
1387
|
const currency = item.currency ?? firing.currency ?? null;
|
|
1060
1388
|
const value = item.value ?? (firing.value_cents != null && currency ? fromMinor(firing.value_cents, currency) : null);
|
|
1061
|
-
|
|
1389
|
+
const outcome = fireConversionWithConsent({
|
|
1062
1390
|
sendTo: firing.send_to,
|
|
1063
1391
|
value,
|
|
1064
1392
|
currency,
|
|
1065
1393
|
transactionId: item.transactionId ?? null
|
|
1066
1394
|
});
|
|
1395
|
+
if (outcome === "retryable") {
|
|
1396
|
+
this.scheduleRetry();
|
|
1397
|
+
return;
|
|
1398
|
+
}
|
|
1399
|
+
this.conversionQueue.shift();
|
|
1067
1400
|
}
|
|
1068
1401
|
}
|
|
1069
1402
|
};
|
|
1070
|
-
function automaticThresholdMet(goal, eventType, metadata) {
|
|
1071
|
-
const t = goal.trigger;
|
|
1072
|
-
if (!t || t.event_type !== eventType) return false;
|
|
1073
|
-
switch (eventType) {
|
|
1074
|
-
case "scroll_depth":
|
|
1075
|
-
return typeof metadata.depth_percent === "number" && t.threshold_percent != null && metadata.depth_percent >= t.threshold_percent;
|
|
1076
|
-
case "time_on_site":
|
|
1077
|
-
return typeof metadata.duration_ms === "number" && t.threshold_seconds != null && metadata.duration_ms >= t.threshold_seconds * 1e3;
|
|
1078
|
-
case "multi_page_session":
|
|
1079
|
-
return typeof metadata.page_count === "number" && t.page_threshold != null && metadata.page_count >= t.page_threshold;
|
|
1080
|
-
case "specific_page_visit":
|
|
1081
|
-
return typeof metadata.page_name === "string" && metadata.page_name === t.page_name;
|
|
1082
|
-
case "page_view":
|
|
1083
|
-
case "form_start":
|
|
1084
|
-
case "phone_click":
|
|
1085
|
-
return true;
|
|
1086
|
-
default:
|
|
1087
|
-
return false;
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
1403
|
function getTrackingConfigRuntime(ref, fetchImpl) {
|
|
1091
1404
|
const key = `${ref.cdnUrl}|${ref.businessId}|${ref.environment}`;
|
|
1092
1405
|
const existing = runtimes.get(key);
|
|
@@ -1097,26 +1410,6 @@ function getTrackingConfigRuntime(ref, fetchImpl) {
|
|
|
1097
1410
|
}
|
|
1098
1411
|
|
|
1099
1412
|
// ../tracking-core/src/resources/conversion-autofire.ts
|
|
1100
|
-
function thresholdMet(goal, eventType, metadata) {
|
|
1101
|
-
const t = goal.trigger;
|
|
1102
|
-
if (!t || t.event_type !== eventType) return false;
|
|
1103
|
-
switch (eventType) {
|
|
1104
|
-
case "scroll_depth":
|
|
1105
|
-
return typeof metadata.depth_percent === "number" && t.threshold_percent != null && metadata.depth_percent >= t.threshold_percent;
|
|
1106
|
-
case "time_on_site":
|
|
1107
|
-
return typeof metadata.duration_ms === "number" && t.threshold_seconds != null && metadata.duration_ms >= t.threshold_seconds * 1e3;
|
|
1108
|
-
case "multi_page_session":
|
|
1109
|
-
return typeof metadata.page_count === "number" && t.page_threshold != null && metadata.page_count >= t.page_threshold;
|
|
1110
|
-
case "specific_page_visit":
|
|
1111
|
-
return typeof metadata.page_name === "string" && metadata.page_name === t.page_name;
|
|
1112
|
-
case "page_view":
|
|
1113
|
-
case "form_start":
|
|
1114
|
-
case "phone_click":
|
|
1115
|
-
return true;
|
|
1116
|
-
default:
|
|
1117
|
-
return false;
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
1413
|
function currentPath() {
|
|
1121
1414
|
return typeof window === "undefined" ? "" : window.location.pathname;
|
|
1122
1415
|
}
|
|
@@ -1124,13 +1417,14 @@ var MAX_BUFFERED_EVENTS = 50;
|
|
|
1124
1417
|
function createConversionAutoFire(store) {
|
|
1125
1418
|
const pending = [];
|
|
1126
1419
|
let subscribed = false;
|
|
1127
|
-
function fireMatching(eventType, metadata) {
|
|
1420
|
+
function fireMatching(eventType, metadata, transactionScope) {
|
|
1128
1421
|
for (const goal of store.listGoals()) {
|
|
1129
1422
|
if (goal.kind !== "event" || !goal.firing) continue;
|
|
1130
|
-
if (!
|
|
1423
|
+
if (!automaticThresholdMet(goal, eventType, metadata)) continue;
|
|
1424
|
+
const transactionId = getAutomaticTransactionId(transactionScope, goal.key, currentPath());
|
|
1131
1425
|
if ("queueAutomaticEvent" in store) {
|
|
1132
1426
|
store.fireConversion(goal.key, {
|
|
1133
|
-
transactionId
|
|
1427
|
+
transactionId
|
|
1134
1428
|
});
|
|
1135
1429
|
continue;
|
|
1136
1430
|
}
|
|
@@ -1141,28 +1435,30 @@ function createConversionAutoFire(store) {
|
|
|
1141
1435
|
sendTo: firing.send_to,
|
|
1142
1436
|
value: cents != null && currency ? fromMinor(cents, currency) : null,
|
|
1143
1437
|
currency,
|
|
1144
|
-
|
|
1145
|
-
// shouldn't re-fire as the visitor scrolls back and forth or re-enters a page.
|
|
1146
|
-
transactionId: `auto:${goal.key}:${currentPath()}`
|
|
1438
|
+
transactionId
|
|
1147
1439
|
});
|
|
1148
1440
|
}
|
|
1149
1441
|
}
|
|
1150
1442
|
return {
|
|
1151
|
-
onAutomaticEvent(eventType, metadata) {
|
|
1443
|
+
onAutomaticEvent(eventType, metadata, transactionScope) {
|
|
1152
1444
|
if ("queueAutomaticEvent" in store) {
|
|
1153
|
-
store.queueAutomaticEvent(eventType, metadata, currentPath());
|
|
1445
|
+
store.queueAutomaticEvent(eventType, metadata, currentPath(), transactionScope);
|
|
1154
1446
|
return;
|
|
1155
1447
|
}
|
|
1156
1448
|
if (store.isReady()) {
|
|
1157
|
-
fireMatching(eventType, metadata);
|
|
1449
|
+
fireMatching(eventType, metadata, transactionScope);
|
|
1158
1450
|
return;
|
|
1159
1451
|
}
|
|
1160
|
-
if (pending.length < MAX_BUFFERED_EVENTS)
|
|
1452
|
+
if (pending.length < MAX_BUFFERED_EVENTS) {
|
|
1453
|
+
pending.push({ eventType, metadata, transactionScope });
|
|
1454
|
+
}
|
|
1161
1455
|
if (!subscribed) {
|
|
1162
1456
|
subscribed = true;
|
|
1163
1457
|
store.onResolve(() => {
|
|
1164
1458
|
const buffered = pending.splice(0);
|
|
1165
|
-
for (const event of buffered)
|
|
1459
|
+
for (const event of buffered) {
|
|
1460
|
+
fireMatching(event.eventType, event.metadata, event.transactionScope);
|
|
1461
|
+
}
|
|
1166
1462
|
});
|
|
1167
1463
|
}
|
|
1168
1464
|
}
|
|
@@ -1174,7 +1470,7 @@ function withConversionAutoFire(client, autoFire) {
|
|
|
1174
1470
|
trackEvent: (input) => {
|
|
1175
1471
|
client.trackEvent(input);
|
|
1176
1472
|
try {
|
|
1177
|
-
autoFire.onAutomaticEvent(input.eventType, input.metadata ?? {});
|
|
1473
|
+
autoFire.onAutomaticEvent(input.eventType, input.metadata ?? {}, client.getSessionId());
|
|
1178
1474
|
} catch {
|
|
1179
1475
|
}
|
|
1180
1476
|
}
|
|
@@ -1589,6 +1885,8 @@ function createTrackingClient(config) {
|
|
|
1589
1885
|
session_id: sessionId,
|
|
1590
1886
|
visitor_id: visitorId,
|
|
1591
1887
|
gclid: params.gclid,
|
|
1888
|
+
wbraid: params.wbraid,
|
|
1889
|
+
gbraid: params.gbraid,
|
|
1592
1890
|
fbclid: params.fbclid,
|
|
1593
1891
|
fbc: getFbcCookie(),
|
|
1594
1892
|
fbp: getFbpCookie(),
|
|
@@ -1635,6 +1933,13 @@ function createTrackingClient(config) {
|
|
|
1635
1933
|
function trackEvent(input) {
|
|
1636
1934
|
if (destroyed) return;
|
|
1637
1935
|
if (!input || typeof input.eventType !== "string" || input.eventType.length === 0) return;
|
|
1936
|
+
if (input.eventType === "form_submit" && getConsentState() !== "denied") {
|
|
1937
|
+
try {
|
|
1938
|
+
const fields = input.metadata?.form?.fields;
|
|
1939
|
+
if (fields) stashUserDataFromFormFields(fields, config.phone?.defaultCountry);
|
|
1940
|
+
} catch {
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1638
1943
|
const occurredAt = input.occurredAt instanceof Date ? input.occurredAt.toISOString() : typeof input.occurredAt === "string" ? input.occurredAt : (/* @__PURE__ */ new Date()).toISOString();
|
|
1639
1944
|
queue.push({
|
|
1640
1945
|
event_type: input.eventType,
|
|
@@ -2298,7 +2603,7 @@ function attachScrollDepth(client, config) {
|
|
|
2298
2603
|
}
|
|
2299
2604
|
|
|
2300
2605
|
// ../tracking-core/src/triggers/multi-page-session.ts
|
|
2301
|
-
var
|
|
2606
|
+
var STORAGE_KEY2 = "aranova_tracking_mps_paths";
|
|
2302
2607
|
var SESSION_KEY = "aranova_tracking_mps_session";
|
|
2303
2608
|
var FIRED_KEY = "aranova_tracking_mps_fired";
|
|
2304
2609
|
function getSessionStorage() {
|
|
@@ -2320,7 +2625,7 @@ function attachMultiPageSession(client, config) {
|
|
|
2320
2625
|
let lastCheckedPath = "";
|
|
2321
2626
|
function getDistinctPaths() {
|
|
2322
2627
|
try {
|
|
2323
|
-
const raw = storage.getItem(
|
|
2628
|
+
const raw = storage.getItem(STORAGE_KEY2);
|
|
2324
2629
|
return raw ? new Set(JSON.parse(raw)) : /* @__PURE__ */ new Set();
|
|
2325
2630
|
} catch {
|
|
2326
2631
|
return /* @__PURE__ */ new Set();
|
|
@@ -2328,7 +2633,7 @@ function attachMultiPageSession(client, config) {
|
|
|
2328
2633
|
}
|
|
2329
2634
|
function saveDistinctPaths(paths) {
|
|
2330
2635
|
try {
|
|
2331
|
-
storage.setItem(
|
|
2636
|
+
storage.setItem(STORAGE_KEY2, JSON.stringify([...paths]));
|
|
2332
2637
|
} catch {
|
|
2333
2638
|
}
|
|
2334
2639
|
}
|
|
@@ -2337,7 +2642,7 @@ function attachMultiPageSession(client, config) {
|
|
|
2337
2642
|
const storedSession = storage.getItem(SESSION_KEY);
|
|
2338
2643
|
if (storedSession !== currentSession) {
|
|
2339
2644
|
storage.setItem(SESSION_KEY, currentSession);
|
|
2340
|
-
storage.removeItem(
|
|
2645
|
+
storage.removeItem(STORAGE_KEY2);
|
|
2341
2646
|
storage.removeItem(FIRED_KEY);
|
|
2342
2647
|
}
|
|
2343
2648
|
}
|
|
@@ -2598,46 +2903,6 @@ function attachCtaClickCapture(client, config) {
|
|
|
2598
2903
|
};
|
|
2599
2904
|
}
|
|
2600
2905
|
|
|
2601
|
-
// ../tracking-core/src/phone.ts
|
|
2602
|
-
var import_libphonenumber_js = require("libphonenumber-js");
|
|
2603
|
-
var DEFAULT_PHONE_COUNTRY = "CA";
|
|
2604
|
-
function parsePhone(raw, country) {
|
|
2605
|
-
const region = country ?? DEFAULT_PHONE_COUNTRY;
|
|
2606
|
-
const parsed = (0, import_libphonenumber_js.parsePhoneNumberFromString)(raw ?? "", region);
|
|
2607
|
-
if (!parsed) {
|
|
2608
|
-
return { e164: null, national: "", international: "", country: region, isValid: false };
|
|
2609
|
-
}
|
|
2610
|
-
const isValid = parsed.isValid();
|
|
2611
|
-
return {
|
|
2612
|
-
// E.164 is only surfaced for a *valid* number — a possible-but-invalid input
|
|
2613
|
-
// (e.g. too few digits) still parses but must not be transmitted.
|
|
2614
|
-
e164: isValid ? parsed.number : null,
|
|
2615
|
-
national: parsed.formatNational(),
|
|
2616
|
-
international: parsed.formatInternational(),
|
|
2617
|
-
country: parsed.country ?? region,
|
|
2618
|
-
isValid
|
|
2619
|
-
};
|
|
2620
|
-
}
|
|
2621
|
-
function toE164(raw, country) {
|
|
2622
|
-
return parsePhone(raw, country).e164;
|
|
2623
|
-
}
|
|
2624
|
-
function formatPhone(value, format = "national", country) {
|
|
2625
|
-
const parsed = parsePhone(value, country);
|
|
2626
|
-
if (typeof format === "function") return format(parsed);
|
|
2627
|
-
switch (format) {
|
|
2628
|
-
case "international":
|
|
2629
|
-
return parsed.international || value;
|
|
2630
|
-
case "e164":
|
|
2631
|
-
return parsed.e164 ?? value;
|
|
2632
|
-
case "national":
|
|
2633
|
-
default:
|
|
2634
|
-
return parsed.national || value;
|
|
2635
|
-
}
|
|
2636
|
-
}
|
|
2637
|
-
function formatPhoneAsTyped(raw, country) {
|
|
2638
|
-
return new import_libphonenumber_js.AsYouType(country ?? DEFAULT_PHONE_COUNTRY).input(raw ?? "");
|
|
2639
|
-
}
|
|
2640
|
-
|
|
2641
2906
|
// ../tracking-core/src/triggers/phone-click-capture.ts
|
|
2642
2907
|
var DEFAULT_TEL_SELECTOR = 'a[href^="tel:"]';
|
|
2643
2908
|
function safeDecodeURIComponent(value) {
|
|
@@ -2747,6 +3012,8 @@ async function salesRequest(config, method, path, body) {
|
|
|
2747
3012
|
// ../tracking-core/src/resources/sales/client.ts
|
|
2748
3013
|
function fireRecordedConversions(firing, input, recorded, sale, currency) {
|
|
2749
3014
|
if (!firing) return;
|
|
3015
|
+
const userData = input.customer_email || input.customer_phone ? { email: input.customer_email ?? null, phone: input.customer_phone ?? null } : null;
|
|
3016
|
+
if (userData && getConsentState() !== "denied") stashUserData(userData);
|
|
2750
3017
|
const txnBase = input.external_id ?? sale.id;
|
|
2751
3018
|
for (const item of recorded) {
|
|
2752
3019
|
if (!item.service) continue;
|
|
@@ -2761,12 +3028,15 @@ function fireRecordedConversions(firing, input, recorded, sale, currency) {
|
|
|
2761
3028
|
const config = firing.getFiring(item.service);
|
|
2762
3029
|
if (!config) continue;
|
|
2763
3030
|
const cents = item.amount_cents ?? config.value_cents ?? null;
|
|
2764
|
-
fireConversionWithConsent(
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
3031
|
+
fireConversionWithConsent(
|
|
3032
|
+
{
|
|
3033
|
+
sendTo: config.send_to,
|
|
3034
|
+
value: cents != null ? fromMinor(cents, currency) : null,
|
|
3035
|
+
currency: config.currency ?? currency,
|
|
3036
|
+
transactionId: `${txnBase}:${item.service}`
|
|
3037
|
+
},
|
|
3038
|
+
{ userData }
|
|
3039
|
+
);
|
|
2770
3040
|
}
|
|
2771
3041
|
}
|
|
2772
3042
|
function createSalesClient(config) {
|
|
@@ -2801,6 +3071,7 @@ function createSalesClient(config) {
|
|
|
2801
3071
|
recordSale: record,
|
|
2802
3072
|
trackConversion(key, options) {
|
|
2803
3073
|
if (config.firing && "fireConversion" in config.firing) {
|
|
3074
|
+
if (options?.userData && getConsentState() !== "denied") stashUserData(options.userData);
|
|
2804
3075
|
config.firing.fireConversion(key, {
|
|
2805
3076
|
value: options?.value ?? void 0,
|
|
2806
3077
|
currency: options?.currency ?? config.defaultCurrency ?? void 0,
|
|
@@ -2813,12 +3084,15 @@ function createSalesClient(config) {
|
|
|
2813
3084
|
const currency = firing.currency ?? options?.currency ?? config.defaultCurrency ?? null;
|
|
2814
3085
|
const cents = firing.value_cents ?? null;
|
|
2815
3086
|
const value = options?.value ?? (cents != null && currency ? fromMinor(cents, currency) : null);
|
|
2816
|
-
fireConversionWithConsent(
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
3087
|
+
fireConversionWithConsent(
|
|
3088
|
+
{
|
|
3089
|
+
sendTo: firing.send_to,
|
|
3090
|
+
value,
|
|
3091
|
+
currency,
|
|
3092
|
+
transactionId: options?.transactionId ?? null
|
|
3093
|
+
},
|
|
3094
|
+
{ userData: options?.userData }
|
|
3095
|
+
);
|
|
2822
3096
|
},
|
|
2823
3097
|
async list(query) {
|
|
2824
3098
|
const { cursor, limit, sort, order, want_total, ...filters } = query ?? {};
|
|
@@ -3363,7 +3637,7 @@ function GoogleAdsTracking(props) {
|
|
|
3363
3637
|
var import_react6 = require("react");
|
|
3364
3638
|
|
|
3365
3639
|
// package.json
|
|
3366
|
-
var version = "0.
|
|
3640
|
+
var version = "0.19.1";
|
|
3367
3641
|
|
|
3368
3642
|
// ../tracking-core/src/phone-react.tsx
|
|
3369
3643
|
var import_react5 = require("react");
|
|
@@ -3494,31 +3768,46 @@ function createTracking(options) {
|
|
|
3494
3768
|
metaPixelIds,
|
|
3495
3769
|
children
|
|
3496
3770
|
}) {
|
|
3497
|
-
const
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
}),
|
|
3771
|
+
const gtagIdsKey = (0, import_react6.useMemo)(() => gtagIds ? JSON.stringify(gtagIds) : "", [gtagIds]);
|
|
3772
|
+
const resolvedGtagIds = (0, import_react6.useMemo)(
|
|
3773
|
+
() => gtagIds ? Object.fromEntries(
|
|
3774
|
+
Object.entries(gtagIds).filter((e) => e[1] != null)
|
|
3775
|
+
) : gtagId ? { default: gtagId } : void 0,
|
|
3776
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- gtagIdsKey is stable proxy
|
|
3777
|
+
[gtagId, gtagIdsKey]
|
|
3778
|
+
);
|
|
3779
|
+
const rawClient = (0, import_react6.useMemo)(
|
|
3780
|
+
() => getOrCreateTrackingClient({
|
|
3781
|
+
apiKey,
|
|
3782
|
+
endpoint,
|
|
3783
|
+
surface: "react",
|
|
3784
|
+
packageName: "@aranova/tracking-react",
|
|
3785
|
+
sdkVersion: version,
|
|
3513
3786
|
triggers,
|
|
3514
|
-
|
|
3515
|
-
|
|
3787
|
+
environment,
|
|
3788
|
+
activeGtagIds: resolvedGtagIds,
|
|
3789
|
+
debug
|
|
3790
|
+
}),
|
|
3791
|
+
[resolvedGtagIds]
|
|
3792
|
+
);
|
|
3793
|
+
const conversionStore = (0, import_react6.useMemo)(
|
|
3794
|
+
() => trackingConfig ? getTrackingConfigRuntime(trackingConfig) : conversionConfig ? resolveConversionConfig({
|
|
3795
|
+
cdnUrl: conversionConfig.cdnUrl,
|
|
3796
|
+
baked: conversionConfig.baked
|
|
3797
|
+
}) : null,
|
|
3516
3798
|
[]
|
|
3517
3799
|
);
|
|
3518
|
-
const
|
|
3800
|
+
const conversionClient = (0, import_react6.useMemo)(
|
|
3801
|
+
() => conversionStore ? withConversionAutoFire(rawClient, createConversionAutoFire(conversionStore)) : rawClient,
|
|
3802
|
+
[rawClient, conversionStore]
|
|
3803
|
+
);
|
|
3804
|
+
const client = (0, import_react6.useMemo)(
|
|
3805
|
+
() => createTypedClient(conversionClient, triggers, { debug }),
|
|
3806
|
+
[conversionClient]
|
|
3807
|
+
);
|
|
3519
3808
|
(0, import_react6.useEffect)(() => {
|
|
3520
3809
|
if (trackingConfig) {
|
|
3521
|
-
|
|
3810
|
+
getTrackingConfigRuntime(trackingConfig).start();
|
|
3522
3811
|
} else if (gtagIds && Object.keys(gtagIds).length > 0) {
|
|
3523
3812
|
bootstrapMultipleGtags(gtagIds);
|
|
3524
3813
|
} else if (gtagId) {
|
|
@@ -3537,23 +3826,9 @@ function createTracking(options) {
|
|
|
3537
3826
|
}
|
|
3538
3827
|
}, [metaPixelId, metaPixelIdsKey]);
|
|
3539
3828
|
(0, import_react6.useEffect)(() => {
|
|
3540
|
-
const rawClient = getOrCreateTrackingClient({
|
|
3541
|
-
apiKey,
|
|
3542
|
-
endpoint,
|
|
3543
|
-
surface: "react",
|
|
3544
|
-
packageName: "@aranova/tracking-react",
|
|
3545
|
-
triggers,
|
|
3546
|
-
environment,
|
|
3547
|
-
activeGtagIds: resolvedGtagIds,
|
|
3548
|
-
debug
|
|
3549
|
-
});
|
|
3550
3829
|
return attachClientCapturesOnce(rawClient, () => {
|
|
3551
3830
|
const detachers = [];
|
|
3552
|
-
const
|
|
3553
|
-
cdnUrl: conversionConfig.cdnUrl,
|
|
3554
|
-
baked: conversionConfig.baked
|
|
3555
|
-
}) : null;
|
|
3556
|
-
const detectorClient = conversionStore ? withConversionAutoFire(rawClient, createConversionAutoFire(conversionStore)) : rawClient;
|
|
3831
|
+
const detectorClient = conversionStore ? conversionClient : rawClient;
|
|
3557
3832
|
const pageClient = trackingConfig && conversionStore && "queuePageView" in conversionStore ? {
|
|
3558
3833
|
...detectorClient,
|
|
3559
3834
|
trackEvent: (input) => {
|
|
@@ -3598,7 +3873,7 @@ function createTracking(options) {
|
|
|
3598
3873
|
}
|
|
3599
3874
|
};
|
|
3600
3875
|
});
|
|
3601
|
-
}, []);
|
|
3876
|
+
}, [conversionClient, conversionStore, rawClient]);
|
|
3602
3877
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TrackingContext.Provider, { value: client, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PhoneConfigProvider, { value: phone ?? null, children }) });
|
|
3603
3878
|
}
|
|
3604
3879
|
function useTracking() {
|
|
@@ -3627,6 +3902,7 @@ function createTracking(options) {
|
|
|
3627
3902
|
TRACKING_PARAM_KEYS,
|
|
3628
3903
|
TRACKING_RANGES,
|
|
3629
3904
|
captureTrackingParamsFromLocation,
|
|
3905
|
+
clearStashedUserData,
|
|
3630
3906
|
createSalesClient,
|
|
3631
3907
|
createTracking,
|
|
3632
3908
|
createTrackingClientContext,
|
|
@@ -3655,6 +3931,7 @@ function createTracking(options) {
|
|
|
3655
3931
|
saleUpdateSchema,
|
|
3656
3932
|
salesRequest,
|
|
3657
3933
|
setConsentState,
|
|
3934
|
+
stashUserData,
|
|
3658
3935
|
toE164,
|
|
3659
3936
|
toMinor,
|
|
3660
3937
|
useConsent,
|