@aranova/tracking-next 0.17.2 → 0.18.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/README.md +49 -23
- package/dist/index.d.mts +175 -12
- package/dist/index.d.ts +175 -12
- package/dist/index.js +610 -88
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +584 -65
- package/dist/index.mjs.map +1 -1
- package/dist/middleware.js +90 -0
- package/dist/middleware.js.map +1 -1
- package/dist/middleware.mjs +90 -0
- package/dist/middleware.mjs.map +1 -1
- package/dist/phone.js +90 -0
- package/dist/phone.js.map +1 -1
- package/dist/phone.mjs +90 -0
- package/dist/phone.mjs.map +1 -1
- package/dist/{sales-C3jFBx08.d.mts → sales-QqKh6_iy.d.mts} +55 -2
- package/dist/{sales-C3jFBx08.d.ts → sales-QqKh6_iy.d.ts} +55 -2
- package/dist/sales.d.mts +1 -1
- package/dist/sales.d.ts +1 -1
- package/dist/sales.js +16 -0
- package/dist/sales.js.map +1 -1
- package/dist/sales.mjs +16 -0
- package/dist/sales.mjs.map +1 -1
- package/dist/server.js +90 -0
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +90 -0
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -220,6 +220,11 @@ function captureTrackingParamsFromLocation(url = typeof window === "undefined" ?
|
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
// ../tracking-core/src/gtag.ts
|
|
223
|
+
var GTAG_SCRIPT_HOST = "https://www.googletagmanager.com/gtag/js";
|
|
224
|
+
var TRACKING_SCRIPT_ATTRIBUTE = "data-aranova-tracking";
|
|
225
|
+
function getScriptMarker(id) {
|
|
226
|
+
return `aranova-${id}`;
|
|
227
|
+
}
|
|
223
228
|
var GTAG_ID_PATTERN = /^[A-Z]{1,3}-[A-Za-z0-9_-]+$/;
|
|
224
229
|
function isValidGtagId(id) {
|
|
225
230
|
return GTAG_ID_PATTERN.test(id);
|
|
@@ -248,6 +253,15 @@ gtag('js', new Date());
|
|
|
248
253
|
gtag('config', '${gtagId}');
|
|
249
254
|
`.trim();
|
|
250
255
|
}
|
|
256
|
+
function ensureGtagFunction() {
|
|
257
|
+
window.dataLayer = window.dataLayer || [];
|
|
258
|
+
if (typeof window.gtag === "function") return window.gtag;
|
|
259
|
+
function gtag() {
|
|
260
|
+
window.dataLayer?.push(arguments);
|
|
261
|
+
}
|
|
262
|
+
window.gtag = gtag;
|
|
263
|
+
return window.gtag;
|
|
264
|
+
}
|
|
251
265
|
var SEND_TO_RE = /^AW-[A-Za-z0-9]+\/[A-Za-z0-9_-]+$/;
|
|
252
266
|
function isValidSendTo(sendTo) {
|
|
253
267
|
return SEND_TO_RE.test(sendTo);
|
|
@@ -266,6 +280,27 @@ function fireGtagConversion(input) {
|
|
|
266
280
|
return false;
|
|
267
281
|
}
|
|
268
282
|
}
|
|
283
|
+
function applyDefaultConsentState() {
|
|
284
|
+
const gtag = ensureGtagFunction();
|
|
285
|
+
gtag(
|
|
286
|
+
"consent",
|
|
287
|
+
"default",
|
|
288
|
+
buildConsentPayload(getConsentState() === "denied" ? "denied" : "granted")
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
function loadGtagScript(gtagId) {
|
|
292
|
+
if (typeof document === "undefined") return;
|
|
293
|
+
const marker = getScriptMarker("gtag-loader");
|
|
294
|
+
const existingScript = document.querySelector(
|
|
295
|
+
`script[${TRACKING_SCRIPT_ATTRIBUTE}="${marker}"]`
|
|
296
|
+
);
|
|
297
|
+
if (existingScript) return;
|
|
298
|
+
const script = document.createElement("script");
|
|
299
|
+
script.async = true;
|
|
300
|
+
script.src = `${GTAG_SCRIPT_HOST}?id=${encodeURIComponent(gtagId)}`;
|
|
301
|
+
script.setAttribute(TRACKING_SCRIPT_ATTRIBUTE, marker);
|
|
302
|
+
document.head.append(script);
|
|
303
|
+
}
|
|
269
304
|
function createGtagInitScriptMulti(gtagIds) {
|
|
270
305
|
const safeIds = gtagIds.filter(isValidGtagId);
|
|
271
306
|
const configs = safeIds.map((id) => `gtag('config', '${id}');`).join("\n");
|
|
@@ -552,6 +587,7 @@ function parseConversionConfig(raw) {
|
|
|
552
587
|
business_id: typeof obj.business_id === "string" ? obj.business_id : void 0,
|
|
553
588
|
customer_id: typeof obj.customer_id === "string" ? obj.customer_id : null,
|
|
554
589
|
environment: typeof obj.environment === "string" ? obj.environment : void 0,
|
|
590
|
+
google_tracking_state: obj.google_tracking_state === "active" ? "active" : "disabled",
|
|
555
591
|
gtag_ids: isStringMap(obj.gtag_ids) ? obj.gtag_ids : {},
|
|
556
592
|
meta_pixel_ids: isStringMap(obj.meta_pixel_ids) ? obj.meta_pixel_ids : {},
|
|
557
593
|
services,
|
|
@@ -598,9 +634,9 @@ function resolveConversionConfig(options) {
|
|
|
598
634
|
}
|
|
599
635
|
}
|
|
600
636
|
function notifyResolved() {
|
|
601
|
-
const
|
|
637
|
+
const listeners2 = [...resolveListeners];
|
|
602
638
|
resolveListeners.clear();
|
|
603
|
-
for (const listener of
|
|
639
|
+
for (const listener of listeners2) {
|
|
604
640
|
try {
|
|
605
641
|
listener();
|
|
606
642
|
} catch {
|
|
@@ -687,6 +723,283 @@ function formatDateInTz(iso, timeZone, opts, locale) {
|
|
|
687
723
|
}).format(date);
|
|
688
724
|
}
|
|
689
725
|
|
|
726
|
+
// ../tracking-core/src/resources/tracking-config-runtime.ts
|
|
727
|
+
var CACHE_PREFIX2 = "_aranova_cfg_runtime_";
|
|
728
|
+
var AUTHORITY_TTL_MS = 6e4;
|
|
729
|
+
var runtimes = /* @__PURE__ */ new Map();
|
|
730
|
+
var configuredIds = /* @__PURE__ */ new Set();
|
|
731
|
+
var scriptLoad = null;
|
|
732
|
+
var jsInitialized = false;
|
|
733
|
+
function cacheKey2(url) {
|
|
734
|
+
return `${CACHE_PREFIX2}${url}`;
|
|
735
|
+
}
|
|
736
|
+
function readCache2(url) {
|
|
737
|
+
if (typeof window === "undefined") return null;
|
|
738
|
+
try {
|
|
739
|
+
const raw = window.sessionStorage.getItem(cacheKey2(url));
|
|
740
|
+
if (!raw) return null;
|
|
741
|
+
const parsed = JSON.parse(raw);
|
|
742
|
+
const config = parseConversionConfig(parsed.config);
|
|
743
|
+
if (!config) return null;
|
|
744
|
+
return {
|
|
745
|
+
etag: typeof parsed.etag === "string" ? parsed.etag : null,
|
|
746
|
+
config
|
|
747
|
+
};
|
|
748
|
+
} catch {
|
|
749
|
+
return null;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
function writeCache2(url, entry) {
|
|
753
|
+
if (typeof window === "undefined") return;
|
|
754
|
+
try {
|
|
755
|
+
window.sessionStorage.setItem(cacheKey2(url), JSON.stringify(entry));
|
|
756
|
+
} catch {
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
function isTombstone(config) {
|
|
760
|
+
return config.google_tracking_state === "disabled" || Object.keys(config.gtag_ids).length === 0;
|
|
761
|
+
}
|
|
762
|
+
function validateConfig(config, ref) {
|
|
763
|
+
return config.business_id === ref.businessId && config.environment === ref.environment && (config.google_tracking_state === "active" || config.google_tracking_state === "disabled");
|
|
764
|
+
}
|
|
765
|
+
function pageViewSnapshot() {
|
|
766
|
+
if (typeof window === "undefined" || typeof document === "undefined") return null;
|
|
767
|
+
return {
|
|
768
|
+
href: window.location.href,
|
|
769
|
+
title: document.title || null,
|
|
770
|
+
referrer: document.referrer || null
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
function ensureScript(gtagId) {
|
|
774
|
+
if (typeof window === "undefined" || typeof document === "undefined") return Promise.resolve();
|
|
775
|
+
applyDefaultConsentState();
|
|
776
|
+
loadGtagScript(gtagId);
|
|
777
|
+
if (scriptLoad) return scriptLoad;
|
|
778
|
+
scriptLoad = new Promise((resolve) => {
|
|
779
|
+
const script = document.querySelector(
|
|
780
|
+
'script[data-aranova-tracking="aranova-gtag-loader"]'
|
|
781
|
+
);
|
|
782
|
+
if (!script) {
|
|
783
|
+
resolve();
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
if (script.dataset.loaded === "true") {
|
|
787
|
+
resolve();
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
window.setTimeout(resolve, 0);
|
|
791
|
+
script.addEventListener(
|
|
792
|
+
"load",
|
|
793
|
+
() => {
|
|
794
|
+
script.dataset.loaded = "true";
|
|
795
|
+
resolve();
|
|
796
|
+
},
|
|
797
|
+
{ once: true }
|
|
798
|
+
);
|
|
799
|
+
script.addEventListener("error", () => resolve(), { once: true });
|
|
800
|
+
});
|
|
801
|
+
return scriptLoad;
|
|
802
|
+
}
|
|
803
|
+
var TrackingConfigRuntime = class {
|
|
804
|
+
constructor(ref, fetchImpl = globalThis.fetch) {
|
|
805
|
+
this.ref = ref;
|
|
806
|
+
this.fetchImpl = fetchImpl;
|
|
807
|
+
this.current = null;
|
|
808
|
+
this.etag = null;
|
|
809
|
+
this.stateValue = "unconfirmed";
|
|
810
|
+
this.confirmedAt = 0;
|
|
811
|
+
this.inFlight = null;
|
|
812
|
+
this.conversionQueue = [];
|
|
813
|
+
this.automaticQueue = [];
|
|
814
|
+
this.pageQueue = [];
|
|
815
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
816
|
+
const cached = readCache2(ref.cdnUrl);
|
|
817
|
+
this.current = cached?.config ?? null;
|
|
818
|
+
this.etag = cached?.etag ?? null;
|
|
819
|
+
void this.revalidate();
|
|
820
|
+
if (typeof window !== "undefined") {
|
|
821
|
+
window.addEventListener("visibilitychange", () => {
|
|
822
|
+
if (document.visibilityState === "visible") void this.revalidate();
|
|
823
|
+
});
|
|
824
|
+
window.addEventListener("focus", () => void this.revalidate());
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
state() {
|
|
828
|
+
return this.stateValue;
|
|
829
|
+
}
|
|
830
|
+
config() {
|
|
831
|
+
return this.stateValue === "active" || this.stateValue === "tombstone" ? this.current : null;
|
|
832
|
+
}
|
|
833
|
+
__unsafeExpireAuthorityForTests() {
|
|
834
|
+
this.confirmedAt = 0;
|
|
835
|
+
}
|
|
836
|
+
subscribe(listener) {
|
|
837
|
+
this.listeners.add(listener);
|
|
838
|
+
return () => this.listeners.delete(listener);
|
|
839
|
+
}
|
|
840
|
+
async ensureAuthority() {
|
|
841
|
+
if (this.stateValue !== "unconfirmed" && Date.now() - this.confirmedAt < AUTHORITY_TTL_MS) {
|
|
842
|
+
return true;
|
|
843
|
+
}
|
|
844
|
+
await this.revalidate();
|
|
845
|
+
return this.stateValue !== "unconfirmed" && Date.now() - this.confirmedAt < AUTHORITY_TTL_MS;
|
|
846
|
+
}
|
|
847
|
+
async revalidate() {
|
|
848
|
+
if (typeof window === "undefined" || !this.fetchImpl) return;
|
|
849
|
+
if (this.inFlight) return this.inFlight;
|
|
850
|
+
this.inFlight = this.revalidateNow().finally(() => {
|
|
851
|
+
this.inFlight = null;
|
|
852
|
+
});
|
|
853
|
+
return this.inFlight;
|
|
854
|
+
}
|
|
855
|
+
queuePageView(snapshot = pageViewSnapshot()) {
|
|
856
|
+
if (!snapshot) return;
|
|
857
|
+
this.pageQueue.push(snapshot);
|
|
858
|
+
void this.flush();
|
|
859
|
+
}
|
|
860
|
+
fireConversion(key, options) {
|
|
861
|
+
this.conversionQueue.push({ key, ...options });
|
|
862
|
+
void this.flush();
|
|
863
|
+
}
|
|
864
|
+
queueAutomaticEvent(eventType, metadata, transactionPath) {
|
|
865
|
+
this.automaticQueue.push({ eventType, metadata, transactionPath });
|
|
866
|
+
void this.flush();
|
|
867
|
+
}
|
|
868
|
+
listGoals() {
|
|
869
|
+
return this.current?.goals ?? [];
|
|
870
|
+
}
|
|
871
|
+
async revalidateNow() {
|
|
872
|
+
try {
|
|
873
|
+
const headers = {};
|
|
874
|
+
if (this.etag) headers["If-None-Match"] = this.etag;
|
|
875
|
+
const response = await this.fetchImpl(this.ref.cdnUrl, {
|
|
876
|
+
method: "GET",
|
|
877
|
+
headers,
|
|
878
|
+
cache: "no-cache"
|
|
879
|
+
});
|
|
880
|
+
if (response.status === 304 && this.current && validateConfig(this.current, this.ref)) {
|
|
881
|
+
this.confirm(this.current, this.etag);
|
|
882
|
+
await this.flush();
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
if (!response.ok) {
|
|
886
|
+
this.expireAuthority();
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
const next = parseConversionConfig(await response.json());
|
|
890
|
+
if (!next || !validateConfig(next, this.ref)) {
|
|
891
|
+
this.expireAuthority();
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
if (this.current && next.config_version < this.current.config_version) {
|
|
895
|
+
this.expireAuthority();
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
this.confirm(next, response.headers.get("ETag"));
|
|
899
|
+
await this.flush();
|
|
900
|
+
} catch {
|
|
901
|
+
this.expireAuthority();
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
expireAuthority() {
|
|
905
|
+
if (this.stateValue !== "unconfirmed") this.stateValue = "unconfirmed";
|
|
906
|
+
}
|
|
907
|
+
confirm(config, etag) {
|
|
908
|
+
this.current = config;
|
|
909
|
+
this.etag = etag;
|
|
910
|
+
this.confirmedAt = Date.now();
|
|
911
|
+
this.stateValue = isTombstone(config) ? "tombstone" : "active";
|
|
912
|
+
writeCache2(this.ref.cdnUrl, { etag, config });
|
|
913
|
+
if (this.stateValue === "tombstone") {
|
|
914
|
+
this.conversionQueue.length = 0;
|
|
915
|
+
this.automaticQueue.length = 0;
|
|
916
|
+
this.pageQueue.length = 0;
|
|
917
|
+
}
|
|
918
|
+
for (const listener of this.listeners) listener();
|
|
919
|
+
}
|
|
920
|
+
async flush() {
|
|
921
|
+
if (!await this.ensureAuthority()) return;
|
|
922
|
+
if (this.stateValue !== "active" || !this.current) return;
|
|
923
|
+
const ids = Object.values(this.current.gtag_ids).filter(
|
|
924
|
+
(id) => typeof id === "string" && isValidGtagId(id)
|
|
925
|
+
);
|
|
926
|
+
if (ids.length === 0) return;
|
|
927
|
+
await ensureScript(ids[0]);
|
|
928
|
+
const gtag = window.gtag;
|
|
929
|
+
if (typeof gtag !== "function") return;
|
|
930
|
+
if (!jsInitialized) {
|
|
931
|
+
gtag("js", /* @__PURE__ */ new Date());
|
|
932
|
+
jsInitialized = true;
|
|
933
|
+
}
|
|
934
|
+
for (const id of ids) {
|
|
935
|
+
if (configuredIds.has(id)) continue;
|
|
936
|
+
gtag("config", id, { send_page_view: false });
|
|
937
|
+
configuredIds.add(id);
|
|
938
|
+
}
|
|
939
|
+
while (this.pageQueue.length) {
|
|
940
|
+
const page = this.pageQueue.shift();
|
|
941
|
+
gtag("event", "page_view", {
|
|
942
|
+
page_location: page.href,
|
|
943
|
+
page_title: page.title ?? void 0,
|
|
944
|
+
page_referrer: page.referrer ?? void 0
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
while (this.automaticQueue.length) {
|
|
948
|
+
const event = this.automaticQueue.shift();
|
|
949
|
+
for (const goal of this.current.goals) {
|
|
950
|
+
if (goal.kind !== "event" || !goal.firing) continue;
|
|
951
|
+
if (!automaticThresholdMet(goal, event.eventType, event.metadata)) continue;
|
|
952
|
+
this.conversionQueue.push({
|
|
953
|
+
key: goal.key,
|
|
954
|
+
transactionId: `auto:${goal.key}:${event.transactionPath}`
|
|
955
|
+
});
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
while (this.conversionQueue.length) {
|
|
959
|
+
const item = this.conversionQueue.shift();
|
|
960
|
+
const goal = this.current.goals.find((g) => g.key === item.key);
|
|
961
|
+
const firing = goal?.firing;
|
|
962
|
+
if (!firing || getConsentState() === "denied") continue;
|
|
963
|
+
const currency = item.currency ?? firing.currency ?? null;
|
|
964
|
+
const value = item.value ?? (firing.value_cents != null && currency ? fromMinor(firing.value_cents, currency) : null);
|
|
965
|
+
fireGtagConversion({
|
|
966
|
+
sendTo: firing.send_to,
|
|
967
|
+
value,
|
|
968
|
+
currency,
|
|
969
|
+
transactionId: item.transactionId ?? null
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
};
|
|
974
|
+
function automaticThresholdMet(goal, eventType, metadata) {
|
|
975
|
+
const t = goal.trigger;
|
|
976
|
+
if (!t || t.event_type !== eventType) return false;
|
|
977
|
+
switch (eventType) {
|
|
978
|
+
case "scroll_depth":
|
|
979
|
+
return typeof metadata.depth_percent === "number" && t.threshold_percent != null && metadata.depth_percent >= t.threshold_percent;
|
|
980
|
+
case "time_on_site":
|
|
981
|
+
return typeof metadata.duration_ms === "number" && t.threshold_seconds != null && metadata.duration_ms >= t.threshold_seconds * 1e3;
|
|
982
|
+
case "multi_page_session":
|
|
983
|
+
return typeof metadata.page_count === "number" && t.page_threshold != null && metadata.page_count >= t.page_threshold;
|
|
984
|
+
case "specific_page_visit":
|
|
985
|
+
return typeof metadata.page_name === "string" && metadata.page_name === t.page_name;
|
|
986
|
+
case "page_view":
|
|
987
|
+
case "form_start":
|
|
988
|
+
case "phone_click":
|
|
989
|
+
return true;
|
|
990
|
+
default:
|
|
991
|
+
return false;
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
function getTrackingConfigRuntime(ref, fetchImpl) {
|
|
995
|
+
const key = `${ref.cdnUrl}|${ref.businessId}|${ref.environment}`;
|
|
996
|
+
const existing = runtimes.get(key);
|
|
997
|
+
if (existing) return existing;
|
|
998
|
+
const runtime = new TrackingConfigRuntime(ref, fetchImpl ?? globalThis.fetch);
|
|
999
|
+
runtimes.set(key, runtime);
|
|
1000
|
+
return runtime;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
690
1003
|
// ../tracking-core/src/resources/conversion-autofire.ts
|
|
691
1004
|
function thresholdMet(goal, eventType, metadata) {
|
|
692
1005
|
const t = goal.trigger;
|
|
@@ -719,6 +1032,12 @@ function createConversionAutoFire(store) {
|
|
|
719
1032
|
for (const goal of store.listGoals()) {
|
|
720
1033
|
if (goal.kind !== "event" || !goal.firing) continue;
|
|
721
1034
|
if (!thresholdMet(goal, eventType, metadata)) continue;
|
|
1035
|
+
if ("queueAutomaticEvent" in store) {
|
|
1036
|
+
store.fireConversion(goal.key, {
|
|
1037
|
+
transactionId: `auto:${goal.key}:${currentPath()}`
|
|
1038
|
+
});
|
|
1039
|
+
continue;
|
|
1040
|
+
}
|
|
722
1041
|
const firing = goal.firing;
|
|
723
1042
|
const cents = firing.value_cents ?? null;
|
|
724
1043
|
const currency = firing.currency ?? null;
|
|
@@ -734,6 +1053,10 @@ function createConversionAutoFire(store) {
|
|
|
734
1053
|
}
|
|
735
1054
|
return {
|
|
736
1055
|
onAutomaticEvent(eventType, metadata) {
|
|
1056
|
+
if ("queueAutomaticEvent" in store) {
|
|
1057
|
+
store.queueAutomaticEvent(eventType, metadata, currentPath());
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
737
1060
|
if (store.isReady()) {
|
|
738
1061
|
fireMatching(eventType, metadata);
|
|
739
1062
|
return;
|
|
@@ -1330,6 +1653,14 @@ var pageExitMetadataSchema = z7.object({
|
|
|
1330
1653
|
// null = left without any scroll signal; floor is 0 so a valid 0% is never
|
|
1331
1654
|
// rejected (a single bad field 422s the whole keepalive beacon batch).
|
|
1332
1655
|
max_scroll_percent: z7.number().int().min(0).max(100).nullable(),
|
|
1656
|
+
// The gating baseline: the fraction of the page visible at load with
|
|
1657
|
+
// zero scrolling — or, for pages that grew after the post-paint snapshot
|
|
1658
|
+
// (skeleton/streaming renders), the first-scroll position that
|
|
1659
|
+
// established it. null = page had no scrollable range, or the segment
|
|
1660
|
+
// ended before the snapshot. `.optional()` is load-bearing: SDK builds
|
|
1661
|
+
// predating this field keep POSTing page_exit without the key —
|
|
1662
|
+
// requiring it would 422 whole keepalive beacon batches.
|
|
1663
|
+
scroll_baseline_percent: z7.number().int().min(0).max(100).nullable().optional(),
|
|
1333
1664
|
page: z7.object({
|
|
1334
1665
|
path: z7.string()
|
|
1335
1666
|
}).strict()
|
|
@@ -1405,69 +1736,154 @@ var timeOnSiteConfigSchema = z11.object({
|
|
|
1405
1736
|
thresholdSeconds: z11.number().int().positive()
|
|
1406
1737
|
}).strict();
|
|
1407
1738
|
|
|
1739
|
+
// ../tracking-core/src/events/semantics.ts
|
|
1740
|
+
var EVENT_SEMANTICS = {
|
|
1741
|
+
page_view: {
|
|
1742
|
+
label: "Page view",
|
|
1743
|
+
category: "page",
|
|
1744
|
+
outcomeRole: "navigation",
|
|
1745
|
+
clientVisibility: "simple"
|
|
1746
|
+
},
|
|
1747
|
+
time_on_site: {
|
|
1748
|
+
label: "Time on site",
|
|
1749
|
+
category: "engagement",
|
|
1750
|
+
outcomeRole: "engagement",
|
|
1751
|
+
clientVisibility: "detailed"
|
|
1752
|
+
},
|
|
1753
|
+
specific_page_visit: {
|
|
1754
|
+
label: "Key page visit",
|
|
1755
|
+
category: "engagement",
|
|
1756
|
+
outcomeRole: "engagement",
|
|
1757
|
+
clientVisibility: "detailed"
|
|
1758
|
+
},
|
|
1759
|
+
scroll_depth: {
|
|
1760
|
+
label: "Scroll depth",
|
|
1761
|
+
category: "engagement",
|
|
1762
|
+
outcomeRole: "engagement",
|
|
1763
|
+
clientVisibility: "detailed"
|
|
1764
|
+
},
|
|
1765
|
+
multi_page_session: {
|
|
1766
|
+
label: "Multi-page session",
|
|
1767
|
+
category: "engagement",
|
|
1768
|
+
outcomeRole: "engagement",
|
|
1769
|
+
clientVisibility: "detailed"
|
|
1770
|
+
},
|
|
1771
|
+
form_start: {
|
|
1772
|
+
label: "Form started",
|
|
1773
|
+
category: "engagement",
|
|
1774
|
+
outcomeRole: "engagement",
|
|
1775
|
+
clientVisibility: "simple"
|
|
1776
|
+
},
|
|
1777
|
+
sdk_heartbeat: {
|
|
1778
|
+
label: "SDK heartbeat",
|
|
1779
|
+
category: "system",
|
|
1780
|
+
outcomeRole: "diagnostic",
|
|
1781
|
+
clientVisibility: "hidden"
|
|
1782
|
+
},
|
|
1783
|
+
page_exit: {
|
|
1784
|
+
label: "Page exit",
|
|
1785
|
+
category: "engagement",
|
|
1786
|
+
outcomeRole: "diagnostic",
|
|
1787
|
+
clientVisibility: "detailed"
|
|
1788
|
+
},
|
|
1789
|
+
form_submit: {
|
|
1790
|
+
label: "Form submitted",
|
|
1791
|
+
category: "lead",
|
|
1792
|
+
outcomeRole: "lead",
|
|
1793
|
+
clientVisibility: "simple"
|
|
1794
|
+
},
|
|
1795
|
+
phone_click: {
|
|
1796
|
+
label: "Phone click",
|
|
1797
|
+
category: "lead",
|
|
1798
|
+
outcomeRole: "lead",
|
|
1799
|
+
clientVisibility: "simple"
|
|
1800
|
+
},
|
|
1801
|
+
cta_click: {
|
|
1802
|
+
label: "CTA click",
|
|
1803
|
+
category: "engagement",
|
|
1804
|
+
outcomeRole: "engagement",
|
|
1805
|
+
clientVisibility: "simple"
|
|
1806
|
+
}
|
|
1807
|
+
};
|
|
1808
|
+
function getEventSemantics(eventName) {
|
|
1809
|
+
return eventName in EVENT_SEMANTICS ? EVENT_SEMANTICS[eventName] : null;
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1408
1812
|
// ../tracking-core/src/events/registry.ts
|
|
1409
1813
|
var EVENT_REGISTRY = {
|
|
1410
1814
|
// --- automatic triggers ---
|
|
1411
1815
|
page_view: {
|
|
1412
1816
|
kind: "automatic",
|
|
1817
|
+
semantics: EVENT_SEMANTICS.page_view,
|
|
1413
1818
|
metadataSchema: pageViewMetadataSchema,
|
|
1414
1819
|
configSchema: pageViewConfigSchema
|
|
1415
1820
|
},
|
|
1416
1821
|
time_on_site: {
|
|
1417
1822
|
kind: "automatic",
|
|
1823
|
+
semantics: EVENT_SEMANTICS.time_on_site,
|
|
1418
1824
|
metadataSchema: timeOnSiteMetadataSchema,
|
|
1419
1825
|
configSchema: timeOnSiteConfigSchema
|
|
1420
1826
|
},
|
|
1421
1827
|
specific_page_visit: {
|
|
1422
1828
|
kind: "automatic",
|
|
1829
|
+
semantics: EVENT_SEMANTICS.specific_page_visit,
|
|
1423
1830
|
metadataSchema: specificPageVisitMetadataSchema,
|
|
1424
1831
|
configSchema: specificPageVisitConfigSchema
|
|
1425
1832
|
},
|
|
1426
1833
|
scroll_depth: {
|
|
1427
1834
|
kind: "automatic",
|
|
1835
|
+
semantics: EVENT_SEMANTICS.scroll_depth,
|
|
1428
1836
|
metadataSchema: scrollDepthMetadataSchema,
|
|
1429
1837
|
configSchema: scrollDepthConfigSchema
|
|
1430
1838
|
},
|
|
1431
1839
|
multi_page_session: {
|
|
1432
1840
|
kind: "automatic",
|
|
1841
|
+
semantics: EVENT_SEMANTICS.multi_page_session,
|
|
1433
1842
|
metadataSchema: multiPageSessionMetadataSchema,
|
|
1434
1843
|
configSchema: multiPageSessionConfigSchema
|
|
1435
1844
|
},
|
|
1436
1845
|
form_start: {
|
|
1437
1846
|
kind: "automatic",
|
|
1847
|
+
semantics: EVENT_SEMANTICS.form_start,
|
|
1438
1848
|
metadataSchema: formStartMetadataSchema,
|
|
1439
1849
|
configSchema: formStartConfigSchema
|
|
1440
1850
|
},
|
|
1441
1851
|
// --- SDK-internal automatic (not consumer-configurable) ---
|
|
1442
1852
|
sdk_heartbeat: {
|
|
1443
1853
|
kind: "automatic",
|
|
1854
|
+
semantics: EVENT_SEMANTICS.sdk_heartbeat,
|
|
1444
1855
|
metadataSchema: sdkHeartbeatMetadataSchema,
|
|
1445
1856
|
configSchema: sdkHeartbeatConfigSchema
|
|
1446
1857
|
},
|
|
1447
1858
|
page_exit: {
|
|
1448
1859
|
kind: "automatic",
|
|
1860
|
+
semantics: EVENT_SEMANTICS.page_exit,
|
|
1449
1861
|
metadataSchema: pageExitMetadataSchema,
|
|
1450
1862
|
configSchema: pageExitConfigSchema
|
|
1451
1863
|
},
|
|
1452
1864
|
// --- manual triggers ---
|
|
1453
1865
|
form_submit: {
|
|
1454
1866
|
kind: "manual",
|
|
1867
|
+
semantics: EVENT_SEMANTICS.form_submit,
|
|
1455
1868
|
metadataSchema: formSubmitMetadataSchema,
|
|
1456
1869
|
configSchema: formSubmitConfigSchema
|
|
1457
1870
|
},
|
|
1458
1871
|
phone_click: {
|
|
1459
1872
|
kind: "manual",
|
|
1873
|
+
semantics: EVENT_SEMANTICS.phone_click,
|
|
1460
1874
|
metadataSchema: phoneClickMetadataSchema,
|
|
1461
1875
|
configSchema: phoneClickConfigSchema
|
|
1462
1876
|
},
|
|
1463
1877
|
cta_click: {
|
|
1464
1878
|
kind: "manual",
|
|
1879
|
+
semantics: EVENT_SEMANTICS.cta_click,
|
|
1465
1880
|
metadataSchema: ctaClickMetadataSchema,
|
|
1466
1881
|
configSchema: ctaClickConfigSchema
|
|
1467
1882
|
}
|
|
1468
1883
|
};
|
|
1469
1884
|
var ALL_AUTOMATIC_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def]) => def.kind === "automatic").map(([name]) => name);
|
|
1470
1885
|
var ALL_MANUAL_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def]) => def.kind === "manual").map(([name]) => name);
|
|
1886
|
+
var ALL_LEAD_EVENT_NAMES = Object.entries(EVENT_REGISTRY).filter(([, def]) => def.semantics.outcomeRole === "lead").map(([name]) => name);
|
|
1471
1887
|
function getEventDefinition(name) {
|
|
1472
1888
|
return EVENT_REGISTRY[name];
|
|
1473
1889
|
}
|
|
@@ -1554,6 +1970,97 @@ function attachTimeOnSite(client, config) {
|
|
|
1554
1970
|
};
|
|
1555
1971
|
}
|
|
1556
1972
|
|
|
1973
|
+
// ../tracking-core/src/triggers/navigation.ts
|
|
1974
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
1975
|
+
var restorePatch = null;
|
|
1976
|
+
function notify() {
|
|
1977
|
+
for (const listener of listeners) listener();
|
|
1978
|
+
}
|
|
1979
|
+
function notifyDeferred() {
|
|
1980
|
+
setTimeout(notify, 0);
|
|
1981
|
+
}
|
|
1982
|
+
function installPatch() {
|
|
1983
|
+
const originalPushState = history.pushState;
|
|
1984
|
+
const originalReplaceState = history.replaceState;
|
|
1985
|
+
function patchedPushState(...args) {
|
|
1986
|
+
originalPushState.apply(this, args);
|
|
1987
|
+
notifyDeferred();
|
|
1988
|
+
}
|
|
1989
|
+
function patchedReplaceState(...args) {
|
|
1990
|
+
originalReplaceState.apply(this, args);
|
|
1991
|
+
notifyDeferred();
|
|
1992
|
+
}
|
|
1993
|
+
history.pushState = patchedPushState;
|
|
1994
|
+
history.replaceState = patchedReplaceState;
|
|
1995
|
+
window.addEventListener("popstate", notify);
|
|
1996
|
+
restorePatch = () => {
|
|
1997
|
+
history.pushState = originalPushState;
|
|
1998
|
+
history.replaceState = originalReplaceState;
|
|
1999
|
+
window.removeEventListener("popstate", notify);
|
|
2000
|
+
restorePatch = null;
|
|
2001
|
+
};
|
|
2002
|
+
}
|
|
2003
|
+
function onHistoryChange(listener) {
|
|
2004
|
+
if (listeners.size === 0) installPatch();
|
|
2005
|
+
listeners.add(listener);
|
|
2006
|
+
return () => {
|
|
2007
|
+
if (!listeners.delete(listener)) return;
|
|
2008
|
+
if (listeners.size === 0) restorePatch?.();
|
|
2009
|
+
};
|
|
2010
|
+
}
|
|
2011
|
+
|
|
2012
|
+
// ../tracking-core/src/triggers/scroll-measurement.ts
|
|
2013
|
+
var BOTTOM_EPSILON_PX = 2;
|
|
2014
|
+
function measureScrollPercent() {
|
|
2015
|
+
const root = document.scrollingElement ?? document.documentElement;
|
|
2016
|
+
const scrollHeight = root.scrollHeight;
|
|
2017
|
+
const clientHeight = root.clientHeight;
|
|
2018
|
+
if (scrollHeight <= 0 || clientHeight <= 0) return null;
|
|
2019
|
+
if (scrollHeight <= clientHeight + BOTTOM_EPSILON_PX) return null;
|
|
2020
|
+
const maxTop = scrollHeight - clientHeight;
|
|
2021
|
+
const scrollTop = Math.min(Math.max(root.scrollTop, 0), maxTop);
|
|
2022
|
+
if (scrollTop + clientHeight >= scrollHeight - BOTTOM_EPSILON_PX) return 100;
|
|
2023
|
+
return Math.max(1, Math.min(100, Math.round((scrollTop + clientHeight) / scrollHeight * 100)));
|
|
2024
|
+
}
|
|
2025
|
+
function scheduleBaselineSnapshot(onSnapshot) {
|
|
2026
|
+
let rafId = requestAnimationFrame(() => {
|
|
2027
|
+
rafId = requestAnimationFrame(() => {
|
|
2028
|
+
onSnapshot(measureScrollPercent());
|
|
2029
|
+
});
|
|
2030
|
+
});
|
|
2031
|
+
return () => cancelAnimationFrame(rafId);
|
|
2032
|
+
}
|
|
2033
|
+
function createBaselineGate() {
|
|
2034
|
+
let baselinePercent = null;
|
|
2035
|
+
let ready = false;
|
|
2036
|
+
let cancelSnapshot = null;
|
|
2037
|
+
return {
|
|
2038
|
+
rebaseline() {
|
|
2039
|
+
cancelSnapshot?.();
|
|
2040
|
+
ready = false;
|
|
2041
|
+
baselinePercent = null;
|
|
2042
|
+
cancelSnapshot = scheduleBaselineSnapshot((b) => {
|
|
2043
|
+
baselinePercent = b;
|
|
2044
|
+
ready = true;
|
|
2045
|
+
});
|
|
2046
|
+
},
|
|
2047
|
+
cancel() {
|
|
2048
|
+
cancelSnapshot?.();
|
|
2049
|
+
},
|
|
2050
|
+
baseline() {
|
|
2051
|
+
return ready ? baselinePercent : null;
|
|
2052
|
+
},
|
|
2053
|
+
sample() {
|
|
2054
|
+
if (!ready) return null;
|
|
2055
|
+
if (baselinePercent === null) {
|
|
2056
|
+
baselinePercent = measureScrollPercent();
|
|
2057
|
+
return null;
|
|
2058
|
+
}
|
|
2059
|
+
return measureScrollPercent();
|
|
2060
|
+
}
|
|
2061
|
+
};
|
|
2062
|
+
}
|
|
2063
|
+
|
|
1557
2064
|
// ../tracking-core/src/triggers/scroll-depth.ts
|
|
1558
2065
|
function attachScrollDepth(client, config) {
|
|
1559
2066
|
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
@@ -1564,17 +2071,14 @@ function attachScrollDepth(client, config) {
|
|
|
1564
2071
|
let firedForPath = /* @__PURE__ */ new Set();
|
|
1565
2072
|
let currentPath2 = window.location.pathname;
|
|
1566
2073
|
let rafId = null;
|
|
1567
|
-
|
|
1568
|
-
const doc = document.documentElement;
|
|
1569
|
-
const scrollTop = window.scrollY || doc.scrollTop;
|
|
1570
|
-
const scrollHeight = doc.scrollHeight;
|
|
1571
|
-
const clientHeight = doc.clientHeight;
|
|
1572
|
-
if (scrollHeight <= clientHeight) return 100;
|
|
1573
|
-
return Math.round((scrollTop + clientHeight) / scrollHeight * 100);
|
|
1574
|
-
}
|
|
2074
|
+
const gate = createBaselineGate();
|
|
1575
2075
|
function checkThresholds() {
|
|
1576
|
-
const percent =
|
|
2076
|
+
const percent = gate.sample();
|
|
2077
|
+
if (percent === null) return;
|
|
2078
|
+
const baseline = gate.baseline();
|
|
2079
|
+
if (baseline === null) return;
|
|
1577
2080
|
for (const threshold of thresholds) {
|
|
2081
|
+
if (threshold <= baseline) continue;
|
|
1578
2082
|
if (percent >= threshold && !firedForPath.has(threshold)) {
|
|
1579
2083
|
firedForPath.add(threshold);
|
|
1580
2084
|
client.trackEvent({
|
|
@@ -1601,28 +2105,15 @@ function attachScrollDepth(client, config) {
|
|
|
1601
2105
|
if (newPath === currentPath2) return;
|
|
1602
2106
|
currentPath2 = newPath;
|
|
1603
2107
|
firedForPath = /* @__PURE__ */ new Set();
|
|
1604
|
-
|
|
1605
|
-
}
|
|
1606
|
-
const originalPushState = history.pushState.bind(history);
|
|
1607
|
-
const originalReplaceState = history.replaceState.bind(history);
|
|
1608
|
-
function patchedPushState(...args) {
|
|
1609
|
-
originalPushState(...args);
|
|
1610
|
-
setTimeout(resetIfPathChanged, 0);
|
|
2108
|
+
gate.rebaseline();
|
|
1611
2109
|
}
|
|
1612
|
-
|
|
1613
|
-
originalReplaceState(...args);
|
|
1614
|
-
setTimeout(resetIfPathChanged, 0);
|
|
1615
|
-
}
|
|
1616
|
-
history.pushState = patchedPushState;
|
|
1617
|
-
history.replaceState = patchedReplaceState;
|
|
1618
|
-
window.addEventListener("popstate", resetIfPathChanged);
|
|
2110
|
+
const unsubscribeNav = onHistoryChange(resetIfPathChanged);
|
|
1619
2111
|
window.addEventListener("scroll", onScroll, { passive: true });
|
|
1620
|
-
|
|
2112
|
+
gate.rebaseline();
|
|
1621
2113
|
return () => {
|
|
1622
2114
|
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
window.removeEventListener("popstate", resetIfPathChanged);
|
|
2115
|
+
gate.cancel();
|
|
2116
|
+
unsubscribeNav();
|
|
1626
2117
|
window.removeEventListener("scroll", onScroll);
|
|
1627
2118
|
};
|
|
1628
2119
|
}
|
|
@@ -1704,21 +2195,14 @@ function attachPageExit(client) {
|
|
|
1704
2195
|
let accumulatedMs = 0;
|
|
1705
2196
|
let maxScrollPercent = null;
|
|
1706
2197
|
let rafId = null;
|
|
1707
|
-
|
|
1708
|
-
const doc = document.documentElement;
|
|
1709
|
-
const scrollTop = window.scrollY || doc.scrollTop;
|
|
1710
|
-
const scrollHeight = doc.scrollHeight;
|
|
1711
|
-
const clientHeight = doc.clientHeight;
|
|
1712
|
-
if (scrollHeight <= clientHeight) return 100;
|
|
1713
|
-
return Math.round((scrollTop + clientHeight) / scrollHeight * 100);
|
|
1714
|
-
}
|
|
2198
|
+
const gate = createBaselineGate();
|
|
1715
2199
|
function onScroll() {
|
|
1716
2200
|
if (rafId !== null) return;
|
|
1717
2201
|
rafId = requestAnimationFrame(() => {
|
|
1718
2202
|
rafId = null;
|
|
1719
|
-
const percent =
|
|
1720
|
-
if (percent
|
|
1721
|
-
maxScrollPercent =
|
|
2203
|
+
const percent = gate.sample();
|
|
2204
|
+
if (percent !== null && (maxScrollPercent === null || percent > maxScrollPercent)) {
|
|
2205
|
+
maxScrollPercent = percent;
|
|
1722
2206
|
}
|
|
1723
2207
|
});
|
|
1724
2208
|
}
|
|
@@ -1737,6 +2221,12 @@ function attachPageExit(client) {
|
|
|
1737
2221
|
metadata: {
|
|
1738
2222
|
dwell_ms: dwell,
|
|
1739
2223
|
max_scroll_percent: maxScrollPercent,
|
|
2224
|
+
// Lets the backend tell "scrolled to the bottom" apart from "the page
|
|
2225
|
+
// was barely scrollable". null = unscrollable page or the segment
|
|
2226
|
+
// ended before the post-paint snapshot landed. For pages that grew
|
|
2227
|
+
// after the snapshot this is the first-scroll position, not the
|
|
2228
|
+
// at-load fraction (see BaselineGate.baseline).
|
|
2229
|
+
scroll_baseline_percent: gate.baseline(),
|
|
1740
2230
|
page: { path }
|
|
1741
2231
|
},
|
|
1742
2232
|
pageUrl: window.location.href,
|
|
@@ -1754,6 +2244,7 @@ function attachPageExit(client) {
|
|
|
1754
2244
|
emitSegment(currentPath2, false);
|
|
1755
2245
|
currentPath2 = newPath;
|
|
1756
2246
|
maxScrollPercent = null;
|
|
2247
|
+
gate.rebaseline();
|
|
1757
2248
|
accumulatedMs = 0;
|
|
1758
2249
|
activeSince = document.visibilityState === "visible" ? Date.now() : null;
|
|
1759
2250
|
}
|
|
@@ -1767,27 +2258,15 @@ function attachPageExit(client) {
|
|
|
1767
2258
|
function onPageHide() {
|
|
1768
2259
|
emitSegment(currentPath2, true);
|
|
1769
2260
|
}
|
|
1770
|
-
const
|
|
1771
|
-
const originalReplaceState = history.replaceState.bind(history);
|
|
1772
|
-
function patchedPushState(...args) {
|
|
1773
|
-
originalPushState(...args);
|
|
1774
|
-
setTimeout(onNavigate, 0);
|
|
1775
|
-
}
|
|
1776
|
-
function patchedReplaceState(...args) {
|
|
1777
|
-
originalReplaceState(...args);
|
|
1778
|
-
setTimeout(onNavigate, 0);
|
|
1779
|
-
}
|
|
1780
|
-
history.pushState = patchedPushState;
|
|
1781
|
-
history.replaceState = patchedReplaceState;
|
|
1782
|
-
window.addEventListener("popstate", onNavigate);
|
|
2261
|
+
const unsubscribeNav = onHistoryChange(onNavigate);
|
|
1783
2262
|
window.addEventListener("scroll", onScroll, { passive: true });
|
|
1784
2263
|
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
1785
2264
|
window.addEventListener("pagehide", onPageHide);
|
|
2265
|
+
gate.rebaseline();
|
|
1786
2266
|
return () => {
|
|
1787
2267
|
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
window.removeEventListener("popstate", onNavigate);
|
|
2268
|
+
gate.cancel();
|
|
2269
|
+
unsubscribeNav();
|
|
1791
2270
|
window.removeEventListener("scroll", onScroll);
|
|
1792
2271
|
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
1793
2272
|
window.removeEventListener("pagehide", onPageHide);
|
|
@@ -2002,6 +2481,14 @@ function fireRecordedConversions(firing, input, recorded, sale, currency) {
|
|
|
2002
2481
|
const txnBase = input.external_id ?? sale.id;
|
|
2003
2482
|
for (const item of recorded) {
|
|
2004
2483
|
if (!item.service) continue;
|
|
2484
|
+
if ("fireConversion" in firing) {
|
|
2485
|
+
firing.fireConversion(item.service, {
|
|
2486
|
+
value: item.amount_cents != null ? fromMinor(item.amount_cents, currency) : void 0,
|
|
2487
|
+
currency,
|
|
2488
|
+
transactionId: `${txnBase}:${item.service}`
|
|
2489
|
+
});
|
|
2490
|
+
continue;
|
|
2491
|
+
}
|
|
2005
2492
|
const config = firing.getFiring(item.service);
|
|
2006
2493
|
if (!config) continue;
|
|
2007
2494
|
const cents = item.amount_cents ?? config.value_cents ?? null;
|
|
@@ -2044,6 +2531,14 @@ function createSalesClient(config) {
|
|
|
2044
2531
|
// recordSale is the intent-revealing alias — same behavior, clearer call site.
|
|
2045
2532
|
recordSale: record,
|
|
2046
2533
|
trackConversion(key, options) {
|
|
2534
|
+
if (config.firing && "fireConversion" in config.firing) {
|
|
2535
|
+
config.firing.fireConversion(key, {
|
|
2536
|
+
value: options?.value ?? void 0,
|
|
2537
|
+
currency: options?.currency ?? config.defaultCurrency ?? void 0,
|
|
2538
|
+
transactionId: options?.transactionId ?? null
|
|
2539
|
+
});
|
|
2540
|
+
return;
|
|
2541
|
+
}
|
|
2047
2542
|
const firing = config.firing?.getFiring(key);
|
|
2048
2543
|
if (!firing) return;
|
|
2049
2544
|
const currency = firing.currency ?? options?.currency ?? config.defaultCurrency ?? null;
|
|
@@ -2549,14 +3044,24 @@ var ANIMATION_KEYFRAMES = `
|
|
|
2549
3044
|
|
|
2550
3045
|
// src/AdPlatformTracking.tsx
|
|
2551
3046
|
import Script from "next/script";
|
|
3047
|
+
import { useEffect as useEffect3 } from "react";
|
|
2552
3048
|
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2553
3049
|
function AdPlatformTracking({
|
|
2554
3050
|
gtagId,
|
|
2555
3051
|
gtagIds,
|
|
3052
|
+
trackingConfig,
|
|
3053
|
+
standalonePageView = false,
|
|
2556
3054
|
metaPixelId,
|
|
2557
3055
|
metaPixelIds
|
|
2558
3056
|
}) {
|
|
2559
|
-
const
|
|
3057
|
+
const trackingConfigKey = trackingConfig ? `${trackingConfig.cdnUrl}:${trackingConfig.businessId}:${trackingConfig.environment}` : "";
|
|
3058
|
+
useEffect3(() => {
|
|
3059
|
+
if (!trackingConfig) return;
|
|
3060
|
+
const runtime = getTrackingConfigRuntime(trackingConfig);
|
|
3061
|
+
if (standalonePageView) runtime.queuePageView();
|
|
3062
|
+
else void runtime.revalidate();
|
|
3063
|
+
}, [trackingConfigKey, standalonePageView]);
|
|
3064
|
+
const gtagAll = trackingConfig ? [] : gtagIds ? Object.values(gtagIds).filter((id) => id != null) : gtagId ? [gtagId] : [];
|
|
2560
3065
|
const metaAll = metaPixelIds ? Object.values(metaPixelIds).filter((id) => id != null) : metaPixelId ? [metaPixelId] : [];
|
|
2561
3066
|
const gtagLoaderId = gtagAll[0];
|
|
2562
3067
|
const gtagInitScript = gtagAll.length === 1 ? createGtagInitScript(gtagAll[0]) : createGtagInitScriptMulti(gtagAll);
|
|
@@ -2606,7 +3111,7 @@ function GoogleAdsTracking(props) {
|
|
|
2606
3111
|
import { usePathname, useSearchParams } from "next/navigation";
|
|
2607
3112
|
|
|
2608
3113
|
// package.json
|
|
2609
|
-
var version = "0.
|
|
3114
|
+
var version = "0.18.0";
|
|
2610
3115
|
|
|
2611
3116
|
// src/factory.tsx
|
|
2612
3117
|
import {
|
|
@@ -2614,7 +3119,7 @@ import {
|
|
|
2614
3119
|
Suspense,
|
|
2615
3120
|
useCallback as useCallback3,
|
|
2616
3121
|
useContext as useContext2,
|
|
2617
|
-
useEffect as
|
|
3122
|
+
useEffect as useEffect4,
|
|
2618
3123
|
useMemo as useMemo2,
|
|
2619
3124
|
useRef
|
|
2620
3125
|
} from "react";
|
|
@@ -2717,13 +3222,23 @@ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
|
2717
3222
|
function PageViewTracker({ fire }) {
|
|
2718
3223
|
const pathname = usePathname();
|
|
2719
3224
|
const searchParams = useSearchParams();
|
|
2720
|
-
|
|
3225
|
+
useEffect4(() => {
|
|
2721
3226
|
fire();
|
|
2722
3227
|
}, [pathname, searchParams, fire]);
|
|
2723
3228
|
return null;
|
|
2724
3229
|
}
|
|
2725
3230
|
function createTracking(options) {
|
|
2726
|
-
const {
|
|
3231
|
+
const {
|
|
3232
|
+
apiKey,
|
|
3233
|
+
endpoint,
|
|
3234
|
+
triggers,
|
|
3235
|
+
environment,
|
|
3236
|
+
gtagIds,
|
|
3237
|
+
debug,
|
|
3238
|
+
phone,
|
|
3239
|
+
conversionConfig,
|
|
3240
|
+
trackingConfig
|
|
3241
|
+
} = options;
|
|
2727
3242
|
if (!apiKey || !endpoint) {
|
|
2728
3243
|
if (apiKey || endpoint) {
|
|
2729
3244
|
console.warn(
|
|
@@ -2767,7 +3282,7 @@ function createTracking(options) {
|
|
|
2767
3282
|
[]
|
|
2768
3283
|
);
|
|
2769
3284
|
const conversionStore = useMemo2(
|
|
2770
|
-
() => conversionConfig ? resolveConversionConfig({
|
|
3285
|
+
() => trackingConfig ? getTrackingConfigRuntime(trackingConfig) : conversionConfig ? resolveConversionConfig({
|
|
2771
3286
|
cdnUrl: conversionConfig.cdnUrl,
|
|
2772
3287
|
baked: conversionConfig.baked
|
|
2773
3288
|
}) : null,
|
|
@@ -2789,9 +3304,10 @@ function createTracking(options) {
|
|
|
2789
3304
|
debug
|
|
2790
3305
|
});
|
|
2791
3306
|
fireManualPageView(wrapClient(rawClient));
|
|
3307
|
+
if (trackingConfig) getTrackingConfigRuntime(trackingConfig).queuePageView();
|
|
2792
3308
|
}, [wrapClient]);
|
|
2793
3309
|
const firedPagesRef = useRef(/* @__PURE__ */ new Set());
|
|
2794
|
-
|
|
3310
|
+
useEffect4(() => {
|
|
2795
3311
|
if (!specificPageVisitConfig || pathname === null) return;
|
|
2796
3312
|
const rawClient = getOrCreateTrackingClient({
|
|
2797
3313
|
apiKey,
|
|
@@ -2822,7 +3338,7 @@ function createTracking(options) {
|
|
|
2822
3338
|
}, [pathname]);
|
|
2823
3339
|
const multiPageSessionConfig = triggers.automatic.multi_page_session ?? null;
|
|
2824
3340
|
const mpsLastPathRef = useRef(null);
|
|
2825
|
-
|
|
3341
|
+
useEffect4(() => {
|
|
2826
3342
|
if (!multiPageSessionConfig || pathname === null) return;
|
|
2827
3343
|
if (pathname === mpsLastPathRef.current) return;
|
|
2828
3344
|
mpsLastPathRef.current = pathname;
|
|
@@ -2869,7 +3385,7 @@ function createTracking(options) {
|
|
|
2869
3385
|
} catch {
|
|
2870
3386
|
}
|
|
2871
3387
|
}, [pathname]);
|
|
2872
|
-
|
|
3388
|
+
useEffect4(() => {
|
|
2873
3389
|
const rawClient = getOrCreateTrackingClient({
|
|
2874
3390
|
apiKey,
|
|
2875
3391
|
endpoint,
|
|
@@ -2933,6 +3449,7 @@ export {
|
|
|
2933
3449
|
ConsentBanner,
|
|
2934
3450
|
DEFAULT_DECLINE_TTL_DAYS,
|
|
2935
3451
|
DEFAULT_PHONE_COUNTRY,
|
|
3452
|
+
EVENT_SEMANTICS,
|
|
2936
3453
|
GoogleAdsTracking,
|
|
2937
3454
|
NAMED_RANGES,
|
|
2938
3455
|
PhoneField,
|
|
@@ -2953,6 +3470,8 @@ export {
|
|
|
2953
3470
|
fromMinor,
|
|
2954
3471
|
getConsentChoice,
|
|
2955
3472
|
getConsentState,
|
|
3473
|
+
getEventSemantics,
|
|
3474
|
+
getTrackingConfigRuntime,
|
|
2956
3475
|
onConsentChange,
|
|
2957
3476
|
optIn,
|
|
2958
3477
|
optOut,
|