Ruby API Integration

The Mixpanel Ruby library is designed to be used for scripting, or in circumstances when a user isn't directly interacting with your application on the web or a mobile device.

Mixpanel also provides a powerful and easy to use client-side JavaScript library for web applications. This library offers platform-specific features and conveniences that can make Mixpanel implementations much simpler, and can scale naturally to an unlimited number of clients. The client-side Javascript library is the preferred way to add Mixpanel to user-facing web applications.

Installing the library

You can get the library with

$ gem install mixpanel-ruby

Once the mixpanel-ruby gem is installed, you can use the Mixpanel library in your applications with:

require 'mixpanel-ruby'

Sending events

Mixpanel events are sent using an instance of the Mixpanel::Tracker class.

You can instantiate an instance of Mixpanel::Tracker with a String containing your Mixpanel project token. You can find your project token in the settings dialog of the Mixpanel web application.

Once you have an instance of the tracker, you can track events with by providing a distinct id and a name for your event to the Mixpanel::Tracker#track

require 'mixpanel-ruby'

tracker = Mixpanel::Tracker.new(PROJECT_TOKEN)

# Tracks an event, 'Sent Message',
# with distinct_id user_id
tracker.track(user_id, 'Sent Message')

# You can also include properties to describe
# the circumstances of the event
tracker.track(user_id, 'Plan Upgraded', {
    'Old Plan' => 'Business',
    'New Plan' => 'Premium'
})

Mixpanel determines default geolocation data ($city, $region, mp_country_code) using the IP address on the incoming request. As all server-side calls will likely originate from the same IP (that is, the IP of your server), this can have the unintended effect of setting the location of all of your users to the location of your datacenter. Read about best practices for geolocation with server-side implementations.

Combining anonymous and identifiable user data

It's important to send the same distinct_id with each event that an individual user triggers. Events recorded with different distinct_ids will be treated in Mixpanel as if they were performed by different users.

There are times when it can be convenient to start referring to a user by a different identifier in your implementation. The most common case is after registration, when a user switches from being an anonymous user (with an anonymous distinct_id) to an authenticated user with an (authenticated id). In this case, you can create an alias for the user to keep the distinct_id consistent. An alias is a string stored in a Mixpanel lookup table that is associated with an anonymous distinct_id. Once written, aliases are not editable. Any data sent to Mixpanel with an alias as the distinct_id will be remapped and written to disk using the alias's corresponding anonymous distinct_id. This allows you to start identifying a user by an authenticated id without changing the distinct_id that is ultimately written in Mixpanel.

# This call will send a request to Mixpanel to
# associate all future events with new_internal_id
# with existing events associated with
# original_anonymous_id
tracker.alias(new_internal_id, original_anonymous_id)

Typically, you will call tracker.alias once in a user's lifetime, when the user first signs up and is assigned an internal id.

Aliases don't take effect until the alias request hits the Mixpanel server. Because of this, unlike most Mixpanel tracking and update methods, alias sends a synchronous HTTP request directly to Mixpanel whenever it is called, regardless of how you've configured your tracker.

Storing user profiles

In addition to events, you can send People Analytics profile updates to Mixpanel. Mixpanel can maintain a profile of each of your users, storing information you know about them. An update is a message that changes the properties of a People Analytics profile.

You can use profiles to explore and segment users by who they are, rather than what they did. You can also use profiles to send messages, such as emails, SMS, or push notifications.

Mixpanel determines default geolocation data ($city, $region, mp_country_code) using the IP address on the incoming request. As all server-side calls will likely originate from the same IP (that is, the IP of your server), this can have the unintended effect of setting the location of all of your users to the location of your datacenter. Read about best practices for geolocation with server-side implementations.

Setting profile properties

Instances of Mixpanel::Tracker have a property called people that is an instance of Mixpanel::People. You can use people to send profile updates.

// create or update a profile with First Name, Last Name,
// E-Mail Address, Phone Number, and Favorite Color
// without updating geolocation data or $last_seen
tracker.people.set('12345', {
    '$first_name'       => 'John',
    '$last_name'        => 'Doe',
    '$email'            => 'john.doe@example.com',
    '$phone'            => '5555555555',
    'Favorite Color'    => 'red'
}, ip = 0, {'$ignore_time' => 'true'});

This call to Mixpanel::People#set will change the value of properties on user 12345's profile. If there isn't a profile with distinct_id 12345 in Mixpanel already, a new profile will be created. If user 12345 already has has any of these properties set on their profile, the old values will be overwritten with the new ones.

Incrementing numeric properties

You can change the current value of numeric properties using people.increment. This is useful when you want to keep a running tally of things, such as games played, emails sent, or points earned.

tracker.people.increment('12345', {
   'Logins used' => 1,
   # use a negative number to subtract
   'Logins remaining' => -1,
})

Appending to list properties

Use people.append to add an item to an existing list-valued property. The values you send with the append will be added to the end of the list for each named property. If the property doesn't exist, it will be created with a one element list as its value.

tracker.people.append('12345', {
    'Favorite Fruits' => 'Apples'
})

Other types of profile updates

There are a few other types of profile updates. They're exposed as members of Mixpanel::People

Tracking revenue

Mixpanel makes it easy to analyze the revenue you make from individual customers. By associating charges with user profiles, you can compare revenue across different customer segments and calculate things like lifetime value.

You can track a single transaction with the track_charge method of Mixpanel::Tracker#people. Sending a message created with track_charge will add transactions to the individual user profile, which will also be reflected in the Mixpanel Revenue report.

# Records a charge of $9.99 from user '12345'
tracker.people.track_charge('12345', 9.99)

# records a charge of $30.50 on the 2nd of January
mixpanel.people.track_charge("12345", 30.50, {
    '$time' => DateTime.parse("Jan 2 2013"),
})

Scaling your server-side tracking

By default, Mixpanel::Tracker sends a request to Mixpanel immediately for every tracking message or profile update. This is convenient for getting started quickly, but almost all server-side use of the Mixpanel library will eventually want to do the IO associated with tracking in a separate thread or process from the events being tracked.

The Mixpanel library provides two mechanisms for separating your tracking from your IO; The Mixpanel::Tracker block constructor and the Mixpanel::Consumer class.

Using blocks with Mixpanel::Tracker.new

In addition to your token, Mixpanel::Tracker::new takes an optional block. A block is given, when you call Mixpanel::Tracker#track or any of the profile update methods on Mixpanel::Tracker#people, the tracker will call your block instead of sending data directly to Mixpanel.

You can use the code in your block to send the data to a separate process, add it to a queue, or write it to a log.

tracker_log = open("MIXPANEL_LOG.txt", "w+")

# Tracker blocks take two arguments-
# a type (either :event or :profile_update)
# and a message (a JSON string containing
# your Mixpanel message, suitable for
# sending to Mixpanel)

tracker = Mixpanel::Tracker.new(YOUR_TOKEN) do |type, message|
    tracker_log.write([ type, message ].to_json + "\n")
end

Using Mixpanel::Consumer

The Mixpanel library also offers classes to send the messages you record. You can use Mixpanel::Consumer to send messages to Mixpanel.

mixpanel = Mixpanel::Consumer.new
open("MIXPANEL_LOG.txt", "r+") do |log|
    log.each_line do |line|
        type, message = JSON.load(line)
        # Each call communicates with Mixpanel
        mixpanel.send!(type, message)
    end
end

The combination of a block passed to Mixpanel::Tracker::new and a Mixpanel::Consumer makes it simple to use the Mixpanel library with a queueing system. For example

# In your time-sensitive process
tracker = Mixpanel::Tracker.new(YOUR_TOKEN) do |type, message|
    @queue.set('mixpanel_queue', [ type, message ].to_json)
end

# Track just like you would in any other situation
tracker.track(user_id, 'Sent Message')
tracker.people.increment(user_id, {
    'Messages Sent' => 1
})

# In a worker process on another machine
mixpanel = Mixpanel::Consumer.new
loop do
    job = @queue.get('mixpanel_queue')
    mixpanel.send!(*JSON.load(job))
end