ga_events 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/CHANGELOG.md +17 -0
- data/Gemfile +4 -0
- data/README.md +34 -5
- data/Rakefile +6 -1
- data/app/assets/javascripts/ga_events.js.coffee +5 -2
- data/ga_events.gemspec +8 -9
- data/lib/ga_events/list.rb +20 -19
- data/lib/ga_events/middleware.rb +37 -22
- data/lib/ga_events/version.rb +1 -1
- data/spec/middleware_spec.rb +59 -0
- data/spec/spec_helper.rb +18 -0
- metadata +15 -12
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
N2FlNTM2ZmYyMDRlOTQ0MjRjZTZmNTNiZWQwMDBiOTgyNTM1MTNmYQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
Mzk2ZmY4OGNlYjI0NTUzOWNkZTBjYjQyMDM3MmM4Y2VmNmIyZThmNA==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
N2UxZGZiOTQ0NTI3ZmEyY2Y4ODY1NWY3ZmIzYTA4OWQzNWJjY2E0MWM4ZmYw
|
10
|
+
Njc2NzhjMzFjY2ZhYmZhZDczNjUzZTY2NzAwYTZiNTY5ZmYxNmQ0MzIzYzI5
|
11
|
+
NzY0MjA4NWRlZmMyOTZmMDc2OWNjYjU5MGM4ZTJhZTBkMGE1ZTM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NDFlZjM5NjI3ODdiNjdmMWI4ZGMwMDE2MGI0MDQ4Y2UzOGE3NDA5NTQ5NTc1
|
14
|
+
MDYxNWJmZDkwMDJiNDY3YjYzZDM3YjkzNTMzZGZkYmNhMDRiYzY1MmE0Y2Zh
|
15
|
+
ZDY1MmYzNWQ4ZjVlOWQwNzJmZmU1ZmExYzg4MmVkNjJiMzM2MDA=
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Changelog
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
The format suggested at http://keepachangelog.com/ is used.
|
4
|
+
|
5
|
+
## 1.0.1 - 2014-04-29
|
6
|
+
|
7
|
+
### Fixed
|
8
|
+
- Universal Analytics Adapter now marks event as non-interaction.
|
9
|
+
|
10
|
+
## 1.1.0 - 2014-10-17
|
11
|
+
|
12
|
+
### Added
|
13
|
+
- Some documentation regarding controller specs (closes #10)
|
14
|
+
- More middleware specs
|
15
|
+
|
16
|
+
### Fixed
|
17
|
+
- Error returns white page
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -13,6 +13,7 @@ pushes it to Google Analytics via ga.js or Google Tag Manager.
|
|
13
13
|
|
14
14
|
## Dependencies
|
15
15
|
|
16
|
+
* Ruby >= 1.9
|
16
17
|
* Rails 3.1 onwards
|
17
18
|
* jQuery
|
18
19
|
|
@@ -32,9 +33,9 @@ Add to the top of your `application.js` (but after requiring jQuery):
|
|
32
33
|
//= require ga_events.js
|
33
34
|
```
|
34
35
|
|
35
|
-
After requiring `ga_events.js`, choose an adapter.
|
36
|
+
After requiring `ga_events.js`, you have to choose an adapter.
|
36
37
|
|
37
|
-
|
38
|
+
### Google Analytics (ga.js)
|
38
39
|
|
39
40
|
```javascript
|
40
41
|
GaEvents.Event.adapter = function() {
|
@@ -42,7 +43,7 @@ GaEvents.Event.adapter = function() {
|
|
42
43
|
}
|
43
44
|
```
|
44
45
|
|
45
|
-
|
46
|
+
### Google Universal Analytics (analytics.js)
|
46
47
|
|
47
48
|
```javascript
|
48
49
|
GaEvents.Event.adapter = function() {
|
@@ -50,6 +51,16 @@ GaEvents.Event.adapter = function() {
|
|
50
51
|
}
|
51
52
|
```
|
52
53
|
|
54
|
+
Optionally you can specify a custom method to call and a custom tracker name:
|
55
|
+
|
56
|
+
```javascript
|
57
|
+
GaEvents.Event.adapter = function() {
|
58
|
+
return new GaEvents.GoogleUniversalAnalyticsAdapter("sendNow", "customTracker");
|
59
|
+
}
|
60
|
+
```
|
61
|
+
|
62
|
+
### Google TagManager
|
63
|
+
|
53
64
|
If you are using Google Tag Manager you can add custom events which are then
|
54
65
|
passed through to Google Analytics.
|
55
66
|
|
@@ -59,7 +70,9 @@ GaEvents.Event.adapter = function() {
|
|
59
70
|
}
|
60
71
|
```
|
61
72
|
|
62
|
-
|
73
|
+
### Testing
|
74
|
+
|
75
|
+
For your testing pleasure we included `NullAdapter`.
|
63
76
|
|
64
77
|
```javascript
|
65
78
|
GaEvents.Event.adapter = function() {
|
@@ -112,13 +125,29 @@ class ApplicationController < ActionController::Base
|
|
112
125
|
end
|
113
126
|
```
|
114
127
|
|
128
|
+
### Testing
|
129
|
+
|
130
|
+
Middlewares aren't loaded in controller specs, so you have to initialize
|
131
|
+
GaEvents by hand. You can do this eg. in your `spec_helper.rb`:
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
RSpec.configure do |config|
|
135
|
+
[...]
|
136
|
+
config.before(:each, type: :controller) do
|
137
|
+
GaEvents::List.init
|
138
|
+
end
|
139
|
+
end
|
140
|
+
```
|
141
|
+
|
115
142
|
## Contributing
|
116
143
|
|
117
144
|
Yes please! Use pull requests.
|
118
145
|
|
119
146
|
### Credits
|
120
147
|
|
121
|
-
* [
|
148
|
+
* [danielbayerlein](https://github.com/danielbayerlein) former core committer
|
149
|
+
* [jhilden](https://github.com/jhilden) for ideas and bug reports
|
150
|
+
* [brain-geek](https://github.com/brain-geek) for bug fixes, specs, features
|
122
151
|
|
123
152
|
## More docs and tools
|
124
153
|
|
data/Rakefile
CHANGED
@@ -61,9 +61,12 @@ class GaEvents.GoogleTagManagerAdapter
|
|
61
61
|
window.dataLayer.push data
|
62
62
|
|
63
63
|
class GaEvents.GoogleUniversalAnalyticsAdapter
|
64
|
+
constructor: (@method_call_name = "send", tracker_name) ->
|
65
|
+
@method_call_name = "#{tracker_name}.#{@method_call_name}" if tracker_name
|
66
|
+
|
64
67
|
push: (h) ->
|
65
|
-
window.ga
|
66
|
-
{"nonInteraction": true}
|
68
|
+
window.ga @method_call_name, "event", h.category, h.action, h.label,
|
69
|
+
h.value, {"nonInteraction": true}
|
67
70
|
|
68
71
|
class GaEvents.GoogleAnalyticsAdapter
|
69
72
|
# Send events non_interactive => no influence on bounce rates
|
data/ga_events.gemspec
CHANGED
@@ -2,12 +2,11 @@
|
|
2
2
|
require File.expand_path('../lib/ga_events/version', __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
|
-
gem.authors = ['Florian Dütsch', 'Sven Winkler'
|
5
|
+
gem.authors = ['Florian Dütsch', 'Sven Winkler']
|
6
6
|
gem.email = ['florian.duetsch@nix-wie-weg.de',
|
7
|
-
'sven.winkler@nix-wie-weg.de'
|
8
|
-
'daniel.bayerlein@nix-wie-weg.de']
|
7
|
+
'sven.winkler@nix-wie-weg.de']
|
9
8
|
gem.description =
|
10
|
-
|
9
|
+
"Google Analytics' Event Tracking everywhere in your Rails app)"
|
11
10
|
gem.summary = 'This gem allows you to annotate events everywhere in ' \
|
12
11
|
'the code of your Rails app. A rack middleware is ' \
|
13
12
|
'automatically inserted into the stack. It transports ' \
|
@@ -19,11 +18,11 @@ Gem::Specification.new do |gem|
|
|
19
18
|
'Tag Manager.'
|
20
19
|
gem.homepage = 'https://github.com/Nix-wie-weg/ga_events'
|
21
20
|
|
22
|
-
gem.files = `git ls-files`.split(
|
23
|
-
gem.executables = gem.files.grep(
|
24
|
-
gem.test_files = gem.files.grep(
|
25
|
-
gem.name =
|
26
|
-
gem.require_paths = [
|
21
|
+
gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
22
|
+
gem.executables = gem.files.grep(/^bin\//).map { |f| File.basename(f) }
|
23
|
+
gem.test_files = gem.files.grep(/^(test|spec|features)\//)
|
24
|
+
gem.name = 'ga_events'
|
25
|
+
gem.require_paths = ['lib']
|
27
26
|
gem.version = GaEvents::VERSION
|
28
27
|
|
29
28
|
gem.add_dependency 'rails', '>= 3.1'
|
data/lib/ga_events/list.rb
CHANGED
@@ -1,28 +1,29 @@
|
|
1
1
|
# NOTE: Collecting the events is thread-safe, but will cause problems in an
|
2
2
|
# asynchronous/evented environment.
|
3
3
|
|
4
|
-
|
5
|
-
def self.<<(event)
|
6
|
-
data << event
|
7
|
-
end
|
4
|
+
require 'forwardable'
|
8
5
|
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
module GaEvents
|
7
|
+
module List
|
8
|
+
class << self
|
9
|
+
extend Forwardable
|
10
|
+
def_delegators :data, :<<, :present?
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
def to_s
|
13
|
+
data.collect(&:to_s).join('$')
|
14
|
+
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
# Init list, optionally with a string of serialized events
|
17
|
+
def init(str = nil)
|
18
|
+
Thread.current[:ga_events] = []
|
19
|
+
(str || '').split('$').each { |s| GaEvents::Event.from_string(s) }
|
20
|
+
end
|
22
21
|
|
23
|
-
|
24
|
-
Thread.current[:ga_events]
|
25
|
-
end
|
22
|
+
private
|
26
23
|
|
27
|
-
|
24
|
+
def data
|
25
|
+
Thread.current[:ga_events]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
28
29
|
end
|
data/lib/ga_events/middleware.rb
CHANGED
@@ -5,17 +5,9 @@ module GaEvents
|
|
5
5
|
def initialize(app)
|
6
6
|
@app = app
|
7
7
|
end
|
8
|
-
def call(env)
|
9
|
-
# Handle events stored in flash
|
10
|
-
# Parts borrowed from Rails:
|
11
|
-
# https://github.com/rails/rails/blob/v3.2.14/actionpack/lib/action_dispatch/middleware/flash.rb
|
12
|
-
flash = env['rack.session'] && env['rack.session']['flash']
|
13
|
-
|
14
|
-
# Fix for Rails 4
|
15
|
-
flash &&= flash['flashes'] if Rails::VERSION::MAJOR > 3
|
16
|
-
|
17
|
-
GaEvents::List.init(flash && flash['ga_events'])
|
18
8
|
|
9
|
+
def call(env)
|
10
|
+
init_event_list(env)
|
19
11
|
status, headers, response = @app.call(env)
|
20
12
|
|
21
13
|
headers = Rack::Utils::HeaderHash.new(headers)
|
@@ -30,17 +22,10 @@ module GaEvents
|
|
30
22
|
|
31
23
|
elsif (300..399).include?(status)
|
32
24
|
# 30x/redirect? Then add event list to flash to survive the redirect.
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
elsif is_html?(status, headers)
|
39
|
-
body = response
|
40
|
-
body = body.each.to_a.join if body.respond_to?(:each)
|
41
|
-
body = body.sub('</body>',
|
42
|
-
"<div data-ga-events='#{serialized}'></div>\\0")
|
43
|
-
response = [body]
|
25
|
+
add_events_to_flash(env, serialized)
|
26
|
+
|
27
|
+
elsif html?(status, headers)
|
28
|
+
response = inject_div(response, serialized)
|
44
29
|
end
|
45
30
|
end
|
46
31
|
|
@@ -49,9 +34,39 @@ module GaEvents
|
|
49
34
|
|
50
35
|
private
|
51
36
|
|
37
|
+
def init_event_list(env)
|
38
|
+
# Handle events stored in flash
|
39
|
+
# Parts borrowed from Rails:
|
40
|
+
# https://github.com/rails/rails/blob/v3.2.14/actionpack/lib/action_dispatch/middleware/flash.rb
|
41
|
+
flash = env['rack.session'] && env['rack.session']['flash']
|
42
|
+
|
43
|
+
# Fix for Rails 4
|
44
|
+
flash &&= flash['flashes'] if Rails::VERSION::MAJOR > 3
|
45
|
+
|
46
|
+
GaEvents::List.init(flash && flash['ga_events'])
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_events_to_flash env, serialized_data
|
50
|
+
flash_hash = env[ActionDispatch::Flash::KEY]
|
51
|
+
flash_hash ||= ActionDispatch::Flash::FlashHash.new
|
52
|
+
flash_hash['ga_events'] = serialized_data
|
53
|
+
env[ActionDispatch::Flash::KEY] = flash_hash
|
54
|
+
end
|
55
|
+
|
56
|
+
def normalize_response(r)
|
57
|
+
r = r.body if r.respond_to?(:body)
|
58
|
+
r = r.join if r.respond_to?(:join)
|
59
|
+
r
|
60
|
+
end
|
61
|
+
|
62
|
+
def inject_div(response, serialized_data)
|
63
|
+
r = normalize_response(response)
|
64
|
+
[r.sub('</body>', "<div data-ga-events='#{serialized_data}'></div>\\0")]
|
65
|
+
end
|
66
|
+
|
52
67
|
# Taken from:
|
53
68
|
# https://github.com/rack/rack-contrib/blob/master/lib/rack/contrib/jsonp.rb
|
54
|
-
def
|
69
|
+
def html?(status, headers)
|
55
70
|
!Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status.to_i) &&
|
56
71
|
headers.key?('Content-Type') &&
|
57
72
|
headers['Content-Type'].include?('text/html')
|
data/lib/ga_events/version.rb
CHANGED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GaEvents::Middleware do
|
4
|
+
let(:app) do
|
5
|
+
proc { [200, { 'Content-Type' => 'text/html' }, [response_body]] }
|
6
|
+
end
|
7
|
+
let(:response_body) { 'Hello, world.' }
|
8
|
+
|
9
|
+
let(:stack) { described_class.new(app) }
|
10
|
+
let(:request) { Rack::MockRequest.new(stack) }
|
11
|
+
|
12
|
+
describe 'Body code injection' do
|
13
|
+
context 'no events in GaEvents::List' do
|
14
|
+
context 'there is no body closing tag' do
|
15
|
+
let(:response) { request.get('/') }
|
16
|
+
it 'leaves everything as it was' do
|
17
|
+
expect(response.body).to eq response_body
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'there exists body closing tag' do
|
22
|
+
let(:response) { request.get('/') }
|
23
|
+
let(:response_body) { 'something awesome!</body>' }
|
24
|
+
|
25
|
+
it 'leaves everything as it was' do
|
26
|
+
expect(response.body).to eq response_body
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'events present in GaEvents::List' do
|
32
|
+
let(:app) do
|
33
|
+
proc do |_|
|
34
|
+
GaEvents::Event.new('category', 'action', 'label', 'value')
|
35
|
+
[200, { 'Content-Type' => 'text/html' }, response_body]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'there is no body closing tag' do
|
40
|
+
let(:response) { request.get('/') }
|
41
|
+
it 'leaves everything as it was' do
|
42
|
+
expect(response.body).to eq response_body
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'there exists body closing tag' do
|
47
|
+
let(:response) { request.get('/') }
|
48
|
+
let(:response_body) { 'something awesome!</body>' }
|
49
|
+
|
50
|
+
it 'injects data-ga-events' do
|
51
|
+
expect(response.body).to eq(
|
52
|
+
'something awesome!' \
|
53
|
+
"<div data-ga-events='category|action|label|value'></div></body>"
|
54
|
+
)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'pry'
|
3
|
+
require 'rspec'
|
4
|
+
require 'rails'
|
5
|
+
require 'ga_events'
|
6
|
+
|
7
|
+
# Disabling old rspec 'should' syntax
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.expect_with :rspec do |c|
|
10
|
+
c.syntax = :expect
|
11
|
+
end
|
12
|
+
|
13
|
+
config.raise_errors_for_deprecations!
|
14
|
+
|
15
|
+
config.before do
|
16
|
+
GaEvents::List.init
|
17
|
+
end
|
18
|
+
end
|
metadata
CHANGED
@@ -1,41 +1,40 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ga_events
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Dütsch
|
8
8
|
- Sven Winkler
|
9
|
-
- Daniel Bayerlein
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date: 2014-
|
12
|
+
date: 2014-10-17 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: rails
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
17
|
requirements:
|
19
|
-
- -
|
18
|
+
- - ! '>='
|
20
19
|
- !ruby/object:Gem::Version
|
21
20
|
version: '3.1'
|
22
21
|
type: :runtime
|
23
22
|
prerelease: false
|
24
23
|
version_requirements: !ruby/object:Gem::Requirement
|
25
24
|
requirements:
|
26
|
-
- -
|
25
|
+
- - ! '>='
|
27
26
|
- !ruby/object:Gem::Version
|
28
27
|
version: '3.1'
|
29
|
-
description: Google Analytics' Event Tracking everywhere in your Rails app
|
28
|
+
description: Google Analytics' Event Tracking everywhere in your Rails app)
|
30
29
|
email:
|
31
30
|
- florian.duetsch@nix-wie-weg.de
|
32
31
|
- sven.winkler@nix-wie-weg.de
|
33
|
-
- daniel.bayerlein@nix-wie-weg.de
|
34
32
|
executables: []
|
35
33
|
extensions: []
|
36
34
|
extra_rdoc_files: []
|
37
35
|
files:
|
38
|
-
-
|
36
|
+
- .gitignore
|
37
|
+
- CHANGELOG.md
|
39
38
|
- Gemfile
|
40
39
|
- LICENSE
|
41
40
|
- README.md
|
@@ -49,6 +48,8 @@ files:
|
|
49
48
|
- lib/ga_events/list.rb
|
50
49
|
- lib/ga_events/middleware.rb
|
51
50
|
- lib/ga_events/version.rb
|
51
|
+
- spec/middleware_spec.rb
|
52
|
+
- spec/spec_helper.rb
|
52
53
|
homepage: https://github.com/Nix-wie-weg/ga_events
|
53
54
|
licenses: []
|
54
55
|
metadata: {}
|
@@ -58,17 +59,17 @@ require_paths:
|
|
58
59
|
- lib
|
59
60
|
required_ruby_version: !ruby/object:Gem::Requirement
|
60
61
|
requirements:
|
61
|
-
- -
|
62
|
+
- - ! '>='
|
62
63
|
- !ruby/object:Gem::Version
|
63
64
|
version: '0'
|
64
65
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
66
|
requirements:
|
66
|
-
- -
|
67
|
+
- - ! '>='
|
67
68
|
- !ruby/object:Gem::Version
|
68
69
|
version: '0'
|
69
70
|
requirements: []
|
70
71
|
rubyforge_project:
|
71
|
-
rubygems_version: 2.
|
72
|
+
rubygems_version: 2.4.1
|
72
73
|
signing_key:
|
73
74
|
specification_version: 4
|
74
75
|
summary: This gem allows you to annotate events everywhere in the code of your Rails
|
@@ -77,4 +78,6 @@ summary: This gem allows you to annotate events everywhere in the code of your R
|
|
77
78
|
a data-pounded custom HTTP header appended. The asset pipeline-ready CoffeeScript
|
78
79
|
extracts this data on the client side and pushes it to Google Analytics via ga.js
|
79
80
|
or Google Tag Manager.
|
80
|
-
test_files:
|
81
|
+
test_files:
|
82
|
+
- spec/middleware_spec.rb
|
83
|
+
- spec/spec_helper.rb
|