PostHog makes it easy to get data about traffic and usage of your Ruby on Rails app. Integrating PostHog enables analytics, custom event capture, feature flags, and automatic exception tracking.
This guide walks you through integrating PostHog into your Rails app using the posthog-rails gem.
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.
PostHog.init creates a single client instance used across your app. Avoid creating multiple PostHog::Client instances with the same API key, as this can cause dropped events and inconsistent behavior.
The generated initializer includes the most common options:
config/initializers/posthog.rb
PostHog AI
ruby
# Rails-specific configurationPostHog::Rails.configure do |config| config.auto_capture_exceptions = true # Enable automatic exception capture (default: false) config.report_rescued_exceptions = true # Report exceptions Rails rescues (default: false) config.auto_instrument_active_job = true # Instrument background jobs (default: false) config.use_tracing_headers = true # Use PostHog tracing headers for identity/session context (default: true) config.capture_user_context = true # Include authenticated user info in exceptions (default: true) config.current_user_method = :current_user # Method to get current user (default: :current_user) config.user_id_method = nil # Method to get ID from user object (default: auto-detect) # Add additional exceptions to ignore config.excluded_exceptions = ['MyCustomError']end# Core PostHog client initializationPostHog.init do |config| # Required: Your PostHog project 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' # Maximum number of events to queue before dropping (default: 10000) config.max_queue_size = 10_000 # Send events synchronously on the calling thread (default: false) config.sync_mode = false # Feature flags polling interval in seconds (default: 30) config.feature_flags_polling_interval = 30 # Feature flag request timeout in seconds (default: 3) config.feature_flag_request_timeout_seconds = 3 # Error callback to detect misconfiguration config.on_error = proc { |status, msg| Rails.logger.error("PostHog error: #{msg}") } # Before-send callback to modify or drop events config.before_send = proc { |event| event[:properties] ||= {} event[:properties]['environment'] = Rails.env event } # Disable network calls in test mode config.test_mode = true if Rails.env.test?end
The Rails integration delegates methods like capture, identify, alias, group_identify, evaluate_flags, capture_exception, flush, and shutdown to the initialized PostHog::Client.
PostHog Rails automatically applies request-scoped context to events captured during web requests. Request metadata such as $current_url, $request_method, $request_path, $user_agent, and $ip is added to event properties.
When use_tracing_headers is enabled, PostHog tracing headers (X-PostHog-Distinct-Id and X-PostHog-Session-Id) are also used as default distinct_id and $session_id values. Explicit distinct_id and properties passed to PostHog.capture always take precedence.
Disable tracing header identity/session capture if you do not want client-supplied tracing headers used for server-side events. Request metadata is still captured:
When auto_capture_exceptions is enabled, exceptions are automatically captured:
Ruby
PostHog AI
ruby
class PostsController < ApplicationController def show @post = Post.find(params[:id]) # Any exception here is automatically captured endend
report_rescued_exceptions controls whether exceptions Rails rescues (for example, exceptions rendered by Rails error pages) are captured. Enable it along with auto_capture_exceptions for complete error visibility, or leave it disabled to capture only unhandled exceptions.
class ProcessOrderJob < ApplicationJob posthog_distinct_id do |_order, notify_user_id| notify_user_id end def perform(order, notify_user_id) # Process the order... endend
PostHog integrates with Rails’ built-in error reporting:
Ruby
PostHog AI
ruby
# These errors are automatically sent to PostHogRails.error.handle do # Code that might raise an errorendRails.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. Other context keys are included as properties on the exception event.
PostHog Rails automatically captures authenticated user information from your controllers for exceptions. Authenticated Rails user context takes precedence over client-supplied tracing headers for exception identity.
If your user method has a different name, configure it:
Evaluate flags once for the current user, then read values from the returned snapshot:
Ruby
PostHog AI
ruby
class PostsController < ApplicationController def show flags = PostHog.evaluate_flags(current_user.id) if flags.enabled?('new-post-design') render 'posts/show_new' else render 'posts/show' end endend
For multivariate flags and experiments, use get_flag:
Note:PostHog.is_feature_enabled, PostHog.get_feature_flag, PostHog.get_feature_flag_result, PostHog.get_feature_flag_payload, and PostHog.capture({ ..., send_feature_flags: true }) still work during the migration period, but they’re deprecated. Prefer PostHog.evaluate_flags for new code.
Personal API key for local feature flag evaluation and remote config payloads.
max_queue_size
Integer
10000
Maximum number of events to keep in the async queue before dropping new events.
test_mode
Boolean
false
Keep events queued and do not send them. Useful for tests.
sync_mode
Boolean
false
Send events synchronously on the calling thread.
on_error
Proc
no-op
Callback called as on_error.call(status, error).
feature_flags_polling_interval
Integer
30
Seconds between local feature flag definition polls.
feature_flag_request_timeout_seconds
Integer
3
Timeout, in seconds, for feature flag requests.
before_send
Proc
nil
Callback that receives the event hash before it is queued or sent. Return a modified event hash, or nil to drop the event.
The PostHog.init block supports the options above. Less common core options like batch_size, disable_singleton_warning, skip_ssl_verification, and flag_definition_cache_provider can be passed as an options hash to PostHog.init(...); see the Ruby SDK docs (opens in a new tab) for details.
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).