@loamly/tracker 2.0.2 → 2.1.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.mts CHANGED
@@ -77,6 +77,30 @@ interface LoamlyConfig {
77
77
  disableBehavioral?: boolean;
78
78
  /** Custom session timeout in milliseconds (default: 30 minutes) */
79
79
  sessionTimeout?: number;
80
+ /**
81
+ * Feature flags for lightweight mode
82
+ * Set to false to reduce initialization overhead
83
+ */
84
+ features?: {
85
+ /** Scroll depth tracking (default: true) */
86
+ scroll?: boolean;
87
+ /** Time on page tracking (default: true) */
88
+ time?: boolean;
89
+ /** Form interaction tracking (default: true) */
90
+ forms?: boolean;
91
+ /** SPA navigation support (default: true) */
92
+ spa?: boolean;
93
+ /** Behavioral ML classification (default: true) */
94
+ behavioralML?: boolean;
95
+ /** Focus/blur paste detection (default: true) */
96
+ focusBlur?: boolean;
97
+ /** Agentic browser detection (default: true) */
98
+ agentic?: boolean;
99
+ /** Event queue with retry (default: true) */
100
+ eventQueue?: boolean;
101
+ /** Heartbeat ping service (default: false - opt-in) */
102
+ ping?: boolean;
103
+ };
80
104
  }
81
105
  interface TrackEventOptions {
82
106
  /** Custom properties to attach to the event */
@@ -246,7 +270,7 @@ declare function detectAIFromUTM(url: string): AIDetectionResult | null;
246
270
  * @license MIT
247
271
  * @see https://github.com/loamly/loamly
248
272
  */
249
- declare const VERSION = "2.0.2";
273
+ declare const VERSION = "2.1.0";
250
274
  /**
251
275
  * Known AI platforms for referrer detection
252
276
  */
package/dist/index.d.ts CHANGED
@@ -77,6 +77,30 @@ interface LoamlyConfig {
77
77
  disableBehavioral?: boolean;
78
78
  /** Custom session timeout in milliseconds (default: 30 minutes) */
79
79
  sessionTimeout?: number;
80
+ /**
81
+ * Feature flags for lightweight mode
82
+ * Set to false to reduce initialization overhead
83
+ */
84
+ features?: {
85
+ /** Scroll depth tracking (default: true) */
86
+ scroll?: boolean;
87
+ /** Time on page tracking (default: true) */
88
+ time?: boolean;
89
+ /** Form interaction tracking (default: true) */
90
+ forms?: boolean;
91
+ /** SPA navigation support (default: true) */
92
+ spa?: boolean;
93
+ /** Behavioral ML classification (default: true) */
94
+ behavioralML?: boolean;
95
+ /** Focus/blur paste detection (default: true) */
96
+ focusBlur?: boolean;
97
+ /** Agentic browser detection (default: true) */
98
+ agentic?: boolean;
99
+ /** Event queue with retry (default: true) */
100
+ eventQueue?: boolean;
101
+ /** Heartbeat ping service (default: false - opt-in) */
102
+ ping?: boolean;
103
+ };
80
104
  }
81
105
  interface TrackEventOptions {
82
106
  /** Custom properties to attach to the event */
@@ -246,7 +270,7 @@ declare function detectAIFromUTM(url: string): AIDetectionResult | null;
246
270
  * @license MIT
247
271
  * @see https://github.com/loamly/loamly
248
272
  */
249
- declare const VERSION = "2.0.2";
273
+ declare const VERSION = "2.1.0";
250
274
  /**
251
275
  * Known AI platforms for referrer detection
252
276
  */
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/config.ts
2
- var VERSION = "2.0.2";
2
+ var VERSION = "2.1.0";
3
3
  var DEFAULT_CONFIG = {
4
4
  apiHost: "https://app.loamly.ai",
5
5
  endpoints: {
@@ -1770,16 +1770,32 @@ function init(userConfig = {}) {
1770
1770
  apiHost: userConfig.apiHost || DEFAULT_CONFIG.apiHost
1771
1771
  };
1772
1772
  debugMode = userConfig.debug ?? false;
1773
+ const features = {
1774
+ scroll: true,
1775
+ time: true,
1776
+ forms: true,
1777
+ spa: true,
1778
+ behavioralML: true,
1779
+ focusBlur: true,
1780
+ agentic: true,
1781
+ eventQueue: true,
1782
+ ping: false,
1783
+ // Opt-in only
1784
+ ...userConfig.features
1785
+ };
1773
1786
  log("Initializing Loamly Tracker v" + VERSION);
1787
+ log("Features:", features);
1774
1788
  visitorId = getVisitorId();
1775
1789
  log("Visitor ID:", visitorId);
1776
1790
  const session = getSessionId();
1777
1791
  sessionId = session.sessionId;
1778
1792
  log("Session ID:", sessionId, session.isNew ? "(new)" : "(existing)");
1779
- eventQueue = new EventQueue(endpoint(DEFAULT_CONFIG.endpoints.behavioral), {
1780
- batchSize: DEFAULT_CONFIG.batchSize,
1781
- batchTimeout: DEFAULT_CONFIG.batchTimeout
1782
- });
1793
+ if (features.eventQueue) {
1794
+ eventQueue = new EventQueue(endpoint(DEFAULT_CONFIG.endpoints.behavioral), {
1795
+ batchSize: DEFAULT_CONFIG.batchSize,
1796
+ batchTimeout: DEFAULT_CONFIG.batchTimeout
1797
+ });
1798
+ }
1783
1799
  navigationTiming = detectNavigationType();
1784
1800
  log("Navigation timing:", navigationTiming);
1785
1801
  aiDetection = detectAIFromReferrer(document.referrer) || detectAIFromUTM(window.location.href);
@@ -1791,21 +1807,27 @@ function init(userConfig = {}) {
1791
1807
  pageview();
1792
1808
  }
1793
1809
  if (!userConfig.disableBehavioral) {
1794
- setupAdvancedBehavioralTracking();
1810
+ setupAdvancedBehavioralTracking(features);
1811
+ }
1812
+ if (features.behavioralML) {
1813
+ behavioralClassifier = new BehavioralClassifier(1e4);
1814
+ behavioralClassifier.setOnClassify(handleBehavioralClassification);
1815
+ setupBehavioralMLTracking();
1816
+ }
1817
+ if (features.focusBlur) {
1818
+ focusBlurAnalyzer = new FocusBlurAnalyzer();
1819
+ focusBlurAnalyzer.initTracking();
1820
+ setTimeout(() => {
1821
+ if (focusBlurAnalyzer) {
1822
+ handleFocusBlurAnalysis(focusBlurAnalyzer.analyze());
1823
+ }
1824
+ }, 5e3);
1795
1825
  }
1796
- behavioralClassifier = new BehavioralClassifier(1e4);
1797
- behavioralClassifier.setOnClassify(handleBehavioralClassification);
1798
- setupBehavioralMLTracking();
1799
- focusBlurAnalyzer = new FocusBlurAnalyzer();
1800
- focusBlurAnalyzer.initTracking();
1801
- setTimeout(() => {
1802
- if (focusBlurAnalyzer) {
1803
- handleFocusBlurAnalysis(focusBlurAnalyzer.analyze());
1804
- }
1805
- }, 5e3);
1806
- agenticAnalyzer = new AgenticBrowserAnalyzer();
1807
- agenticAnalyzer.init();
1808
- if (visitorId && sessionId) {
1826
+ if (features.agentic) {
1827
+ agenticAnalyzer = new AgenticBrowserAnalyzer();
1828
+ agenticAnalyzer.init();
1829
+ }
1830
+ if (features.ping && visitorId && sessionId) {
1809
1831
  pingService = new PingService(sessionId, visitorId, VERSION, {
1810
1832
  interval: DEFAULT_CONFIG.pingInterval,
1811
1833
  endpoint: endpoint(DEFAULT_CONFIG.endpoints.ping)
@@ -1820,48 +1842,63 @@ function init(userConfig = {}) {
1820
1842
  reportHealth("initialized");
1821
1843
  log("Initialization complete");
1822
1844
  }
1823
- function setupAdvancedBehavioralTracking() {
1824
- scrollTracker = new ScrollTracker({
1825
- chunks: [30, 60, 90, 100],
1826
- onChunkReached: (event) => {
1827
- log("Scroll chunk:", event.chunk);
1828
- queueEvent("scroll_depth", {
1829
- depth: event.depth,
1830
- chunk: event.chunk,
1831
- time_to_reach_ms: event.time_to_reach_ms
1832
- });
1833
- }
1834
- });
1835
- scrollTracker.start();
1836
- timeTracker = new TimeTracker({
1837
- updateIntervalMs: 1e4,
1838
- // Report every 10 seconds
1839
- onUpdate: (event) => {
1840
- if (event.active_time_ms >= DEFAULT_CONFIG.timeSpentThresholdMs) {
1841
- queueEvent("time_spent", {
1842
- active_time_ms: event.active_time_ms,
1843
- total_time_ms: event.total_time_ms,
1844
- idle_time_ms: event.idle_time_ms,
1845
- is_engaged: event.is_engaged
1845
+ function setupAdvancedBehavioralTracking(features) {
1846
+ if (features.scroll) {
1847
+ scrollTracker = new ScrollTracker({
1848
+ chunks: [30, 60, 90, 100],
1849
+ onChunkReached: (event) => {
1850
+ log("Scroll chunk:", event.chunk);
1851
+ queueEvent("scroll_depth", {
1852
+ depth: event.depth,
1853
+ chunk: event.chunk,
1854
+ time_to_reach_ms: event.time_to_reach_ms
1846
1855
  });
1847
1856
  }
1848
- }
1849
- });
1850
- timeTracker.start();
1851
- formTracker = new FormTracker({
1852
- onFormEvent: (event) => {
1853
- log("Form event:", event.event_type, event.form_id);
1854
- queueEvent(event.event_type, {
1855
- form_id: event.form_id,
1856
- form_type: event.form_type,
1857
- field_name: event.field_name,
1858
- field_type: event.field_type,
1859
- time_to_submit_ms: event.time_to_submit_ms,
1860
- is_conversion: event.is_conversion
1861
- });
1862
- }
1863
- });
1864
- formTracker.start();
1857
+ });
1858
+ scrollTracker.start();
1859
+ }
1860
+ if (features.time) {
1861
+ timeTracker = new TimeTracker({
1862
+ updateIntervalMs: 1e4,
1863
+ // Report every 10 seconds
1864
+ onUpdate: (event) => {
1865
+ if (event.active_time_ms >= DEFAULT_CONFIG.timeSpentThresholdMs) {
1866
+ queueEvent("time_spent", {
1867
+ active_time_ms: event.active_time_ms,
1868
+ total_time_ms: event.total_time_ms,
1869
+ idle_time_ms: event.idle_time_ms,
1870
+ is_engaged: event.is_engaged
1871
+ });
1872
+ }
1873
+ }
1874
+ });
1875
+ timeTracker.start();
1876
+ }
1877
+ if (features.forms) {
1878
+ formTracker = new FormTracker({
1879
+ onFormEvent: (event) => {
1880
+ log("Form event:", event.event_type, event.form_id);
1881
+ queueEvent(event.event_type, {
1882
+ form_id: event.form_id,
1883
+ form_type: event.form_type,
1884
+ field_name: event.field_name,
1885
+ field_type: event.field_type,
1886
+ time_to_submit_ms: event.time_to_submit_ms,
1887
+ is_conversion: event.is_conversion
1888
+ });
1889
+ }
1890
+ });
1891
+ formTracker.start();
1892
+ }
1893
+ if (features.spa) {
1894
+ spaRouter = new SPARouter({
1895
+ onNavigate: (event) => {
1896
+ log("SPA navigation:", event.navigation_type);
1897
+ pageview(event.to_url);
1898
+ }
1899
+ });
1900
+ spaRouter.start();
1901
+ }
1865
1902
  document.addEventListener("click", (e) => {
1866
1903
  const target = e.target;
1867
1904
  const link = target.closest("a");