{"id":13416488,"url":"https://github.com/railslove/rack-tracker","last_synced_at":"2025-06-14T13:05:52.172Z","repository":{"id":19853243,"uuid":"23115567","full_name":"railslove/rack-tracker","owner":"railslove","description":"Tracking made easy: Don’t fool around with adding tracking and analytics partials to your app and concentrate on the things that matter.","archived":false,"fork":false,"pushed_at":"2024-03-19T14:09:52.000Z","size":516,"stargazers_count":649,"open_issues_count":17,"forks_count":122,"subscribers_count":22,"default_branch":"master","last_synced_at":"2025-06-02T07:10:51.793Z","etag":null,"topics":["ecommerce","facebook","google-analytics","rack","rack-middleware","ruby","tracking","tracking-pixels"],"latest_commit_sha":null,"homepage":"https://www.railslove.com/open-source","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/railslove.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-08-19T15:34:30.000Z","updated_at":"2024-11-08T10:17:31.000Z","dependencies_parsed_at":"2024-06-18T15:29:44.282Z","dependency_job_id":"7482a601-d860-4b78-a606-49df40a49ad5","html_url":"https://github.com/railslove/rack-tracker","commit_stats":{"total_commits":278,"total_committers":43,"mean_commits":6.465116279069767,"dds":0.7913669064748201,"last_synced_commit":"de0da83dd0316ac6dc7f24faaab9b428751bdfa0"},"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"purl":"pkg:github/railslove/rack-tracker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railslove%2Frack-tracker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railslove%2Frack-tracker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railslove%2Frack-tracker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railslove%2Frack-tracker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/railslove","download_url":"https://codeload.github.com/railslove/rack-tracker/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railslove%2Frack-tracker/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259820812,"owners_count":22916548,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ecommerce","facebook","google-analytics","rack","rack-middleware","ruby","tracking","tracking-pixels"],"created_at":"2024-07-30T21:00:59.532Z","updated_at":"2025-06-14T13:05:52.152Z","avatar_url":"https://github.com/railslove.png","language":"Ruby","readme":"# Rack::Tracker\n\n[![Code Climate](https://codeclimate.com/github/railslove/rack-tracker/badges/gpa.svg)](https://codeclimate.com/github/railslove/rack-tracker) [![Build Status](https://travis-ci.org/railslove/rack-tracker.svg?branch=master)](https://travis-ci.org/railslove/rack-tracker)\n\n## Rationale\n\nMost of the applications we're working on are using some sort of tracking/analytics service,\nGoogle Analytics comes first but its likely that more are added as the project grows.\nNormally you'd go ahead and add some partials to your application that will render out the\nneeded tracking codes. As time passes by you'll find yourself with lots of tracking\nsnippets, that will clutter your codebase :) When just looking at Analytics there are\nsolutions like `rack-google-analytics` but they just soley tackle the existence of one\nservice.\n\nWe wanted a solution that ties all services together in one place and offers\nan easy interface to drop in new services. This is why we created `rack-tracker`, a\nrack middleware that can be hooked up to multiple services and exposing them in a unified\nfashion. It comes in two parts, the first one is the actual middleware that you can add\nto the middleware stack the second part are the service-handlers that you're going to use\nin your application. It's easy to add your own [custom handlers](#custom-handlers),\nbut to get you started we're shipping support for the services [mentioned below](#services)\nout of the box:\n\n\n## Respecting the Do Not Track (DNT) HTTP header\n\nThe Do Not Track (DNT) HTTP header is a HTTP header that requests the server to disable its tracking of the individual user.\nThis 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.\nWe believe evey application should respect the user's choice to opt-out and respect this HTTP header.\n\nSince 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\".\n\nThis option can be overwriten using the `DO_NOT_RESPECT_DNT_HEADER =\u003e true` option which must be set on any handler that should ignore the DNT header. (but please think twice before doing that)\n\n### Example on how to not respect the DNT header\n\n```ruby\nuse Rack::Tracker do\n  # this tracker will be injected EVEN IF the DNT header is set to 1\n  handler :maybe_a_friendly_tracker, { tracker: 'U-XXXXX-Y', DO_NOT_RESPECT_DNT_HEADER: true }\n  # this tracker will NOT be injected if the DNT header is set to 1\n  handler :google_analytics, { tracker: 'U-XXXXX-Y' }\nend\n```\n\nFurther reading on the DNT header:\n\n* [Wikipedia Do Not Track](https://en.wikipedia.org/wiki/Do_Not_Track)\n* [EFF: Do Not Track](https://www.eff.org/issues/do-not-track)\n\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n    gem 'rack-tracker'\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install rack-tracker\n\n## Usage\n\nAdd it to your middleware stack\n\n```ruby\nconfig.middleware.use(Rack::Tracker) do\n  handler :google_analytics, { tracker: 'U-XXXXX-Y' }\nend\n````\n\nThis will add Google Analytics as a tracking handler.\n\n## Sinatra / Rack\n\nYou can even use Rack::Tracker with Sinatra or respectively with every Rack application\n\nJust insert the Tracker in your Rack stack:\n\n```ruby\nweb = Rack::Builder.new do\n  use Rack::Tracker do\n    handler :google_analytics, { tracker: 'U-XXXXX-Y' }\n  end\n  run Sinatra::Web\nend\n\nrun web\n```\n\nAlthough you cannot use the Rails controller extensions for obvious reasons, its easy\nto inject arbitrary events into the request environment.\n\n```ruby\nrequest.env['tracker'] = {\n  'google_analytics' =\u003e [\n    { 'class_name' =\u003e 'Send', 'category' =\u003e 'Users', 'action' =\u003e 'Login', 'label' =\u003e 'Standard' }\n  ]\n}\n```\n\n## Services\n\n### Google Global Site Tag (gtag.js)\n\n* `:anonymize_ip` -  sets the tracker to remove the last octet from all IP addresses, see https://developers.google.com/analytics/devguides/collection/gtagjs/ip-anonymization for details.\n* `:cookie_domain` -  sets the domain name for the [GATC cookies](https://developers.google.com/analytics/devguides/collection/gtagjs/cookies-user-id). If not set its the website domain, with the www. prefix removed.\n* `:user_id` -  defines a proc to set the [userId](https://developers.google.com/analytics/devguides/collection/gtagjs/cookies-user-id). Ex: `user_id: lambda { |env| env['rack.session']['user_id'] }` would return the user_id from the session.\n* `:link_attribution` - Enables [Enhanced Link Attribution](https://developers.google.com/analytics/devguides/collection/gtagjs/enhanced-link-attribution).\n* `:allow_display_features` - Can be used to disable [Display Features](https://developers.google.com/analytics/devguides/collection/gtagjs/display-features).\n* `:custom_map` - Used to [Configure and send custom dimensions](https://developers.google.com/analytics/devguides/collection/gtagjs/custom-dims-mets)\n* `:optimize_id` - Used to [Deploy Optimize using gtag](https://support.google.com/optimize/answer/7513085)\n* `:set` - Used in the [set command to configure multiple properties](https://developers.google.com/analytics/devguides/collection/gtagjs/setting-values)\n\n#### Trackers\n\nGoogle Global Site tag allows configuring multiple trackers. Use the tracker option to configure the ids:\n\n\n```ruby\nconfig.middleware.use(Rack::Tracker) do\n  handler :google_global, { trackers: [ { id: 'U-XXXXX-Y' }, { id: 'U-WWWWWW-Z'} ] }\nend\n```\n\n### Google Analytics\n\n* `:anonymize_ip` -  sets the tracker to remove the last octet from all IP addresses, see https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApi_gat?hl=de#_gat._anonymizeIp for details.\n* `:cookie_domain` -  sets the domain name for the [GATC cookies](https://developers.google.com/analytics/devguides/collection/analyticsjs/domains#implementation). If not set its the website domain, with the www. prefix removed.\n* `:user_id` -  defines a proc to set the [userId](https://developers.google.com/analytics/devguides/collection/analyticsjs/cookies-user-id#user_id). Ex: `user_id: lambda { |env| env['rack.session']['user_id'] }` would return the user_id from the session.\n* `:site_speed_sample_rate` - Defines a new sample set size for Site Speed data collection, see https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiBasicConfiguration?hl=de#_gat.GA_Tracker_._setSiteSpeedSampleRate\n* `:adjusted_bounce_rate_timeouts` - An array of times in seconds that the tracker will use to set timeouts for adjusted bounce rate tracking. See http://analytics.blogspot.ca/2012/07/tracking-adjusted-bounce-rate-in-google.html for details.\n* `:enhanced_link_attribution` - Enables [Enhanced Link Attribution](https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-link-attribution).\n* `:advertising` - Enables [Display Features](https://developers.google.com/analytics/devguides/collection/analyticsjs/display-features).\n* `:ecommerce` - Enables [Ecommerce Tracking](https://developers.google.com/analytics/devguides/collection/analyticsjs/ecommerce).\n* `:enhanced_ecommerce` - Enables [Enhanced Ecommerce Tracking](https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce)\n* `:optimize` - pass [Google Optimize container ID](https://support.google.com/360suite/optimize/answer/6262084#example-combined-snippet) as value (e.g. `optimize: 'GTM-1234'`).\n* `:pageview_url_script` - a String containing a custom js script evaluating to the url that shoudl be given to the pageview event. Default to `window.location.pathname + window.location.search`.\n* `:explicit_pageview` - A boolean that controls whether to send the `pageview` event on pageload. This defaults to true.\n\n#### Events\n\nTo issue [Events](https://developers.google.com/analytics/devguides/collection/analyticsjs/events) from the server side just call the `tracker` method in your controller.\n\n```ruby\n  def show\n    tracker do |t|\n      t.google_analytics :send, { type: 'event', category: 'button', action: 'click', label: 'nav-buttons', value: 'X' }\n    end\n  end\n```\n\nIt will render the following to the site source:\n\n```javascript\n  ga('send', { 'hitType': 'event', 'eventCategory': 'button', 'eventAction': 'click', 'eventLabel': 'nav-buttons', 'value': 'X' })\n```\n\n#### Parameters\n\nYou can set parameters in your controller too:\n\n```ruby\n  def show\n    tracker do |t|\n      t.google_analytics :parameter, { dimension1: 'pink' }\n    end\n  end\n```\n\nWill render this:\n\n```javascript\n  ga('set', 'dimension1', 'pink');\n```\n\n\n\n#### Enhanced Ecommerce\n\nYou can set parameters in your controller:\n\n```ruby\n  def show\n    tracker do |t|\n      t.google_analytics :enhanced_ecommerce, {\n        type: 'addItem',\n        id: '1234',\n        name: 'Fluffy Pink Bunnies',\n        sku: 'DD23444',\n        category: 'Party Toys',\n        price: '11.99',\n        quantity: '1'\n      }\n    end\n  end\n```\n\nWill render this:\n\n```javascript\n  ga(\"ec:addItem\", {\"id\": \"1234\", \"name\": \"Fluffy Pink Bunnies\", \"sku\": \"DD23444\", \"category\": \"Party Toys\", \"price\": \"11.99\", \"quantity\": \"1\"});\n```\n\n\n\n#### Ecommerce\n\nYou can even trigger ecommerce directly from within your controller:\n\n```ruby\n  def show\n    tracker do |t|\n      t.google_analytics :ecommerce, { type: 'addItem', id: '1234', affiliation: 'Acme Clothing', revenue: '11.99', shipping: '5', tax: '1.29' }\n    end\n  end\n```\n\nWill give you this:\n\n```javascript\n  ga('ecommerce:addItem', { 'id': '1234', 'affiliation': 'Acme Clothing', 'revenue': '11.99', 'shipping': '5', 'tax': '1.29'  })\n```\n\nTo load the `ecommerce`-plugin, add some configuration to the middleware initialization.\nThis is _not_ needed for the above to work, but recommened, so you don't have to\ntake care of the plugin on your own.\n\n```ruby\n  config.middleware.use(Rack::Tracker) do\n    handler :google_analytics, { tracker: 'U-XXXXX-Y', ecommerce: true }\n  end\n```\n\n### Google Adwords Conversion\n\nYou can configure the handler with default options:\n```ruby\nconfig.middleware.use(Rack::Tracker) do\n  handler :google_adwords_conversion, { id: 123456,\n                                        language: \"en\",\n                                        format: \"3\",\n                                        color: \"ffffff\",\n                                        label: \"Conversion label\",\n                                        currency: \"USD\" }\nend\n```\n\nTo track adwords conversion from the server side just call the `tracker` method in your controller.\n```ruby\n  def show\n    tracker do |t|\n      t.google_adwords_conversion :conversion, { value: 10.0 }\n    end\n  end\n```\n\nYou can also specify a different value from default options:\n```ruby\n  def show\n    tracker do |t|\n      t.google_adwords_conversion :conversion, { id: 123456,\n                                                 language: 'en',\n                                                 format: '3',\n                                                 color: 'ffffff',\n                                                 label: 'Conversion Label',\n                                                 value: 10.0 }\n    end\n  end\n```\n\n### Google Tag Manager\n\nGoogle Tag manager code snippet supports the container id\n\n```ruby\n  config.middleware.use(Rack::Tracker) do\n    handler :google_tag_manager, { container: 'GTM-XXXXXX' }\n  end\n```\n\nYou can also use an experimental feature to track pageviews under turbolinks, which adds a `pageView` event with a `virtualUrl` of the current url.\n\n```ruby\n  config.middleware.use(Rack::Tracker) do\n    handler :google_tag_manager, { container: 'GTM-XXXXXX', turbolinks: true }\n  end\n```\n\n#### Data Layer\n\nGTM supports a [dataLayer](https://developers.google.com/tag-manager/devguide#datalayer) for pushing events as well as variables.\n\nTo add events or variables to the dataLayer from the server side, just call the `tracker` method in your controller.\n\n```ruby\n  def show\n    tracker do |t|\n      t.google_tag_manager :push, { price: 'X', another_variable: ['array', 'values'] }\n    end\n  end\n```\n\n\n### Facebook\n\n* `Facebook Pixel` - adds the [Facebook Pixel](https://www.facebook.com/business/help/952192354843755)\n\nUse in conjunction with the [Facebook Helper](https://developers.facebook.com/docs/facebook-pixel/pixel-helper) to confirm your event fires correctly.\n\nFirst, add the following to your config:\n\n```ruby\n  config.middleware.use(Rack::Tracker) do\n    handler :facebook_pixel, { id: 'PIXEL_ID' }\n  end\n```\n\n#### Dynamic Pixel Configuration\n\nIf 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:\n\n```ruby\n  config.middleware.use(Rack::Tracker) do\n    handler :facebook_pixel, { id: lambda { |env| env['PIXEL_ID'] } }\n  end\n```\n\nand set the pixel id within the request `env` variable. Here an example on how it can be done in a rails action:\n\n```ruby\n  class MyController \u003c ApplicationController\n    def show\n      request.env['PIXEL_ID'] = 'DYNAMIC_PIXEL_ID'\n    end\n  end\n```\n\n#### Standard Events\n\nTo track Standard Events from the server side just call the `tracker` method in your controller.\n\n```ruby\n  def show\n    tracker do |t|\n      t.facebook_pixel :track, { type: 'Purchase', options: { value: 100, currency: 'USD' } }\n    end\n  end\n```\n\nWill result in the following:\n\n```javascript\n  fbq(\"track\", \"Purchase\", {\"value\":\"100.0\",\"currency\":\"USD\"});\n```\n\nYou can also use non-standard (custom) event names for audience building when you do not need to track or optimize for conversions.\n\n```\n  tracker do |t|\n    t.facebook_pixel :track_custom, { type: 'FrequentShopper', options: { purchases: 24, category: 'Sport' } }\n  end\n```\n\n\n### Visual website Optimizer (VWO)\nJust integrate the handler with your matching account_id and you will be ready to go\n\n```ruby\n  use Rack::Tracker do\n    handler :vwo, { account_id: 'YOUR_ACCOUNT_ID' }\n  end\n```\n\n### GoSquared\n\nTo enable GoSquared tracking:\n\n```ruby\nconfig.middleware.use(Rack::Tracker) do\n  handler :go_squared, { tracker: 'ABCDEFGH' }\nend\n````\n\nThis will add the tracker to the page like so:\n\n``` javascript\n  _gs('ABCDEFGH');\n```\n\nYou can also set multiple named trackers if need be:\n\n```ruby\nconfig.middleware.use(Rack::Tracker) do\n  handler :go_squared, {\n    trackers: {\n      primaryTracker: 'ABCDEFGH',\n      secondaryTracker: '1234567',\n    }\n  }\nend\n````\n\nThis will add the specified trackers to the page like so:\n\n``` javascript\n  _gs('ABCDEFGH', 'primaryTracker');\n  _gs('1234567', 'secondaryTracker');\n```\n\nYou can set [a variety of options](https://www.gosquared.com/developer/tracker/configuration/) by passing the following settings. If you don't set any of the following options, they will be omitted from the rendered code.\n\n* `:anonymize_ip`\n* `:cookie_domain`\n* `:use_cookies`\n* `:track_hash`\n* `:track_local`\n* `:track_params`\n\n#### Visitor Name\n\nTo track the [visitor name](https://www.gosquared.com/developer/tracker/tagging/) from the server side, just call the `tracker` method in your controller.\n\n```ruby\n  def show\n    tracker do |t|\n      t.go_squared :visitor_name, { name: 'John Doe' }\n    end\n  end\n```\n\nIt will render the following to the site source:\n\n```javascript\n  _gs(\"set\", \"visitorName\", \"John Doe\");\n```\n\n#### Visitor Properties\n\nTo track [visitor properties](https://www.gosquared.com/developer/tracker/tagging/) from the server side, just call the `tracker` method in your controller.\n\n```ruby\n  def show\n    tracker do |t|\n      t.go_squared :visitor_info, { age: 35, favorite_food: 'pizza' }\n    end\n  end\n```\n\nIt will render the following to the site source:\n\n```javascript\n  _gs(\"set\", \"visitor\", { \"age\": 35, \"favorite_food\": \"pizza\" });\n```\n\n### Criteo\n\n[Criteo](http://www.criteo.com/) retargeting service.\n\n#### Basic configuration\n\n```\nconfig.middleware.use(Rack::Tracker) do\n  handler :criteo, { set_account: '1234' }\nend\n```\n\nOther global criteo handler options are:\n* `set_customer_id: 'x'`\n* `set_site_type: 'd'` - possible values are `m` (mobile), `t` (tablet), `d` (desktop)\n* `set_email: 'email'`\n\nOption 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'] }`\n\n#### Tracking events\n\nThis will track a basic event:\n\n```\ndef show\n  tracker do |t|\n    t.criteo :view_item, { item: 'P0001' }\n  end\nend\n```\n\nThis will render to the follwing code in the JS:\n\n```\nwindow.criteo_q.push({\"event\": \"viewItem\", \"item\": \"P001\" });\n```\n\nThe 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.\n\nAnother example\n\n```\nt.criteo :track_transaction, { id: 'id', item: { id: \"P0038\", price: \"6.54\", quantity: 1 } }\n```\n\n### Zanox\n\n[Zanox](http://www.zanox.com/us/)\n\n#### Basic Configuration\n\n```\nconfig.middleware.use(Rack::Tracker) do\n  handler :zanox, { account_id: '1234' }\nend\n```\n\n#### Mastertag\n\nThis is an example of a mastertag:\n\n```\ndef show\n  tracker do |t|\n    t.zanox :mastertag, { id: \"25GHTE9A07DF67DFG90T\", category: 'Swimming', amount: '3.50' }\n  end\nend\n```\n\nThis will render to the follwing code in the JS:\n\n```\nwindow._zx.push({\"id\": \"25GHTE9A07DF67DFG90T\"});\n```\n\nand the following variables:\n```\nzx_category = 'Swimming';\nzx_amount = '3.50';\n```\n\n#### Conversion tracking\n\nThis is an example of a lead event:\n\n```\ndef show\n  tracker do |t|\n    t.zanox :lead, { order_i_d: 'DEFC-4321' }\n  end\nend\n```\n\nThis is an example of a sale event:\n\n```\ndef show\n  tracker do |t|\n    t.zanox :sale, { customer_i_d: '123456', order_i_d: 'DEFC-4321', currency_symbol: 'EUR', total_price: '150.00' }\n  end\nend\n```\n\n### Hotjar\n\n[Hotjar](https://www.hotjar.com/)\n\n```\nconfig.middleware.use(Rack::Tracker) do\n  handler :hotjar, { site_id: '1234' }\nend\n```\n\n### Bing\n\n[Bing](https://bingads.microsoft.com/)\n\nTo add the tracking snippet:\n\n```\nconfig.middleware.use(Rack::Tracker) do\n  handler :bing, { tracker: '12345678' }\nend\n```\n\nTo send conversion events:\n```\ntracker do |t|\n  t.bing :conversion, {\n    type: 'event',\n    category: 'Users',\n    action: 'Login',\n    label: 'Standard',\n    value: 10\n  }\nend\n```\n\n### Hubspot\n\n[Hubspot](https://www.hubspot.com/)\n\n```\nconfig.middleware.use(Rack::Tracker) do\n  handler :hubspot, { site_id: '1234' }\nend\n```\n\n### Drift\n\n[Drift](https://www.drift.com/)\n\n```\nconfig.middleware.use(Rack::Tracker) do\n  handler :drift, account_id: 'DRIFT_ID'\nend\n```\n\n### Heap\n\n[Heap](https://heap.io/). Heap has Projects (e.g. \"Main\") which have multiple\nEnvironments (e.g. \"Production\" or \"Development\"). `env_id` is therefore the numerical ID\nthat represents the Environment. See Settings -\u003e Projects -\u003e Environments in your dashboard.\n\n```\nconfig.middleware.use(Rack::Tracker) do\n  handler :heap, env_id: 'HEAP_ID'\nend\n```\n\n### Custom Handlers\n\nTough we give you handlers for a few tracking services right out of the box, you might\nbe interested adding support for your custom tracking/analytics service.\n\nWriting a handler is straight forward ;) and there are just a couple of methods that\nyour class needs to implement.\n\nStart with a plain ruby class that inherits from `Rack::Tracker::Handler`\n\n```ruby\nclass MyHandler \u003c Rack::Tracker::Handler\n  ...\nend\n```\n\nIf you want to customize the rendering of your template, you can overwrite the handlers `#render` method:\n\n```ruby\ndef render\n  Tilt.new( File.join( File.dirname(__FILE__), 'template', 'my_handler.erb') ).render(self)\nend\n```\n\n\u003e There might be cases where you need to modify the response at multiple places. To do so you\ncan overwrite the `#inject`-method in your handler. For an example please have a look at the\nGoogle Tag Manager [implementation](https://github.com/railslove/rack-tracker/blob/master/lib/rack/tracker/google_tag_manager/google_tag_manager.rb#L9-L20).\n\nThis will render the `template/my_handler.erb` and inject the result into the source. You\ncan be creative about where the template is stored, but we tend to have them around\nour actual handler code.\n\n```erb\n\u003cscript\u003e\n  console.log('my tracker: ' + \u003c%= options.to_json %\u003e)\n\u003c/script\u003e\n```\n\nLets give it a try! We need to mount our new handler in the `Rack::Tracker` middleware\n\n```ruby\n  config.middleware.use(Rack::Tracker) do\n    handler MyHandler, { awesome: true }\n  end\n````\n\nEverything you're passing to the `handler` will be available as `#options` in your\ntemplate, so you'll also gain access to the `env`-hash belonging to the current request.\n\nRun your application and make a request, the result of the above template can be\nfound right before `\u003c/head\u003e`. You can change the position in your handler-code:\n\n```ruby\nclass MyHandler \u003c Rack::Tracker::Handler\n  self.position = :body\n\n  ...\nend\n```\n\nThe snippit will then be rendered right before `\u003c/body\u003e`.\n\nTo enable the *tracker dsl* functionality in your controllers\nyou need to implement the `track` class method on your handler:\n\n```ruby\ndef self.track(name, *event)\n  # do something with the event(s) to prepare them for your template\n  # and return a hash with a signature like { name =\u003e event }\nend\n```\n\nCheckout the existing handlers in `lib/rack/tracker` for some inspiration. :)\n\n\n## Please note\n\nMost tracking is done using some kind of Javascript and any tracking data is simply passed on.\nUsing unvalidated user input in the tracking might result in [XSS issues](https://en.wikipedia.org/wiki/Cross-site_scripting). Do only use secure data.\n\n\n## Contributing\n\nFirst of all, **thank** you for your help! :green_heart:\n\nIf you want a feature implemented, the best way to get it done\nis to submit a pull request that implements it.\nTests, readme and changelog entries would be nice.\n\n1. Fork it ( http://github.com/railslove/rack-tracker/fork )\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n","funding_links":[],"categories":["Ruby","Analytics"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frailslove%2Frack-tracker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frailslove%2Frack-tracker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frailslove%2Frack-tracker/lists"}