Ruby Library

Our Ruby library lets you record analytics data from your ruby code. The requests hit our servers, and then we route your data to any analytics service you enable on your integrations page. The library is open-source, so you can check it out on Github.

All of our server-side libraries are built for high-performance, so you can use them in your web server controller code. This library uses an internal queue to make identify and track calls non-blocking and fast. It also batches messages and flushes asynchronously to our servers.

If you have any questions, run into any problems or just want to chat about the code, feel free to email us at friends@segment.io or submit an issue on Github.

Getting Started

Bundler

If you’re using bundler, add the following line to your project’s Gemfile:

gem 'analytics-ruby', '<1.0'

Then if you’re using rails, you can initialize inside your config/initializers/analytics_ruby.rb

Analytics = AnalyticsRuby       # Alias for convenience
Analytics.init({
    secret: 'YOUR_WRITE_KEY',          # The write key for #{project.owner.login}/#{project.slug}
    on_error: Proc.new { |status, msg| print msg }  # Optional error handler
})

Directly from your Application

If you’re using the gem directly from your application you’ll need to:

gem install analytics-ruby
require 'analytics-ruby'

Analytics = AnalyticsRuby       # Alias for convenience
Analytics.init({
    secret: 'YOUR_WRITE_KEY',          # The write key for #{project.owner.login}/#{project.slug}
    on_error: Proc.new { |status, msg| print msg }  # Optional error handler
})

Unicorn

If you’re using unicorn in production to run multiple ruby processes, you’ll need to initialize the module in the post-fork section of your unicorn.rb config file.

# unicorn.rb
require 'analytics-ruby'

before_fork do |server, worker|
  [...]
end

after_fork do |server, worker|
  [...]
  if defined? AnalyticsRuby
    Analytics = AnalyticsRuby     # Alias for convenience
    Analytics.init({
      secret: 'YOUR_WRITE_KEY',        # The write key for #{project.owner.login}/#{project.slug}
      on_error: Proc.new { |status, msg| print msg }  # Optional error handler
    })
  end
end

This happens because init spawns a different thread, which is not properly copied and run between separate processes.

Huge thanks to Michael Whalen for being the first to debug the process.

Passenger

If you’re using passenger in production to run multiple worker processes, you’ll need to initialize the analytics module in your environment.rb when those workers are initiated.

# config/environment.rb
require 'analytics-ruby'

if defined?(PhusionPassenger)
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
    if forked # We're in smart spawning mode.
      Analytics = AnalyticsRuby     # Alias for convenience
      Analytics.init({
        secret: 'YOUR_WRITE_KEY',        # The write key for #{project.owner.login}/#{project.slug}
        on_error: Proc.new { |status, msg| print msg }  # Optional error handler
      })
    else
      # We're in direct spawning mode. We don't need to do anything.
    end
  end
end

This happens because Analytics.init spawns a different thread, which is not properly copied and run between separate processes.

Thanks to the developers at Meetingless for creating the initial config.


Identify

identify lets you tie a user to their actions and record traits about them.

You’ll want to identify a user with any relevant information as soon as they log-in or sign-up. Learn more on the Identify page.

Analytics.identify(
    user_id: '019mr8mf4r',
    traits: { email: '#{ user.email }', friends: 872 })
user_id String The ID for this user in your database.
traits Hash, optional A Hash of traits you know about the user. Things like: email, name or friends.
timestamp Time, optional A Time object representing when the identify took place. This is most useful if you’re importing historical data. If the identify just happened, leave it blank and we’ll use the server’s time.
context Hash, optional A Hash that can include things like userAgent or ip.

Track

track lets you record the actions your users perform.

You’ll want to track an event whenever the user clicks, taps or submits something in your app. Learn more on the Track page.

Analytics.track(
    user_id: '019mr8mf4r', 
    event: 'Purchased Item', 
    properties: { revenue: 39.95, shipping: '2-day' })
user_id String The ID for this user in your database.
event String The name of the event you’re tracking. We recommend human-readable names like Played Song or Updated Status.
properties Hash, optional A Hash of properties for the event. If the event was Added to Cart, it might have properties like price or product.
timestamp DateTime, optional A DateTime representing when the event took place. If the identify just happened, leave it out and we’ll use the server’s time. If you’re importing data from the past make sure you send a timestamp.
context Hash, optional A Hash that can include things like userAgent or ip.

Alias

alias is how you associate one identity with another. In Mixpanel it’s used to associate an anonymous user with an identified user once they sign up. For KISSmetrics and Trak.io if your user switches IDs, you can use ‘alias’ to rename the ‘user_id’.

This is most frequently needed if you’re using Mixpanel. Read the method docs here.

Analytics.alias(from, to)

Here’s a full example:

# the anonymous user does actions ...
Analytics.track(user_id: 'anonymous_user', event: 'Anonymous Event')
# the anonymous user signs up and is aliased
Analytics.alias(from: 'anonymous_user', to: 'identified@gmail.com')
# the identified user is identified
Analytics.identify(user_id: 'identified@gmail.com', traits: { plan: 'Free' })
# the identified user does actions ...
Analytics.track(user_id: 'identified@gmail.com', event: 'Identified Action')

Flush

If you’re running any sort of script or internal queue system to upload data, you’ll want to call analytics.flush() at the end of execution to ensure that all messages are sent to our servers.

analytics.flush()

Calling flush will block execution until all messages are processed, so it is not recommended in normal execution of your production application.

In order to track pageviews in a Rails app with Turbolinks you’ll need to do more than just our standard analytics.page(); function.

You’ll need to use this code, which listens for a page change:

$(document).on('ready page:change', function() {
analytics.page();
})

This will also track regular pageviews, so it can be replace the standard analytics.page(); found in your Segment.io javascript snippet.

Performance

Our libraries are built to support high performance environments. That means it is safe to use analytics-ruby on a web server that’s serving hundreds of requests per second.

Every method you call does not result in an HTTP request, but is queued in memory instead. Messages are flushed in batch in the background, which allows for much faster operation.

By default, our library will flush:

  • the very first time it gets a message
  • whenever messages are queued and there is no outstanding request

The queue consumer makes only a single outbound request at a time to avoid saturating your server’s resources. If multiple messages are in the queue, they are sent together in a batch call.

You can specify the following additional options to determine how the queue operates and to help debug possible errors. None of them are required for normal operation.

# Error handler to log statements
on_error = Proc.new { |status, msg| print msg }

Analytics.init({
  secret: 'YOUR_WRITE_KEY',
  on_error: on_error,
  max_queue_size: 10000,
  batch_size: 100
})
on_error Proc, optional A handler which is called whenever errors are returned from the API. Useful for debugging and first time integrations.
max_queue_size FixNum, optional The max number of messages to put in the queue before refusing to queue more (defaults to 10,000).
batch_size FixNum, optional The max number of events/identifies to send in a single batch (defaults to 100). The API servers will not respond to messages over a certain size, so 100 is a safe default.

If you ever have any questions, or see anywhere we can improve our documentation, just shoot us an email at friends@segment.io!