Server-Side Google Analytics Event Tracking with Rails

Server-Side Google Analytics Event Tracking with Rails

As part of the signup and onboarding process improvements we're doing right now at Deveo, we're also trying to improve the usefulness of our metrics. One of the most important actions to track is user signups, and so we've been looking into ways of doing that accurately with Google Analytics.


A signup happens when a user fills and submits a form on our website. The form is processed by the website's Rails backend, and the user is redirected to Deveo itself if everything went OK. There are several approaches one could take to track something like this:

  • We could just look at new customers popping up in our CRM system. The problem with this is that the data can't be connected easily with any of the other data Google Analytics is collecting: Where do users come from? What do they do before they sign up?
  • We could track signups by triggering an event on the next page that follows a successful signup. In our case though, that path might be different for different users, and we don't want to have an extraneous "Welcome" or "Thank You" page interrupting the user flow, just to get some analytics recorded.
  • We could trigger an analytics event with JavaScript when the user submits the form. The problem with this is that the event delivery in Google Analytics is asynchronous, so we cannot be sure if the event was really recorded before the user's browser left the page (without resorting to some iffy setTimeout() trickery).

If you do some research (AKA Googling) around this problem, you'll find recommendations for all of these methods. For us, none of them felt right.

Universal Analytics And The Measurement Protocol

What we really want to do is send the event to Google Analytics from the server, since that seems to be the only option that's both reliable and unobtrusive to the user.

This used to be quite tricky with Google Analytics, but now they have a proper solution for it in their new Universal Analytics traking (currently in public beta): The Measurement Protocol.

From our perspective, the Measurement Protocol is basically nothing but an HTTP endpoint that receives Google Analytics tracking data. We can call it from our server-side code as long as we have the Analytics account information available.

Here is how we set it up for our marketing site - and how you can set it up for your Rails app or site:

1. Set Up A Universal Google Analytics Property

Unless your Analytics web property is already uses the Universal Analytics tracking method, you'll need to create a new web property. Most old properties use Classic Analytics instead, and that's still the default for new properties. You can see the type by navigating to the property in GA Admin, and opening the Tracking Info tab. If it says something like "Universal Analytics have been enabled", you're good to go.

If you do need to create a new property, just make sure you've selected the Universal property column on the creation screen:


Note that you'll also need to update the Google Analytics JavaScript tracking code on all your pages, so that your site will start gathering analytics to this new profile.

2. Set Up Google Analytics Configuration for Your Rails Application

After Step 1, your normal client-side tracking should already be fully functional. The rest of the article will be about setting up the server-side tracking in your Rails application.

First of all, let's put the Google Analytics configuration in its own YAML configuration file:

# config/google_analytics_settings.yml
  endpoint: ""
  version: 1
  tracking_code: UA-12345678-9
  • We have one configuration entry per Rails environment. We're only really interested in production data so that's the only one we configure (you may also want to add a second entry for the development environment while you're setting this up).
  • We configure the Measurement Protocol endpoint and version, matching the values in the GA documentation
  • We define our Google Analytics tracking code. This should be the same as you have in your client-side JavaScript tracking snippet (the value beginning with UA).

Next, let's make a simple Rails initializer that makes this configuration available to our code at runtime:

# config/initializers/load_google_analytics_settings.rb

config = YAML.load_file(Rails.root.join("config", "google_analytics_settings.yml"))[Rails.env]  
if config  
  • Here, we make the settings available in a global constant. It is initialized as an ActiveSupport HashWithIndifferentAccess, which means we will be able to access its keys either as Symbols or as Strings.
  • We load the YAML config file and look up the environment configuration that matches the current Rails environment. If there is one, we update our constant hash with its contents.

3. Add A Library Class for Invoking The Measurement Protocol

We want event tracking to be as simple as possible from our application's point of view, so let's make a library class that encapsulates all the details.

What we want is a method that sends an event to Google Analytics. To make this as simple as possible, we're going to include no more than a couple of things in the event:

  • The event category and action. These specify what the event is about, and you can use them later to associate the event with measurement goals.
  • The client id associated with the event. This will let you connect the event to all the other data you have about the same user's actions.

See the GA documentation for other kinds of data you could associate with the event.

Let's define a simple class with a method that takes these arguments. The method invokes the Measurement Protocol API in order to record the event. Here we are using the rest_client Gem, which makes HTTP calls ridiculously easy. (Be sure to add it to your Gemfile if you want to use it.)

# lib/google_analytics_api.rb
require 'rest_client'

class GoogleAnalyticsApi

  def event(category, action, client_id = '555')
    return unless GOOGLE_ANALYTICS_SETTINGS[:tracking_code].present?

    params = {
      tid: GOOGLE_ANALYTICS_SETTINGS[:tracking_code],
      cid: client_id
      t: "event",
      ec: category,
      ea: action

      RestClient.get(GOOGLE_ANALYTICS_SETTINGS[:endpoint], params: params, timeout: 4, open_timeout: 4)
      return true
    rescue  RestClient::Exception => rex
      return false

  • Line 5: The client_id argument is optional, with a default value of 555. This is a convention we picked up from the documentation.
  • Line 6: We skip the tracking if there's no tracking code in the configuration (which will be the case in development and test environments).
  • Lines 8-15: We construct the parameters for the API call, based on the method arguments and the global Analytics configuration
  • Lines 17-22: Here we make the actual API call to the Measurement Protocol. Note how we also set some timeout values so that the request won't be left hanging for too long if there's a network problem. We ignore any problems raised (by just returning false), so that a failing analytics call won't disturb other application behavior.

4. Pass The Analytics Client Id to Your Rails Actions

Before we're ready to call this new class from our controllers, there's one piece of data we need to pass from the web browser: This is the client id. It is an identifier Google Analytics assigns to each of your visitors, so that it can track their behavior over time.

Including the client id isn't strictly required (that's why we defined the default value 555), but it is highly recommended, because otherwise you won't be able to associate the server-side events with any other data you have in Google Analytics.

First, in all the forms that execute actions that you want to track - in our case, our signup forms - include a hidden form field for the Analytics client id:

<%= hidden_field_tag 'ga_client_id', '', :class => 'ga-client-id' %>

The value of the field is empty at first, because we won't know it before the Analytics JavaScript library has loaded. Instead, we will populate it from JavaScript.

The following snippet assumes you're using jQuery. Put it in a JavaScript file (or simply in a <script> tag in your HTML) somewhere after the Google Analytics JavaScript snippet.

{% codeblock app/assets/javascripts/ga.js %} $(document).ready(function() { ga(function(tracker) { var clientId = tracker.get('clientId'); $('.ga-client-id').val(clientId); }); }); {% endcodeblock %}

Our code is inside two callbacks: The first one is jQuery's document.ready, making sure that our page has loaded, and the second one is from Google Analytics, making sure it has initialized. In the code we simply get the current client id from the Google Analytics library, and put it as the value of any of those hidden form fields we might have on the page (identified by the CSS class).

5. Call the Analytics Client to Trigger An Event

That's it for all the setup! Now all we need to do is call our Google Analytics client from anywhere we want to track an event from. For example, we have something like this in the controller that handles signups:

# app/controllers/users_controller.rb'billing', 'signup', params[:ga_client_id])  

Finally, it is highly recommended you tuck these calls away in a background job, over Resque or one of its alternatives, so that you don't make a potentially slow and unreliable HTTP call to an external service during request processing.

When you've set everything up, you should start seeing these events in your Google Analytics reports. You can actually track them in real time, by navigating to Real-time -> Events in the Google Analytics web interface. You'll be able to see signups - all of them - fly past as they happen!

by: Tero Parviainen

Seamless software development.

Code management and collaboration platform with Git, Subversion, and Mercurial.

Sign up for free
comments powered by Disqus