@aranova/tracking-next 0.17.2 → 0.17.3
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 +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +132 -61
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +128 -57
- package/dist/index.mjs.map +1 -1
- package/dist/middleware.js +8 -0
- package/dist/middleware.js.map +1 -1
- package/dist/middleware.mjs +8 -0
- package/dist/middleware.mjs.map +1 -1
- package/dist/phone.js +8 -0
- package/dist/phone.js.map +1 -1
- package/dist/phone.mjs +8 -0
- package/dist/phone.mjs.map +1 -1
- package/dist/server.js +8 -0
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +8 -0
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -598,9 +598,9 @@ function resolveConversionConfig(options) {
|
|
|
598
598
|
}
|
|
599
599
|
}
|
|
600
600
|
function notifyResolved() {
|
|
601
|
-
const
|
|
601
|
+
const listeners2 = [...resolveListeners];
|
|
602
602
|
resolveListeners.clear();
|
|
603
|
-
for (const listener of
|
|
603
|
+
for (const listener of listeners2) {
|
|
604
604
|
try {
|
|
605
605
|
listener();
|
|
606
606
|
} catch {
|
|
@@ -1330,6 +1330,14 @@ var pageExitMetadataSchema = z7.object({
|
|
|
1330
1330
|
// null = left without any scroll signal; floor is 0 so a valid 0% is never
|
|
1331
1331
|
// rejected (a single bad field 422s the whole keepalive beacon batch).
|
|
1332
1332
|
max_scroll_percent: z7.number().int().min(0).max(100).nullable(),
|
|
1333
|
+
// The gating baseline: the fraction of the page visible at load with
|
|
1334
|
+
// zero scrolling — or, for pages that grew after the post-paint snapshot
|
|
1335
|
+
// (skeleton/streaming renders), the first-scroll position that
|
|
1336
|
+
// established it. null = page had no scrollable range, or the segment
|
|
1337
|
+
// ended before the snapshot. `.optional()` is load-bearing: SDK builds
|
|
1338
|
+
// predating this field keep POSTing page_exit without the key —
|
|
1339
|
+
// requiring it would 422 whole keepalive beacon batches.
|
|
1340
|
+
scroll_baseline_percent: z7.number().int().min(0).max(100).nullable().optional(),
|
|
1333
1341
|
page: z7.object({
|
|
1334
1342
|
path: z7.string()
|
|
1335
1343
|
}).strict()
|
|
@@ -1554,6 +1562,97 @@ function attachTimeOnSite(client, config) {
|
|
|
1554
1562
|
};
|
|
1555
1563
|
}
|
|
1556
1564
|
|
|
1565
|
+
// ../tracking-core/src/triggers/navigation.ts
|
|
1566
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
1567
|
+
var restorePatch = null;
|
|
1568
|
+
function notify() {
|
|
1569
|
+
for (const listener of listeners) listener();
|
|
1570
|
+
}
|
|
1571
|
+
function notifyDeferred() {
|
|
1572
|
+
setTimeout(notify, 0);
|
|
1573
|
+
}
|
|
1574
|
+
function installPatch() {
|
|
1575
|
+
const originalPushState = history.pushState;
|
|
1576
|
+
const originalReplaceState = history.replaceState;
|
|
1577
|
+
function patchedPushState(...args) {
|
|
1578
|
+
originalPushState.apply(this, args);
|
|
1579
|
+
notifyDeferred();
|
|
1580
|
+
}
|
|
1581
|
+
function patchedReplaceState(...args) {
|
|
1582
|
+
originalReplaceState.apply(this, args);
|
|
1583
|
+
notifyDeferred();
|
|
1584
|
+
}
|
|
1585
|
+
history.pushState = patchedPushState;
|
|
1586
|
+
history.replaceState = patchedReplaceState;
|
|
1587
|
+
window.addEventListener("popstate", notify);
|
|
1588
|
+
restorePatch = () => {
|
|
1589
|
+
history.pushState = originalPushState;
|
|
1590
|
+
history.replaceState = originalReplaceState;
|
|
1591
|
+
window.removeEventListener("popstate", notify);
|
|
1592
|
+
restorePatch = null;
|
|
1593
|
+
};
|
|
1594
|
+
}
|
|
1595
|
+
function onHistoryChange(listener) {
|
|
1596
|
+
if (listeners.size === 0) installPatch();
|
|
1597
|
+
listeners.add(listener);
|
|
1598
|
+
return () => {
|
|
1599
|
+
if (!listeners.delete(listener)) return;
|
|
1600
|
+
if (listeners.size === 0) restorePatch?.();
|
|
1601
|
+
};
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
// ../tracking-core/src/triggers/scroll-measurement.ts
|
|
1605
|
+
var BOTTOM_EPSILON_PX = 2;
|
|
1606
|
+
function measureScrollPercent() {
|
|
1607
|
+
const root = document.scrollingElement ?? document.documentElement;
|
|
1608
|
+
const scrollHeight = root.scrollHeight;
|
|
1609
|
+
const clientHeight = root.clientHeight;
|
|
1610
|
+
if (scrollHeight <= 0 || clientHeight <= 0) return null;
|
|
1611
|
+
if (scrollHeight <= clientHeight + BOTTOM_EPSILON_PX) return null;
|
|
1612
|
+
const maxTop = scrollHeight - clientHeight;
|
|
1613
|
+
const scrollTop = Math.min(Math.max(root.scrollTop, 0), maxTop);
|
|
1614
|
+
if (scrollTop + clientHeight >= scrollHeight - BOTTOM_EPSILON_PX) return 100;
|
|
1615
|
+
return Math.max(1, Math.min(100, Math.round((scrollTop + clientHeight) / scrollHeight * 100)));
|
|
1616
|
+
}
|
|
1617
|
+
function scheduleBaselineSnapshot(onSnapshot) {
|
|
1618
|
+
let rafId = requestAnimationFrame(() => {
|
|
1619
|
+
rafId = requestAnimationFrame(() => {
|
|
1620
|
+
onSnapshot(measureScrollPercent());
|
|
1621
|
+
});
|
|
1622
|
+
});
|
|
1623
|
+
return () => cancelAnimationFrame(rafId);
|
|
1624
|
+
}
|
|
1625
|
+
function createBaselineGate() {
|
|
1626
|
+
let baselinePercent = null;
|
|
1627
|
+
let ready = false;
|
|
1628
|
+
let cancelSnapshot = null;
|
|
1629
|
+
return {
|
|
1630
|
+
rebaseline() {
|
|
1631
|
+
cancelSnapshot?.();
|
|
1632
|
+
ready = false;
|
|
1633
|
+
baselinePercent = null;
|
|
1634
|
+
cancelSnapshot = scheduleBaselineSnapshot((b) => {
|
|
1635
|
+
baselinePercent = b;
|
|
1636
|
+
ready = true;
|
|
1637
|
+
});
|
|
1638
|
+
},
|
|
1639
|
+
cancel() {
|
|
1640
|
+
cancelSnapshot?.();
|
|
1641
|
+
},
|
|
1642
|
+
baseline() {
|
|
1643
|
+
return ready ? baselinePercent : null;
|
|
1644
|
+
},
|
|
1645
|
+
sample() {
|
|
1646
|
+
if (!ready) return null;
|
|
1647
|
+
if (baselinePercent === null) {
|
|
1648
|
+
baselinePercent = measureScrollPercent();
|
|
1649
|
+
return null;
|
|
1650
|
+
}
|
|
1651
|
+
return measureScrollPercent();
|
|
1652
|
+
}
|
|
1653
|
+
};
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1557
1656
|
// ../tracking-core/src/triggers/scroll-depth.ts
|
|
1558
1657
|
function attachScrollDepth(client, config) {
|
|
1559
1658
|
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
@@ -1564,17 +1663,14 @@ function attachScrollDepth(client, config) {
|
|
|
1564
1663
|
let firedForPath = /* @__PURE__ */ new Set();
|
|
1565
1664
|
let currentPath2 = window.location.pathname;
|
|
1566
1665
|
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
|
-
}
|
|
1666
|
+
const gate = createBaselineGate();
|
|
1575
1667
|
function checkThresholds() {
|
|
1576
|
-
const percent =
|
|
1668
|
+
const percent = gate.sample();
|
|
1669
|
+
if (percent === null) return;
|
|
1670
|
+
const baseline = gate.baseline();
|
|
1671
|
+
if (baseline === null) return;
|
|
1577
1672
|
for (const threshold of thresholds) {
|
|
1673
|
+
if (threshold <= baseline) continue;
|
|
1578
1674
|
if (percent >= threshold && !firedForPath.has(threshold)) {
|
|
1579
1675
|
firedForPath.add(threshold);
|
|
1580
1676
|
client.trackEvent({
|
|
@@ -1601,28 +1697,15 @@ function attachScrollDepth(client, config) {
|
|
|
1601
1697
|
if (newPath === currentPath2) return;
|
|
1602
1698
|
currentPath2 = newPath;
|
|
1603
1699
|
firedForPath = /* @__PURE__ */ new Set();
|
|
1604
|
-
|
|
1700
|
+
gate.rebaseline();
|
|
1605
1701
|
}
|
|
1606
|
-
const
|
|
1607
|
-
const originalReplaceState = history.replaceState.bind(history);
|
|
1608
|
-
function patchedPushState(...args) {
|
|
1609
|
-
originalPushState(...args);
|
|
1610
|
-
setTimeout(resetIfPathChanged, 0);
|
|
1611
|
-
}
|
|
1612
|
-
function patchedReplaceState(...args) {
|
|
1613
|
-
originalReplaceState(...args);
|
|
1614
|
-
setTimeout(resetIfPathChanged, 0);
|
|
1615
|
-
}
|
|
1616
|
-
history.pushState = patchedPushState;
|
|
1617
|
-
history.replaceState = patchedReplaceState;
|
|
1618
|
-
window.addEventListener("popstate", resetIfPathChanged);
|
|
1702
|
+
const unsubscribeNav = onHistoryChange(resetIfPathChanged);
|
|
1619
1703
|
window.addEventListener("scroll", onScroll, { passive: true });
|
|
1620
|
-
|
|
1704
|
+
gate.rebaseline();
|
|
1621
1705
|
return () => {
|
|
1622
1706
|
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
window.removeEventListener("popstate", resetIfPathChanged);
|
|
1707
|
+
gate.cancel();
|
|
1708
|
+
unsubscribeNav();
|
|
1626
1709
|
window.removeEventListener("scroll", onScroll);
|
|
1627
1710
|
};
|
|
1628
1711
|
}
|
|
@@ -1704,21 +1787,14 @@ function attachPageExit(client) {
|
|
|
1704
1787
|
let accumulatedMs = 0;
|
|
1705
1788
|
let maxScrollPercent = null;
|
|
1706
1789
|
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
|
-
}
|
|
1790
|
+
const gate = createBaselineGate();
|
|
1715
1791
|
function onScroll() {
|
|
1716
1792
|
if (rafId !== null) return;
|
|
1717
1793
|
rafId = requestAnimationFrame(() => {
|
|
1718
1794
|
rafId = null;
|
|
1719
|
-
const percent =
|
|
1720
|
-
if (percent
|
|
1721
|
-
maxScrollPercent =
|
|
1795
|
+
const percent = gate.sample();
|
|
1796
|
+
if (percent !== null && (maxScrollPercent === null || percent > maxScrollPercent)) {
|
|
1797
|
+
maxScrollPercent = percent;
|
|
1722
1798
|
}
|
|
1723
1799
|
});
|
|
1724
1800
|
}
|
|
@@ -1737,6 +1813,12 @@ function attachPageExit(client) {
|
|
|
1737
1813
|
metadata: {
|
|
1738
1814
|
dwell_ms: dwell,
|
|
1739
1815
|
max_scroll_percent: maxScrollPercent,
|
|
1816
|
+
// Lets the backend tell "scrolled to the bottom" apart from "the page
|
|
1817
|
+
// was barely scrollable". null = unscrollable page or the segment
|
|
1818
|
+
// ended before the post-paint snapshot landed. For pages that grew
|
|
1819
|
+
// after the snapshot this is the first-scroll position, not the
|
|
1820
|
+
// at-load fraction (see BaselineGate.baseline).
|
|
1821
|
+
scroll_baseline_percent: gate.baseline(),
|
|
1740
1822
|
page: { path }
|
|
1741
1823
|
},
|
|
1742
1824
|
pageUrl: window.location.href,
|
|
@@ -1754,6 +1836,7 @@ function attachPageExit(client) {
|
|
|
1754
1836
|
emitSegment(currentPath2, false);
|
|
1755
1837
|
currentPath2 = newPath;
|
|
1756
1838
|
maxScrollPercent = null;
|
|
1839
|
+
gate.rebaseline();
|
|
1757
1840
|
accumulatedMs = 0;
|
|
1758
1841
|
activeSince = document.visibilityState === "visible" ? Date.now() : null;
|
|
1759
1842
|
}
|
|
@@ -1767,27 +1850,15 @@ function attachPageExit(client) {
|
|
|
1767
1850
|
function onPageHide() {
|
|
1768
1851
|
emitSegment(currentPath2, true);
|
|
1769
1852
|
}
|
|
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);
|
|
1853
|
+
const unsubscribeNav = onHistoryChange(onNavigate);
|
|
1783
1854
|
window.addEventListener("scroll", onScroll, { passive: true });
|
|
1784
1855
|
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
1785
1856
|
window.addEventListener("pagehide", onPageHide);
|
|
1857
|
+
gate.rebaseline();
|
|
1786
1858
|
return () => {
|
|
1787
1859
|
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
window.removeEventListener("popstate", onNavigate);
|
|
1860
|
+
gate.cancel();
|
|
1861
|
+
unsubscribeNav();
|
|
1791
1862
|
window.removeEventListener("scroll", onScroll);
|
|
1792
1863
|
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
1793
1864
|
window.removeEventListener("pagehide", onPageHide);
|
|
@@ -2606,7 +2677,7 @@ function GoogleAdsTracking(props) {
|
|
|
2606
2677
|
import { usePathname, useSearchParams } from "next/navigation";
|
|
2607
2678
|
|
|
2608
2679
|
// package.json
|
|
2609
|
-
var version = "0.17.
|
|
2680
|
+
var version = "0.17.3";
|
|
2610
2681
|
|
|
2611
2682
|
// src/factory.tsx
|
|
2612
2683
|
import {
|