Coder Social home page Coder Social logo

railslove / rack-tracker Goto Github PK

View Code? Open in Web Editor NEW
643.0 23.0 121.0 516 KB

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

Home Page: https://www.railslove.com/open-source

License: MIT License

Ruby 86.83% HTML 12.89% Roff 0.28%
rack-middleware google-analytics ruby ecommerce rack facebook tracking tracking-pixels

rack-tracker's Introduction

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

rack-tracker's People

Contributors

atd avatar bumi avatar chriscoffey avatar donschado avatar fabn avatar glaszig avatar haerezis avatar jhilden avatar jivagoalves avatar jolim avatar kspe avatar marisveide avatar mnin avatar mohanzhang avatar mortro avatar nachoabad avatar namxam avatar nicolasleger avatar pjkelly avatar remi avatar salimhb avatar sassela avatar smadeja avatar stephanpavlovic avatar stuwil avatar suninthesky avatar tongboy avatar wrozka avatar yutoji avatar zpfled avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rack-tracker's Issues

Support DNT (Do Not Track) request header

The DNT (Do Not Track) request header indicates the user's tracking preference. 
It lets users indicate whether they would prefer privacy rather than personalized content.

It should be very simple to add this feature and respect the users preference.

  • DNT: 0 The user prefers to allow tracking on the target site.
  • DNT: 1 The user prefers not to be tracked on the target site.

https://www.w3.org/2011/tracking-protection/drafts/tracking-dnt.html#dnt-header-field

facebook pixel fired outside concerned views

Hi,

first at all, thanks for your great work !

I have installed the tracker and I have few comments.

When specified in the controller method :
tracker do |t|
t.facebook_pixel :track, { type: 'ViewContent', options: { p: 'my_way' } }
end
the facebook pixel is correctly fired ..

but there is another one pixel fired too , PageView, altough I have modifyed the facebook_pixel template and delete the js track call in the template.

I still have fbq('track',"PageView"); at the end of the script.

how to avoid having pageview fb pixel on pages whereas nothing about it in the controller method ?

Regards,

Dynamic trackers

Hi,

I really would like to use this GEM.

Only thing is holding me back:
Ability to dynamically load different trackers.
For example: we have a multi tenant app. Every customer of us have their own GA code.
Due to the configuration it seems not really possible (in a decent way) to do this.

Is there an elegant solution for this?

Implement Facebook "Advanced Matching with the Pixel"

Hi!

Facebook has this advanced matching method when it allows to pass additional params about visitors to track when Facebook cookie is not present (like in apps which are inside iframe).

Here is the Facebook Tracking article:
https://developers.facebook.com/docs/facebook-pixel/pixel-with-ads/conversion-tracking/#advanced_match

Really need this feature.
It should allow to pass those params for each user session separately.

Thanks a lot!

Maris

No way of tracking virtual page views

This gem is pretty great, but it doesn't seem to have a way to set the page value to a virtual page and check refreshing js. Is this something in the pipes, or simply beyond the intended scope of the gem?

Html is messed up when analytics custom dimensions contain quotes, potential XSS vulnerability.

I'm tracking post authors as custom dimensions in analytics, I have this code in my controller:

POST_AUTHOR = :dimension3
# later in the controller
t.google_analytics :parameter, POST_AUTHOR => post.author.name

Issue n.1: If dimension's value contains a quote produced javascript is wrong, i.e. javascript output is

  ga('set', 'dimension3', 'Author's name');

I added the escape by myself (using a call to rails's ActionView::Helpers::JavaScriptHelper) and author's name was properly escaped to 'Author\'s name', however with this value something bad happens in the whole html document with some part of the HTML code is repeated twice starting at that variable value.

I did not understand what part of the code is causing this issue but you can easily reproduce it in analytics using "Some' value" as dimension value. Don't know if other trackers are affected by this issue.

For the moment I simply removed all quotes from my dimension values but imho this gem should handle escaping in values.

Can't get the google analytics part to work

I installed the gem and setup the google analytics part as specificed in the readme.

in config/application.rb i have got

config.middleware.use(Rack::Tracker) do
handler :google_analytics, { tracker: "U-XXX-X"}
end

and when i check the produced script then i get

ga('create', 'U-xxxxxx-X', {"cookieDomain":"auto"});

and not the expected

ga('create', 'U-xxxxxx-X', 'auto');

I am using rack-tracker 0.3.0 and rails 4.1.6 and ruby 2.1.3

Cheers,
Thomas

Google tag manager - dataLayer - array support

I would to like add an array to the dataLayer. I tried with the following code:

t.google_tag_manager :push, name: 'transactionProducts', value: [{ sku: 'DD44', name: 'T-shirt' }, { sku: 'DD66', name: 'Jeans' }]

But the output is a regular JSON object, with the ruby array being interpreted as a string:

dataLayer.push({
  'transactionProducts': '[{"sku"=>"DD44", "name"=>"T-shirt"}, {"sku"=>"DD66", "name"=>"Jeans"}]'
});

dateLayer.push data gets duplicated

In my registrations controller, if have a simple

 tracker do |t|
    t.google_tag_manager :push, {
        event:'eventName',
        eventContent:'signup'
    }
end

However, the generated code in my HTML ends up being :

dataLayer.push(
    {"event":"eventName","eventContent":"signup"},
    {"event":"eventName","eventContent":"signup"}
);

So I get 2 events fired up, instead of one. I debugged it in controller, with an iterator, with the debug mode of my IDE ... The generating code doesn't seem to be called twice. Would there be a way to check the content of the hash beforehand ? Therefore not pushing the data inside if it's already there. That would be kind of an ugly fix though :)

Let me know if I can be of assistance ! Thanks

Async?

We have a controller action that will trigger a Google Adwords Conversion. Unfortunately, it's asynchronous. How can we go about this and still benefit from using rack-tracker?

Can I use Rack::Tracker middleware both on my host application and my mountable engine ?

I have an application with an isolated engine mounted.
I'm trying to insert Rack::Tracker middleware on both my host application and my engine, both using the Google Analytics handler.

But I want the engine and the host application to use a different handler. I'm trying to achieve it like:

on config/application.rb:

config.middleware.use('Rack::Tracker') do
      handler :google_analytics, { tracker: 'UA-123222-2' }
end

and at engines/my_engine/lib/my_engine/engine.rb:

    initializer "professor.add_middleware" do |app|
      config.app_middleware.use('Rack::Tracker') do
        handler :google_analytics, { tracker: 'UA-0983333-3' }
      end
    end

But as I do that, when I go to any page on either my host application or my engine, I see that the both scripts are added to the page, not just the specific one I need.

i.e.:

<script type="text/javascript">
  if(typeof ga === 'undefined') {
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

    ga('create', 'UA-0983333-3', {});
  }
  ga('send', 'pageview', window.location.pathname + window.location.search);
</script>
<script type="text/javascript">
  if(typeof ga === 'undefined') {
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

    ga('create', 'UA-123222-2', {});
  }
  ga('send', 'pageview', window.location.pathname + window.location.search);
</script>

this snippet occurs either on myhostapplication.com/home or myengine/home. And I wanted that only the snippet defined on the engine initializer loads with the engine pages, and the snippet defined on the application loads with the application pages.

Does anyone knows how can I accomplish that? What I am doing wrong?

exact_position branch is no more

Hello Guys,

Thanks for the nice work :). I am maintaining an application who depended on this.

gem "rack-tracker", git:    "https://github.com/railslove/rack-tracker",
                    branch: "exact_position"

Looks like the branch is gone, and I can't tell weather this "exact_position" extra functionality got inside the current releases.

is it possible that I will be good by just moving to the stable release of the gem?

gem "rack-tracker"

Where to put custom handlers?

Thanks for the great gem — I'm using it successfully in production for FB and GA.

I'm trying to add a custom handler for Drip, but I'm having trouble.

By placing your sample code for a generic "MyHandler" into app/middleware, I get this error:

/app/middleware/templates/my_handler.erb:2:in 'block in singleton class': undefined local variable or method 'options' for MyHandler:Class (NameError)

I reckon it's a simple mistake. Any idea where I've gone awry?

app/middleware/my_handler.rb looks like:

class MyHandler < Rack::Tracker::Handler
  Tilt.new( File.join( File.dirname(__FILE__), 'templates', 'my_handler.erb')).render(self)
end

app/middleware/templates/my_handler.erb

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

relevant bit from config/development.rb:

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

Event objects can't be properly serialized using Rails :json serializer

Background: Rails.application.config.action_dispatch.cookies_serializer is set to :json (or :hybrid)

Problem: A rack tracker event object (such as Rack::Tracker::GoogleAnalytics::Send) wich was stored in the session and retrieved again, will be deserialized as a string like "#<Rack::Tracker::GoogleAnalytics::Send type=\"event\", category=\"...\", action=\"...\">"" instead of a proper object.

This results in an exception like NoMethodError: undefined method 'write' for #<String:0x00000007ae8bf0>

I'm not sure what the event objects need to implement in order to serialize well to JSON. Maybe include http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html ?

Add the functionality to dynamically deactivate tracker injection

Feature request

Would it make sense to you to have the possibility to add a lambda option in order to deactivate dynamically the tracker injection?
Something like:

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

Execution of tracker with render VS redirect_to and other types of responses

I am wondering a couple things concerning this gem.
I seem to have understood that what the gem does is to inject the various tracking codes into the view that's about to be rendered. The readme isn't clear about

  • Whether calling trackerin the controller action A1 that redirect_to an controller action A2 that renders something will replay the tracker code into the view of A2. Pretty much like Rails' flash VS flash_now
    For example : how do you track user registration ? It would make sense to track a register event in the controller action with a POST, and not in whatever page you are redirected to after.

  • Whether there is a support for non HTML responses such as JS responses
    For example : suppose I submit some AJAX form and I'm getting a JS response to confirm the event creation. Can I still track that and it will add a inject the code in the JS response ?

(not-set) in google analytics when sending events from server side?

I track some event server side using rack-tracker

However, when I view the results in GA, it seems like location, browser info are all not set when sending from server-side.

I want to know, how can I fill this information? I think this info can all get from cookies and then sent to GA from server-side?

Sending trackCustom events for Facebook

Facebook requirements state that to fire events that are non-standard events, should be fired with trackCustom method.
I see that there is a hard-coded 'track' method, regardless of what is set here:

tracker.facebook_pixel :track, {...}

If I call it like this:

tracker.facebook_pixel :trackCustom, {...}

it will anyway send fbq("track", ...).

What's your suggestion, how to send custom events?
Can you fix that, or I am using it wrong?

Thanks!

Multiple Trackers, per domain

Hi,

Is there a way I can configure multiple trackers, depending on domain?

config.middleware.use(Rack::Tracker) do
  handler :google_analytics, { tracker: 'XXXXX', cookieDomain: 'example.com' }
  handler :google_analytics, { tracker: 'YYYYY', cookieDomain: 'another.com' }
end

Maybe not this way, but something I can be capable to do this. My case, I have the one website, with 2 brands, depending on domain, today I load different tracker, since I'm using the common js solution (snippet on my page)

Tracking with params

I am trying to pass parameters in with my event tracking but it's not working as expected. I was following this, https://github.com/railslove/rack-tracker#parameters. Also I want to know how I can set things up so I can look at and filter each parameter associated with the event. I'm assuming these parameters get passed as "custom variables"?

top_events_-_google_analytics

Here's the code.

     tracker do |t|
        t.google_analytics :parameter, { category: params[:category] }
        t.google_analytics :parameter, { people: "#{params[:num_people_min]}-#{params[:num_people_max]}" }
        t.google_analytics :parameter, { appt_duration: params[:appt_duration] }
        t.google_analytics :parameter, { location: location.name } if location.present?
        t.google_analytics :parameter, { appt_start_time_s: params[:appt_start_time_s] }
        t.google_analytics :send, type: "event",
                                  category: "Reservation Form",
                                  action: "Buy Appt",
                                  label: formatted_data_for_analytics(p)
      end

I also noticed that for some reason events are not triggering every time. I had a few events that didn't fire when they should have. Let me know if there's common gotchas I'm missing.

Same property ID tracked twice

Hi there
In one of our projects I replaced the traditional google-analytics tracking-snippet with the rack-racker gem:

Like in the ReadMe, I added this:

config.middleware.use(Rack::Tracker) do
    handler :google_analytics, tracker: ENV['GOOGLE_ANALYTICS_ID'], anonymize_ip: true, advertising: true
end

to my production.rb

To get it working with Turbolinks, I also had to add the position: :body option.

Now, when I check the page with the Google Tag Assistant Add-On for Chrome, it complains about the property being tracked twice:

screen shot 2016-04-06 at 17 19 09
(The more pages you visit, the more duplicated properties are shown in the addon)

Is it really an issue or something, which can be ignored?
Thanks in advance

Any plans to convert FB custom audience & conversion pixels to new single pixel?

With FB switching from the existing two pixel system to a single pixel system with an EOL sometime in '16 is there any existing work to move the existing facebook tracker handler to the new standard?

Info: https://www.facebook.com/business/help/1686199411616919

If there is interest but nobody working on it yet I'd be happy to put together a pull request - I figured it would be better to ask first in case the question has come up before.

Thank you

How do I set to NOT use the debug version of google analytics ?

I ran it locally and thought that because it's running on development environment, the gem decided to use the debug version of the analytics.js

However even when pushed to production environment, it still requests for the analytics debug js.

How do I stop this from happening ?

Disable tracker from controller

Hi, looked through code and it seems there's no way to disable tracker from specific controller action? If that's the current case what would be the cleanest way to implement it?

rack-tracker fails with older Rails versions (e.g. 4.0.2)

In Rails 4.0.2 booting the server rack-tracker fails with following error. Upgrading the Rails version to 4.1.4 solved it for me. Maybe add backward compatibility for older Rails versions?

/Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/actionpack-4.0.2/lib/action_dispatch/middleware/stack.rb:43:in build': undefined method new' for Rack::Tracker:Module (NoMethodError) from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/actionpack-4.0.2/lib/action_dispatch/middleware/stack.rb:118:in block in build'
from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/actionpack-4.0.2/lib/action_dispatch/middleware/stack.rb:118:in each' from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/actionpack-4.0.2/lib/action_dispatch/middleware/stack.rb:118:in inject'
from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/actionpack-4.0.2/lib/action_dispatch/middleware/stack.rb:118:in build' from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/railties-4.0.2/lib/rails/engine.rb:495:in app'
from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/railties-4.0.2/lib/rails/application/finisher.rb:34:in block in <module:Finisher>' from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/railties-4.0.2/lib/rails/initializable.rb:30:in instance_exec'
from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/railties-4.0.2/lib/rails/initializable.rb:30:in run' from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/railties-4.0.2/lib/rails/initializable.rb:55:in block in run_initializers'
from /Users/koos/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/tsort.rb:150:in block in tsort_each' from /Users/koos/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/tsort.rb:183:in block (2 levels) in each_strongly_connected_component'
from /Users/koos/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/tsort.rb:219:in each_strongly_connected_component_from' from /Users/koos/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/tsort.rb:182:in block in each_strongly_connected_component'
from /Users/koos/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/tsort.rb:180:in each' from /Users/koos/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/tsort.rb:180:in each_strongly_connected_component'
from /Users/koos/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/tsort.rb:148:in tsort_each' from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/railties-4.0.2/lib/rails/initializable.rb:54:in run_initializers'
from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/railties-4.0.2/lib/rails/application.rb:215:in initialize!' from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/railties-4.0.2/lib/rails/railtie/configurable.rb:30:in method_missing'
from /Volumes/code/execli/config/environment.rb:7:in <top (required)>' from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.0.2/lib/active_support/dependencies.rb:229:in require'
from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.0.2/lib/active_support/dependencies.rb:229:in block in require' from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.0.2/lib/active_support/dependencies.rb:214:in load_dependency'
from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.0.2/lib/active_support/dependencies.rb:229:in require' from /Volumes/code/execli/config.ru:3:in block in

'
from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/rack-1.5.2/lib/rack/builder.rb:55:in instance_eval' from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/rack-1.5.2/lib/rack/builder.rb:55:in initialize'
from /Volumes/code/execli/config.ru:in new' from /Volumes/code/execli/config.ru:in '
from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/rack-1.5.2/lib/rack/builder.rb:49:in eval' from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/rack-1.5.2/lib/rack/builder.rb:49:in new_from_string'
from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/rack-1.5.2/lib/rack/builder.rb:40:in parse_file' from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/rack-1.5.2/lib/rack/server.rb:277:in build_app_and_options_from_config'
from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/rack-1.5.2/lib/rack/server.rb:199:in app' from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/railties-4.0.2/lib/rails/commands/server.rb:48:in app'
from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/rack-1.5.2/lib/rack/server.rb:314:in wrapped_app' from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/railties-4.0.2/lib/rails/commands/server.rb:75:in start'
from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/railties-4.0.2/lib/rails/commands.rb:76:in block in <top (required)>' from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/railties-4.0.2/lib/rails/commands.rb:71:in tap'
from /Users/koos/.rvm/gems/ruby-2.0.0-p353/gems/railties-4.0.2/lib/rails/commands.rb:71:in <top (required)>' from bin/rails:4:in require'
from bin/rails:4:in <main>

Will append to <head> in incorrect circumstances

Use Case: Usabilla.com script, includes <head> in the javascript. The JS is included before the </body>tag, and would be the second <head> tag in the document. Rack-tracker misinterprets this as being the actual <head>, and then tries to insert the code inside the javascript itself.

I can only assume the suggested solution would be "write a handler for usabilla" which I intend to do, however, this is something important to consider. I believe rack-tracker requires better validation when it parses <head> to remain reliable and consistent.

There are circumstances where <head> may appear in a document. For example, on a website that provides code samples or snippets.

I have tested this theory, and indeed, rack-tracker adds the code to my test case.

<pre> <head> <!--rack tracker code appears here --> </pre>

Easy solution would be to only add rack-tracker code to <head>:first

Note: I have not dug into rack-tracker codebase to see what the problem is, and it's very possible this could be unique to this particular application. I am on the clock, which is why I haven't taken the time to look into it, or test it on a fresh install. Please double check me, or I'll do a test myself when I have some time.

Bing tracking

Request

Like Google conversion tracking, add Bing tracking as well.

Google Tag Manager validation fails

Hello,

we are using rack-tracker v1.1.0 and we are having problems validating our site. Google says it can't verify the site becouse it is missing the google analytics snippet in the section.

A look at the google documentation confirms that one part of the gtm intergration has to be in the tag and the other one after the opening of the tag.

https://developers.google.com/tag-manager/quickstart

rack-tracker renders both parts before the closing of the body tag. Is there any way to change this?

Thanks in advance!

Best regards
Roberto

Google analytics events not working when value is provided?

Hi,

Thanks for a very handful and useful gem! I think there maybe a bug when a value is provided for a Google Analytics event. If I do something like this:

tracker do |t|
t.google_analytics :send, { type: 'event', category: 'test', action: 'action', label: 'label' }
end

then it works fine. But if I add a value to the params hash, the event wont track. I think it may have something to do with that the template seems to render eventValue: theValue (instead of value: theValue).

In my case I don't need a value so I worked-around it by not providing a value...

Does not work correctly with turbolinks

I have a Rails 4.2 app with turbolinks. Google Analytics is set up through rack-tracker and I can see the correct code being rendered on the page. However, it only tracks page views or events, if I do a full page reload in the browser. If I simply click through my page via links, I do NOT get any page views or events. I guess this is due to turbolinks, which prevents a full page reload. Is there an option, to attach the page view and event reporting to the "page:change" event instead of a full page reload?

Facebook Pixel doesn't work with Turbolinks

Hello guys!

I have this in my config file
config.middleware.use(Rack::Tracker) do handler :facebook_pixel, { id: ENV.fetch('PIXEL_ID'), position: :body } end

and this in index action in controller
tracker do |t| t.facebook_pixel :track, { type: 'ViewContent' } end

I'm using Facebook Pixel Helper and it shows "one pixel found" only if a do a full page reload ( I'm using turbolinks )

Getting data from Google analytics

Hello.

I have set analytics for my mobile application which sends track data to GA. According to this gems readme, I can send tracking data to google via my rails application. However, there isn't written anything about retrieving data from GA.

Is it even possible?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.