@faina/phantom
v1.0.0
Published
Persistent user session tracker that survives cache clearing, incognito mode, and storage deletion
Maintainers
Readme
Phantom - Tracker
Stable visitor identification with comprehensive tracking and security detection.
Features
| Category | Feature | Default | |----------|---------|---------| | Fingerprinting | Tier 1: Hardware (cores, screen, timezone) | ✅ | | | Tier 2: Stable (GPU, WebGPU, CSS features) | ✅ | | | Tier 3: Variable (canvas, fonts, audio) | ✅ | | | Server-side progressive matching | ✅ | | Security | Bot detection (webdriver, automation, headless) | ✅ On | | | Incognito detection (storage quota, filesystem) | ✅ On | | | Tampering detection (canvas noise, spoofing) | ✅ On | | | Confidence scoring | ✅ | | Auto-Tracking | Page views | ✅ On | | | Scroll depth (25%, 50%, 75%, 90%, 100%) | ✅ On | | | Clicks (with coordinates) | ✅ On | | | Form interactions (focus, blur, change, submit) | ✅ On | | | Page visibility (tab hidden/visible) | ✅ On | | | Performance metrics (TTFB, FCP, load) | ✅ On | | | SPA route changes | ✅ On | | | Session end | ✅ On | | | Mouse movement (heatmaps) | ⚪ Off | | | Drag and drop | ⚪ Off | | Storage | localStorage, sessionStorage, cookies, IndexedDB | ✅ |
Quick Start
<script type="module">
import { Phantom } from './phantom.esm.js';
const phantom = new Phantom({
endpoint: 'http://localhost:8080',
apiKey: 'your-api-key'
});
const result = await phantom.init();
console.log('Visitor:', result.visitorId);
console.log('Confidence:', result.confidence);
console.log('Is Bot:', result.security.bot.isBot);
console.log('Is Tampered:', result.security.tampering.isTampered);
</script>Security Detection
Bot Detection
webdriver- navigator.webdriver flag__webdriver_evaluate- Selenium globalscallPhantom- PhantomJSheadless_ua- HeadlessChrome UAno_plugins- Missing pluginsfake_chrome- Chrome UA without chrome object
Incognito Detection
storage_quota- Limited storage (<120MB)filesystem- FileSystem API fails
Tampering Detection
canvas_noise- Inconsistent canvas rendersnavigator_spoofed- Modified navigator propertiesprototype_polluted- Modified prototypesfunction_tampered- Modified Function.toStringscreen_spoofed- Inconsistent screen dimensionswebgl_spoofed- GPU vendor/renderer mismatch
Confidence Scoring
Confidence (0.0-1.0) based on match method, bot score, and tampering score.
Auto-Tracked Events
| Event | Data |
|-------|------|
| $pageview | url, path, title, referrer |
| $scroll | threshold, percent |
| $click | tag, id, cls, text, href, x, y |
| $form_focus | tag, type, name, id |
| $form_blur | tag, type, name, filled |
| $input_change | tag, type, len |
| $form_submit | id, name, action, method |
| $page_hidden | - |
| $page_visible | duration |
| $performance | dns, tcp, ttfb, domReady, load, fcp |
| $route_change | trigger, url, path |
| $session_end | duration, pageViews, events |
API
// Initialize
const result = await phantom.init();
// Track
phantom.track('event', { data });
phantom.trackPageView();
await phantom.setUserId('user123', { traits });
await phantom.flush();
// Getters
phantom.getVisitorId(); // string | null
phantom.getConfidence(); // number (0-1)
phantom.getSecurity(); // { bot, incognito, tampering, confidence }
phantom.isBot(); // boolean
phantom.isIncognito(); // boolean
phantom.isTampered(); // boolean
// Cleanup
phantom.reset(); // Clear data
phantom.destroy(); // Flush and cleanupTiered Matching
- Exact (1.0) - All tiers match
- Stored ID (0.95) - localStorage ID + Tier1 match
- Tier 1+2 (0.90) - Hardware + Stable match
- Fuzzy (0.85+) - Component similarity
- New (1.0) - Create new visitor
Files
src/phantom.ts # Client (982 lines)
dist/phantom.esm.js # ES Module (17.8KB)
dist/phantom.js # UMD (18.3KB)
server/main.go # Server
demo/v3-test.html # Test page