vTilt
By roleFoundersKnow what to fix firstMarketersSee what happens after the clickCMOsSee what your budget really buys
By businessSaaSTurn signups into active usersEcommerceSee why shoppers abandon cartsAgenciesProve your work to clientsEnterpriseOne customer record for every team
MeasureWeb AnalyticsFind where buyers leaveSession ReplaySee why they left, not just that they didAdsKnow what paid visitors do nextIntegrationsOne snippet feeds your stack
ThinkPeopleOne profile per customerCustomer MemoryvTilt remembers every visitorSite KnowledgeAnswers and audits from your own pages
ActAsk AIAnswers from real behaviorAI ChatChat that knows the visitorEmail CampaignsEmail from real visits
PricingWhy vTiltDocs
Docs / Ruby on Rails
Getting Started
OverviewInstallInitializeIdentify usersTrack eventsLogout & resetVerify eventsCommon mistakes
Guides
Event forwardingReverse proxyRealtime dashboardSite knowledge
Frontend frameworks
Next.jsNuxt.jsVue.jsReactReact RouterRemixGatsbySvelte / SvelteKitAstroAngularTanStack StartDocusaurus
Backend frameworks
NestJSHonoCloudflare WorkersDjangoFlaskLaravelPhoenixRuby on Rails
Backend languages
PythonPHPRubyElixirGoJava.NET / C#Rust
Stack guides
Vue + PHP
API Reference
Browser SDK
Script bundlesAutocaptureWeb VitalsSession recordingChat widgetFeature readinessRemote configurationDebug logging
Node SDK
Install & setupCapture, identify & aliasContext & shutdownGlobal properties & opt-outError tracking
MCP server
Guides
OverviewAuthenticationOAuthAgent skills (prompts)AI intelligenceSite knowledgeGoogle AdsMeta Ads
Client setup
CursorClaude DesktopVS CodeCodex

Getting Started

OverviewInstallInitializeIdentify usersTrack eventsLogout & resetVerify eventsCommon mistakes

Guides

Event forwardingReverse proxyRealtime dashboardSite knowledge
NestJSHonoCloudflare WorkersDjangoFlaskLaravelPhoenixRuby on Rails

API Reference

MCP server

On this page

On this page

  • 1. Configure credentials
  • 2. Render the SDK in your application layout
  • 3. Server-side capture helper
  • 4. Run captures via Active Job
  • Next steps
DocsGuidesBackend frameworksRuby on Rails

Ruby on Rails

Last updated July 22, 2026

Integrate vTilt with Rails — render the SDK in your application layout, identify on every authenticated request, send server-side events from a Net::HTTP helper.

There's no native Ruby SDK yet, but vTilt's wire format is a plain JSON POST so any Ruby HTTP client (Net::HTTP, Faraday, HTTP.rb) can emit events. The pattern below covers rendering the Browser SDK in your Rails layout, identifying the authenticated user on every request, and sending server-side events from a queued job.

#1. Configure credentials

# config/credentials.yml.enc (or environment variables)
vtilt:
  token: { { TOKEN } }
  host: { { ORIGIN } }
yaml
# config/initializers/vtilt.rb
Rails.application.config.vtilt = {
  token: Rails.application.credentials.dig(:vtilt, :token) || ENV.fetch('VTILT_TOKEN'),
  host:  Rails.application.credentials.dig(:vtilt, :host)  || ENV.fetch('VTILT_HOST', 'https://www.vtilt.com'),
}
ruby

#2. Render the SDK in your application layout

<%# app/views/layouts/application.html.erb %>
<!doctype html>
<html lang="en">
<head>
  <script>
    window.__vtilt = <%= {
      token: Rails.application.config.vtilt[:token],
      host:  Rails.application.config.vtilt[:host],
      user:  current_user ? { id: current_user.id.to_s, email: current_user.email } : nil
    }.to_json.html_safe %>;
  </script>
  <script>
    !(function(t,e){/* ...vTilt loader snippet from Quick start... */})(document, window.vt || []);

    vt.init(window.__vtilt.token, {
      api_host: window.__vtilt.host,
      autocapture: true,
      capture_pageview: true,
      capture_pageleave: true,
    });

    if (window.__vtilt.user) {
      vt.identify(window.__vtilt.user.id, { email: window.__vtilt.user.email });
    }
  </script>
</head>
<body><%= yield %></body>
</html>
erb

Important

Identifying users in the application layout means every authenticated page load identifies — not just login. This is the most common bug to avoid; see Identify & alias for the full model.

#3. Server-side capture helper

For events that fire outside a browser session — webhooks, Active Job tasks, server-side conversions — POST directly to vTilt.

# app/services/vtilt.rb
require 'net/http'
require 'json'

class Vtilt
  def self.capture(distinct_id:, event:, properties: {})
    cfg = Rails.application.config.vtilt
    uri = URI.join(cfg[:host], '/api/e')

    Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https', open_timeout: 2, read_timeout: 2) do |http|
      req = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json')
      req.body = {
        api_key: cfg[:token],
        event: event,
        distinct_id: distinct_id,
        properties: properties,
      }.to_json
      http.request(req)
    end
  rescue StandardError => e
    Rails.logger.warn("vtilt capture failed: #{e.message}")
  end
end
ruby
# app/controllers/checkouts_controller.rb
class CheckoutsController < ApplicationController
  def complete
    Vtilt.capture(
      distinct_id: current_user.id.to_s,
      event: 'purchase_completed',
      properties: { amount: 99.99 },
    )
    render json: { ok: true }
  end
end
ruby

#4. Run captures via Active Job

For low-latency endpoints, push the capture to a background job so analytics never blocks the user-facing response.

# app/jobs/vtilt_capture_job.rb
class VtiltCaptureJob < ApplicationJob
  queue_as :default

  def perform(distinct_id, event, properties = {})
    Vtilt.capture(distinct_id: distinct_id, event: event, properties: properties)
  end
end
ruby
VtiltCaptureJob.perform_later(user.id.to_s, 'subscription_renewed', { plan: user.plan })
ruby

#Next steps

  • Identify & alias — anonymous → known user merge.
  • Event forwarding — fan events out to GA4, Meta CAPI, PostHog.
  • Reverse proxy — block-resistant ingestion.
  • Common mistakes — integration pitfalls to avoid before you ship.
PreviousPhoenixIntegration guidesNextPythonIntegration guides