Pulse Analytics

Every qm new --mode=rails ships with Pulse: a complete first-party analytics stack. No third-party tracking. No cookies. Privacy-first.

What's Included

ComponentPurpose
public/t.jsLightweight page tracker (page_view, duration)
POST /eEvent ingestion endpoint
/admin/analyticsDashboard: top pages, traffic sources, devices
config/pulse_events.ymlKey events registry
bin/mcp_serverClaude Desktop MCP server (7 tools)

Architecture

LayerComponents
ModelsEvent, SessionRecord, DailyMetric
ServicesAnalytics::Collector, SessionManager, BotDetector, IpHasher, Rollup, Reporter, EventTracker
JobsAnalyticsRollupJob (daily), EventPruneJob (90-day retention)
ControllersEventsController, Admin::AnalyticsController

Event Types

EventTriggerProperties
page_viewPage load (automatic)referrer, title
durationPage exit (automatic)seconds
Custom eventsPulse.track() or EventTrackerUser-defined

Custom Key Events

Register domain-specific events:

qm generate event signup --description="User signed up"

Track from JavaScript:

window.Pulse.track('signup', { plan: 'pro' })

Track from Ruby:

Analytics::EventTracker.new.track('signup',
  path: '/register',
  properties: { plan: 'pro' }
)

MCP Server

Claude Desktop integration via bin/mcp_server. 7 tools:

ToolDescription
pulse_summaryAnalytics summary for a date range
pulse_top_pagesTop pages by views
pulse_traffic_sourcesReferrer breakdown
pulse_devicesDevice type distribution
pulse_event_countsEvent counts by type
pulse_list_eventsList registered key events
pulse_register_eventRegister a new key event

Setup in claude_desktop_config.json:

{
  "mcpServers": {
    "pulse": {
      "command": "ruby",
      "args": ["bin/mcp_server"],
      "cwd": "/path/to/your-app"
    }
  }
}

Privacy

  • IPs hashed with salted SHA256 (first 16 chars, not reversible)
  • No cookies; sessions use sessionStorage (cleared on browser close)
  • Bot detection: scoring system flags known bots and suspicious patterns
  • 90-day event retention (configurable via EventPruneJob)
  • Admin access via HTTP basic auth (credentials or env vars)