Visitor Tracking
The tracking system records detailed visitor behavior for analytics, heatmaps, and session replay.
Frontend Integration
Include the tracker script on any page. The script is minified when served (same build step as /form.js; run npm run build:form locally if you change the source).
<script src="https://your-worker.your-domain.workers.dev/tracker.js"></script>
<script>
PulseGateSession.init({ endpoint: 'https://your-worker.your-domain.workers.dev' });
</script>What Gets Tracked
| Event Type | Trigger | Data Captured |
|---|---|---|
page_view | Page load, SPA navigation | Page URL |
click | Mouse click | x, y coordinates, element selector |
scroll | Window scroll (250ms throttle) | Scroll depth percentage (0-100) |
mousemove | Mouse movement (100ms throttle) | x, y coordinates |
navigation | pushState or popstate | Page URL |
visibility_change | Tab switch | Visibility state |
Session Lifecycle
- Start —
PulseGateSession.init()generates a fingerprint, calls/track/session/start, receivessession_id - Track — Events are queued client-side and flushed every 5 seconds via
/track/events/batchonly while the page is active (document.visibilityState === 'visible') - Inactive — When the tab is hidden or the user leaves, nothing is sent (no flush on hidden, no send on
beforeunload); this avoids beacon queue limits and cancelled requests
Client-Side Queue
Events are buffered in an in-memory queue (max 500 events) and flushed:
- Every 5 seconds (interval timer), but only when the page is visible
Flushing runs only when the page is visible; when the tab is hidden or the user navigates away, nothing is sent. Flushing uses navigator.sendBeacon when available, with XHR fallback. To avoid the browser’s ~64KB limit on queued keepalive data, payloads larger than 50KB (e.g. rrweb recording batches) are sent via XHR instead of sendBeacon.
SPA Support
The tracker monkey-patches history.pushState and listens for popstate events to detect client-side navigation in single-page applications.
Public API
PulseGateSession.init({ endpoint: '...' }) // Start session
PulseGateSession.trackEvent('custom', data) // Queue a custom event
PulseGateSession.flush() // Force-flush event queueStorage
- D1 — Session records with aggregates (
event_count,page_views,clicks,max_scroll_percent). Raw events are not stored in D1; see R2-first events. - KV — Real-time counters (session count, unique IPs/ASNs per fingerprint), session update throttle (20s)
- R2 — Raw event batches (append-only); used for session replay and analytics