Skip to content

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).

html
<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 TypeTriggerData Captured
page_viewPage load, SPA navigationPage URL
clickMouse clickx, y coordinates, element selector
scrollWindow scroll (250ms throttle)Scroll depth percentage (0-100)
mousemoveMouse movement (100ms throttle)x, y coordinates
navigationpushState or popstatePage URL
visibility_changeTab switchVisibility state

Session Lifecycle

  1. StartPulseGateSession.init() generates a fingerprint, calls /track/session/start, receives session_id
  2. Track — Events are queued client-side and flushed every 5 seconds via /track/events/batch only while the page is active (document.visibilityState === 'visible')
  3. 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

javascript
PulseGateSession.init({ endpoint: '...' })   // Start session
PulseGateSession.trackEvent('custom', data)  // Queue a custom event
PulseGateSession.flush()                     // Force-flush event queue

Storage

  • 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