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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 901b2af03cc91c3ad7ccef91dedfd1514e452357
4
- data.tar.gz: 83494b26ea230cf54836b3d67eb6efc88cbac45f
3
+ metadata.gz: aae43abe84c855bce95234160c4e8e0a2496155c
4
+ data.tar.gz: 037987022eaaf1738e0187b86683823a632639a2
5
5
  SHA512:
6
- metadata.gz: 1772c4ed5abe7395b6cf651f48ef05ec7454b3e30c80d9e54989407e8dd510fdba40f2ff827b5041dbe93fc22160eba8dc612fe780657bce4ba55bb5da6f50ce
7
- data.tar.gz: a33c3b9ea6cb8e4ae7104085b392c7d0bd49ed1121eaef0eace1c9157f11098843236f66792c0138286e2e11c3ee41bb5d2ce97676428f1ef28f3b812e9cc269
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
- controller.request.ip == "192.168.1.1"
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] || generate_token
6
- visitor_token = params[:visitor_token] || generate_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
@@ -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 = cookies[:ahoy_visit] || request.headers["Ahoy-Visit"]
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 ahoy
20
- @ahoy ||= Ahoy::Tracker.new(controller: self)
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 !(@controller and Ahoy.exclude_method and Ahoy.exclude_method.call(@controller))
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
@@ -1,3 +1,3 @@
1
1
  module Ahoy
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/ahoy/warden.rb CHANGED
@@ -9,6 +9,6 @@ Warden::Manager.after_set_user except: :fetch do |user, auth, opts|
9
9
  visit.save!
10
10
  end
11
11
  end
12
- ahoy = Ahoy::Tracker.new
12
+ ahoy = Ahoy::Tracker.new(request: request)
13
13
  ahoy.track "$authenticate", {}, user: user, visit: visit
14
14
  end
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 "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.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 visitToken, visitorToken;
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
- // https://github.com/klughammer/node-randomstring
84
+ // http://stackoverflow.com/a/2117523/1177228
76
85
  function generateId() {
77
- var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz';
78
- var length = 32;
79
- var string = '';
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
- visitToken = getCookie("ahoy_visit");
133
- visitorToken = getCookie("ahoy_visitor");
137
+ visitId = getCookie("ahoy_visit");
138
+ visitorId = getCookie("ahoy_visitor");
134
139
 
135
- if (visitToken && visitorToken) {
140
+ if (visitId && visitorId) {
136
141
  // TODO keep visit alive?
137
142
  log("Active visit");
138
143
  setReady();
139
144
  } else {
140
- visitToken = generateId();
141
- setCookie("ahoy_visit", visitToken, visitTtl);
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 (!visitorToken) {
148
- visitorToken = generateId();
149
- setCookie("ahoy_visitor", visitorToken, visitorTtl);
152
+ if (!visitorId) {
153
+ visitorId = generateId();
154
+ setCookie("ahoy_visitor", visitorId, visitorTtl);
150
155
  }
151
156
 
152
157
  var data = {
153
- visit_token: visitToken,
154
- visitor_token: visitorToken,
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.2.2
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-05-27 00:00:00.000000000 Z
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