Rails developers have plenty of analytics options — but most of them involve third-party JavaScript that bloats your bundle, requires consent banners, or sends user data to Google. If you want clean traffic data without the compliance overhead, here’s how to add privacy-first analytics to a Rails app in under 5 minutes.
The One-Line Setup
Add the Measure.events tracking script to your application layout:
<%# app/views/layouts/application.html.erb %>
<head>
<title>My App</title>
<%= csrf_meta_tags %>
<%= csp_meta_tags %>
<!-- Measure.events — no cookies, no consent required -->
<script async src="https://lets.measure.events/api/script/YOUR_SITE_KEY"></script>
</head>
Replace YOUR_SITE_KEY with the key from your Measure.events dashboard. That’s the minimum setup — pageviews are now tracked automatically across your entire app.
Turbo and SPA Support
If your Rails app uses Turbo (Hotwire), single-page transitions don’t trigger a full page reload — which means the standard script won’t catch navigation events. Fix it with a Stimulus controller or a Turbo event listener:
// app/javascript/controllers/analytics_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
connect() {
document.addEventListener("turbo:load", () => {
if (typeof measure !== 'undefined') {
measure("pageview")
}
})
}
}
Or more directly in your application.js:
// app/javascript/application.js
document.addEventListener("turbo:load", () => {
if (window.measure) window.measure("pageview")
})
Tracking Custom Events
Beyond pageviews, you’ll want to track meaningful user actions — signups, button clicks, feature usage:
<!-- Track a signup button click -->
<button data-action="click->analytics#trackSignup">
Get Started
</button>
// In your Stimulus controller or vanilla JS
trackSignup() {
measure("signup_click", { plan: "starter" })
}
Or inline for simpler cases:
<%= button_to "Subscribe", subscribe_path,
data: { action: "click->analytics#track",
"analytics-event-param": "subscribe_click" } %>
Server-Side Events via the API
For events you can’t track client-side — completed payments, background job completions, webhook events — use the Measure.events HTTP API directly from Ruby:
# lib/measure_events.rb
require 'net/http'
require 'json'
module MeasureEvents
SITE_KEY = ENV.fetch('MEASURE_SITE_KEY')
BASE_URL = 'https://lets.measure.events/api/v1'
def self.track(event_name, properties = {})
uri = URI("#{BASE_URL}/events")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request['Authorization'] = "Bearer #{ENV.fetch('MEASURE_API_KEY')}"
request.body = { event: event_name, site_key: SITE_KEY, **properties }.to_json
http.request(request)
rescue => e
Rails.logger.warn "MeasureEvents tracking failed: #{e.message}"
end
end
Then call it from any model, controller, or job:
# After a successful Stripe webhook
class StripeWebhooksController < ApplicationController
def create
case event.type
when 'checkout.session.completed'
MeasureEvents.track('subscription_started', plan: params[:plan])
when 'customer.subscription.deleted'
MeasureEvents.track('subscription_cancelled')
end
end
end
Excluding Admin Traffic
You don’t want your own dashboard visits inflating your numbers. Exclude them cleanly:
<%# app/views/layouts/application.html.erb %>
<% unless current_user&.admin? %>
<script async src="https://lets.measure.events/api/script/YOUR_SITE_KEY"></script>
<% end %>
Or if you prefer a data attribute approach:
<script async src="https://lets.measure.events/api/script/YOUR_SITE_KEY"
data-exclude-paths="/admin,/sidekiq"></script>
The MCP Server: Query Your Traffic with AI
This is where Measure.events goes beyond a standard analytics tool.
Add the MCP server to your Cursor or Claude configuration:
{
"mcpServers": {
"measure-events": {
"url": "https://lets.measure.events/mcp",
"headers": {
"Authorization": "Bearer your_api_key_here"
}
}
}
}
Now you can ask your AI assistant directly:
“How many signups did we get this week?” “Which blog post is driving the most traffic to /pricing?” “Is /dashboard usage trending up since we shipped the new feature?”
No dashboard tab-switching. No building custom queries. Your Rails app’s traffic data is part of your AI workflow.
GDPR Compliance
Measure.events is fully cookieless — no document.cookie writes, no localStorage tracking, no fingerprinting. There’s nothing to consent to. You can remove your cookie consent banner entirely for analytics purposes (check your jurisdiction, but for most EU sites, cookieless analytics doesn’t require consent).
For Rails apps with a consent management setup, you can conditionally load the script:
<% if user_consented_to_analytics? %>
<script async src="https://lets.measure.events/api/script/YOUR_SITE_KEY"></script>
<% end %>
Though with a truly cookieless setup, this conditional isn’t strictly necessary.
Get Started
- Sign up for a free 14-day trial
- Create a site and copy your site key
- Add the script tag to
app/views/layouts/application.html.erb - Deploy — you’re tracking
The whole setup takes about 5 minutes. The MCP server config takes another 2.
Ready to see accurate analytics?
No cookies. No consent banners. No personal data. $29/mo with a 14-day free trial.
Start free trial →