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. Start — PulseGateSession.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