Chapter 160 · Omnibus Instrument Integration
Subchapter 160.56
references/ruby-on-rails.mdMarkdown11 KBView on GitHub
PostHog makes it easy to get data about traffic and usage of your Ruby on Rails app. Integrating PostHog enables analytics, custom events capture, feature flags, and automatic exception tracking.
This guide walks you through integrating PostHog into your Rails app using the .
Install PostHog for Rails in seconds with our wizard by running this prompt with LLM coding agents (opens in a new tab) like Cursor and Bolt, or by running it in your terminal.
npx @posthog/wizard@latest
Or, to integrate manually, continue with the rest of this guide.
Add both gems to your Gemfile:
Gemfile
PostHog AI
gem 'posthog-ruby'
gem 'posthog-rails'Then run:
Terminal
PostHog AI
bundle installIdentifying users is required. Backend events need a
distinct_idthat matches the ID your frontend uses when callingposthog.identify(). Without this, backend events are orphaned — they can’t be linked to frontend event captures, session replays (opens in a new tab), LLM traces (opens in a new tab), or error tracking (opens in a new tab).See our guide on identifying users (opens in a new tab) for how to set this up.
Run the install generator to create the PostHog initializer:
Terminal
PostHog AI
rails generate posthog:installThis creates config/initializers/posthog.rb with sensible defaults and documentation.
The generated initializer includes all available options:
config/initializers/posthog.rb
PostHog AI
# Core PostHog client initialization
PostHog.init do |config|
# Required: Your PostHog API key
config.api_key = '<ph_project_token>'
# Optional: Your PostHog instance URL
config.host = 'https://us.i.posthog.com'
# Optional: Personal API key for feature flags
config.personal_api_key = 'phx_xxxxxxxxx'
# Error callback to detect misconfiguration
config.on_error = proc { |status, msg|
Rails.logger.error("PostHog error: #{msg}")
}
end
# Rails-specific configuration
PostHog::Rails.configure do |config|
config.auto_capture_exceptions = true # Enable automatic exception capture
config.report_rescued_exceptions = true # Report exceptions Rails rescues
config.auto_instrument_active_job = true # Instrument background jobs
config.capture_user_context = true # Include user info in exceptions
config.current_user_method = :current_user # Method to get current user
# Add additional exceptions to ignore
config.excluded_exceptions = ['MyCustomError']
endYou can find your project token and instance address in your project settings (opens in a new tab).
Tip: Use
Rails.application.credentials(opens in a new tab) to avoid hardcoding API keys. First, add your keys and then reference them in your initializer:Terminal
PostHog AI
rails credentials:editconfig/credentials.yml.enc
PostHog AI
posthog: api_key: <ph_project_token> host: https://us.i.posthog.com personal_api_key: phx_xxxxxxxxxconfig/initializers/posthog.rb
PostHog AI
config.api_key = Rails.application.credentials.posthog[:api_key] config.host = Rails.application.credentials.posthog[:host] config.personal_api_key = Rails.application.credentials.posthog[:personal_api_key]
Track custom events anywhere in your Rails app:
Ruby
PostHog AI
# Track an event
PostHog.capture(
distinct_id: current_user.id,
event: 'post_created',
properties: { title: @post.title }
)
# Identify a user
PostHog.identify(
distinct_id: current_user.id,
properties: {
email: current_user.email,
plan: current_user.plan
}
)For full details on setting up error tracking with Rails, see our Rails error tracking installation guide (opens in a new tab).
When auto_capture_exceptions is enabled, exceptions are automatically captured:
Ruby
PostHog AI
class PostsController < ApplicationController
def show
@post = Post.find(params[:id])
# Any exception here is automatically captured
end
endYou can also manually capture exceptions:
Ruby
PostHog AI
PostHog.capture_exception(
exception,
current_user.id,
{ custom_property: 'value' }
)When auto_instrument_active_job is enabled, ActiveJob exceptions are automatically captured with job context:
Ruby
PostHog AI
class EmailJob < ApplicationJob
def perform(user_id)
user = User.find(user_id)
UserMailer.welcome(user).deliver_now
# Exceptions are automatically captured
end
endBy default, PostHog extracts a distinct_id from job arguments by looking for a user_id key:
Ruby
PostHog AI
# PostHog will automatically use options[:user_id] as the distinct_id
ProcessOrderJob.perform_later(order.id, user_id: current_user.id)For more control, use the posthog_distinct_id class method:
Ruby
PostHog AI
class SendWelcomeEmailJob < ApplicationJob
posthog_distinct_id ->(user, options) { user.id }
def perform(user, options = {})
UserMailer.welcome(user).deliver_now
end
endPostHog integrates with Rails’ built-in error reporting:
Ruby
PostHog AI
# These errors are automatically sent to PostHog
Rails.error.handle do
# Code that might raise an error
end
Rails.error.record(exception, context: { user_id: current_user.id })PostHog automatically extracts the user’s distinct ID from user_id or distinct_id in the context hash.
PostHog Rails automatically captures user information from your controllers. If your user method has a different name, configure it:
Ruby
PostHog AI
PostHog::Rails.config.current_user_method = :logged_in_userBy default, PostHog Rails auto-detects the user’s distinct ID by trying these methods:
posthog_distinct_id – Define this on your User model for full controldistinct_id – Common analytics conventionid – Standard ActiveRecord primary keyYou can configure a specific method:
Ruby
PostHog AI
PostHog::Rails.config.user_id_method = :emailOr define a method on your User model:
Ruby
PostHog AI
class User < ApplicationRecord
def posthog_distinct_id
"user_#{id}" # or external_id, or any unique identifier
end
endThe following exceptions are not reported by default (common 4xx errors):
AbstractController::ActionNotFoundActionController::BadRequestActionController::InvalidAuthenticityTokenActionController::RoutingErrorActionController::UnknownFormatActiveRecord::RecordNotFoundAdd more with:
Ruby
PostHog AI
PostHog::Rails.config.excluded_exceptions = ['MyException']Use feature flags in your Rails app:
Ruby
PostHog AI
class PostsController < ApplicationController
def show
if PostHog.is_feature_enabled('new-post-design', current_user.id)
render 'posts/show_new'
else
render 'posts/show'
end
end
endFor local evaluation, ensure you’ve set personal_api_key:
Ruby
PostHog AI
config.personal_api_key = Rails.application.credentials.posthog[:personal_api_key]See our Ruby SDK docs (opens in a new tab) for details on local evaluation with Puma and Unicorn servers.
In your test environment, disable PostHog or use test mode:
config/environments/test.rb
PostHog AI
PostHog.init do |config|
config.test_mode = true # Events are queued but not sent
endOr in your specs:
spec/rails_helper.rb
PostHog AI
RSpec.configure do |config|
config.before(:each) do
allow(PostHog).to receive(:capture)
end
end| Option | Type | Default | Description |
|---|---|---|---|
| api_key | String | required | Your PostHog project token |
| host | String | https://us.i.posthog.com (opens in a new tab) | PostHog instance URL |
| personal_api_key | String | nil | For feature flag evaluation |
| test_mode | Boolean | false | Don’t send events (for testing) |
| on_error | Proc | nil | Error callback |
| Option | Type | Default | Description |
|---|---|---|---|
| auto_capture_exceptions | Boolean | false | Automatically capture exceptions |
| report_rescued_exceptions | Boolean | false | Report exceptions Rails rescues |
| auto_instrument_active_job | Boolean | false | Instrument ActiveJob |
| capture_user_context | Boolean | true | Include user info |
| current_user_method | Symbol | :current_user | Controller method for user |
| user_id_method | Symbol | nil | Method to extract ID from user object |
| excluded_exceptions | Array | [] | Additional exceptions to ignore |
Verify PostHog is initialized:
Ruby
PostHog AI
Rails.console
> PostHog.initialized?
=> trueCheck your excluded exceptions list
Verify middleware is installed:
Ruby
PostHog AI
Rails.application.middlewarecurrent_user_method matches your controller methodposthog_distinct_id, distinct_id, or idPostHog::Rails.config.user_id_method = :your_methodEnsure you’ve set personal_api_key in your configuration.
For any technical questions for how to integrate specific PostHog features into Rails (such as analytics, feature flags, A/B testing, etc.), have a look at our Ruby SDK docs (opens in a new tab).
Ask a question
HelpfulCould be better