@loamly/tracker 2.0.1 → 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 */
@@ -189,6 +213,7 @@ interface LoamlyTracker {
189
213
  */
190
214
  declare const loamly: LoamlyTracker & {
191
215
  getAgentic: () => AgenticDetectionResult | null;
216
+ reportHealth: (status: 'initialized' | 'error' | 'ready', errorMessage?: string) => void;
192
217
  };
193
218
 
194
219
  /**
@@ -245,7 +270,7 @@ declare function detectAIFromUTM(url: string): AIDetectionResult | null;
245
270
  * @license MIT
246
271
  * @see https://github.com/loamly/loamly
247
272
  */
248
- declare const VERSION = "2.0.1";
273
+ declare const VERSION = "2.1.0";
249
274
  /**
250
275
  * Known AI platforms for referrer detection
251
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 */
@@ -189,6 +213,7 @@ interface LoamlyTracker {
189
213
  */
190
214
  declare const loamly: LoamlyTracker & {
191
215
  getAgentic: () => AgenticDetectionResult | null;
216
+ reportHealth: (status: 'initialized' | 'error' | 'ready', errorMessage?: string) => void;
192
217
  };
193
218
 
194
219
  /**
@@ -245,7 +270,7 @@ declare function detectAIFromUTM(url: string): AIDetectionResult | null;
245
270
  * @license MIT
246
271
  * @see https://github.com/loamly/loamly
247
272
  */
248
- declare const VERSION = "2.0.1";
273
+ declare const VERSION = "2.1.0";
249
274
  /**
250
275
  * Known AI platforms for referrer detection
251
276
  */
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/config.ts
2
- var VERSION = "2.0.1";
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)
@@ -1817,50 +1839,66 @@ function init(userConfig = {}) {
1817
1839
  });
1818
1840
  spaRouter.start();
1819
1841
  setupUnloadHandlers();
1842
+ reportHealth("initialized");
1820
1843
  log("Initialization complete");
1821
1844
  }
1822
- function setupAdvancedBehavioralTracking() {
1823
- scrollTracker = new ScrollTracker({
1824
- chunks: [30, 60, 90, 100],
1825
- onChunkReached: (event) => {
1826
- log("Scroll chunk:", event.chunk);
1827
- queueEvent("scroll_depth", {
1828
- depth: event.depth,
1829
- chunk: event.chunk,
1830
- time_to_reach_ms: event.time_to_reach_ms
1831
- });
1832
- }
1833
- });
1834
- scrollTracker.start();
1835
- timeTracker = new TimeTracker({
1836
- updateIntervalMs: 1e4,
1837
- // Report every 10 seconds
1838
- onUpdate: (event) => {
1839
- if (event.active_time_ms >= DEFAULT_CONFIG.timeSpentThresholdMs) {
1840
- queueEvent("time_spent", {
1841
- active_time_ms: event.active_time_ms,
1842
- total_time_ms: event.total_time_ms,
1843
- idle_time_ms: event.idle_time_ms,
1844
- 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
1845
1855
  });
1846
1856
  }
1847
- }
1848
- });
1849
- timeTracker.start();
1850
- formTracker = new FormTracker({
1851
- onFormEvent: (event) => {
1852
- log("Form event:", event.event_type, event.form_id);
1853
- queueEvent(event.event_type, {
1854
- form_id: event.form_id,
1855
- form_type: event.form_type,
1856
- field_name: event.field_name,
1857
- field_type: event.field_type,
1858
- time_to_submit_ms: event.time_to_submit_ms,
1859
- is_conversion: event.is_conversion
1860
- });
1861
- }
1862
- });
1863
- 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
+ }
1864
1902
  document.addEventListener("click", (e) => {
1865
1903
  const target = e.target;
1866
1904
  const link = target.closest("a");
@@ -2162,6 +2200,39 @@ function getAgenticResult() {
2162
2200
  function isTrackerInitialized() {
2163
2201
  return initialized;
2164
2202
  }
2203
+ function reportHealth(status, errorMessage) {
2204
+ if (!config.apiKey) return;
2205
+ try {
2206
+ const healthData = {
2207
+ workspace_id: config.apiKey,
2208
+ status,
2209
+ error_message: errorMessage || null,
2210
+ version: VERSION,
2211
+ url: typeof window !== "undefined" ? window.location.href : null,
2212
+ user_agent: typeof navigator !== "undefined" ? navigator.userAgent : null,
2213
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2214
+ features: {
2215
+ scroll_tracker: !!scrollTracker,
2216
+ time_tracker: !!timeTracker,
2217
+ form_tracker: !!formTracker,
2218
+ spa_router: !!spaRouter,
2219
+ behavioral_ml: !!behavioralClassifier,
2220
+ focus_blur: !!focusBlurAnalyzer,
2221
+ agentic: !!agenticAnalyzer,
2222
+ ping_service: !!pingService,
2223
+ event_queue: !!eventQueue
2224
+ }
2225
+ };
2226
+ safeFetch(endpoint(DEFAULT_CONFIG.endpoints.health), {
2227
+ method: "POST",
2228
+ headers: { "Content-Type": "application/json" },
2229
+ body: JSON.stringify(healthData)
2230
+ }).catch(() => {
2231
+ });
2232
+ log("Health reported:", status);
2233
+ } catch {
2234
+ }
2235
+ }
2165
2236
  function reset() {
2166
2237
  log("Resetting tracker");
2167
2238
  pingService?.stop();
@@ -2211,7 +2282,8 @@ var loamly = {
2211
2282
  getAgentic: getAgenticResult,
2212
2283
  isInitialized: isTrackerInitialized,
2213
2284
  reset,
2214
- debug: setDebug
2285
+ debug: setDebug,
2286
+ reportHealth
2215
2287
  };
2216
2288
  export {
2217
2289
  AI_BOT_PATTERNS,