ga_events 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ga_events.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Nix-wie-weg GmbH & Co. KG
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,93 @@
1
+ # GaEvents
2
+
3
+ Use Google Analytics' Event Tracking everywhere in your Rails app!
4
+
5
+ This gem alllows you to annotate events everywhere in the code of your Rails
6
+ app.
7
+ A rack middleware is automatically inserted into the stack. It transports
8
+ the event data to the client. Normal requests get a DIV injected, Ajax requests
9
+ get a data-pounded custom HTTP header appended.
10
+ The asset pipeline-ready CoffeeScript extracts this data on the client-side and
11
+ pushes it to Google Analytics via ga.js or Google Tag Manager.
12
+
13
+ ## Installation
14
+
15
+ GaEvents works with Rails 3.1 onwards. You can add it to your `Gemfile` with:
16
+
17
+ ```ruby
18
+ gem 'ga_events'
19
+ ```
20
+
21
+ Run the `bundle` command to install it.
22
+
23
+ Add to the top of your `application.js`:
24
+
25
+ ```javascript
26
+ //= require ga_events.js
27
+ ```
28
+
29
+ After requiring `ga_events.js`, choose an adapter.
30
+
31
+ For stock Google Analytics (ga.js) use:
32
+
33
+ ```javascript
34
+ GaEvents.Event.adapter = function() {
35
+ return new GaEvents.GoogleAnalyticsAdapter();
36
+ }
37
+ ```
38
+
39
+ If you are using Google Tag Manager you can add custom events which are then passed through to Google Analytics.
40
+
41
+ ```javascript
42
+ GaEvents.Event.adapter = function() {
43
+ return new GaEvents.GoogleTagManagerAdapter("event_name"); // defaults to ga_event
44
+ }
45
+ ```
46
+
47
+ ## Usage
48
+
49
+ On the server-side a new event is added to a list, serialized into a container
50
+ element and then added to your HTML response. On Ajax requests a custom
51
+ HTTP header is added to the response.
52
+
53
+ You can create a new event like this:
54
+
55
+ ```ruby
56
+ GaEvents::Event.new(category, action, label, value)
57
+ ```
58
+
59
+ On the client-side there is a similar interface to GaEvents:
60
+
61
+ ```javascript
62
+ new GaEvents.Event(category, action, label, value)
63
+ ```
64
+
65
+ We have taken special care of tracking events while the DOM is loading.
66
+ Events get collected until the DOM is ready and flushed afterwards.
67
+
68
+ ### Too many events
69
+
70
+ Use something like this snippet to get informed of bloating HTTP headers with
71
+ event data:
72
+
73
+ ```ruby
74
+ class ApplicationController < ActionController::Base
75
+ after_filter :too_many_ga_events?
76
+ private
77
+ def too_many_ga_events?
78
+ if (serialized = GaEvents::List.to_s).length > 1_024
79
+ notify("GaEvents too big: #{serialized}")
80
+ end
81
+ true
82
+ end
83
+ end
84
+ ```
85
+
86
+ ## Contributing
87
+
88
+ Yes please! Use pull requests.
89
+
90
+ ## More docs
91
+
92
+ * [Google Analytics: Event Tracking](https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide)
93
+ * [Google Tag Manager: Custom Events](http://support.google.com/tagmanager/answer/2574372#GoogleAnalytics)
data/REVIEW ADDED
@@ -0,0 +1,2 @@
1
+ Flo: 2013-01-28 17:40
2
+ Sven: 2013-01-29 10:10
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/TODO ADDED
@@ -0,0 +1,4 @@
1
+ v0.2
2
+ * Remove REVIEW, use Barkeep
3
+ * Tests
4
+ * Announcement
@@ -0,0 +1,64 @@
1
+ # This file should be required as soon a possible to allow for
2
+ # early event tracking.
3
+
4
+ window.GaEvents = {}
5
+
6
+ class GaEvents.Event
7
+ adapter: null
8
+ @list: []
9
+ @may_flush: false
10
+ @header_key: "X-GA-Events"
11
+ @html_key: "ga-events"
12
+ klass: @
13
+
14
+ # Decompose a dom-string (ruby side) into an event object.
15
+ @from_string: (string) ->
16
+ $.map string.split("$"), (part) =>
17
+ [category, action, label, value] = part.split("|")
18
+ new @(category, action, label, value)
19
+
20
+ # Events should not be send to an adapter unless the DOM has finished loading.
21
+ @flush: ->
22
+ if @list.length > 0 and @may_flush
23
+ $.map @list, (event) -> event.push_to_adapter()
24
+ @list = []
25
+
26
+ # Add all events to a queue to flush them later
27
+ constructor: (@category, @action, @label, @value) ->
28
+ @klass.list.push @
29
+ @klass.flush()
30
+
31
+ push_to_adapter: ->
32
+ data =
33
+ action: @action
34
+ category: @category
35
+ data.label = @label if @is_valid_value(@label)
36
+ data.value = @value if @is_valid_value(@value)
37
+ @klass.adapter().push data
38
+
39
+ is_valid_value: (value) -> value? and value != ''
40
+
41
+ jQuery =>
42
+ @may_flush = true
43
+ @flush()
44
+
45
+ $(document).ajaxComplete (event, xhr) =>
46
+ xhr_events = xhr.getResponseHeader(@header_key)
47
+ @from_string(xhr_events) if xhr_events?
48
+
49
+ dom_events = $("div[data-#{@html_key}]").data(@html_key)
50
+ @from_string(dom_events) if dom_events?
51
+
52
+ class GaEvents.GoogleTagManagerAdapter
53
+ constructor: (@event = "ga_event") ->
54
+ push: (data) ->
55
+ data["event"] = @event
56
+ data["non_interaction"] = true
57
+ window.dataLayer.push(data)
58
+
59
+ class GaEvents.GoogleAnalyticsAdapter
60
+ push: (obj) ->
61
+ data = ["_trackEvent", obj["action"], obj["category"]]
62
+ data.push(obj["label"]) if obj.label?
63
+ data.push(obj["value"]) if obj.value?
64
+ window._qaq.push(data)
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+ require File.expand_path('../lib/ga_events/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ['Florian Dütsch', 'Sven Winkler']
6
+ gem.email = ['florian.duetsch@nix-wie-weg.de',
7
+ 'sven.winkler@nix-wie-weg.de']
8
+ gem.description =
9
+ %q{Google Analytics' Event Tracking everywhere in your Rails app}
10
+ gem.summary = 'This gem alllows you to annotate events everywhere in ' \
11
+ 'the code of your Rails app. A rack middleware is ' \
12
+ 'automatically inserted into the stack. It transports ' \
13
+ 'the event data to the client. Normal requests get a ' \
14
+ 'DIV injected, AJAX requests get a data-pounded custom ' \
15
+ 'HTTP header appended. The asset pipeline-ready ' \
16
+ 'CoffeeScript extracts this data on the client side ' \
17
+ 'and pushes it to Google Analytics via ga.js or Google ' \
18
+ 'Tag Manager.'
19
+ gem.homepage = 'https://github.com/Nix-wie-weg/ga_events'
20
+
21
+ gem.files = `git ls-files`.split($\)
22
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
23
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
24
+ gem.name = "ga_events"
25
+ gem.require_paths = ["lib"]
26
+ gem.version = GaEvents::VERSION
27
+
28
+ gem.add_dependency 'rails', '~> 3.1'
29
+ end
@@ -0,0 +1 @@
1
+ %w(middleware engine event list version).each { |f| require "ga_events/#{f}" }
@@ -0,0 +1,5 @@
1
+ module GaEvents
2
+ class Engine < ::Rails::Engine
3
+ config.app_middleware.use GaEvents::Middleware
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ module GaEvents
2
+ class Event < Struct.new(:category, :action, :label, :value)
3
+ def initialize(category, action, label = nil, value = nil)
4
+ super
5
+ GaEvents::List << self
6
+ end
7
+
8
+ def to_s
9
+ [category, action, label, value].join('|')
10
+ end
11
+ end
12
+ end
13
+
@@ -0,0 +1,26 @@
1
+ # NOTE: Collecting the events is thread-safe, but will cause problems in an
2
+ # asynchronous environment.
3
+
4
+ module GaEvents::List
5
+ def self.<<(event)
6
+ data << event
7
+ end
8
+
9
+ def self.to_s
10
+ data.collect(&:to_s).join('$')
11
+ end
12
+
13
+ def self.present?
14
+ data.present?
15
+ end
16
+
17
+ def self.init
18
+ Thread.current[:ga_events] = []
19
+ end
20
+
21
+ def self.data
22
+ Thread.current[:ga_events]
23
+ end
24
+
25
+ private_class_method :data
26
+ end
@@ -0,0 +1,43 @@
1
+ require 'rack/utils'
2
+
3
+ module GaEvents
4
+ class Middleware
5
+
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+ def call(env)
10
+ GaEvents::List.init
11
+ status, headers, response = @app.call(env)
12
+ headers = Rack::Utils::HeaderHash.new(headers)
13
+
14
+ if GaEvents::List.present?
15
+ request = Rack::Request.new(env)
16
+
17
+ # Can outgrow, headers might get too big
18
+ serialized = GaEvents::List.to_s
19
+
20
+ if request.xhr?
21
+ headers['X-GA-Events'] = serialized
22
+ elsif is_html?(status, headers)
23
+ new_body = response.body.sub('</body>',
24
+ "<div data-ga-events='#{serialized}'></div>\\0")
25
+ response = [new_body]
26
+ end
27
+ end
28
+
29
+ [status, headers, response]
30
+ end
31
+
32
+ private
33
+
34
+ # Taken from:
35
+ # https://github.com/rack/rack-contrib/blob/master/lib/rack/contrib/jsonp.rb
36
+ def is_html?(status, headers)
37
+ !Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status.to_i) &&
38
+ headers.key?('Content-Type') &&
39
+ headers['Content-Type'].include?('text/html')
40
+ end
41
+ end
42
+ end
43
+
@@ -0,0 +1,3 @@
1
+ module GaEvents
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ga_events
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Florian Dütsch
9
+ - Sven Winkler
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-01-29 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rails
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '3.1'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: '3.1'
31
+ description: Google Analytics' Event Tracking everywhere in your Rails app
32
+ email:
33
+ - florian.duetsch@nix-wie-weg.de
34
+ - sven.winkler@nix-wie-weg.de
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - .gitignore
40
+ - Gemfile
41
+ - LICENSE
42
+ - README.md
43
+ - REVIEW
44
+ - Rakefile
45
+ - TODO
46
+ - app/assets/javascripts/ga_events.js.coffee
47
+ - ga_events.gemspec
48
+ - lib/ga_events.rb
49
+ - lib/ga_events/engine.rb
50
+ - lib/ga_events/event.rb
51
+ - lib/ga_events/list.rb
52
+ - lib/ga_events/middleware.rb
53
+ - lib/ga_events/version.rb
54
+ homepage: https://github.com/Nix-wie-weg/ga_events
55
+ licenses: []
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubyforge_project:
74
+ rubygems_version: 1.8.24
75
+ signing_key:
76
+ specification_version: 3
77
+ summary: This gem alllows you to annotate events everywhere in the code of your Rails
78
+ app. A rack middleware is automatically inserted into the stack. It transports
79
+ the event data to the client. Normal requests get a DIV injected, AJAX requests
80
+ get a data-pounded custom HTTP header appended. The asset pipeline-ready CoffeeScript
81
+ extracts this data on the client side and pushes it to Google Analytics via ga.js
82
+ or Google Tag Manager.
83
+ test_files: []