@loamly/tracker 1.7.0 → 1.8.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.cjs +418 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +82 -2
- package/dist/index.d.ts +82 -2
- package/dist/index.mjs +416 -2
- package/dist/index.mjs.map +1 -1
- package/dist/loamly.iife.global.js +196 -2
- package/dist/loamly.iife.global.js.map +1 -1
- package/dist/loamly.iife.min.global.js +8 -1
- package/dist/loamly.iife.min.global.js.map +1 -1
- package/package.json +1 -1
- package/src/config.ts +4 -1
- package/src/core.ts +67 -1
- package/src/detection/agentic-browser.ts +328 -0
- package/src/detection/focus-blur.ts +251 -0
- package/src/detection/index.ts +15 -0
- package/src/index.ts +7 -0
- package/src/types.ts +17 -0
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/config.ts
|
|
2
|
-
var VERSION = "1.
|
|
2
|
+
var VERSION = "1.8.0";
|
|
3
3
|
var DEFAULT_CONFIG = {
|
|
4
4
|
apiHost: "https://app.loamly.ai",
|
|
5
5
|
endpoints: {
|
|
@@ -492,6 +492,151 @@ var BehavioralClassifier = class {
|
|
|
492
492
|
}
|
|
493
493
|
};
|
|
494
494
|
|
|
495
|
+
// src/detection/focus-blur.ts
|
|
496
|
+
var FocusBlurAnalyzer = class {
|
|
497
|
+
constructor() {
|
|
498
|
+
this.sequence = [];
|
|
499
|
+
this.firstInteractionTime = null;
|
|
500
|
+
this.analyzed = false;
|
|
501
|
+
this.result = null;
|
|
502
|
+
this.pageLoadTime = performance.now();
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Initialize event tracking
|
|
506
|
+
* Must be called after DOM is ready
|
|
507
|
+
*/
|
|
508
|
+
initTracking() {
|
|
509
|
+
document.addEventListener("focus", (e) => {
|
|
510
|
+
this.recordEvent("focus", e.target);
|
|
511
|
+
}, true);
|
|
512
|
+
document.addEventListener("blur", (e) => {
|
|
513
|
+
this.recordEvent("blur", e.target);
|
|
514
|
+
}, true);
|
|
515
|
+
window.addEventListener("focus", () => {
|
|
516
|
+
this.recordEvent("window_focus", null);
|
|
517
|
+
});
|
|
518
|
+
window.addEventListener("blur", () => {
|
|
519
|
+
this.recordEvent("window_blur", null);
|
|
520
|
+
});
|
|
521
|
+
const recordFirstInteraction = () => {
|
|
522
|
+
if (this.firstInteractionTime === null) {
|
|
523
|
+
this.firstInteractionTime = performance.now();
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
document.addEventListener("click", recordFirstInteraction, { once: true, passive: true });
|
|
527
|
+
document.addEventListener("keydown", recordFirstInteraction, { once: true, passive: true });
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Record a focus/blur event
|
|
531
|
+
*/
|
|
532
|
+
recordEvent(type, target) {
|
|
533
|
+
const event = {
|
|
534
|
+
type,
|
|
535
|
+
target: target?.tagName || "WINDOW",
|
|
536
|
+
timestamp: performance.now()
|
|
537
|
+
};
|
|
538
|
+
this.sequence.push(event);
|
|
539
|
+
if (this.sequence.length > 20) {
|
|
540
|
+
this.sequence = this.sequence.slice(-20);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Analyze the focus/blur sequence for paste patterns
|
|
545
|
+
*/
|
|
546
|
+
analyze() {
|
|
547
|
+
if (this.analyzed && this.result) {
|
|
548
|
+
return this.result;
|
|
549
|
+
}
|
|
550
|
+
const signals = [];
|
|
551
|
+
let confidence = 0;
|
|
552
|
+
const earlyEvents = this.sequence.filter((e) => e.timestamp < this.pageLoadTime + 500);
|
|
553
|
+
const hasEarlyWindowFocus = earlyEvents.some((e) => e.type === "window_focus");
|
|
554
|
+
if (hasEarlyWindowFocus) {
|
|
555
|
+
signals.push("early_window_focus");
|
|
556
|
+
confidence += 0.15;
|
|
557
|
+
}
|
|
558
|
+
const hasEarlyBodyFocus = earlyEvents.some(
|
|
559
|
+
(e) => e.type === "focus" && e.target === "BODY"
|
|
560
|
+
);
|
|
561
|
+
if (hasEarlyBodyFocus) {
|
|
562
|
+
signals.push("early_body_focus");
|
|
563
|
+
confidence += 0.15;
|
|
564
|
+
}
|
|
565
|
+
const hasLinkFocus = this.sequence.some(
|
|
566
|
+
(e) => e.type === "focus" && e.target === "A"
|
|
567
|
+
);
|
|
568
|
+
if (!hasLinkFocus) {
|
|
569
|
+
signals.push("no_link_focus");
|
|
570
|
+
confidence += 0.1;
|
|
571
|
+
}
|
|
572
|
+
const firstFocus = this.sequence.find((e) => e.type === "focus");
|
|
573
|
+
if (firstFocus && (firstFocus.target === "BODY" || firstFocus.target === "HTML")) {
|
|
574
|
+
signals.push("first_focus_body");
|
|
575
|
+
confidence += 0.1;
|
|
576
|
+
}
|
|
577
|
+
const windowEvents = this.sequence.filter(
|
|
578
|
+
(e) => e.type === "window_focus" || e.type === "window_blur"
|
|
579
|
+
);
|
|
580
|
+
if (windowEvents.length <= 2) {
|
|
581
|
+
signals.push("minimal_window_switches");
|
|
582
|
+
confidence += 0.05;
|
|
583
|
+
}
|
|
584
|
+
if (this.firstInteractionTime !== null) {
|
|
585
|
+
const timeToInteraction = this.firstInteractionTime - this.pageLoadTime;
|
|
586
|
+
if (timeToInteraction > 3e3) {
|
|
587
|
+
signals.push("delayed_first_interaction");
|
|
588
|
+
confidence += 0.1;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
confidence = Math.min(confidence, 0.65);
|
|
592
|
+
let navType;
|
|
593
|
+
if (confidence >= 0.35) {
|
|
594
|
+
navType = "likely_paste";
|
|
595
|
+
} else if (signals.length === 0) {
|
|
596
|
+
navType = "unknown";
|
|
597
|
+
} else {
|
|
598
|
+
navType = "likely_click";
|
|
599
|
+
}
|
|
600
|
+
this.result = {
|
|
601
|
+
nav_type: navType,
|
|
602
|
+
confidence,
|
|
603
|
+
signals,
|
|
604
|
+
sequence: this.sequence.slice(-10),
|
|
605
|
+
time_to_first_interaction_ms: this.firstInteractionTime ? Math.round(this.firstInteractionTime - this.pageLoadTime) : null
|
|
606
|
+
};
|
|
607
|
+
this.analyzed = true;
|
|
608
|
+
return this.result;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Get current result (analyze if not done)
|
|
612
|
+
*/
|
|
613
|
+
getResult() {
|
|
614
|
+
return this.analyze();
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Check if analysis has been performed
|
|
618
|
+
*/
|
|
619
|
+
hasAnalyzed() {
|
|
620
|
+
return this.analyzed;
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Get the raw sequence for debugging
|
|
624
|
+
*/
|
|
625
|
+
getSequence() {
|
|
626
|
+
return [...this.sequence];
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Reset the analyzer
|
|
630
|
+
*/
|
|
631
|
+
reset() {
|
|
632
|
+
this.sequence = [];
|
|
633
|
+
this.pageLoadTime = performance.now();
|
|
634
|
+
this.firstInteractionTime = null;
|
|
635
|
+
this.analyzed = false;
|
|
636
|
+
this.result = null;
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
|
|
495
640
|
// src/utils.ts
|
|
496
641
|
function generateUUID() {
|
|
497
642
|
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
@@ -579,6 +724,8 @@ var navigationTiming = null;
|
|
|
579
724
|
var aiDetection = null;
|
|
580
725
|
var behavioralClassifier = null;
|
|
581
726
|
var behavioralMLResult = null;
|
|
727
|
+
var focusBlurAnalyzer = null;
|
|
728
|
+
var focusBlurResult = null;
|
|
582
729
|
function log(...args) {
|
|
583
730
|
if (debugMode) {
|
|
584
731
|
console.log("[Loamly]", ...args);
|
|
@@ -621,6 +768,13 @@ function init(userConfig = {}) {
|
|
|
621
768
|
behavioralClassifier = new BehavioralClassifier(1e4);
|
|
622
769
|
behavioralClassifier.setOnClassify(handleBehavioralClassification);
|
|
623
770
|
setupBehavioralMLTracking();
|
|
771
|
+
focusBlurAnalyzer = new FocusBlurAnalyzer();
|
|
772
|
+
focusBlurAnalyzer.initTracking();
|
|
773
|
+
setTimeout(() => {
|
|
774
|
+
if (focusBlurAnalyzer) {
|
|
775
|
+
handleFocusBlurAnalysis(focusBlurAnalyzer.analyze());
|
|
776
|
+
}
|
|
777
|
+
}, 5e3);
|
|
624
778
|
log("Initialization complete");
|
|
625
779
|
}
|
|
626
780
|
function pageview(customUrl) {
|
|
@@ -874,7 +1028,8 @@ function handleBehavioralClassification(result) {
|
|
|
874
1028
|
signals: result.signals,
|
|
875
1029
|
session_duration_ms: result.sessionDurationMs,
|
|
876
1030
|
navigation_timing: navigationTiming,
|
|
877
|
-
ai_detection: aiDetection
|
|
1031
|
+
ai_detection: aiDetection,
|
|
1032
|
+
focus_blur: focusBlurResult
|
|
878
1033
|
});
|
|
879
1034
|
if (result.classification === "ai_influenced" && result.confidence >= 0.7) {
|
|
880
1035
|
aiDetection = {
|
|
@@ -885,6 +1040,32 @@ function handleBehavioralClassification(result) {
|
|
|
885
1040
|
log("AI detection updated from behavioral ML:", aiDetection);
|
|
886
1041
|
}
|
|
887
1042
|
}
|
|
1043
|
+
function handleFocusBlurAnalysis(result) {
|
|
1044
|
+
log("Focus/blur analysis:", result);
|
|
1045
|
+
focusBlurResult = {
|
|
1046
|
+
navType: result.nav_type,
|
|
1047
|
+
confidence: result.confidence,
|
|
1048
|
+
signals: result.signals,
|
|
1049
|
+
timeToFirstInteractionMs: result.time_to_first_interaction_ms
|
|
1050
|
+
};
|
|
1051
|
+
sendBehavioralEvent("focus_blur_analysis", {
|
|
1052
|
+
nav_type: result.nav_type,
|
|
1053
|
+
confidence: result.confidence,
|
|
1054
|
+
signals: result.signals,
|
|
1055
|
+
time_to_first_interaction_ms: result.time_to_first_interaction_ms,
|
|
1056
|
+
sequence_length: result.sequence.length
|
|
1057
|
+
});
|
|
1058
|
+
if (result.nav_type === "likely_paste" && result.confidence >= 0.4) {
|
|
1059
|
+
if (!aiDetection || aiDetection.confidence < result.confidence) {
|
|
1060
|
+
aiDetection = {
|
|
1061
|
+
isAI: true,
|
|
1062
|
+
confidence: result.confidence,
|
|
1063
|
+
method: "behavioral"
|
|
1064
|
+
};
|
|
1065
|
+
log("AI detection updated from focus/blur analysis:", aiDetection);
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
888
1069
|
function getCurrentSessionId() {
|
|
889
1070
|
return sessionId;
|
|
890
1071
|
}
|
|
@@ -900,6 +1081,9 @@ function getNavigationTimingResult() {
|
|
|
900
1081
|
function getBehavioralMLResult() {
|
|
901
1082
|
return behavioralMLResult;
|
|
902
1083
|
}
|
|
1084
|
+
function getFocusBlurResult() {
|
|
1085
|
+
return focusBlurResult;
|
|
1086
|
+
}
|
|
903
1087
|
function isTrackerInitialized() {
|
|
904
1088
|
return initialized;
|
|
905
1089
|
}
|
|
@@ -913,6 +1097,8 @@ function reset() {
|
|
|
913
1097
|
aiDetection = null;
|
|
914
1098
|
behavioralClassifier = null;
|
|
915
1099
|
behavioralMLResult = null;
|
|
1100
|
+
focusBlurAnalyzer = null;
|
|
1101
|
+
focusBlurResult = null;
|
|
916
1102
|
try {
|
|
917
1103
|
sessionStorage.removeItem("loamly_session");
|
|
918
1104
|
sessionStorage.removeItem("loamly_start");
|
|
@@ -934,20 +1120,246 @@ var loamly = {
|
|
|
934
1120
|
getAIDetection: getAIDetectionResult,
|
|
935
1121
|
getNavigationTiming: getNavigationTimingResult,
|
|
936
1122
|
getBehavioralML: getBehavioralMLResult,
|
|
1123
|
+
getFocusBlur: getFocusBlurResult,
|
|
937
1124
|
isInitialized: isTrackerInitialized,
|
|
938
1125
|
reset,
|
|
939
1126
|
debug: setDebug
|
|
940
1127
|
};
|
|
1128
|
+
|
|
1129
|
+
// src/detection/agentic-browser.ts
|
|
1130
|
+
var CometDetector = class {
|
|
1131
|
+
constructor() {
|
|
1132
|
+
this.detected = false;
|
|
1133
|
+
this.checkComplete = false;
|
|
1134
|
+
this.observer = null;
|
|
1135
|
+
}
|
|
1136
|
+
/**
|
|
1137
|
+
* Initialize detection
|
|
1138
|
+
* @param timeout - Max time to observe for Comet DOM (default: 5s)
|
|
1139
|
+
*/
|
|
1140
|
+
init(timeout = 5e3) {
|
|
1141
|
+
if (typeof document === "undefined") return;
|
|
1142
|
+
this.check();
|
|
1143
|
+
if (!this.detected && document.body) {
|
|
1144
|
+
this.observer = new MutationObserver(() => this.check());
|
|
1145
|
+
this.observer.observe(document.body, { childList: true, subtree: true });
|
|
1146
|
+
setTimeout(() => {
|
|
1147
|
+
if (this.observer && !this.detected) {
|
|
1148
|
+
this.observer.disconnect();
|
|
1149
|
+
this.observer = null;
|
|
1150
|
+
this.checkComplete = true;
|
|
1151
|
+
}
|
|
1152
|
+
}, timeout);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
check() {
|
|
1156
|
+
if (document.querySelector(".pplx-agent-overlay-stop-button")) {
|
|
1157
|
+
this.detected = true;
|
|
1158
|
+
this.checkComplete = true;
|
|
1159
|
+
if (this.observer) {
|
|
1160
|
+
this.observer.disconnect();
|
|
1161
|
+
this.observer = null;
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
isDetected() {
|
|
1166
|
+
return this.detected;
|
|
1167
|
+
}
|
|
1168
|
+
isCheckComplete() {
|
|
1169
|
+
return this.checkComplete;
|
|
1170
|
+
}
|
|
1171
|
+
destroy() {
|
|
1172
|
+
if (this.observer) {
|
|
1173
|
+
this.observer.disconnect();
|
|
1174
|
+
this.observer = null;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
};
|
|
1178
|
+
var MouseAnalyzer = class {
|
|
1179
|
+
/**
|
|
1180
|
+
* @param teleportThreshold - Distance in pixels to consider a teleport (default: 500)
|
|
1181
|
+
*/
|
|
1182
|
+
constructor(teleportThreshold = 500) {
|
|
1183
|
+
this.lastX = -1;
|
|
1184
|
+
this.lastY = -1;
|
|
1185
|
+
this.teleportingClicks = 0;
|
|
1186
|
+
this.totalMovements = 0;
|
|
1187
|
+
this.handleMove = (e) => {
|
|
1188
|
+
this.totalMovements++;
|
|
1189
|
+
this.lastX = e.clientX;
|
|
1190
|
+
this.lastY = e.clientY;
|
|
1191
|
+
};
|
|
1192
|
+
this.handleClick = (e) => {
|
|
1193
|
+
if (this.lastX !== -1 && this.lastY !== -1) {
|
|
1194
|
+
const dx = Math.abs(e.clientX - this.lastX);
|
|
1195
|
+
const dy = Math.abs(e.clientY - this.lastY);
|
|
1196
|
+
if (dx > this.teleportThreshold || dy > this.teleportThreshold) {
|
|
1197
|
+
this.teleportingClicks++;
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
this.lastX = e.clientX;
|
|
1201
|
+
this.lastY = e.clientY;
|
|
1202
|
+
};
|
|
1203
|
+
this.teleportThreshold = teleportThreshold;
|
|
1204
|
+
}
|
|
1205
|
+
/**
|
|
1206
|
+
* Initialize mouse tracking
|
|
1207
|
+
*/
|
|
1208
|
+
init() {
|
|
1209
|
+
if (typeof document === "undefined") return;
|
|
1210
|
+
document.addEventListener("mousemove", this.handleMove, { passive: true });
|
|
1211
|
+
document.addEventListener("mousedown", this.handleClick, { passive: true });
|
|
1212
|
+
}
|
|
1213
|
+
getPatterns() {
|
|
1214
|
+
return {
|
|
1215
|
+
teleportingClicks: this.teleportingClicks,
|
|
1216
|
+
totalMovements: this.totalMovements
|
|
1217
|
+
};
|
|
1218
|
+
}
|
|
1219
|
+
destroy() {
|
|
1220
|
+
if (typeof document === "undefined") return;
|
|
1221
|
+
document.removeEventListener("mousemove", this.handleMove);
|
|
1222
|
+
document.removeEventListener("mousedown", this.handleClick);
|
|
1223
|
+
}
|
|
1224
|
+
};
|
|
1225
|
+
var CDPDetector = class {
|
|
1226
|
+
constructor() {
|
|
1227
|
+
this.detected = false;
|
|
1228
|
+
}
|
|
1229
|
+
/**
|
|
1230
|
+
* Run detection checks
|
|
1231
|
+
*/
|
|
1232
|
+
detect() {
|
|
1233
|
+
if (typeof navigator === "undefined") return false;
|
|
1234
|
+
if (navigator.webdriver) {
|
|
1235
|
+
this.detected = true;
|
|
1236
|
+
return true;
|
|
1237
|
+
}
|
|
1238
|
+
if (typeof window !== "undefined") {
|
|
1239
|
+
const win = window;
|
|
1240
|
+
const automationProps = [
|
|
1241
|
+
"__webdriver_evaluate",
|
|
1242
|
+
"__selenium_evaluate",
|
|
1243
|
+
"__webdriver_script_function",
|
|
1244
|
+
"__webdriver_script_func",
|
|
1245
|
+
"__webdriver_script_fn",
|
|
1246
|
+
"__fxdriver_evaluate",
|
|
1247
|
+
"__driver_unwrapped",
|
|
1248
|
+
"__webdriver_unwrapped",
|
|
1249
|
+
"__driver_evaluate",
|
|
1250
|
+
"__selenium_unwrapped",
|
|
1251
|
+
"__fxdriver_unwrapped"
|
|
1252
|
+
];
|
|
1253
|
+
for (const prop of automationProps) {
|
|
1254
|
+
if (prop in win) {
|
|
1255
|
+
this.detected = true;
|
|
1256
|
+
return true;
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
return false;
|
|
1261
|
+
}
|
|
1262
|
+
isDetected() {
|
|
1263
|
+
return this.detected;
|
|
1264
|
+
}
|
|
1265
|
+
};
|
|
1266
|
+
var AgenticBrowserAnalyzer = class {
|
|
1267
|
+
constructor() {
|
|
1268
|
+
this.initialized = false;
|
|
1269
|
+
this.cometDetector = new CometDetector();
|
|
1270
|
+
this.mouseAnalyzer = new MouseAnalyzer();
|
|
1271
|
+
this.cdpDetector = new CDPDetector();
|
|
1272
|
+
}
|
|
1273
|
+
/**
|
|
1274
|
+
* Initialize all detectors
|
|
1275
|
+
*/
|
|
1276
|
+
init() {
|
|
1277
|
+
if (this.initialized) return;
|
|
1278
|
+
this.initialized = true;
|
|
1279
|
+
this.cometDetector.init();
|
|
1280
|
+
this.mouseAnalyzer.init();
|
|
1281
|
+
this.cdpDetector.detect();
|
|
1282
|
+
}
|
|
1283
|
+
/**
|
|
1284
|
+
* Get current detection result
|
|
1285
|
+
*/
|
|
1286
|
+
getResult() {
|
|
1287
|
+
const signals = [];
|
|
1288
|
+
let probability = 0;
|
|
1289
|
+
if (this.cometDetector.isDetected()) {
|
|
1290
|
+
signals.push("comet_dom_detected");
|
|
1291
|
+
probability = Math.max(probability, 0.85);
|
|
1292
|
+
}
|
|
1293
|
+
if (this.cdpDetector.isDetected()) {
|
|
1294
|
+
signals.push("cdp_detected");
|
|
1295
|
+
probability = Math.max(probability, 0.92);
|
|
1296
|
+
}
|
|
1297
|
+
const mousePatterns = this.mouseAnalyzer.getPatterns();
|
|
1298
|
+
if (mousePatterns.teleportingClicks > 0) {
|
|
1299
|
+
signals.push(`teleporting_clicks:${mousePatterns.teleportingClicks}`);
|
|
1300
|
+
probability = Math.max(probability, 0.78);
|
|
1301
|
+
}
|
|
1302
|
+
return {
|
|
1303
|
+
cometDOMDetected: this.cometDetector.isDetected(),
|
|
1304
|
+
cdpDetected: this.cdpDetector.isDetected(),
|
|
1305
|
+
mousePatterns,
|
|
1306
|
+
agenticProbability: probability,
|
|
1307
|
+
signals
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* Cleanup resources
|
|
1312
|
+
*/
|
|
1313
|
+
destroy() {
|
|
1314
|
+
this.cometDetector.destroy();
|
|
1315
|
+
this.mouseAnalyzer.destroy();
|
|
1316
|
+
}
|
|
1317
|
+
};
|
|
1318
|
+
function createAgenticAnalyzer() {
|
|
1319
|
+
const analyzer = new AgenticBrowserAnalyzer();
|
|
1320
|
+
if (typeof document !== "undefined") {
|
|
1321
|
+
if (document.readyState === "loading") {
|
|
1322
|
+
document.addEventListener("DOMContentLoaded", () => analyzer.init());
|
|
1323
|
+
} else {
|
|
1324
|
+
analyzer.init();
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
return analyzer;
|
|
1328
|
+
}
|
|
941
1329
|
export {
|
|
942
1330
|
AI_BOT_PATTERNS,
|
|
943
1331
|
AI_PLATFORMS,
|
|
1332
|
+
AgenticBrowserAnalyzer,
|
|
944
1333
|
VERSION,
|
|
1334
|
+
createAgenticAnalyzer,
|
|
945
1335
|
loamly as default,
|
|
946
1336
|
detectAIFromReferrer,
|
|
947
1337
|
detectAIFromUTM,
|
|
948
1338
|
detectNavigationType,
|
|
949
1339
|
loamly
|
|
950
1340
|
};
|
|
1341
|
+
/**
|
|
1342
|
+
* Loamly Tracker Configuration
|
|
1343
|
+
*
|
|
1344
|
+
* @module @loamly/tracker
|
|
1345
|
+
* @license MIT
|
|
1346
|
+
* @see https://github.com/loamly/loamly
|
|
1347
|
+
*/
|
|
1348
|
+
/**
|
|
1349
|
+
* Agentic Browser Detection
|
|
1350
|
+
*
|
|
1351
|
+
* LOA-187: Detects AI agentic browsers like Perplexity Comet, ChatGPT Atlas,
|
|
1352
|
+
* and other automated browsing agents.
|
|
1353
|
+
*
|
|
1354
|
+
* Detection methods:
|
|
1355
|
+
* - DOM fingerprinting (Perplexity Comet overlay)
|
|
1356
|
+
* - Mouse movement patterns (teleporting clicks)
|
|
1357
|
+
* - CDP (Chrome DevTools Protocol) automation fingerprint
|
|
1358
|
+
* - navigator.webdriver detection
|
|
1359
|
+
*
|
|
1360
|
+
* @module @loamly/tracker/detection/agentic-browser
|
|
1361
|
+
* @license MIT
|
|
1362
|
+
*/
|
|
951
1363
|
/**
|
|
952
1364
|
* Loamly Tracker
|
|
953
1365
|
*
|
|
@@ -955,7 +1367,9 @@ export {
|
|
|
955
1367
|
* See what AI tells your customers — and track when they click.
|
|
956
1368
|
*
|
|
957
1369
|
* @module @loamly/tracker
|
|
1370
|
+
* @version 1.8.0
|
|
958
1371
|
* @license MIT
|
|
1372
|
+
* @see https://github.com/loamly/loamly
|
|
959
1373
|
* @see https://loamly.ai
|
|
960
1374
|
*/
|
|
961
1375
|
//# sourceMappingURL=index.mjs.map
|