Ruby on Rails
Contents
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.
Beta: integration via LLM
Install PostHog for Rails in seconds with our wizard by running this prompt with LLM coding agents like Cursor and Bolt, or by running it in your terminal.
Or, to integrate manually, continue with the rest of this guide.
Features
- Automatic exception tracking – Captures unhandled and rescued exceptions
- ActiveJob instrumentation – Tracks background job exceptions
- User context – Automatically associates exceptions with the current user
- Smart filtering – Excludes common Rails exceptions (404s, etc.) by default
- Request context – Adds request metadata and optional PostHog tracing header identity/session context to captured events
- Rails 7.0+ error reporter – Integrates with Rails' built-in error reporting
Installation
Add both gems to your Gemfile:
Then run:
Identifying users
Identifying 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, LLM traces, or error tracking.See our guide on identifying users for how to set this up.
Generate the initializer
Run the install generator to create the PostHog initializer:
This creates config/initializers/posthog.rb with sensible defaults and documentation.
Configuration
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:
You can find your project token and instance address in your project settings.
Tip: Use
Rails.application.credentialsto avoid hardcoding API keys. First, add your keys and then reference them in your initializer:Terminalconfig/credentials.yml.encconfig/initializers/posthog.rb
Capturing events
Track custom events anywhere in your Rails app:
Identify a user and set their person properties:
The Rails integration delegates methods like capture, identify, alias, group_identify, evaluate_flags, capture_exception, flush, and shutdown to the initialized PostHog::Client.
Request context
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:
Error tracking
For full details on setting up error tracking with Rails, see our Rails error tracking installation guide.
Automatic exception tracking
When auto_capture_exceptions is enabled, exceptions are automatically captured:
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.
Manual exception capture
You can also manually capture exceptions:
If you evaluated feature flags for the request, pass the same snapshot to include matching flag properties on the exception event:
Background job exceptions
When auto_instrument_active_job is enabled, ActiveJob exceptions are automatically captured with job context:
Associating jobs with users
By default, PostHog extracts a distinct_id from job arguments by looking for a user_id key in hash arguments:
For more control, use the posthog_distinct_id class method. The proc or block receives the same arguments as perform:
You can also use a block:
Rails 7.0+ error reporter
PostHog integrates with Rails' built-in error reporting:
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.
User context
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:
User ID extraction
By default, PostHog Rails auto-detects the user's distinct ID by trying these methods in order:
posthog_distinct_id– Define this on your User model for full controldistinct_id– Common analytics conventionid– Standard ActiveRecord primary keypk– Primary key aliasuuid– For UUID-based primary keys
It also checks hash-like users for id, pk, and uuid keys.
You can configure a specific method:
Or define a method on your User model:
Excluded exceptions
The following exceptions are not reported by default (common 4xx errors):
AbstractController::ActionNotFoundActionController::BadRequestActionController::InvalidAuthenticityTokenActionController::InvalidCrossOriginRequestActionController::MethodNotAllowedActionController::NotImplementedActionController::ParameterMissingActionController::RoutingErrorActionController::UnknownFormatActionController::UnknownHttpMethodActionDispatch::Http::Parameters::ParseErrorActiveRecord::RecordNotFoundActiveRecord::RecordNotUnique
Add more with:
Feature flags
Evaluate flags once for the current user, then read values from the returned snapshot:
For multivariate flags and experiments, use get_flag:
When capturing an event after branching on a flag, pass the same flags snapshot so the event includes the exact flag values used by your code:
For local evaluation, ensure you've set personal_api_key:
See our Ruby SDK docs for details on local evaluation with Puma and Unicorn servers.
Note:
PostHog.is_feature_enabled,PostHog.get_feature_flag,PostHog.get_feature_flag_result,PostHog.get_feature_flag_payload, andPostHog.capture({ ..., send_feature_flags: true })still work during the migration period, but they're deprecated. PreferPostHog.evaluate_flagsfor new code.
Testing
In your test environment, disable network calls with test mode:
Or in your specs:
Configuration reference
Core PostHog options
| Option | Type | Default | Description |
|---|---|---|---|
api_key | String | required | Your PostHog project token. |
host | String | https://us.i.posthog.com | Fully qualified PostHog API host. |
personal_api_key | String | nil | 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 the experimental flag_definition_cache_provider can be passed as an options hash to PostHog.init(...); see the Ruby SDK docs for details.
Rails-specific options
Configure these via PostHog::Rails.configure or PostHog::Rails.config:
| 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 | Capture ActiveJob exceptions with job context. |
excluded_exceptions | Array | [] | Additional exception class names to ignore. |
use_tracing_headers | Boolean | true | Use X-PostHog-Distinct-Id and X-PostHog-Session-Id as request-scoped defaults. |
capture_user_context | Boolean | true | Include authenticated user info in exceptions. |
current_user_method | Symbol | :current_user | Controller method used to fetch the current user. |
user_id_method | Symbol | nil | Method used to extract the distinct ID from the user object. Auto-detects when nil. |
Troubleshooting
Exceptions not being captured
Verify PostHog is initialized:
RubyCheck your excluded exceptions list.
Verify middleware is installed:
Ruby
User context not working
- Verify
current_user_methodmatches your controller method. - Check that the user object responds to
posthog_distinct_id,distinct_id,id,pk, oruuid. - If using a custom identifier, set
PostHog::Rails.config.user_id_method = :your_method.
Feature flags not working
Ensure you've set personal_api_key in your configuration.
Next steps
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.