react-marketing-tools 1.0.0-alpha.5 → 1.0.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.
@@ -1,45 +1,6 @@
1
- //#region lib/core/validate.ts
2
- var e = /^[A-Za-z][A-Za-z0-9_]{0,39}$/, t = [
3
- "google_",
4
- "ga_",
5
- "firebase_"
6
- ], n = 25, r = 100, i = {
7
- page_location: 1e3,
8
- page_referrer: 420,
9
- page_title: 300
10
- }, a = [
11
- "email",
12
- "phone",
13
- "first_name",
14
- "last_name",
15
- "address",
16
- "password"
17
- ], o = String.raw`[\w.+-]+(?:@|%40)[\w-]+(?:\.[\w-]+)+`, s = "[redacted]", c = (n) => {
18
- if (!e.test(n)) return "must start with a letter, contain only letters, digits and underscores, and be at most 40 characters";
19
- let r = t.find((e) => n.toLowerCase().startsWith(e));
20
- return r && `must not start with the reserved prefix "${r}"`;
21
- }, ee = (e) => {
22
- let t = c(e);
23
- return t && `event name "${e}" ${t}`;
24
- }, l = (e) => {
25
- let t = Object.keys(e), a = t.flatMap((t) => {
26
- let n = c(t);
27
- if (n) return [`param "${t}" ${n}`];
28
- let a = e[t], o = i[t] ?? r;
29
- return typeof a == "string" && a.length > o ? [`param "${t}" is longer than ${o} characters`] : [];
30
- });
31
- return t.length > n ? [`has ${t.length} params; the limit is ${n}`, ...a] : a;
32
- }, u = (e) => new RegExp(o, "i").test(e), d = (e, t) => (typeof t == "string" || typeof t == "number") && a.some((t) => e.toLowerCase().includes(t)) ? s : typeof t == "string" ? t.replace(new RegExp(o, "gi"), s) : t, f = (e) => {
33
- let t = Object.entries(e).map(([e, t]) => [
34
- e,
35
- t,
36
- d(e, t)
37
- ]);
38
- return {
39
- params: Object.fromEntries(t.map(([e, , t]) => [e, t])),
40
- redactedKeys: t.filter(([, e, t]) => t !== e).map(([e]) => e)
41
- };
42
- }, p = [
1
+ import { a as e, i as t, n, r, t as i } from "./cookies.js";
2
+ //#region lib/attribution/attribution.ts
3
+ var a = [
43
4
  "utm_source",
44
5
  "utm_medium",
45
6
  "utm_campaign",
@@ -58,67 +19,91 @@ var e = /^[A-Za-z][A-Za-z0-9_]{0,39}$/, t = [
58
19
  "ttclid",
59
20
  "li_fat_id",
60
21
  "twclid"
61
- ], m = 100, h = (e) => {
22
+ ], o = 100, s = (e) => {
62
23
  if (!URL.canParse(e)) return;
63
24
  let { origin: t, pathname: n } = new URL(e);
64
25
  return t + n;
65
- }, g = ({ url: e, referrer: t, capturedAt: n }) => {
66
- if (!URL.canParse(e)) return;
67
- let { searchParams: r } = new URL(e), i = p.flatMap((e) => {
68
- let t = r.get(e)?.trim();
26
+ }, c = ({ referrer: e, aiSources: t }) => {
27
+ if (!e || !t || !URL.canParse(e)) return;
28
+ let n = new URL(e).hostname.toLowerCase();
29
+ return Object.entries(t).find(([, e]) => e.some((e) => {
30
+ let t = e.toLowerCase();
31
+ return n === t || n.endsWith(`.${t}`);
32
+ }))?.[0];
33
+ }, l = ({ url: t, referrer: n, capturedAt: r, aiSources: i }) => {
34
+ if (!URL.canParse(t)) return;
35
+ let { searchParams: l } = new URL(t), u = a.flatMap((e) => {
36
+ let t = l.get(e)?.trim();
69
37
  return t ? [[e, t]] : [];
38
+ }), d = c({
39
+ referrer: n,
40
+ aiSources: i
70
41
  });
71
- if (i.length === 0) return;
72
- let { params: a } = f(Object.fromEntries(i)), o = Object.fromEntries(Object.entries(a).map(([e, t]) => [e, String(t).slice(0, m)])), s = t ? h(t) : void 0;
42
+ if (u.length === 0 && !d) return;
43
+ let { params: f } = e(Object.fromEntries(u)), p = Object.fromEntries(Object.entries(f).map(([e, t]) => [e, String(t).slice(0, o)])), m = n ? s(n) : void 0;
73
44
  return {
74
- ...o,
75
- landing_page: h(e) ?? e,
76
- ...s ? { referrer: s } : {},
77
- captured_at: n
45
+ ...p,
46
+ landing_page: s(t) ?? t,
47
+ ...m ? { referrer: m } : {},
48
+ ...d ? { ai_source: d } : {},
49
+ captured_at: r
78
50
  };
79
- }, _ = (e) => typeof e == "object" && !!e, v = (e) => {
80
- if (_(e) && typeof e.captured_at == "number" && typeof e.landing_page == "string") return {
81
- ...Object.fromEntries(p.flatMap((t) => typeof e[t] == "string" ? [[t, e[t]]] : [])),
51
+ }, u = (e) => typeof e == "object" && !!e, d = (e) => {
52
+ if (u(e) && typeof e.captured_at == "number" && typeof e.landing_page == "string") return {
53
+ ...Object.fromEntries(a.flatMap((t) => typeof e[t] == "string" ? [[t, e[t]]] : [])),
82
54
  landing_page: e.landing_page,
83
55
  ...typeof e.referrer == "string" ? { referrer: e.referrer } : {},
56
+ ...typeof e.ai_source == "string" ? { ai_source: e.ai_source } : {},
84
57
  captured_at: e.captured_at
85
58
  };
86
- }, te = ({ fbcCookie: e, touch: t }) => e ?? (t?.fbclid ? `fb.1.${t.captured_at}.${t.fbclid}` : void 0), y = "rmt:attribution:first", b = "rmt:attribution:last", x = 864e5, S = (e, t) => {
59
+ }, f = ({ fbcCookie: e, touch: t }) => e ?? (t?.fbclid ? `fb.1.${t.captured_at}.${t.fbclid}` : void 0), p = "rmt:attribution:first", m = "rmt:attribution:last", h = 864e5, g = (e, t) => {
87
60
  try {
88
61
  return t(window[e]);
89
62
  } catch {
90
63
  return;
91
64
  }
92
- }, C = (e, t) => S(e, (e) => {
65
+ }, _ = (e, t) => g(e, (e) => {
93
66
  let n = e.getItem(t);
94
- return n === null ? void 0 : v(JSON.parse(n));
95
- }), ne = ({ ttlDays: e }) => {
96
- let t, n, r = (t) => Date.now() - t.captured_at < e * x;
67
+ return n === null ? void 0 : d(JSON.parse(n));
68
+ }), ee = ({ ttlDays: e }) => {
69
+ let t, n, r = (t) => Date.now() - t.captured_at < e * h;
97
70
  return {
98
71
  observe(e) {
99
72
  e && (t ??= e, n = e);
100
73
  },
101
74
  restore() {
102
- let e = C("localStorage", y);
103
- e && r(e) && (!t || e.captured_at <= t.captured_at) && (t = e), n ??= C("sessionStorage", b);
75
+ let e = _("localStorage", p);
76
+ e && r(e) && (!t || e.captured_at <= t.captured_at) && (t = e), n ??= _("sessionStorage", m);
104
77
  },
105
78
  persist() {
106
- S("localStorage", (e) => t && r(t) ? e.setItem(y, JSON.stringify(t)) : e.removeItem(y)), n && S("sessionStorage", (e) => e.setItem(b, JSON.stringify(n)));
79
+ g("localStorage", (e) => t && r(t) ? e.setItem(p, JSON.stringify(t)) : e.removeItem(p)), n && g("sessionStorage", (e) => e.setItem(m, JSON.stringify(n)));
107
80
  },
108
81
  erase() {
109
- S("localStorage", (e) => e.removeItem(y)), S("sessionStorage", (e) => e.removeItem(b));
82
+ g("localStorage", (e) => e.removeItem(p)), g("sessionStorage", (e) => e.removeItem(m));
110
83
  },
111
84
  get: () => ({
112
85
  firstTouch: t,
113
86
  lastTouch: n
114
87
  })
115
88
  };
116
- }, w = [
89
+ }, v = "data-analytics-event", y = "data-analytics-param-", b = (e) => {
90
+ if (!(e instanceof Element)) return;
91
+ let t = e.closest(`[${v}]`), n = t?.getAttribute(v);
92
+ if (t && n) return {
93
+ name: n,
94
+ params: Object.fromEntries(Array.from(t.attributes).filter((e) => e.name.startsWith(y)).map((e) => [e.name.slice(21).replaceAll("-", "_"), e.value]))
95
+ };
96
+ }, te = (e) => {
97
+ document.addEventListener("click", (t) => {
98
+ let n = b(t.target);
99
+ n && e(n.name, n.params);
100
+ }, { capture: !0 });
101
+ }, ne = [
117
102
  "analytics",
118
103
  "ads",
119
104
  "adUserData",
120
105
  "adPersonalization"
121
- ], T = (e) => e === "granted" || e === "denied", E = ({ consent: e, gpc: t }) => {
106
+ ], x = (e) => e === "granted" || e === "denied", S = ({ consent: e, gpc: t }) => {
122
107
  let n = t ? "denied" : e;
123
108
  return {
124
109
  analytics: e,
@@ -126,35 +111,35 @@ var e = /^[A-Za-z][A-Za-z0-9_]{0,39}$/, t = [
126
111
  adUserData: n,
127
112
  adPersonalization: n
128
113
  };
129
- }, D = (e, t) => ({
114
+ }, re = (e, t) => ({
130
115
  analytics: t.analytics ?? e.analytics,
131
116
  ads: t.ads ?? e.ads,
132
117
  adUserData: t.adUserData ?? t.ads ?? e.adUserData,
133
118
  adPersonalization: t.adPersonalization ?? t.ads ?? e.adPersonalization
134
- }), O = (e) => ({
119
+ }), C = (e) => ({
135
120
  analytics_storage: e.analytics,
136
121
  ad_storage: e.ads,
137
122
  ad_user_data: e.adUserData,
138
123
  ad_personalization: e.adPersonalization
139
- }), k = (e) => Object.values(e).includes("denied"), re = () => typeof navigator < "u" && navigator.globalPrivacyControl === !0, A = () => window.dataLayer ??= [], ie = () => Array.from(document.scripts).some((e) => URL.canParse(e.src) && new URL(e.src).pathname.endsWith("/gtag/js")), j = () => window.gtag ??= function() {
140
- A().push(arguments);
141
- }, M = ({ consent: e, waitForUpdate: t }) => {
142
- j()("consent", "default", {
143
- ...O(e),
144
- ...k(e) ? { wait_for_update: t } : {}
124
+ }), w = (e) => Object.values(e).includes("denied"), ie = () => typeof navigator < "u" && navigator.globalPrivacyControl === !0, T = () => window.dataLayer ??= [], E = () => Array.from(document.scripts).some((e) => URL.canParse(e.src) && new URL(e.src).pathname.endsWith("/gtag/js")), D = () => window.gtag ??= function() {
125
+ T().push(arguments);
126
+ }, O = ({ consent: e, waitForUpdate: t }) => {
127
+ D()("consent", "default", {
128
+ ...C(e),
129
+ ...w(e) ? { wait_for_update: t } : {}
145
130
  });
146
- }, N = (e) => {
147
- j()("consent", "update", O(e));
148
- }, P = (e, t) => {
131
+ }, k = (e) => {
132
+ D()("consent", "update", C(e));
133
+ }, A = (e, t) => {
149
134
  let n = URL.canParse(e) ? new URL(e) : void 0;
150
135
  if (n?.protocol !== "https:") throw Error(`[react-marketing-tools] ${t} must be an https:// URL (received ${JSON.stringify(e)}).`);
151
136
  return n;
152
- }, F = (e) => Array.from(document.scripts).some((t) => t.src === e), I = ({ src: e, nonce: t }) => {
137
+ }, j = (e) => Array.from(document.scripts).some((t) => t.src === e), M = ({ src: e, nonce: t }) => {
153
138
  let n = document.createElement("script");
154
139
  n.async = !0, n.src = e, t && n.setAttribute("nonce", t), document.head.append(n);
155
- }, L = /^G-[A-Z0-9]+$/, R = ({ measurementId: e, pageViews: t = "auto", loadScript: n = !0, serverContainerUrl: r, waitForUpdate: i = 500, nonce: a }) => {
156
- if (!L.test(e)) throw Error(`[react-marketing-tools] ga4.measurementId must look like "G-XXXXXXX" (received ${JSON.stringify(e)}).`);
157
- r !== void 0 && P(r, "ga4.serverContainerUrl");
140
+ }, ae = /^G-[A-Z0-9]+$/, oe = ({ measurementId: e, pageViews: t = "auto", loadScript: n = !0, serverContainerUrl: r, waitForUpdate: i = 500, nonce: a }) => {
141
+ if (!ae.test(e)) throw Error(`[react-marketing-tools] ga4.measurementId must look like "G-XXXXXXX" (received ${JSON.stringify(e)}).`);
142
+ r !== void 0 && A(r, "ga4.serverContainerUrl");
158
143
  let o = `https://www.googletagmanager.com/gtag/js?id=${e}`, s = (e, t) => r ? {
159
144
  ...e,
160
145
  event_id: t
@@ -162,55 +147,55 @@ var e = /^[A-Za-z][A-Za-z0-9_]{0,39}$/, t = [
162
147
  return {
163
148
  name: "ga4",
164
149
  start({ consent: s }) {
165
- M({
150
+ O({
166
151
  consent: s,
167
152
  waitForUpdate: i
168
- }), ie() || (j()("js", /* @__PURE__ */ new Date()), n && I({
153
+ }), E() || (D()("js", /* @__PURE__ */ new Date()), n && M({
169
154
  src: o,
170
155
  nonce: a
171
- })), j()("config", e, {
156
+ })), D()("config", e, {
172
157
  ...t === "manual" ? { send_page_view: !1 } : {},
173
158
  ...r ? { server_container_url: r } : {}
174
159
  });
175
160
  },
176
161
  track({ name: e, params: t, eventId: n }) {
177
- j()("event", e, s(t, n));
162
+ D()("event", e, s(t, n));
178
163
  },
179
164
  consent(e) {
180
- N(e);
165
+ k(e);
181
166
  },
182
167
  page({ params: e, eventId: n }) {
183
- t === "manual" && j()("event", "page_view", s(e, n));
168
+ t === "manual" && D()("event", "page_view", s(e, n));
184
169
  },
185
170
  identify({ userId: e }) {
186
- j()("set", { user_id: e });
171
+ D()("set", { user_id: e });
187
172
  },
188
173
  reset() {
189
- j()("set", { user_id: null });
174
+ D()("set", { user_id: null });
190
175
  }
191
176
  };
192
- }, z = /^GTM-[A-Z0-9]+$/, B = (e, t) => {
193
- let n = P(t ?? "https://www.googletagmanager.com/gtm.js", "gtm.scriptUrl");
177
+ }, N = /^GTM-[A-Z0-9]+$/, P = (e, t) => {
178
+ let n = A(t ?? "https://www.googletagmanager.com/gtm.js", "gtm.scriptUrl");
194
179
  return n.searchParams.set("id", e), n.href;
195
- }, V = ({ containerId: e, loadScript: t = !0, scriptUrl: n, waitForUpdate: r = 500, nonce: i }) => {
196
- if (!z.test(e)) throw Error(`[react-marketing-tools] gtm.containerId must look like "GTM-XXXXXXX" (received ${JSON.stringify(e)}).`);
197
- let a = B(e, n);
180
+ }, F = ({ containerId: e, loadScript: t = !0, scriptUrl: n, waitForUpdate: r = 500, nonce: i }) => {
181
+ if (!N.test(e)) throw Error(`[react-marketing-tools] gtm.containerId must look like "GTM-XXXXXXX" (received ${JSON.stringify(e)}).`);
182
+ let a = P(e, n);
198
183
  return {
199
184
  name: "gtm",
200
185
  start({ consent: e }) {
201
- M({
186
+ O({
202
187
  consent: e,
203
188
  waitForUpdate: r
204
- }), t && !F(a) && (A().push({
189
+ }), t && !j(a) && (T().push({
205
190
  "gtm.start": Date.now(),
206
191
  event: "gtm.js"
207
- }), I({
192
+ }), M({
208
193
  src: a,
209
194
  nonce: i
210
195
  }));
211
196
  },
212
197
  track({ name: e, params: t, eventId: n, attribution: r }) {
213
- A().push({
198
+ T().push({
214
199
  ...t,
215
200
  ...r && { attribution: r },
216
201
  event: e,
@@ -218,22 +203,22 @@ var e = /^[A-Za-z][A-Za-z0-9_]{0,39}$/, t = [
218
203
  });
219
204
  },
220
205
  consent(e) {
221
- N(e);
206
+ k(e);
222
207
  },
223
208
  identify({ userId: e }) {
224
- A().push({
209
+ T().push({
225
210
  event: "identify",
226
211
  user_id: e
227
212
  });
228
213
  },
229
214
  reset() {
230
- A().push({
215
+ T().push({
231
216
  event: "reset",
232
217
  user_id: void 0
233
218
  });
234
219
  }
235
220
  };
236
- }, H = /* @__PURE__ */ new Set([
221
+ }, I = /* @__PURE__ */ new Set([
237
222
  "AddPaymentInfo",
238
223
  "AddToCart",
239
224
  "AddToWishlist",
@@ -252,7 +237,7 @@ var e = /^[A-Za-z][A-Za-z0-9_]{0,39}$/, t = [
252
237
  "SubmitApplication",
253
238
  "Subscribe",
254
239
  "ViewContent"
255
- ]), U = {
240
+ ]), L = {
256
241
  purchase: "Purchase",
257
242
  sign_up: "CompleteRegistration",
258
243
  generate_lead: "Lead",
@@ -262,8 +247,8 @@ var e = /^[A-Za-z][A-Za-z0-9_]{0,39}$/, t = [
262
247
  search: "Search",
263
248
  add_payment_info: "AddPaymentInfo",
264
249
  add_to_wishlist: "AddToWishlist"
265
- }, W = (e) => typeof e == "object" && !!e, G = (e) => {
266
- let t = e.filter(W).filter((e) => e.item_id !== void 0).map((e) => ({
250
+ }, R = (e) => typeof e == "object" && !!e, z = (e) => {
251
+ let t = e.filter(R).filter((e) => e.item_id !== void 0).map((e) => ({
267
252
  id: String(e.item_id),
268
253
  quantity: typeof e.quantity == "number" ? e.quantity : 1
269
254
  }));
@@ -273,21 +258,21 @@ var e = /^[A-Za-z][A-Za-z0-9_]{0,39}$/, t = [
273
258
  num_items: t.reduce((e, t) => e + t.quantity, 0),
274
259
  content_type: "product"
275
260
  };
276
- }, K = ({ items: e, search_term: t, ...n }) => ({
261
+ }, B = ({ items: e, search_term: t, ...n }) => ({
277
262
  ...n,
278
263
  ...typeof t == "string" ? { search_string: t } : {},
279
- ...Array.isArray(e) ? G(e) : {}
280
- }), q = ({ name: e, params: t, options: n }) => {
281
- let r = n?.meta, i = r?.event ?? U[e] ?? e;
264
+ ...Array.isArray(e) ? z(e) : {}
265
+ }), V = ({ name: e, params: t, options: n }) => {
266
+ let r = n?.meta || void 0, i = r?.event ?? L[e] ?? e;
282
267
  return {
283
- command: H.has(i) ? "track" : "trackCustom",
268
+ command: I.has(i) ? "track" : "trackCustom",
284
269
  name: i,
285
270
  params: {
286
- ...K(t),
271
+ ...B(t),
287
272
  ...r?.params
288
273
  }
289
274
  };
290
- }, J = /^\d+$/, ae = "https://connect.facebook.net/en_US/fbevents.js", Y = () => {
275
+ }, H = /^\d+$/, U = "https://connect.facebook.net/en_US/fbevents.js", W = () => {
291
276
  let e = window;
292
277
  if (!e.fbq) {
293
278
  let t = function() {
@@ -297,130 +282,288 @@ var e = /^[A-Za-z][A-Za-z0-9_]{0,39}$/, t = [
297
282
  t.push = t, t.loaded = !0, t.version = "2.0", t.queue = [], e.fbq = t, e._fbq ??= t;
298
283
  }
299
284
  return e.fbq;
300
- }, oe = () => Array.from(document.scripts).some((e) => URL.canParse(e.src) && new URL(e.src).pathname.endsWith("/fbevents.js")), se = ({ userId: e, traits: t }) => Object.fromEntries(Object.entries({
285
+ }, G = () => Array.from(document.scripts).some((e) => URL.canParse(e.src) && new URL(e.src).pathname.endsWith("/fbevents.js")), K = ({ userId: e, traits: t }) => Object.fromEntries(Object.entries({
301
286
  external_id: e,
302
287
  em: t.email,
303
288
  ph: t.phone,
304
289
  fn: t.firstName,
305
290
  ln: t.lastName
306
- }).filter(([, e]) => e !== void 0)), X = (e) => e.adUserData === "granted" ? "grant" : "revoke", ce = ({ pixelId: e, pageViews: t = "auto", loadScript: n = !0, nonce: r }) => {
307
- if (!J.test(e)) throw Error(`[react-marketing-tools] metaPixel.pixelId must be the numeric pixel ID (received ${JSON.stringify(e)}).`);
291
+ }).filter(([, e]) => e !== void 0)), q = (e) => e.adUserData === "granted" ? "grant" : "revoke", se = ({ pixelId: e, pageViews: t = "auto", loadScript: n = !0, nonce: r }) => {
292
+ if (!H.test(e)) throw Error(`[react-marketing-tools] metaPixel.pixelId must be the numeric pixel ID (received ${JSON.stringify(e)}).`);
308
293
  return {
309
294
  name: "metaPixel",
310
295
  start({ consent: i, identity: a }) {
311
- let o = Y();
312
- t === "manual" && (o.disablePushState = !0), X(i) === "revoke" && o("consent", "revoke"), a ? o("init", e, se(a)) : o("init", e), t === "auto" && o("track", "PageView"), n && !oe() && I({
313
- src: ae,
296
+ let o = W();
297
+ t === "manual" && (o.disablePushState = !0), q(i) === "revoke" && o("consent", "revoke"), a ? o("init", e, K(a)) : o("init", e), t === "auto" && o("track", "PageView"), n && !G() && M({
298
+ src: U,
314
299
  nonce: r
315
300
  });
316
301
  },
317
302
  track(e) {
318
- let { command: t, name: n, params: r } = q(e);
319
- Y()(t, n, r, { eventID: e.eventId });
303
+ if (e.options?.meta === !1) return;
304
+ let { command: t, name: n, params: r } = V(e);
305
+ W()(t, n, r, { eventID: e.eventId });
320
306
  },
321
307
  page({ eventId: e }) {
322
- t === "manual" && Y()("track", "PageView", {}, { eventID: e });
308
+ t === "manual" && W()("track", "PageView", {}, { eventID: e });
323
309
  },
324
310
  consent(e) {
325
- Y()("consent", X(e));
311
+ W()("consent", q(e));
326
312
  }
327
313
  };
328
- }, Z = class extends Error {
314
+ }, J = class extends Error {
329
315
  code;
330
316
  constructor(e, t, n) {
331
317
  super(`[react-marketing-tools] ${t}`, n), this.name = "AnalyticsError", this.code = e;
332
318
  }
333
- }, Q = (e, t) => {
334
- for (let n of e.split(";")) {
335
- let e = n.indexOf("=");
336
- if (e !== -1 && n.slice(0, e).trim() === t) return n.slice(e + 1).trim();
319
+ }, ce = (e) => e.startsWith("/") && !e.startsWith("//") || URL.canParse(e) && new URL(e).protocol === "https:", le = ({ endpoint: e, relayPageViews: t, visitorId: n, onError: r }) => {
320
+ if (!ce(e)) throw Error(`[react-marketing-tools] server.endpoint must be a path on your site, such as '/api/track', or an https:// URL (received ${JSON.stringify(e)}).`);
321
+ let a = "denied", o, s = (e) => {
322
+ let t = i(document.cookie, "_fbp"), r = f({
323
+ fbcCookie: i(document.cookie, "_fbc"),
324
+ touch: e.attribution
325
+ }), a = o?.userId ?? n();
326
+ return {
327
+ ...a && { externalId: a },
328
+ ...o?.traits,
329
+ ...r && { fbc: r },
330
+ ...t && { fbp: t }
331
+ };
332
+ }, c = ({ event: t, eventName: n, customData: i }) => {
333
+ let o = {
334
+ v: 1,
335
+ eventName: n,
336
+ eventId: t.eventId,
337
+ customData: i,
338
+ eventSourceUrl: location.href,
339
+ consent: { adUserData: a },
340
+ userData: s(t)
341
+ }, c = JSON.stringify(o);
342
+ typeof navigator.sendBeacon == "function" && navigator.sendBeacon(e, c) || fetch(e, {
343
+ method: "POST",
344
+ body: c,
345
+ keepalive: !0,
346
+ mode: "no-cors"
347
+ }).catch((t) => {
348
+ r(new J("destination_failed", `destination "server" could not reach ${e}`, { cause: t }));
349
+ });
350
+ };
351
+ return {
352
+ name: "server",
353
+ start(e) {
354
+ a = e.consent.adUserData, o = e.identity;
355
+ },
356
+ track(e) {
357
+ if (a !== "granted" || e.options?.meta === !1) return;
358
+ let { name: t, params: n } = V(e);
359
+ c({
360
+ event: e,
361
+ eventName: t,
362
+ customData: n
363
+ });
364
+ },
365
+ page(e) {
366
+ a === "granted" && t && c({
367
+ event: e,
368
+ eventName: "PageView",
369
+ customData: {}
370
+ });
371
+ },
372
+ consent(e) {
373
+ a = e.adUserData;
374
+ },
375
+ identify(e) {
376
+ o = e;
377
+ },
378
+ reset() {
379
+ o = void 0;
380
+ }
381
+ };
382
+ }, Y = () => typeof crypto.randomUUID == "function" ? crypto.randomUUID() : "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (e) => (Number(e) ^ crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(1))[0] & 15 >> Number(e) / 4).toString(16)), X = "rmt:vid", ue = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/, de = () => {
383
+ try {
384
+ let e = localStorage.getItem(X);
385
+ return e !== null && ue.test(e) ? e : void 0;
386
+ } catch {
387
+ return;
388
+ }
389
+ }, Z = (e) => {
390
+ try {
391
+ e ? localStorage.setItem(X, e) : localStorage.removeItem(X);
392
+ } catch {}
393
+ }, fe = () => {
394
+ let e, t = (t) => {
395
+ if (t.analytics !== "granted") return;
396
+ let n = de();
397
+ return n ? e = n : (e ??= Y(), Z(e), e);
398
+ };
399
+ return {
400
+ peek: t,
401
+ get: (e) => Promise.resolve(t(e)),
402
+ erase() {
403
+ e = void 0, Z(void 0);
404
+ }
405
+ };
406
+ }, pe = ({ fingerprint: e, onError: t }) => {
407
+ let n, r, i = (e) => e.analytics === "granted" && e.ads === "granted";
408
+ return {
409
+ peek: (e) => i(e) ? r : void 0,
410
+ get(a) {
411
+ return i(a) ? (n ??= Promise.resolve().then(e).then((e) => {
412
+ if (typeof e != "string" || e === "") throw TypeError(`expected a non-empty string, received ${JSON.stringify(e)}`);
413
+ return r = e;
414
+ }).catch((e) => {
415
+ t(new J("visitor_id_failed", "visitorId.fingerprint failed, so this page has no visitor ID", { cause: e }));
416
+ }), n) : Promise.resolve(void 0);
417
+ },
418
+ erase() {
419
+ n = void 0, r = void 0;
420
+ }
421
+ };
422
+ }, me = ({ config: e, onError: t }) => {
423
+ if (e !== !1) {
424
+ if (e === "random") return fe();
425
+ if (typeof e?.fingerprint == "function") return pe({
426
+ fingerprint: e.fingerprint,
427
+ onError: t
428
+ });
429
+ throw Error(`[react-marketing-tools] visitorId must be 'random', false or { fingerprint: () => Promise<string> } (received ${JSON.stringify(e)}).`);
337
430
  }
338
- }, $ = () => typeof window < "u", le = 90, ue = () => typeof crypto.randomUUID == "function" ? crypto.randomUUID() : "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (e) => (Number(e) ^ crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(1))[0] & 15 >> Number(e) / 4).toString(16)), de = (e) => {
431
+ }, he = ({ name: e, track: t, fail: n }) => {
432
+ let r = {
433
+ journey_id: Y(),
434
+ journey_name: e
435
+ }, i = !1, a, o = 0, s, c = (o) => a ? (n(new J("journey_ended", `journey "${e}" is already ${a}, so ${o} was ignored`)), !1) : (i || (i = !0, t("journey_start", r)), !0);
436
+ return {
437
+ step(e, n = {}) {
438
+ c(`step("${e}")`) && (o += 1, s = e, t("journey_step", {
439
+ ...n,
440
+ ...r,
441
+ step_name: e,
442
+ step_index: o
443
+ }));
444
+ },
445
+ complete(e = {}) {
446
+ c("complete()") && (a = "completed", t("journey_complete", {
447
+ ...e,
448
+ ...r,
449
+ step_count: o
450
+ }));
451
+ },
452
+ abandon(e) {
453
+ c("abandon()") && (a = "abandoned", t("journey_abandon", {
454
+ ...r,
455
+ step_count: o,
456
+ ...s && { step_name: s },
457
+ ...e && { reason: e }
458
+ }));
459
+ }
460
+ };
461
+ }, Q = () => typeof window < "u", ge = 90, $ = (e) => {
339
462
  if (e.consent !== "granted" && e.consent !== "denied") throw Error(`[react-marketing-tools] createAnalytics: "consent" must be 'granted' or 'denied' (received ${JSON.stringify(e.consent)}).`);
340
- }, fe = (e) => {
341
- de(e);
342
- let { debug: t = !1, onError: n = console.error, respectGpc: r = !0 } = e, i = E({
343
- consent: e.consent,
344
- gpc: r && re()
345
- }), a = i, o, s = [
346
- ...e.gtm ? [V({
347
- ...e.gtm,
348
- nonce: e.nonce
463
+ }, _e = (a) => {
464
+ $(a);
465
+ let { debug: o = !1, onError: s = console.error, respectGpc: c = !0 } = a, u = S({
466
+ consent: a.consent,
467
+ gpc: c && ie()
468
+ }), d = u, p, m = me({
469
+ config: a.visitorId ?? "random",
470
+ onError: s
471
+ }), h = () => {}, g = new Promise((e) => {
472
+ h = e;
473
+ }), _ = [
474
+ ...a.gtm ? [F({
475
+ ...a.gtm,
476
+ nonce: a.nonce
477
+ })] : [],
478
+ ...a.ga4 ? [oe({
479
+ ...a.ga4,
480
+ nonce: a.nonce
349
481
  })] : [],
350
- ...e.ga4 ? [R({
351
- ...e.ga4,
352
- nonce: e.nonce
482
+ ...a.metaPixel ? [se({
483
+ ...a.metaPixel,
484
+ nonce: a.nonce
353
485
  })] : [],
354
- ...e.metaPixel ? [ce({
355
- ...e.metaPixel,
356
- nonce: e.nonce
486
+ ...a.server ? [le({
487
+ ...a.server,
488
+ relayPageViews: !a.metaPixel || a.metaPixel.pageViews === "manual",
489
+ visitorId: () => m?.peek(d),
490
+ onError: s
357
491
  })] : [],
358
- ...e.destinations ?? []
359
- ], c = [], d = !1, p = e.attribution === !1 ? void 0 : ne({ ttlDays: typeof e.attribution == "object" && e.attribution.ttlDays || le }), m = !1, h = () => {
360
- m || (m = !0, p?.observe(g({
492
+ ...a.destinations ?? []
493
+ ], v = [], y = !1, b = a.attribution === !1 ? void 0 : ee({ ttlDays: typeof a.attribution == "object" && a.attribution.ttlDays || ge }), C = typeof a.attribution == "object" ? a.attribution.aiSources : void 0, w = !1, T = () => {
494
+ w || (w = !0, b?.observe(l({
361
495
  url: location.href,
362
496
  referrer: document.referrer,
363
- capturedAt: Date.now()
497
+ capturedAt: Date.now(),
498
+ aiSources: C
364
499
  })));
365
- }, _ = () => d && a.analytics === "granted", v = (e) => {
366
- if (t) throw e;
367
- n(e);
368
- }, y = (e) => {
369
- for (let t of s) try {
500
+ }, E = () => y && d.analytics === "granted", D = () => {
501
+ y && a.server && m?.get(d);
502
+ }, O = (e) => {
503
+ if (o) throw e;
504
+ s(e);
505
+ }, k = (e) => {
506
+ for (let t of _) try {
370
507
  e(t);
371
508
  } catch (e) {
372
- n(new Z("destination_failed", `destination "${t.name}" failed`, { cause: e }));
509
+ s(new J("destination_failed", `destination "${t.name}" failed`, { cause: e }));
373
510
  }
374
- }, b = (e) => {
375
- d ? y(e) : c.push(e);
376
- }, x = ({ name: e, params: t, options: n }) => {
377
- let r = ee(e);
378
- if (r) {
379
- v(new Z("invalid_event", r));
511
+ }, A = (e) => {
512
+ y ? k(e) : v.push(e);
513
+ }, j = ({ name: n, params: i, options: a }) => {
514
+ let o = r(n);
515
+ if (o) {
516
+ O(new J("invalid_event", o));
380
517
  return;
381
518
  }
382
- for (let n of l(t)) v(new Z("invalid_param", `event "${e}" ${n}`));
383
- let i = f(t), a = n?.meta?.params && f(n.meta.params), o = [...i.redactedKeys, ...a?.redactedKeys.map((e) => `meta.${e}`) ?? []];
384
- o.length > 0 && v(new Z("pii_redacted", `event "${e}": personal data redacted from ${o.join(", ")}`)), h();
385
- let s = p?.get().lastTouch;
519
+ for (let e of t(i)) O(new J("invalid_param", `event "${n}" ${e}`));
520
+ let s = e(i), c = a?.meta || void 0, l = c?.params && e(c.params), u = [...s.redactedKeys, ...l?.redactedKeys.map((e) => `meta.${e}`) ?? []];
521
+ u.length > 0 && O(new J("pii_redacted", `event "${n}": personal data redacted from ${u.join(", ")}`)), T();
522
+ let d = b?.get().lastTouch;
386
523
  return {
387
- name: e,
388
- params: i.params,
389
- ...s && { attribution: s },
390
- ...n && { options: a ? {
391
- ...n,
524
+ name: n,
525
+ params: s.params,
526
+ ...d && { attribution: d },
527
+ ...a && { options: l ? {
528
+ ...a,
392
529
  meta: {
393
- ...n.meta,
394
- params: a.params
530
+ ...c,
531
+ params: l.params
395
532
  }
396
- } : n },
397
- eventId: ue(),
533
+ } : a },
534
+ eventId: Y(),
398
535
  timestamp: Date.now()
399
536
  };
537
+ }, M = (e, t = {}, n) => {
538
+ if (!Q()) return;
539
+ let r = j({
540
+ name: e,
541
+ params: t,
542
+ options: n
543
+ });
544
+ r && A((e) => e.track(r));
400
545
  };
401
546
  return {
402
547
  start() {
403
- !d && $() && (d = !0, h(), _() && (p?.restore(), p?.persist()), y((e) => e.start({
404
- consent: i,
405
- identity: o
406
- })), c.splice(0).forEach(y));
407
- },
408
- track(e, t = {}, n) {
409
- if (!$()) return;
410
- let r = x({
411
- name: e,
412
- params: t,
413
- options: n
414
- });
415
- r && b((e) => e.track(r));
548
+ !y && Q() && (y = !0, T(), E() && (b?.restore(), b?.persist()), D(), k((e) => e.start({
549
+ consent: u,
550
+ identity: p
551
+ })), v.splice(0).forEach(k), a.autocapture?.clicks && te(M), h());
416
552
  },
553
+ track: M,
554
+ journey: (e) => he({
555
+ name: e,
556
+ track: M,
557
+ fail: O
558
+ }),
417
559
  page(e = {}) {
418
- if (!$()) return;
419
- h(), p?.observe(g({
560
+ if (!Q()) return;
561
+ T(), b?.observe(l({
420
562
  url: location.href,
421
- capturedAt: Date.now()
422
- })), _() && p?.persist();
423
- let t = x({
563
+ capturedAt: Date.now(),
564
+ aiSources: C
565
+ })), E() && b?.persist();
566
+ let t = j({
424
567
  name: "page_view",
425
568
  params: {
426
569
  page_location: location.href,
@@ -428,43 +571,43 @@ var e = /^[A-Za-z][A-Za-z0-9_]{0,39}$/, t = [
428
571
  ...e
429
572
  }
430
573
  });
431
- t && b((e) => e.page ? e.page(t) : e.track(t));
574
+ t && A((e) => e.page ? e.page(t) : e.track(t));
432
575
  },
433
576
  identify(e, t = {}) {
434
- if (!$()) return;
435
- if (!e || u(e)) {
436
- v(new Z("invalid_user_id", "identify() needs a non-empty user id that is not personal data such as an email address"));
577
+ if (!Q()) return;
578
+ if (!e || n(e)) {
579
+ O(new J("invalid_user_id", "identify() needs a non-empty user id that is not personal data such as an email address"));
437
580
  return;
438
581
  }
439
- let n = {
582
+ let r = {
440
583
  userId: e,
441
584
  traits: t
442
585
  };
443
- o = n, b((e) => e.identify?.(n));
586
+ p = r, A((e) => e.identify?.(r));
444
587
  },
445
588
  reset() {
446
- $() && (o = void 0, b((e) => e.reset?.()));
589
+ Q() && (p = void 0, A((e) => e.reset?.()));
447
590
  },
448
591
  consent: {
449
592
  update(e) {
450
- if (!$()) return;
451
- let t = Object.entries(e).filter(([e, t]) => t !== void 0 && !(w.includes(e) && T(t)));
593
+ if (!Q()) return;
594
+ let t = Object.entries(e).filter(([e, t]) => t !== void 0 && !(ne.includes(e) && x(t)));
452
595
  if (t.length > 0) {
453
- v(new Z("invalid_consent", `consent.update() ignored: ${t.map(([e, t]) => `${e}=${JSON.stringify(t)}`).join(", ")}. Use analytics, ads, adUserData or adPersonalization with 'granted' or 'denied'.`));
596
+ O(new J("invalid_consent", `consent.update() ignored: ${t.map(([e, t]) => `${e}=${JSON.stringify(t)}`).join(", ")}. Use analytics, ads, adUserData or adPersonalization with 'granted' or 'denied'.`));
454
597
  return;
455
598
  }
456
- let n = a, r = D(a, e);
457
- a = r, n.analytics === "granted" && r.analytics === "denied" ? p?.erase() : _() && (p?.restore(), p?.persist()), b((e) => e.consent?.(r));
599
+ let n = d, r = re(d, e);
600
+ d = r, n.analytics === "granted" && r.analytics === "denied" ? (b?.erase(), m?.erase()) : E() && (b?.restore(), b?.persist()), D(), A((e) => e.consent?.(r));
458
601
  },
459
- get: () => a
602
+ get: () => d
460
603
  },
461
604
  getAttribution() {
462
- if (!$()) return {};
463
- h();
464
- let e = p?.get() ?? {};
465
- if (a.adUserData !== "granted") return e;
466
- let t = Q(document.cookie, "_fbp"), n = te({
467
- fbcCookie: Q(document.cookie, "_fbc"),
605
+ if (!Q()) return {};
606
+ T();
607
+ let e = b?.get() ?? {};
608
+ if (d.adUserData !== "granted") return e;
609
+ let t = i(document.cookie, "_fbp"), n = f({
610
+ fbcCookie: i(document.cookie, "_fbc"),
468
611
  touch: e.lastTouch
469
612
  });
470
613
  return {
@@ -472,8 +615,11 @@ var e = /^[A-Za-z][A-Za-z0-9_]{0,39}$/, t = [
472
615
  ...n && { fbc: n },
473
616
  ...t && { fbp: t }
474
617
  };
618
+ },
619
+ getVisitorId() {
620
+ return !Q() || !m ? Promise.resolve(void 0) : g.then(() => m.get(d));
475
621
  }
476
622
  };
477
623
  };
478
624
  //#endregion
479
- export { Z as n, fe as t };
625
+ export { J as n, _e as t };