@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/README.md +23 -0
- package/dist/index.cjs +96 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +25 -1
- package/dist/index.d.ts +25 -1
- package/dist/index.mjs +96 -59
- package/dist/index.mjs.map +1 -1
- package/dist/loamly.iife.global.js +96 -59
- package/dist/loamly.iife.global.js.map +1 -1
- package/dist/loamly.iife.min.global.js +1 -1
- package/dist/loamly.iife.min.global.js.map +1 -1
- package/package.json +1 -1
- package/src/config.ts +1 -1
- package/src/core.ts +125 -73
- package/src/types.ts +25 -0
package/README.md
CHANGED
|
@@ -110,6 +110,29 @@ loamly.init({
|
|
|
110
110
|
});
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
+
### Lightweight Mode
|
|
114
|
+
|
|
115
|
+
Disable specific features to reduce CPU/memory overhead:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
loamly.init({
|
|
119
|
+
apiKey: 'your-api-key',
|
|
120
|
+
features: {
|
|
121
|
+
scroll: true, // Scroll depth tracking (default: true)
|
|
122
|
+
time: true, // Time on page tracking (default: true)
|
|
123
|
+
forms: true, // Form interaction tracking (default: true)
|
|
124
|
+
spa: true, // SPA navigation support (default: true)
|
|
125
|
+
behavioralML: false, // Behavioral ML classification (default: true) - saves ~2KB CPU
|
|
126
|
+
focusBlur: true, // Focus/blur paste detection (default: true)
|
|
127
|
+
agentic: false, // Agentic browser detection (default: true) - saves ~1.5KB CPU
|
|
128
|
+
eventQueue: true, // Event queue with retry (default: true)
|
|
129
|
+
ping: false, // Heartbeat ping service (default: false - opt-in)
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Note:** All features are included in the bundle (~11KB gzipped). The `features` config only affects runtime initialization, not download size.
|
|
135
|
+
|
|
113
136
|
### `track(eventName, options?)`
|
|
114
137
|
|
|
115
138
|
Track a custom event.
|
package/dist/index.cjs
CHANGED
|
@@ -34,7 +34,7 @@ __export(index_exports, {
|
|
|
34
34
|
module.exports = __toCommonJS(index_exports);
|
|
35
35
|
|
|
36
36
|
// src/config.ts
|
|
37
|
-
var VERSION = "2.0
|
|
37
|
+
var VERSION = "2.1.0";
|
|
38
38
|
var DEFAULT_CONFIG = {
|
|
39
39
|
apiHost: "https://app.loamly.ai",
|
|
40
40
|
endpoints: {
|
|
@@ -1805,16 +1805,32 @@ function init(userConfig = {}) {
|
|
|
1805
1805
|
apiHost: userConfig.apiHost || DEFAULT_CONFIG.apiHost
|
|
1806
1806
|
};
|
|
1807
1807
|
debugMode = userConfig.debug ?? false;
|
|
1808
|
+
const features = {
|
|
1809
|
+
scroll: true,
|
|
1810
|
+
time: true,
|
|
1811
|
+
forms: true,
|
|
1812
|
+
spa: true,
|
|
1813
|
+
behavioralML: true,
|
|
1814
|
+
focusBlur: true,
|
|
1815
|
+
agentic: true,
|
|
1816
|
+
eventQueue: true,
|
|
1817
|
+
ping: false,
|
|
1818
|
+
// Opt-in only
|
|
1819
|
+
...userConfig.features
|
|
1820
|
+
};
|
|
1808
1821
|
log("Initializing Loamly Tracker v" + VERSION);
|
|
1822
|
+
log("Features:", features);
|
|
1809
1823
|
visitorId = getVisitorId();
|
|
1810
1824
|
log("Visitor ID:", visitorId);
|
|
1811
1825
|
const session = getSessionId();
|
|
1812
1826
|
sessionId = session.sessionId;
|
|
1813
1827
|
log("Session ID:", sessionId, session.isNew ? "(new)" : "(existing)");
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1828
|
+
if (features.eventQueue) {
|
|
1829
|
+
eventQueue = new EventQueue(endpoint(DEFAULT_CONFIG.endpoints.behavioral), {
|
|
1830
|
+
batchSize: DEFAULT_CONFIG.batchSize,
|
|
1831
|
+
batchTimeout: DEFAULT_CONFIG.batchTimeout
|
|
1832
|
+
});
|
|
1833
|
+
}
|
|
1818
1834
|
navigationTiming = detectNavigationType();
|
|
1819
1835
|
log("Navigation timing:", navigationTiming);
|
|
1820
1836
|
aiDetection = detectAIFromReferrer(document.referrer) || detectAIFromUTM(window.location.href);
|
|
@@ -1826,21 +1842,27 @@ function init(userConfig = {}) {
|
|
|
1826
1842
|
pageview();
|
|
1827
1843
|
}
|
|
1828
1844
|
if (!userConfig.disableBehavioral) {
|
|
1829
|
-
setupAdvancedBehavioralTracking();
|
|
1845
|
+
setupAdvancedBehavioralTracking(features);
|
|
1846
|
+
}
|
|
1847
|
+
if (features.behavioralML) {
|
|
1848
|
+
behavioralClassifier = new BehavioralClassifier(1e4);
|
|
1849
|
+
behavioralClassifier.setOnClassify(handleBehavioralClassification);
|
|
1850
|
+
setupBehavioralMLTracking();
|
|
1851
|
+
}
|
|
1852
|
+
if (features.focusBlur) {
|
|
1853
|
+
focusBlurAnalyzer = new FocusBlurAnalyzer();
|
|
1854
|
+
focusBlurAnalyzer.initTracking();
|
|
1855
|
+
setTimeout(() => {
|
|
1856
|
+
if (focusBlurAnalyzer) {
|
|
1857
|
+
handleFocusBlurAnalysis(focusBlurAnalyzer.analyze());
|
|
1858
|
+
}
|
|
1859
|
+
}, 5e3);
|
|
1830
1860
|
}
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
setTimeout(() => {
|
|
1837
|
-
if (focusBlurAnalyzer) {
|
|
1838
|
-
handleFocusBlurAnalysis(focusBlurAnalyzer.analyze());
|
|
1839
|
-
}
|
|
1840
|
-
}, 5e3);
|
|
1841
|
-
agenticAnalyzer = new AgenticBrowserAnalyzer();
|
|
1842
|
-
agenticAnalyzer.init();
|
|
1843
|
-
if (visitorId && sessionId) {
|
|
1861
|
+
if (features.agentic) {
|
|
1862
|
+
agenticAnalyzer = new AgenticBrowserAnalyzer();
|
|
1863
|
+
agenticAnalyzer.init();
|
|
1864
|
+
}
|
|
1865
|
+
if (features.ping && visitorId && sessionId) {
|
|
1844
1866
|
pingService = new PingService(sessionId, visitorId, VERSION, {
|
|
1845
1867
|
interval: DEFAULT_CONFIG.pingInterval,
|
|
1846
1868
|
endpoint: endpoint(DEFAULT_CONFIG.endpoints.ping)
|
|
@@ -1855,48 +1877,63 @@ function init(userConfig = {}) {
|
|
|
1855
1877
|
reportHealth("initialized");
|
|
1856
1878
|
log("Initialization complete");
|
|
1857
1879
|
}
|
|
1858
|
-
function setupAdvancedBehavioralTracking() {
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
}
|
|
1869
|
-
});
|
|
1870
|
-
scrollTracker.start();
|
|
1871
|
-
timeTracker = new TimeTracker({
|
|
1872
|
-
updateIntervalMs: 1e4,
|
|
1873
|
-
// Report every 10 seconds
|
|
1874
|
-
onUpdate: (event) => {
|
|
1875
|
-
if (event.active_time_ms >= DEFAULT_CONFIG.timeSpentThresholdMs) {
|
|
1876
|
-
queueEvent("time_spent", {
|
|
1877
|
-
active_time_ms: event.active_time_ms,
|
|
1878
|
-
total_time_ms: event.total_time_ms,
|
|
1879
|
-
idle_time_ms: event.idle_time_ms,
|
|
1880
|
-
is_engaged: event.is_engaged
|
|
1880
|
+
function setupAdvancedBehavioralTracking(features) {
|
|
1881
|
+
if (features.scroll) {
|
|
1882
|
+
scrollTracker = new ScrollTracker({
|
|
1883
|
+
chunks: [30, 60, 90, 100],
|
|
1884
|
+
onChunkReached: (event) => {
|
|
1885
|
+
log("Scroll chunk:", event.chunk);
|
|
1886
|
+
queueEvent("scroll_depth", {
|
|
1887
|
+
depth: event.depth,
|
|
1888
|
+
chunk: event.chunk,
|
|
1889
|
+
time_to_reach_ms: event.time_to_reach_ms
|
|
1881
1890
|
});
|
|
1882
1891
|
}
|
|
1883
|
-
}
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1892
|
+
});
|
|
1893
|
+
scrollTracker.start();
|
|
1894
|
+
}
|
|
1895
|
+
if (features.time) {
|
|
1896
|
+
timeTracker = new TimeTracker({
|
|
1897
|
+
updateIntervalMs: 1e4,
|
|
1898
|
+
// Report every 10 seconds
|
|
1899
|
+
onUpdate: (event) => {
|
|
1900
|
+
if (event.active_time_ms >= DEFAULT_CONFIG.timeSpentThresholdMs) {
|
|
1901
|
+
queueEvent("time_spent", {
|
|
1902
|
+
active_time_ms: event.active_time_ms,
|
|
1903
|
+
total_time_ms: event.total_time_ms,
|
|
1904
|
+
idle_time_ms: event.idle_time_ms,
|
|
1905
|
+
is_engaged: event.is_engaged
|
|
1906
|
+
});
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
});
|
|
1910
|
+
timeTracker.start();
|
|
1911
|
+
}
|
|
1912
|
+
if (features.forms) {
|
|
1913
|
+
formTracker = new FormTracker({
|
|
1914
|
+
onFormEvent: (event) => {
|
|
1915
|
+
log("Form event:", event.event_type, event.form_id);
|
|
1916
|
+
queueEvent(event.event_type, {
|
|
1917
|
+
form_id: event.form_id,
|
|
1918
|
+
form_type: event.form_type,
|
|
1919
|
+
field_name: event.field_name,
|
|
1920
|
+
field_type: event.field_type,
|
|
1921
|
+
time_to_submit_ms: event.time_to_submit_ms,
|
|
1922
|
+
is_conversion: event.is_conversion
|
|
1923
|
+
});
|
|
1924
|
+
}
|
|
1925
|
+
});
|
|
1926
|
+
formTracker.start();
|
|
1927
|
+
}
|
|
1928
|
+
if (features.spa) {
|
|
1929
|
+
spaRouter = new SPARouter({
|
|
1930
|
+
onNavigate: (event) => {
|
|
1931
|
+
log("SPA navigation:", event.navigation_type);
|
|
1932
|
+
pageview(event.to_url);
|
|
1933
|
+
}
|
|
1934
|
+
});
|
|
1935
|
+
spaRouter.start();
|
|
1936
|
+
}
|
|
1900
1937
|
document.addEventListener("click", (e) => {
|
|
1901
1938
|
const target = e.target;
|
|
1902
1939
|
const link = target.closest("a");
|