• Stars
    star
    647
  • Rank 69,579 (Top 2 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 10 years ago
  • Updated 8 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Tracking made easy: Don’t fool around with adding tracking and analytics partials to your app and concentrate on the things that matter.

Rack::Tracker

Code Climate Build Status

Rationale

Most of the applications we're working on are using some sort of tracking/analytics service, Google Analytics comes first but its likely that more are added as the project grows. Normally you'd go ahead and add some partials to your application that will render out the needed tracking codes. As time passes by you'll find yourself with lots of tracking snippets, that will clutter your codebase :) When just looking at Analytics there are solutions like rack-google-analytics but they just soley tackle the existence of one service.

We wanted a solution that ties all services together in one place and offers an easy interface to drop in new services. This is why we created rack-tracker, a rack middleware that can be hooked up to multiple services and exposing them in a unified fashion. It comes in two parts, the first one is the actual middleware that you can add to the middleware stack the second part are the service-handlers that you're going to use in your application. It's easy to add your own custom handlers, but to get you started we're shipping support for the services mentioned below out of the box:

Respecting the Do Not Track (DNT) HTTP header

The Do Not Track (DNT) HTTP header is a HTTP header that requests the server to disable its tracking of the individual user. This is an opt-out option supported by most browsers. This option is disabled by default and has to be explicitly enabled to indicate the user's request to opt-out. We believe evey application should respect the user's choice to opt-out and respect this HTTP header.

Since version 2.0.0 rack-tracker respects that request header by default. That means NO tracker is injected IF the DNT header is set to "1".

This option can be overwriten using the DO_NOT_RESPECT_DNT_HEADER => true option which must be set on any handler that should ignore the DNT header. (but please think twice before doing that)

Example on how to not respect the DNT header

use Rack::Tracker do
  # this tracker will be injected EVEN IF the DNT header is set to 1
  handler :maybe_a_friendly_tracker, { tracker: 'U-XXXXX-Y', DO_NOT_RESPECT_DNT_HEADER: true }
  # this tracker will NOT be injected if the DNT header is set to 1
  handler :google_analytics, { tracker: 'U-XXXXX-Y' }
end

Further reading on the DNT header:

Installation

Add this line to your application's Gemfile:

gem 'rack-tracker'

And then execute:

$ bundle

Or install it yourself as:

$ gem install rack-tracker

Usage

Add it to your middleware stack

config.middleware.use(Rack::Tracker) do
  handler :google_analytics, { tracker: 'U-XXXXX-Y' }
end

This will add Google Analytics as a tracking handler.

Sinatra / Rack

You can even use Rack::Tracker with Sinatra or respectively with every Rack application

Just insert the Tracker in your Rack stack:

web = Rack::Builder.new do
  use Rack::Tracker do
    handler :google_analytics, { tracker: 'U-XXXXX-Y' }
  end
  run Sinatra::Web
end

run web

Although you cannot use the Rails controller extensions for obvious reasons, its easy to inject arbitrary events into the request environment.

request.env['tracker'] = {
  'google_analytics' => [
    { 'class_name' => 'Send', 'category' => 'Users', 'action' => 'Login', 'label' => 'Standard' }
  ]
}

Services

Google Global Site Tag (gtag.js)

Trackers

Google Global Site tag allows configuring multiple trackers. Use the tracker option to configure the ids:

config.middleware.use(Rack::Tracker) do
  handler :google_global, { trackers: [ { id: 'U-XXXXX-Y' }, { id: 'U-WWWWWW-Z'} ] }
end

Google Analytics

Events

To issue Events from the server side just call the tracker method in your controller.

  def show
    tracker do |t|
      t.google_analytics :send, { type: 'event', category: 'button', action: 'click', label: 'nav-buttons', value: 'X' }
    end
  end

It will render the following to the site source:

  ga('send', { 'hitType': 'event', 'eventCategory': 'button', 'eventAction': 'click', 'eventLabel': 'nav-buttons', 'value': 'X' })

Parameters

You can set parameters in your controller too:

  def show
    tracker do |t|
      t.google_analytics :parameter, { dimension1: 'pink' }
    end
  end

Will render this:

  ga('set', 'dimension1', 'pink');

Enhanced Ecommerce

You can set parameters in your controller:

  def show
    tracker do |t|
      t.google_analytics :enhanced_ecommerce, {
        type: 'addItem',
        id: '1234',
        name: 'Fluffy Pink Bunnies',
        sku: 'DD23444',
        category: 'Party Toys',
        price: '11.99',
        quantity: '1'
      }
    end
  end

Will render this:

  ga("ec:addItem", {"id": "1234", "name": "Fluffy Pink Bunnies", "sku": "DD23444", "category": "Party Toys", "price": "11.99", "quantity": "1"});

Ecommerce

You can even trigger ecommerce directly from within your controller:

  def show
    tracker do |t|
      t.google_analytics :ecommerce, { type: 'addItem', id: '1234', affiliation: 'Acme Clothing', revenue: '11.99', shipping: '5', tax: '1.29' }
    end
  end

Will give you this:

  ga('ecommerce:addItem', { 'id': '1234', 'affiliation': 'Acme Clothing', 'revenue': '11.99', 'shipping': '5', 'tax': '1.29'  })

To load the ecommerce-plugin, add some configuration to the middleware initialization. This is not needed for the above to work, but recommened, so you don't have to take care of the plugin on your own.

  config.middleware.use(Rack::Tracker) do
    handler :google_analytics, { tracker: 'U-XXXXX-Y', ecommerce: true }
  end

Google Adwords Conversion

You can configure the handler with default options:

config.middleware.use(Rack::Tracker) do
  handler :google_adwords_conversion, { id: 123456,
                                        language: "en",
                                        format: "3",
                                        color: "ffffff",
                                        label: "Conversion label",
                                        currency: "USD" }
end

To track adwords conversion from the server side just call the tracker method in your controller.

  def show
    tracker do |t|
      t.google_adwords_conversion :conversion, { value: 10.0 }
    end
  end

You can also specify a different value from default options:

  def show
    tracker do |t|
      t.google_adwords_conversion :conversion, { id: 123456,
                                                 language: 'en',
                                                 format: '3',
                                                 color: 'ffffff',
                                                 label: 'Conversion Label',
                                                 value: 10.0 }
    end
  end

Google Tag Manager

Google Tag manager code snippet supports the container id

  config.middleware.use(Rack::Tracker) do
    handler :google_tag_manager, { container: 'GTM-XXXXXX' }
  end

You can also use an experimental feature to track pageviews under turbolinks, which adds a pageView event with a virtualUrl of the current url.

  config.middleware.use(Rack::Tracker) do
    handler :google_tag_manager, { container: 'GTM-XXXXXX', turbolinks: true }
  end

Data Layer

GTM supports a dataLayer for pushing events as well as variables.

To add events or variables to the dataLayer from the server side, just call the tracker method in your controller.

  def show
    tracker do |t|
      t.google_tag_manager :push, { price: 'X', another_variable: ['array', 'values'] }
    end
  end

Facebook

Use in conjunction with the Facebook Helper to confirm your event fires correctly.

First, add the following to your config:

  config.middleware.use(Rack::Tracker) do
    handler :facebook_pixel, { id: 'PIXEL_ID' }
  end

Dynamic Pixel Configuration

If you need to have different pixel ids e.g. based on the request or serving pages for different accounts, you have the possibility to achieve this by passing a lambda:

  config.middleware.use(Rack::Tracker) do
    handler :facebook_pixel, { id: lambda { |env| env['PIXEL_ID'] } }
  end

and set the pixel id within the request env variable. Here an example on how it can be done in a rails action:

  class MyController < ApplicationController
    def show
      request.env['PIXEL_ID'] = 'DYNAMIC_PIXEL_ID'
    end
  end

Standard Events

To track Standard Events from the server side just call the tracker method in your controller.

  def show
    tracker do |t|
      t.facebook_pixel :track, { type: 'Purchase', options: { value: 100, currency: 'USD' } }
    end
  end

Will result in the following:

  fbq("track", "Purchase", {"value":"100.0","currency":"USD"});

You can also use non-standard (custom) event names for audience building when you do not need to track or optimize for conversions.

  tracker do |t|
    t.facebook_pixel :track_custom, { type: 'FrequentShopper', options: { purchases: 24, category: 'Sport' } }
  end

Visual website Optimizer (VWO)

Just integrate the handler with your matching account_id and you will be ready to go

  use Rack::Tracker do
    handler :vwo, { account_id: 'YOUR_ACCOUNT_ID' }
  end

GoSquared

To enable GoSquared tracking:

config.middleware.use(Rack::Tracker) do
  handler :go_squared, { tracker: 'ABCDEFGH' }
end

This will add the tracker to the page like so:

  _gs('ABCDEFGH');

You can also set multiple named trackers if need be:

config.middleware.use(Rack::Tracker) do
  handler :go_squared, {
    trackers: {
      primaryTracker: 'ABCDEFGH',
      secondaryTracker: '1234567',
    }
  }
end

This will add the specified trackers to the page like so:

  _gs('ABCDEFGH', 'primaryTracker');
  _gs('1234567', 'secondaryTracker');

You can set a variety of options by passing the following settings. If you don't set any of the following options, they will be omitted from the rendered code.

  • :anonymize_ip
  • :cookie_domain
  • :use_cookies
  • :track_hash
  • :track_local
  • :track_params

Visitor Name

To track the visitor name from the server side, just call the tracker method in your controller.

  def show
    tracker do |t|
      t.go_squared :visitor_name, { name: 'John Doe' }
    end
  end

It will render the following to the site source:

  _gs("set", "visitorName", "John Doe");

Visitor Properties

To track visitor properties from the server side, just call the tracker method in your controller.

  def show
    tracker do |t|
      t.go_squared :visitor_info, { age: 35, favorite_food: 'pizza' }
    end
  end

It will render the following to the site source:

  _gs("set", "visitor", { "age": 35, "favorite_food": "pizza" });

Criteo

Criteo retargeting service.

Basic configuration

config.middleware.use(Rack::Tracker) do
  handler :criteo, { set_account: '1234' }
end

Other global criteo handler options are:

  • set_customer_id: 'x'
  • set_site_type: 'd' - possible values are m (mobile), t (tablet), d (desktop)
  • set_email: 'email'

Option values can be either static or dynamic by providing a lambda being reevaluated for each request, e.g. set_customer_id: lambda { |env| env['rack.session']['user_id'] }

Tracking events

This will track a basic event:

def show
  tracker do |t|
    t.criteo :view_item, { item: 'P0001' }
  end
end

This will render to the follwing code in the JS:

window.criteo_q.push({"event": "viewItem", "item": "P001" });

The first argument for t.criteo is always the criteo event (e.g. :view_item, :view_list, :track_transaction, :view_basket) and the second argument are additional properties for the event.

Another example

t.criteo :track_transaction, { id: 'id', item: { id: "P0038", price: "6.54", quantity: 1 } }

Zanox

Zanox

Basic Configuration

config.middleware.use(Rack::Tracker) do
  handler :zanox, { account_id: '1234' }
end

Mastertag

This is an example of a mastertag:

def show
  tracker do |t|
    t.zanox :mastertag, { id: "25GHTE9A07DF67DFG90T", category: 'Swimming', amount: '3.50' }
  end
end

This will render to the follwing code in the JS:

window._zx.push({"id": "25GHTE9A07DF67DFG90T"});

and the following variables:

zx_category = 'Swimming';
zx_amount = '3.50';

Conversion tracking

This is an example of a lead event:

def show
  tracker do |t|
    t.zanox :lead, { order_i_d: 'DEFC-4321' }
  end
end

This is an example of a sale event:

def show
  tracker do |t|
    t.zanox :sale, { customer_i_d: '123456', order_i_d: 'DEFC-4321', currency_symbol: 'EUR', total_price: '150.00' }
  end
end

Hotjar

Hotjar

config.middleware.use(Rack::Tracker) do
  handler :hotjar, { site_id: '1234' }
end

Bing

Bing

To add the tracking snippet:

config.middleware.use(Rack::Tracker) do
  handler :bing, { tracker: '12345678' }
end

To send conversion events:

tracker do |t|
  t.bing :conversion, {
    type: 'event',
    category: 'Users',
    action: 'Login',
    label: 'Standard',
    value: 10
  }
end

Hubspot

Hubspot

config.middleware.use(Rack::Tracker) do
  handler :hubspot, { site_id: '1234' }
end

Drift

Drift

config.middleware.use(Rack::Tracker) do
  handler :drift, account_id: 'DRIFT_ID'
end

Heap

Heap. Heap has Projects (e.g. "Main") which have multiple Environments (e.g. "Production" or "Development"). env_id is therefore the numerical ID that represents the Environment. See Settings -> Projects -> Environments in your dashboard.

config.middleware.use(Rack::Tracker) do
  handler :heap, env_id: 'HEAP_ID'
end

Custom Handlers

Tough we give you handlers for a few tracking services right out of the box, you might be interested adding support for your custom tracking/analytics service.

Writing a handler is straight forward ;) and there are just a couple of methods that your class needs to implement.

Start with a plain ruby class that inherits from Rack::Tracker::Handler

class MyHandler < Rack::Tracker::Handler
  ...
end

If you want to customize the rendering of your template, you can overwrite the handlers #render method:

def render
  Tilt.new( File.join( File.dirname(__FILE__), 'template', 'my_handler.erb') ).render(self)
end

There might be cases where you need to modify the response at multiple places. To do so you can overwrite the #inject-method in your handler. For an example please have a look at the Google Tag Manager implementation.

This will render the template/my_handler.erb and inject the result into the source. You can be creative about where the template is stored, but we tend to have them around our actual handler code.

<script>
  console.log('my tracker: ' + <%= options.to_json %>)
</script>

Lets give it a try! We need to mount our new handler in the Rack::Tracker middleware

  config.middleware.use(Rack::Tracker) do
    handler MyHandler, { awesome: true }
  end

Everything you're passing to the handler will be available as #options in your template, so you'll also gain access to the env-hash belonging to the current request.

Run your application and make a request, the result of the above template can be found right before </head>. You can change the position in your handler-code:

class MyHandler < Rack::Tracker::Handler
  self.position = :body

  ...
end

The snippit will then be rendered right before </body>.

To enable the tracker dsl functionality in your controllers you need to implement the track class method on your handler:

def self.track(name, *event)
  # do something with the event(s) to prepare them for your template
  # and return a hash with a signature like { name => event }
end

Checkout the existing handlers in lib/rack/tracker for some inspiration. :)

Please note

Most tracking is done using some kind of Javascript and any tracking data is simply passed on. Using unvalidated user input in the tracking might result in XSS issues. Do only use secure data.

Contributing

First of all, thank you for your help! 💚

If you want a feature implemented, the best way to get it done is to submit a pull request that implements it. Tests, readme and changelog entries would be nice.

  1. Fork it ( http://github.com/railslove/rack-tracker/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

More Repositories

1

epics

EBICS client for Ruby
Ruby
108
star
2

smurfville

Smurfville is the home of SMURF, a new and modular approach to Rails frontend development based on the SMACSS approach for CSS. This gem provides a set of tools that help following this approach.
Ruby
82
star
3

fontello_rails_converter

CLI gem for comfortably working with icon fonts (open, download, convert) from http://fontello.com for usage in Rails apps.
Ruby
73
star
4

cmxl

your friendly MT940 SWIFT file parser for bank statements
Ruby
46
star
5

birthday

LOOKING FOR NEW MAINTAINER - Birthday gem creates convenient methods for date and datetime fields in ActiveRecord, making it possible to look for birthdays or anniversaries without a hassle.
Ruby
45
star
6

rcvr-app

recover provides localities a privacy-compliant, safe, and easy way for their guests to check in. See https://www.recoverapp.de/ for more details.
TypeScript
41
star
7

fight_csv

Makes handling csv documents a breeze!
Ruby
38
star
8

i18n_viz

Gem to visualize i18n strings within a rails project
Ruby
37
star
9

kickerapp

Ruby
25
star
10

railslove_deploy

UNMAINTAINED and OLD. no longer recommended to use. The Railslove Deploy recipes to setup a Rail/rack app from scratch
Ruby
14
star
11

rcvr-api

Recover Cologne Api, kneipen kontakt tracer. recover provides localities a privacy-compliant, safe, and easy way for their guests to check in. See https://www.recoverapp.de/ for more details.
Ruby
13
star
12

showoff-presentations

Railslove presentations created with showoff
JavaScript
11
star
13

iban_calculator

A wrapper for ibanrechner.de API. It allows converting bank account data from legacy syntax to new SEPA IBAN/BIC
Ruby
11
star
14

Scalarium-CLI

Allows you to deploy apps hosted on Scalarium from the command line
Ruby
10
star
15

rails-ssr-react-demo

Demo of Rails with server-side rendered React
Ruby
8
star
16

sepa-clearer

Ruby
7
star
17

ebicsbox

EBICS http interface
Ruby
6
star
18

talks-we-love

5
star
19

roadtrip

Deploy and host static sites with S3, CloudFront and Route53. 🚐
JavaScript
5
star
20

listenl8r

listenl8r is a great way to bookmark audio files on the web.
Ruby
5
star
21

snuffles

A wrapper around the native fetch function, providing a more convenient way to use it for JSON requests
JavaScript
5
star
22

construct

Continuous Integration Server written in Rails, supporting Github and Codebase payloads
Ruby
5
star
23

Freckly

Freckle Gem
Ruby
4
star
24

What-The-Commit

Commits any changes with a message from What The Commit
Ruby
4
star
25

happypdf_renderer

a easy to use interface to happyPDF.com
Ruby
4
star
26

Will-Paypal

Small and Simple Paypal API Wrapper
Ruby
4
star
27

german-onb-geojson

geojson of german "Orts­netz­be­reiche"
JavaScript
4
star
28

Gem-Constructor

Simple gem skeleton build - bundler + rspec
Ruby
3
star
29

chef-nginx-ng

Ruby
3
star
30

contactually-api

This is a simple API Wrapper for the contactually API.
Ruby
3
star
31

discourse_disable_user_activation

Simple gem to disable user activation in Discourse
Ruby
2
star
32

traxel-pipe

A simple Sinatra app to debug HTTP requests created by tracking pixels (traxels), etc. Making use of heroku + pusherapp
JavaScript
2
star
33

mobilove

simple wrapper for mobilant.de
Ruby
2
star
34

patterns

A library of patterns, so you don't have to write them anew every other month
2
star
35

giropay_stalker

Allows you to easily test a german bank code number for giropay support
Ruby
2
star
36

lipisha

API wrapper for https://lipisha.com
Ruby
2
star
37

federung

Helps with your bumps!
TypeScript
2
star
38

revealjs-template

reveal.js Template for Railslove presentations
JavaScript
2
star
39

recover-backlog

Backlog tickets for the recover app. recover provides localities a privacy-compliant, safe, and easy way for their guests to check in. See https://www.recoverapp.de/ for more details.
2
star
40

newrelic_npi

CHEF cookbook for installing/configuring npi and using npi to install newrelic plugins
Ruby
1
star
41

kicker-tinder

Ruby
1
star
42

vention-dention

Vention Dention Homepage
1
star
43

chef-unattended_upgrades

Ruby
1
star
44

meine-checkins

Beauftragt bei Stadt Köln. Meine Checkins macht Kontaktnachverfolgung noch einfacher und zeigt wie wichtig Teamwork in der Pandemie ist. Commissioned by the City of Cologne. Meine Checkins makes contact tracing easier and shows how important teamwork is in the pandemic.
TypeScript
1
star
45

railslove-token

Demo of a ETH token
1
star
46

meine-checkins-backlog

1
star
47

who_got_my

Railslove University Sample App
Ruby
1
star
48

videodelayer

Delayer of everything.
C
1
star
49

key_value_logging

Replacement for rails TaggedLogging using key-value pairs instead of flat tags
Ruby
1
star
50

Hackathon2012

Railslove Hackathon 2012
1
star
51

chef-railslove

Setup Rails apps with love
Ruby
1
star
52

squirrel

Ruby
1
star
53

reorder-github-diff

reorders the github pull request file diff tab to display the spec file below the actual file
JavaScript
1
star
54

react-redux-webpack-template

JavaScript
1
star
55

heart-chamber

Railslove API
1
star
56

railslove-cli

Ruby
1
star
57

instant_login

Ruby
1
star
58

Freckly-App

Shows total minutes tracked (using Freckle) on projects that are in your Pivotal tracker account
Ruby
1
star
59

mbaasy-express-middleware

Middlware for Express to interact with the Mbaasy In-App-Purchase validation service
JavaScript
1
star
60

react-i18n-viz

Visualization of i18n-strings for react
JavaScript
1
star
61

afterbuy_api

This is a ruby wrapper for the afterbuy API
Ruby
1
star
62

wastedtimeprojects.com

The source code for wastedtimeprojects.com
Ruby
1
star
63

build-flow

A toolkit to automatically build and deploy Middleman Site to S3
Ruby
1
star
64

cowokatrapp

JavaScript
1
star
65

example-cookbooks

Example Chef cookbooks for Scalarium
Ruby
1
star
66

expositional

Review apps for expo
JavaScript
1
star