@journium/react 1.1.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -13,14 +13,37 @@ interface JourniumProviderProps {
13
13
  children: ReactNode;
14
14
  config: JourniumConfig;
15
15
  }
16
+ /**
17
+ * Provides the Journium analytics instance to the React tree.
18
+ * Initializes the SDK on mount and tears it down on unmount.
19
+ * Re-initializes if `config` changes.
20
+ */
16
21
  declare const JourniumProvider: React$1.FC<JourniumProviderProps>;
22
+ /**
23
+ * Access the Journium analytics instance and effective options from any component
24
+ * inside `JourniumProvider`. Throws if called outside the provider.
25
+ */
17
26
  declare const useJournium: () => JourniumContextValue;
18
27
 
28
+ /** Returns a stable callback for tracking custom events. */
19
29
  declare const useTrackEvent: () => (event: string, properties?: Record<string, unknown>) => void;
30
+ /** Returns a stable callback for identifying the current user. */
20
31
  declare const useIdentify: () => (distinctId: string, attributes?: Record<string, unknown>) => void;
32
+ /** Returns a stable callback for resetting the current identity and starting a new anonymous session. */
21
33
  declare const useReset: () => () => void;
34
+ /** Returns a stable callback for manually capturing a $pageview event. */
22
35
  declare const useTrackPageview: () => (properties?: Record<string, unknown>) => void;
36
+ /**
37
+ * Automatically captures a $pageview whenever the given dependencies change.
38
+ * Also fires once on mount. Useful for manual SPA route tracking when automatic
39
+ * tracking is disabled.
40
+ */
23
41
  declare const useAutoTrackPageview: (dependencies?: React.DependencyList, properties?: Record<string, unknown>) => void;
42
+ /**
43
+ * Returns `stopAutocapture` to pause DOM event capture and pageview tracking.
44
+ * `startAutocapture` is also exposed for restarting after an explicit stop,
45
+ * but under normal usage autocapture starts automatically on SDK init.
46
+ */
24
47
  declare const useAutocapture: () => {
25
48
  startAutocapture: () => void;
26
49
  stopAutocapture: () => void;
package/dist/index.mjs CHANGED
@@ -1102,28 +1102,31 @@ class PageviewTracker {
1102
1102
  * Start automatic autocapture for pageviews
1103
1103
  * @param captureInitialPageview - whether to fire a $pageview immediately on start (default: true).
1104
1104
  * Pass false when restarting after a remote options update to avoid a spurious pageview.
1105
+ * @param patchHistory - whether to monkey-patch pushState/replaceState/popstate (default: true).
1106
+ * Pass false when a framework-native router tracker (e.g. Next.js) owns SPA pageviews.
1105
1107
  */
1106
- startAutoPageviewTracking(captureInitialPageview = true) {
1108
+ startAutoPageviewTracking(captureInitialPageview = true, patchHistory = true) {
1107
1109
  if (captureInitialPageview) {
1108
1110
  this.capturePageview();
1109
1111
  }
1110
- if (typeof window !== 'undefined') {
1111
- // Store original methods for cleanup
1112
- this.originalPushState = window.history.pushState;
1113
- this.originalReplaceState = window.history.replaceState;
1114
- window.history.pushState = (...args) => {
1115
- this.originalPushState.apply(window.history, args);
1116
- setTimeout(() => this.capturePageview(), 0);
1117
- };
1118
- window.history.replaceState = (...args) => {
1119
- this.originalReplaceState.apply(window.history, args);
1120
- setTimeout(() => this.capturePageview(), 0);
1121
- };
1122
- this.popStateHandler = () => {
1123
- setTimeout(() => this.capturePageview(), 0);
1124
- };
1125
- window.addEventListener('popstate', this.popStateHandler);
1112
+ if (!patchHistory || typeof window === 'undefined') {
1113
+ return;
1126
1114
  }
1115
+ // Store original methods for cleanup
1116
+ this.originalPushState = window.history.pushState;
1117
+ this.originalReplaceState = window.history.replaceState;
1118
+ window.history.pushState = (...args) => {
1119
+ this.originalPushState.apply(window.history, args);
1120
+ setTimeout(() => this.capturePageview(), 0);
1121
+ };
1122
+ window.history.replaceState = (...args) => {
1123
+ this.originalReplaceState.apply(window.history, args);
1124
+ setTimeout(() => this.capturePageview(), 0);
1125
+ };
1126
+ this.popStateHandler = () => {
1127
+ setTimeout(() => this.capturePageview(), 0);
1128
+ };
1129
+ window.addEventListener('popstate', this.popStateHandler);
1127
1130
  }
1128
1131
  /**
1129
1132
  * Stop automatic autocapture for pageviews
@@ -1538,6 +1541,20 @@ class JourniumAnalytics {
1538
1541
  // This handles cached remote options or local options with autocapture enabled
1539
1542
  this.startAutocaptureIfEnabled(initialEffectiveOptions);
1540
1543
  }
1544
+ resolvePageviewOptions(autoTrackPageviews) {
1545
+ if (autoTrackPageviews === false) {
1546
+ return { enabled: false, trackSpaPageviews: false, captureInitialPageview: false };
1547
+ }
1548
+ if (autoTrackPageviews === true || autoTrackPageviews === undefined) {
1549
+ return { enabled: true, trackSpaPageviews: true, captureInitialPageview: true };
1550
+ }
1551
+ // object form implies enabled
1552
+ return {
1553
+ enabled: true,
1554
+ trackSpaPageviews: autoTrackPageviews.trackSpaPageviews !== false,
1555
+ captureInitialPageview: autoTrackPageviews.trackInitialPageview !== false,
1556
+ };
1557
+ }
1541
1558
  resolveAutocaptureOptions(autocapture) {
1542
1559
  if (autocapture === false) {
1543
1560
  return {
@@ -1552,39 +1569,50 @@ class JourniumAnalytics {
1552
1569
  }
1553
1570
  return autocapture;
1554
1571
  }
1572
+ /** Track a custom event with optional properties. */
1555
1573
  track(event, properties) {
1556
1574
  this.client.track(event, properties);
1557
1575
  }
1576
+ /** Associate the current session with a known user identity and optional attributes. */
1558
1577
  identify(distinctId, attributes) {
1559
1578
  this.client.identify(distinctId, attributes);
1560
1579
  }
1580
+ /** Clear the current identity, starting a new anonymous session. */
1561
1581
  reset() {
1562
1582
  this.client.reset();
1563
1583
  }
1584
+ /** Manually capture a $pageview event with optional custom properties. */
1564
1585
  capturePageview(properties) {
1565
1586
  this.pageviewTracker.capturePageview(properties);
1566
1587
  }
1588
+ /**
1589
+ * Manually start autocapture (pageview tracking + DOM event capture).
1590
+ * Under normal usage this is not needed — the SDK starts automatically on init.
1591
+ * Useful only if autocapture was explicitly stopped and needs to be restarted.
1592
+ */
1567
1593
  startAutocapture() {
1568
1594
  // Always check effective options (which may include remote options)
1569
1595
  const effectiveOptions = this.client.getEffectiveOptions();
1570
- // Only enable if effectiveOptions are loaded and autoTrackPageviews is not explicitly false
1571
- const autoTrackPageviews = effectiveOptions && Object.keys(effectiveOptions).length > 0
1572
- ? effectiveOptions.autoTrackPageviews !== false
1573
- : false;
1574
- const autocaptureEnabled = effectiveOptions && Object.keys(effectiveOptions).length > 0
1596
+ // Only start if effectiveOptions are actually loaded (non-empty)
1597
+ const hasOptions = effectiveOptions && Object.keys(effectiveOptions).length > 0;
1598
+ const { enabled: autoTrackPageviews, trackSpaPageviews, captureInitialPageview } = hasOptions
1599
+ ? this.resolvePageviewOptions(effectiveOptions.autoTrackPageviews)
1600
+ : { enabled: false, trackSpaPageviews: false, captureInitialPageview: false };
1601
+ const autocaptureEnabled = hasOptions
1575
1602
  ? effectiveOptions.autocapture !== false
1576
1603
  : false;
1577
1604
  // Update autocapture tracker options if they've changed
1578
1605
  const autocaptureOptions = this.resolveAutocaptureOptions(effectiveOptions.autocapture);
1579
1606
  this.autocaptureTracker.updateOptions(autocaptureOptions);
1580
1607
  if (autoTrackPageviews) {
1581
- this.pageviewTracker.startAutoPageviewTracking();
1608
+ this.pageviewTracker.startAutoPageviewTracking(captureInitialPageview, trackSpaPageviews);
1582
1609
  }
1583
1610
  if (autocaptureEnabled) {
1584
1611
  this.autocaptureTracker.start();
1585
1612
  }
1586
1613
  this.autocaptureStarted = true;
1587
1614
  }
1615
+ /** Stop autocapture — pauses pageview tracking and DOM event capture. */
1588
1616
  stopAutocapture() {
1589
1617
  this.pageviewTracker.stopAutocapture();
1590
1618
  this.autocaptureTracker.stop();
@@ -1604,13 +1632,13 @@ class JourniumAnalytics {
1604
1632
  const hasActualOptions = effectiveOptions && Object.keys(effectiveOptions).length > 0;
1605
1633
  if (hasActualOptions) {
1606
1634
  // Use same logic as manual startAutocapture() but only start automatically
1607
- const autoTrackPageviews = effectiveOptions.autoTrackPageviews !== false;
1635
+ const { enabled: autoTrackPageviews, trackSpaPageviews, captureInitialPageview } = this.resolvePageviewOptions(effectiveOptions.autoTrackPageviews);
1608
1636
  const autocaptureEnabled = effectiveOptions.autocapture !== false;
1609
1637
  // Update autocapture tracker options
1610
1638
  const autocaptureOptions = this.resolveAutocaptureOptions(effectiveOptions.autocapture);
1611
1639
  this.autocaptureTracker.updateOptions(autocaptureOptions);
1612
1640
  if (autoTrackPageviews) {
1613
- this.pageviewTracker.startAutoPageviewTracking();
1641
+ this.pageviewTracker.startAutoPageviewTracking(captureInitialPageview, trackSpaPageviews);
1614
1642
  }
1615
1643
  if (autocaptureEnabled) {
1616
1644
  this.autocaptureTracker.start();
@@ -1635,21 +1663,23 @@ class JourniumAnalytics {
1635
1663
  this.autocaptureTracker.stop();
1636
1664
  this.autocaptureStarted = false;
1637
1665
  }
1638
- const autoTrackPageviews = effectiveOptions.autoTrackPageviews !== false;
1666
+ const { enabled: autoTrackPageviews, trackSpaPageviews, captureInitialPageview } = this.resolvePageviewOptions(effectiveOptions.autoTrackPageviews);
1639
1667
  const autocaptureEnabled = effectiveOptions.autocapture !== false;
1640
1668
  const autocaptureOptions = this.resolveAutocaptureOptions(effectiveOptions.autocapture);
1641
1669
  this.autocaptureTracker.updateOptions(autocaptureOptions);
1642
1670
  if (autoTrackPageviews) {
1643
- this.pageviewTracker.startAutoPageviewTracking(isFirstStart);
1671
+ this.pageviewTracker.startAutoPageviewTracking(isFirstStart && captureInitialPageview, trackSpaPageviews);
1644
1672
  }
1645
1673
  if (autocaptureEnabled) {
1646
1674
  this.autocaptureTracker.start();
1647
1675
  }
1648
1676
  this.autocaptureStarted = autoTrackPageviews || autocaptureEnabled;
1649
1677
  }
1678
+ /** Flush all queued events to the ingestion endpoint immediately. */
1650
1679
  async flush() {
1651
1680
  return this.client.flush();
1652
1681
  }
1682
+ /** Return the currently active options (merged local + remote config). */
1653
1683
  getEffectiveOptions() {
1654
1684
  return this.client.getEffectiveOptions();
1655
1685
  }
@@ -1659,6 +1689,7 @@ class JourniumAnalytics {
1659
1689
  onOptionsChange(callback) {
1660
1690
  return this.client.onOptionsChange(callback);
1661
1691
  }
1692
+ /** Tear down the analytics instance: stop all tracking, flush pending events, and release resources. */
1662
1693
  destroy() {
1663
1694
  this.pageviewTracker.stopAutocapture();
1664
1695
  this.autocaptureTracker.stop();
@@ -1668,11 +1699,17 @@ class JourniumAnalytics {
1668
1699
  this.client.destroy();
1669
1700
  }
1670
1701
  }
1702
+ /** Create and return a new JourniumAnalytics instance for the given config. */
1671
1703
  const init = (config) => {
1672
1704
  return new JourniumAnalytics(config);
1673
1705
  };
1674
1706
 
1675
1707
  const JourniumContext = createContext(undefined);
1708
+ /**
1709
+ * Provides the Journium analytics instance to the React tree.
1710
+ * Initializes the SDK on mount and tears it down on unmount.
1711
+ * Re-initializes if `config` changes.
1712
+ */
1676
1713
  const JourniumProvider = ({ children, config, }) => {
1677
1714
  const [analytics, setAnalytics] = useState(null);
1678
1715
  const [effectiveOptions, setEffectiveOptions] = useState(null);
@@ -1700,6 +1737,10 @@ const JourniumProvider = ({ children, config, }) => {
1700
1737
  }, [config]);
1701
1738
  return (React.createElement(JourniumContext.Provider, { value: { analytics, config, effectiveOptions } }, children));
1702
1739
  };
1740
+ /**
1741
+ * Access the Journium analytics instance and effective options from any component
1742
+ * inside `JourniumProvider`. Throws if called outside the provider.
1743
+ */
1703
1744
  const useJournium = () => {
1704
1745
  const context = useContext(JourniumContext);
1705
1746
  if (!context) {
@@ -1708,6 +1749,7 @@ const useJournium = () => {
1708
1749
  return context;
1709
1750
  };
1710
1751
 
1752
+ /** Returns a stable callback for tracking custom events. */
1711
1753
  const useTrackEvent = () => {
1712
1754
  const { analytics } = useJournium();
1713
1755
  return useCallback((event, properties) => {
@@ -1716,6 +1758,7 @@ const useTrackEvent = () => {
1716
1758
  }
1717
1759
  }, [analytics]);
1718
1760
  };
1761
+ /** Returns a stable callback for identifying the current user. */
1719
1762
  const useIdentify = () => {
1720
1763
  const { analytics } = useJournium();
1721
1764
  return useCallback((distinctId, attributes) => {
@@ -1724,6 +1767,7 @@ const useIdentify = () => {
1724
1767
  }
1725
1768
  }, [analytics]);
1726
1769
  };
1770
+ /** Returns a stable callback for resetting the current identity and starting a new anonymous session. */
1727
1771
  const useReset = () => {
1728
1772
  const { analytics } = useJournium();
1729
1773
  return useCallback(() => {
@@ -1732,6 +1776,7 @@ const useReset = () => {
1732
1776
  }
1733
1777
  }, [analytics]);
1734
1778
  };
1779
+ /** Returns a stable callback for manually capturing a $pageview event. */
1735
1780
  const useTrackPageview = () => {
1736
1781
  const { analytics } = useJournium();
1737
1782
  return useCallback((properties) => {
@@ -1740,12 +1785,22 @@ const useTrackPageview = () => {
1740
1785
  }
1741
1786
  }, [analytics]);
1742
1787
  };
1788
+ /**
1789
+ * Automatically captures a $pageview whenever the given dependencies change.
1790
+ * Also fires once on mount. Useful for manual SPA route tracking when automatic
1791
+ * tracking is disabled.
1792
+ */
1743
1793
  const useAutoTrackPageview = (dependencies = [], properties) => {
1744
1794
  const trackPageview = useTrackPageview();
1745
1795
  useEffect(() => {
1746
1796
  trackPageview(properties);
1747
1797
  }, [trackPageview, properties, ...dependencies]);
1748
1798
  };
1799
+ /**
1800
+ * Returns `stopAutocapture` to pause DOM event capture and pageview tracking.
1801
+ * `startAutocapture` is also exposed for restarting after an explicit stop,
1802
+ * but under normal usage autocapture starts automatically on SDK init.
1803
+ */
1749
1804
  const useAutocapture = () => {
1750
1805
  const { analytics } = useJournium();
1751
1806
  const startAutocapture = useCallback(() => {