ahoy_matey 0.2.2 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +16 -2
- data/app/controllers/ahoy/base_controller.rb +0 -15
- data/app/controllers/ahoy/visits_controller.rb +2 -8
- data/lib/ahoy/controller.rb +16 -3
- data/lib/ahoy/engine.rb +24 -0
- data/lib/ahoy/tracker.rb +27 -1
- data/lib/ahoy/version.rb +1 -1
- data/lib/ahoy/warden.rb +1 -1
- data/lib/ahoy.rb +66 -0
- data/lib/ahoy_matey.rb +1 -59
- data/vendor/assets/javascripts/ahoy.js +38 -24
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aae43abe84c855bce95234160c4e8e0a2496155c
|
4
|
+
data.tar.gz: 037987022eaaf1738e0187b86683823a632639a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f2eae369753dc8710a6ba8c8989b2641923b741feaff09184a5d94a76432ea568b6eeea53f0351dac79a7fe4f95bc4392f264560e6a0e693b92a974b2676d20
|
7
|
+
data.tar.gz: 4e1ff064b585b73a1de6225f5b606855f7aa13a620f187b02578775f2bb0c49f3bb1c87c8e1e88a2bf3dde71da0e92fb19ca2ee0dd5c1bd36e929602197a6524
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 0.3.0
|
2
|
+
|
3
|
+
- Added `current_visit_token` and `current_visitor_token` method
|
4
|
+
- Switched to UUIDs
|
5
|
+
- Quiet endpoint requests
|
6
|
+
- Skip server-side bot events
|
7
|
+
- Added `request` argument to `exclude_method`
|
8
|
+
|
1
9
|
## 0.2.2
|
2
10
|
|
3
11
|
- Added `exclude_method` option
|
data/README.md
CHANGED
@@ -175,6 +175,8 @@ or track all views and clicks with:
|
|
175
175
|
ahoy.trackAll();
|
176
176
|
```
|
177
177
|
|
178
|
+
See [Ahoy.js](https://github.com/ankane/ahoy.js) for a complete list of features.
|
179
|
+
|
178
180
|
#### Ruby
|
179
181
|
|
180
182
|
```ruby
|
@@ -254,6 +256,12 @@ Turn off logging
|
|
254
256
|
ahoy.debug(false);
|
255
257
|
```
|
256
258
|
|
259
|
+
Debug endpoint requests in Ruby [master]
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
Ahoy.quiet = false
|
263
|
+
```
|
264
|
+
|
257
265
|
### More
|
258
266
|
|
259
267
|
- Excludes bots
|
@@ -370,8 +378,8 @@ Ahoy.subscribers << Ahoy::Subscribers::ActiveRecord.new(model: Event)
|
|
370
378
|
Exclude visits and events
|
371
379
|
|
372
380
|
```ruby
|
373
|
-
Ahoy.exclude_method = proc do |controller|
|
374
|
-
|
381
|
+
Ahoy.exclude_method = proc do |controller, request|
|
382
|
+
request.ip == "192.168.1.1"
|
375
383
|
end
|
376
384
|
```
|
377
385
|
|
@@ -383,6 +391,12 @@ Ahoy.track_bots = true
|
|
383
391
|
|
384
392
|
## Upgrading
|
385
393
|
|
394
|
+
### 0.3.0
|
395
|
+
|
396
|
+
Starting with `0.3.0`, visit and visitor tokens are now UUIDs.
|
397
|
+
|
398
|
+
### 0.1.6
|
399
|
+
|
386
400
|
In `0.1.6`, a big improvement was made to `browser` and `os`. Update existing visits with:
|
387
401
|
|
388
402
|
```ruby
|
@@ -2,20 +2,5 @@ module Ahoy
|
|
2
2
|
class BaseController < ApplicationController
|
3
3
|
# skip all filters
|
4
4
|
skip_filter *_process_action_callbacks.map(&:filter)
|
5
|
-
|
6
|
-
before_filter :halt_bots
|
7
|
-
|
8
|
-
protected
|
9
|
-
|
10
|
-
def browser
|
11
|
-
@browser ||= Browser.new(ua: request.user_agent)
|
12
|
-
end
|
13
|
-
|
14
|
-
def halt_bots
|
15
|
-
if !Ahoy.track_bots and browser.bot?
|
16
|
-
render json: {}
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
5
|
end
|
21
6
|
end
|
@@ -2,8 +2,8 @@ module Ahoy
|
|
2
2
|
class VisitsController < BaseController
|
3
3
|
|
4
4
|
def create
|
5
|
-
visit_token = params[:visit_token] ||
|
6
|
-
visitor_token = params[:visitor_token] ||
|
5
|
+
visit_token = params[:visit_token] || Ahoy.generate_id
|
6
|
+
visitor_token = params[:visitor_token] || Ahoy.generate_id
|
7
7
|
|
8
8
|
visit =
|
9
9
|
Ahoy.visit_model.new do |v|
|
@@ -23,11 +23,5 @@ module Ahoy
|
|
23
23
|
render json: {visit_token: visit.visit_token, visitor_token: visit.visitor_token}
|
24
24
|
end
|
25
25
|
|
26
|
-
protected
|
27
|
-
|
28
|
-
def generate_token
|
29
|
-
SecureRandom.urlsafe_base64(32).gsub(/[\-_]/, "").first(32)
|
30
|
-
end
|
31
|
-
|
32
26
|
end
|
33
27
|
end
|
data/lib/ahoy/controller.rb
CHANGED
@@ -4,20 +4,33 @@ module Ahoy
|
|
4
4
|
def self.included(base)
|
5
5
|
base.helper_method :current_visit
|
6
6
|
base.helper_method :ahoy
|
7
|
+
base.before_filter :set_ahoy_visitor_cookie
|
7
8
|
base.before_filter do
|
8
9
|
RequestStore.store[:ahoy_controller] ||= self
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
13
|
+
def ahoy
|
14
|
+
@ahoy ||= Ahoy::Tracker.new(controller: self)
|
15
|
+
end
|
16
|
+
|
12
17
|
def current_visit
|
13
|
-
visit_token =
|
18
|
+
visit_token = current_visit_token
|
14
19
|
if visit_token
|
15
20
|
@current_visit ||= Ahoy.visit_model.where(visit_token: visit_token).first
|
16
21
|
end
|
17
22
|
end
|
18
23
|
|
19
|
-
def
|
20
|
-
@
|
24
|
+
def current_visit_token
|
25
|
+
@current_visit_token ||= request.headers["Ahoy-Visit"] || cookies[:ahoy_visit]
|
26
|
+
end
|
27
|
+
|
28
|
+
def current_visitor_token
|
29
|
+
@current_visitor_token ||= request.headers["Ahoy-Visitor"] || cookies[:ahoy_visitor] || current_visit.try(:visitor_token) || Ahoy.generate_id
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_ahoy_visitor_cookie
|
33
|
+
cookies[:ahoy_visitor] = current_visitor_token if !request.headers["Ahoy-Visitor"] && !cookies[:ahoy_visitor]
|
21
34
|
end
|
22
35
|
|
23
36
|
end
|
data/lib/ahoy/engine.rb
CHANGED
@@ -1,4 +1,28 @@
|
|
1
1
|
module Ahoy
|
2
2
|
class Engine < ::Rails::Engine
|
3
|
+
# from https://github.com/evrone/quiet_assets/blob/master/lib/quiet_assets.rb
|
4
|
+
initializer "ahoy", after: "sprockets.environment" do |app|
|
5
|
+
next unless Ahoy.quiet
|
6
|
+
|
7
|
+
# Parse PATH_INFO by assets prefix
|
8
|
+
AHOY_PREFIX = "/ahoy/"
|
9
|
+
KEY = "ahoy.old_level"
|
10
|
+
|
11
|
+
# Just create an alias for call in middleware
|
12
|
+
Rails::Rack::Logger.class_eval do
|
13
|
+
def call_with_quiet_ahoy(env)
|
14
|
+
begin
|
15
|
+
if env["PATH_INFO"].start_with?(AHOY_PREFIX)
|
16
|
+
env[KEY] = Rails.logger.level
|
17
|
+
Rails.logger.level = Logger::ERROR
|
18
|
+
end
|
19
|
+
call_without_quiet_ahoy(env)
|
20
|
+
ensure
|
21
|
+
Rails.logger.level = env[KEY] if env[KEY]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
alias_method_chain :call, :quiet_ahoy
|
25
|
+
end
|
26
|
+
end
|
3
27
|
end
|
4
28
|
end
|
data/lib/ahoy/tracker.rb
CHANGED
@@ -3,10 +3,11 @@ module Ahoy
|
|
3
3
|
|
4
4
|
def initialize(options = {})
|
5
5
|
@controller = options[:controller]
|
6
|
+
@request = options[:request] || @controller.try(:request)
|
6
7
|
end
|
7
8
|
|
8
9
|
def track(name, properties = {}, options = {})
|
9
|
-
if
|
10
|
+
if (Ahoy.track_bots or !bot?) and !exclude?
|
10
11
|
# publish to each subscriber
|
11
12
|
options = options.dup
|
12
13
|
if @controller
|
@@ -15,8 +16,15 @@ module Ahoy
|
|
15
16
|
if @controller.respond_to?(:current_visit)
|
16
17
|
options[:visit] ||= @controller.current_visit
|
17
18
|
end
|
19
|
+
if @controller.respond_to?(:current_visit_token)
|
20
|
+
options[:visit_token] = @controller.current_visit_token
|
21
|
+
end
|
22
|
+
if @controller.respond_to?(:current_visitor_token)
|
23
|
+
options[:visitor_token] = @controller.current_visitor_token
|
24
|
+
end
|
18
25
|
end
|
19
26
|
options[:time] ||= Time.zone.now
|
27
|
+
options[:id] ||= Ahoy.generate_id
|
20
28
|
|
21
29
|
subscribers = Ahoy.subscribers
|
22
30
|
if subscribers.any?
|
@@ -31,5 +39,23 @@ module Ahoy
|
|
31
39
|
true
|
32
40
|
end
|
33
41
|
|
42
|
+
protected
|
43
|
+
|
44
|
+
def bot?
|
45
|
+
@bot ||= Browser.new(ua: @request.user_agent).bot?
|
46
|
+
end
|
47
|
+
|
48
|
+
def exclude?
|
49
|
+
if Ahoy.exclude_method
|
50
|
+
if Ahoy.exclude_method.arity == 1
|
51
|
+
Ahoy.exclude_method.call(@controller)
|
52
|
+
else
|
53
|
+
Ahoy.exclude_method.call(@controller, @request)
|
54
|
+
end
|
55
|
+
else
|
56
|
+
false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
34
60
|
end
|
35
61
|
end
|
data/lib/ahoy/version.rb
CHANGED
data/lib/ahoy/warden.rb
CHANGED
data/lib/ahoy.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require "addressable/uri"
|
2
|
+
require "browser"
|
3
|
+
require "geocoder"
|
4
|
+
require "referer-parser"
|
5
|
+
require "user_agent_parser"
|
6
|
+
require "request_store"
|
7
|
+
require "ahoy/version"
|
8
|
+
require "ahoy/tracker"
|
9
|
+
require "ahoy/controller"
|
10
|
+
require "ahoy/model"
|
11
|
+
require "ahoy/subscribers/active_record"
|
12
|
+
require "ahoy/engine"
|
13
|
+
require "ahoy/warden" if defined?(Warden)
|
14
|
+
|
15
|
+
module Ahoy
|
16
|
+
|
17
|
+
def self.generate_id
|
18
|
+
SecureRandom.uuid
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.visit_model
|
22
|
+
@visit_model || ::Visit
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.visit_model=(visit_model)
|
26
|
+
@visit_model = visit_model
|
27
|
+
end
|
28
|
+
|
29
|
+
# TODO private
|
30
|
+
# performance hack for referer-parser
|
31
|
+
def self.referrer_parser
|
32
|
+
@referrer_parser ||= RefererParser::Referer.new("https://github.com/ankane/ahoy")
|
33
|
+
end
|
34
|
+
|
35
|
+
# performance
|
36
|
+
def self.user_agent_parser
|
37
|
+
@user_agent_parser ||= UserAgentParser::Parser.new
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.fetch_user(controller)
|
41
|
+
if user_method.respond_to?(:call)
|
42
|
+
user_method.call(controller)
|
43
|
+
else
|
44
|
+
controller.send(user_method)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
mattr_accessor :user_method
|
49
|
+
self.user_method = proc do |controller|
|
50
|
+
(controller.respond_to?(:current_user) && controller.current_user) || (controller.respond_to?(:current_resource_owner, true) && controller.send(:current_resource_owner)) || nil
|
51
|
+
end
|
52
|
+
|
53
|
+
mattr_accessor :exclude_method
|
54
|
+
|
55
|
+
mattr_accessor :subscribers
|
56
|
+
self.subscribers = []
|
57
|
+
|
58
|
+
mattr_accessor :track_bots
|
59
|
+
self.track_bots = false
|
60
|
+
|
61
|
+
mattr_accessor :quiet
|
62
|
+
self.quiet = true
|
63
|
+
end
|
64
|
+
|
65
|
+
ActionController::Base.send :include, Ahoy::Controller
|
66
|
+
ActiveRecord::Base.send(:extend, Ahoy::Model) if defined?(ActiveRecord)
|
data/lib/ahoy_matey.rb
CHANGED
@@ -1,59 +1 @@
|
|
1
|
-
require "
|
2
|
-
require "browser"
|
3
|
-
require "geocoder"
|
4
|
-
require "referer-parser"
|
5
|
-
require "user_agent_parser"
|
6
|
-
require "request_store"
|
7
|
-
require "ahoy/version"
|
8
|
-
require "ahoy/tracker"
|
9
|
-
require "ahoy/controller"
|
10
|
-
require "ahoy/model"
|
11
|
-
require "ahoy/subscribers/active_record"
|
12
|
-
require "ahoy/engine"
|
13
|
-
require "ahoy/warden" if defined?(Warden)
|
14
|
-
|
15
|
-
module Ahoy
|
16
|
-
|
17
|
-
def self.visit_model
|
18
|
-
@visit_model || ::Visit
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.visit_model=(visit_model)
|
22
|
-
@visit_model = visit_model
|
23
|
-
end
|
24
|
-
|
25
|
-
# TODO private
|
26
|
-
# performance hack for referer-parser
|
27
|
-
def self.referrer_parser
|
28
|
-
@referrer_parser ||= RefererParser::Referer.new("https://github.com/ankane/ahoy")
|
29
|
-
end
|
30
|
-
|
31
|
-
# performance
|
32
|
-
def self.user_agent_parser
|
33
|
-
@user_agent_parser ||= UserAgentParser::Parser.new
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.fetch_user(controller)
|
37
|
-
if user_method.respond_to?(:call)
|
38
|
-
user_method.call(controller)
|
39
|
-
else
|
40
|
-
controller.send(user_method)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
mattr_accessor :user_method
|
45
|
-
self.user_method = proc do |controller|
|
46
|
-
(controller.respond_to?(:current_user) && controller.current_user) || (controller.respond_to?(:current_resource_owner, true) && controller.send(:current_resource_owner)) || nil
|
47
|
-
end
|
48
|
-
|
49
|
-
mattr_accessor :exclude_method
|
50
|
-
|
51
|
-
mattr_accessor :subscribers
|
52
|
-
self.subscribers = []
|
53
|
-
|
54
|
-
mattr_accessor :track_bots
|
55
|
-
self.track_bots = false
|
56
|
-
end
|
57
|
-
|
58
|
-
ActionController::Base.send :include, Ahoy::Controller
|
59
|
-
ActiveRecord::Base.send(:extend, Ahoy::Model) if defined?(ActiveRecord)
|
1
|
+
require "ahoy"
|
@@ -1,3 +1,11 @@
|
|
1
|
+
/*
|
2
|
+
* Ahoy.js
|
3
|
+
* Simple, powerful JavaScript analytics
|
4
|
+
* https://github.com/ankane/ahoy.js
|
5
|
+
* v0.1.0
|
6
|
+
* MIT License
|
7
|
+
*/
|
8
|
+
|
1
9
|
/*jslint browser: true, indent: 2, plusplus: true, vars: true */
|
2
10
|
|
3
11
|
(function (window) {
|
@@ -5,13 +13,14 @@
|
|
5
13
|
|
6
14
|
var ahoy = window.ahoy || window.Ahoy || {};
|
7
15
|
var $ = window.jQuery || window.Zepto || window.$;
|
8
|
-
var
|
16
|
+
var visitId, visitorId;
|
9
17
|
var visitTtl = 4 * 60; // 4 hours
|
10
18
|
var visitorTtl = 2 * 365 * 24 * 60; // 2 years
|
11
19
|
var isReady = false;
|
12
20
|
var queue = [];
|
13
21
|
var canStringify = typeof(JSON) !== "undefined" && typeof(JSON.stringify) !== "undefined";
|
14
22
|
var eventQueue = [];
|
23
|
+
var page = ahoy.page || window.location.pathname;
|
15
24
|
|
16
25
|
// cookies
|
17
26
|
|
@@ -72,18 +81,12 @@
|
|
72
81
|
}
|
73
82
|
}
|
74
83
|
|
75
|
-
//
|
84
|
+
// http://stackoverflow.com/a/2117523/1177228
|
76
85
|
function generateId() {
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
for (var i = 0; i < length; i++) {
|
82
|
-
var randomNumber = Math.floor(Math.random() * chars.length);
|
83
|
-
string += chars.substring(randomNumber, randomNumber + 1);
|
84
|
-
}
|
85
|
-
|
86
|
-
return string;
|
86
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
87
|
+
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
|
88
|
+
return v.toString(16);
|
89
|
+
});
|
87
90
|
}
|
88
91
|
|
89
92
|
function saveEventQueue() {
|
@@ -123,35 +126,37 @@
|
|
123
126
|
return {
|
124
127
|
tag: $target.get(0).tagName.toLowerCase(),
|
125
128
|
id: $target.attr("id"),
|
126
|
-
"class": $target.attr("class")
|
129
|
+
"class": $target.attr("class"),
|
130
|
+
page: page,
|
131
|
+
section: $target.closest("*[data-section]").data("section")
|
127
132
|
};
|
128
133
|
}
|
129
134
|
|
130
135
|
// main
|
131
136
|
|
132
|
-
|
133
|
-
|
137
|
+
visitId = getCookie("ahoy_visit");
|
138
|
+
visitorId = getCookie("ahoy_visitor");
|
134
139
|
|
135
|
-
if (
|
140
|
+
if (visitId && visitorId) {
|
136
141
|
// TODO keep visit alive?
|
137
142
|
log("Active visit");
|
138
143
|
setReady();
|
139
144
|
} else {
|
140
|
-
|
141
|
-
setCookie("ahoy_visit",
|
145
|
+
visitId = generateId();
|
146
|
+
setCookie("ahoy_visit", visitId, visitTtl);
|
142
147
|
|
143
148
|
// make sure cookies are enabled
|
144
149
|
if (getCookie("ahoy_visit")) {
|
145
150
|
log("Visit started");
|
146
151
|
|
147
|
-
if (!
|
148
|
-
|
149
|
-
setCookie("ahoy_visitor",
|
152
|
+
if (!visitorId) {
|
153
|
+
visitorId = generateId();
|
154
|
+
setCookie("ahoy_visitor", visitorId, visitorTtl);
|
150
155
|
}
|
151
156
|
|
152
157
|
var data = {
|
153
|
-
visit_token:
|
154
|
-
visitor_token:
|
158
|
+
visit_token: visitId,
|
159
|
+
visitor_token: visitorId,
|
155
160
|
platform: ahoy.platform || "Web",
|
156
161
|
landing_page: window.location.href,
|
157
162
|
screen_width: window.screen.width,
|
@@ -172,6 +177,14 @@
|
|
172
177
|
}
|
173
178
|
}
|
174
179
|
|
180
|
+
ahoy.getVisitToken = function () {
|
181
|
+
return visitId;
|
182
|
+
};
|
183
|
+
|
184
|
+
ahoy.getVisitorToken = function () {
|
185
|
+
return visitorId;
|
186
|
+
};
|
187
|
+
|
175
188
|
ahoy.reset = function () {
|
176
189
|
destroyCookie("ahoy_visit");
|
177
190
|
destroyCookie("ahoy_visitor");
|
@@ -209,7 +222,8 @@
|
|
209
222
|
ahoy.trackView = function () {
|
210
223
|
var properties = {
|
211
224
|
url: window.location.href,
|
212
|
-
title: document.title
|
225
|
+
title: document.title,
|
226
|
+
page: page
|
213
227
|
};
|
214
228
|
ahoy.track("$view", properties);
|
215
229
|
};
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ahoy_matey
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -141,6 +141,7 @@ files:
|
|
141
141
|
- app/controllers/ahoy/visits_controller.rb
|
142
142
|
- app/models/ahoy/event.rb
|
143
143
|
- config/routes.rb
|
144
|
+
- lib/ahoy.rb
|
144
145
|
- lib/ahoy/controller.rb
|
145
146
|
- lib/ahoy/engine.rb
|
146
147
|
- lib/ahoy/model.rb
|