ahoy_matey 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2e6b98a3bbcd3ab67886e562a6a285344a1d0b53
4
- data.tar.gz: 97975b14612ca24bf380584f1020c39407a88894
3
+ metadata.gz: 7973efa4435f37d54dfa0bd84b7441473a4e3ddf
4
+ data.tar.gz: 3ceb16b3595ae8b258e63102ae996667652802af
5
5
  SHA512:
6
- metadata.gz: 3808dc8508cdbf29d1b018224179141d2588be09b76752035ddbb9f697ec22df873a0272de63e536575a6d887fcfee3997e9a9d3eddd7cfee02eafdbc68e8e9a
7
- data.tar.gz: d8c2b3764a85b9f66d0b06da755260e501c089fe3cab7d8a584cf4e167803714b103f1cf6b692eea242e3571ceabda097acb8285da9f88cb79f3213a4b8a3e79
6
+ metadata.gz: a16bd0b6d30f134a901d2574bc944d411e049e1a7fcaae46707245a98287013b2e4c26c69eca8fd77cf00394e34bd6576843b62d85fc7d93e92344565e7e58a1
7
+ data.tar.gz: 6c228da084f4949c9fbd8618b1fdc2a04f83a75402d3f2eadbba954f6f02988b040b223181f4b7a34e5ec6d5e375c218a367ceb3457239966bff877b8b564503
data/README.md CHANGED
@@ -4,16 +4,17 @@
4
4
 
5
5
  In under a minute, start learning more about your visitors.
6
6
 
7
- - traffic source - referrer, referring domain, campaign, landing page
7
+ - traffic source - referrer, referring domain, landing page, search keyword
8
8
  - location - country, region, and city
9
9
  - technology - browser, OS, and device type
10
+ - utm parameters - source, medium, term, content, campaign
10
11
 
11
12
  It’s all stored in **your database** so you can easily combine it with other data.
12
13
 
13
14
  See which campaigns generate the most revenue effortlessly.
14
15
 
15
16
  ```ruby
16
- Order.joins(:visit).group("campaign").sum(:revenue)
17
+ Order.joins(:visit).group("utm_campaign").sum(:revenue)
17
18
  ```
18
19
 
19
20
  ## Ready, Set, Go
@@ -66,8 +67,8 @@ Order.joins(:visit).group("city").count
66
67
 
67
68
  ## Features
68
69
 
69
- - Excludes search engines
70
- - Gracefully degrades when cookies are disabled
70
+ - Excludes bots
71
+ - Degrades gracefully when cookies are disabled
71
72
  - Gets campaign from utm_campaign parameter
72
73
 
73
74
  ## TODO
@@ -75,8 +76,10 @@ Order.joins(:visit).group("city").count
75
76
  - better readme
76
77
  - model integration
77
78
  - update visit when user logs in
78
- - better browser / OS detection
79
79
  - set visit_id automatically on `visitable` models
80
+ - simple dashboard
81
+ - hook to store additional fields
82
+ - turn off modules
80
83
 
81
84
  ## Contributing
82
85
 
data/ahoy_matey.gemspec CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.add_dependency "addressable"
22
22
  spec.add_dependency "browser", ">= 0.4.0"
23
23
  spec.add_dependency "geocoder"
24
+ spec.add_dependency "referer-parser"
24
25
 
25
26
  spec.add_development_dependency "bundler", "~> 1.5"
26
27
  spec.add_development_dependency "rake"
@@ -14,58 +14,10 @@ module Ahoy
14
14
  v.user = current_user if respond_to?(:current_user)
15
15
  end
16
16
 
17
- referring_uri = Addressable::URI.parse(params[:referrer]) rescue nil
18
- if referring_uri
19
- visit.referring_domain = referring_uri.host
20
- end
21
-
22
- landing_uri = Addressable::URI.parse(params[:landing_page]) rescue nil
23
- if landing_uri
24
- visit.campaign = (landing_uri.query_values || {})["utm_campaign"]
25
- end
26
-
27
- visit.browser = browser.name
28
-
29
- # TODO add more
30
- visit.os =
31
- if browser.android?
32
- "Android"
33
- elsif browser.ios?
34
- "iOS"
35
- elsif browser.windows_phone?
36
- "Windows Phone"
37
- elsif browser.blackberry?
38
- "Blackberry"
39
- elsif browser.chrome_os?
40
- "Chrome OS"
41
- elsif browser.mac?
42
- "Mac"
43
- elsif browser.windows?
44
- "Windows"
45
- elsif browser.linux?
46
- "Linux"
47
- end
48
-
49
- visit.device_type =
50
- if browser.tv?
51
- "TV"
52
- elsif browser.console?
53
- "Console"
54
- elsif browser.tablet?
55
- "Tablet"
56
- elsif browser.mobile?
57
- "Mobile"
58
- else
59
- "Desktop"
60
- end
61
-
62
- # location
63
- location = Geocoder.search(request.remote_ip).first rescue nil
64
- if location
65
- visit.country = location.country.presence
66
- visit.region = location.state.presence
67
- visit.city = location.city.presence
68
- end
17
+ visit.set_traffic_source
18
+ visit.set_technology
19
+ visit.set_location
20
+ visit.set_utm_parameters
69
21
 
70
22
  visit.save!
71
23
  render json: {id: visit.id}
@@ -1,5 +1,71 @@
1
1
  module Ahoy
2
2
  class Visit < ActiveRecord::Base
3
3
  belongs_to :user, polymorphic: true
4
+
5
+ def set_traffic_source
6
+ referring_uri = Addressable::URI.parse(referrer) rescue nil
7
+ self.referring_domain = referring_uri.try(:host)
8
+ search_keyword = RefererParser::Referer.new(referrer).search_term rescue nil
9
+ self.search_keyword = search_keyword.present? ? search_keyword : nil
10
+ end
11
+
12
+ def set_utm_parameters
13
+ landing_uri = Addressable::URI.parse(landing_page) rescue nil
14
+ if landing_uri
15
+ query_values = landing_uri.query_values || {}
16
+ %w[utm_source utm_medium utm_term utm_content utm_campaign].each do |name|
17
+ self[name] = query_values[name]
18
+ end
19
+ end
20
+ end
21
+
22
+ def set_technology
23
+ browser = Browser.new(ua: user_agent)
24
+
25
+ self.browser = browser.name
26
+
27
+ # TODO add more
28
+ self.os =
29
+ if browser.android?
30
+ "Android"
31
+ elsif browser.ios?
32
+ "iOS"
33
+ elsif browser.windows_phone?
34
+ "Windows Phone"
35
+ elsif browser.blackberry?
36
+ "Blackberry"
37
+ elsif browser.chrome_os?
38
+ "Chrome OS"
39
+ elsif browser.mac?
40
+ "Mac"
41
+ elsif browser.windows?
42
+ "Windows"
43
+ elsif browser.linux?
44
+ "Linux"
45
+ end
46
+
47
+ self.device_type =
48
+ if browser.tv?
49
+ "TV"
50
+ elsif browser.console?
51
+ "Console"
52
+ elsif browser.tablet?
53
+ "Tablet"
54
+ elsif browser.mobile?
55
+ "Mobile"
56
+ else
57
+ "Desktop"
58
+ end
59
+ end
60
+
61
+ def set_location
62
+ location = Geocoder.search(ip).first rescue nil
63
+ if location
64
+ self.country = location.country.presence
65
+ self.region = location.state.presence
66
+ self.city = location.city.presence
67
+ end
68
+ end
69
+
4
70
  end
5
71
  end
@@ -1,5 +1,5 @@
1
1
  module Ahoy
2
- module ControllerExtensions
2
+ module Controller
3
3
 
4
4
  def self.included(base)
5
5
  base.helper_method :current_visit
@@ -10,13 +10,6 @@ module Ahoy
10
10
  def current_visit
11
11
  if cookies[:ahoy_visit]
12
12
  @current_visit ||= Ahoy::Visit.where(visit_token: cookies[:ahoy_visit]).first
13
- if @current_visit
14
- @current_visit
15
- else
16
- # clear cookie if visits are destroyed
17
- cookies.delete(:ahoy_visit)
18
- nil
19
- end
20
13
  end
21
14
  end
22
15
 
data/lib/ahoy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ahoy
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/lib/ahoy_matey.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  require "ahoy/version"
2
- require "ahoy/controller_extensions"
2
+ require "ahoy/controller"
3
3
  require "addressable/uri"
4
4
  require "browser"
5
5
  require "geocoder"
6
+ require "referer-parser"
6
7
 
7
8
  module Ahoy
8
9
  class Engine < ::Rails::Engine
@@ -10,4 +11,18 @@ module Ahoy
10
11
  end
11
12
  end
12
13
 
13
- ActionController::Base.send :include, Ahoy::ControllerExtensions
14
+ ActionController::Base.send :include, Ahoy::Controller
15
+
16
+ if defined?(Warden)
17
+ Warden::Manager.after_authentication do |user, auth, opts|
18
+ p user
19
+ p auth.env
20
+ p opts
21
+ request = Rack::Request.new(auth.env)
22
+ if request.cookies["ahoy_visit"]
23
+ visit = Ahoy::Visit.where(visit_token: request.cookies["ahoy_visit"]).first
24
+ visit.user = user
25
+ visit.save!
26
+ end
27
+ end
28
+ end
@@ -1,18 +1,23 @@
1
1
  class <%= migration_class_name %> < ActiveRecord::Migration
2
2
  def change
3
3
  create_table :ahoy_visits do |t|
4
+ # cookies
4
5
  t.string :visit_token
5
6
  t.string :visitor_token
6
- t.integer :user_id
7
- t.string :user_type
7
+
8
+ # standard
8
9
  t.string :ip
9
10
  t.text :user_agent
11
+ t.text :referrer
12
+ t.text :landing_page
13
+
14
+ # user
15
+ t.integer :user_id
16
+ t.string :user_type
10
17
 
11
18
  # traffic source
12
- t.text :referrer
13
19
  t.string :referring_domain
14
- t.string :campaign
15
- t.text :landing_page
20
+ t.string :search_keyword
16
21
 
17
22
  # technology
18
23
  t.string :browser
@@ -24,6 +29,13 @@ class <%= migration_class_name %> < ActiveRecord::Migration
24
29
  t.string :region
25
30
  t.string :city
26
31
 
32
+ # utm parameters
33
+ t.string :utm_source
34
+ t.string :utm_medium
35
+ t.string :utm_term
36
+ t.string :utm_content
37
+ t.string :utm_campaign
38
+
27
39
  t.timestamp :created_at
28
40
  end
29
41
 
@@ -1,10 +1,12 @@
1
1
  /*jslint browser: true, indent: 2, plusplus: true, vars: true */
2
2
 
3
- (function () {
3
+ (function (window) {
4
4
  "use strict";
5
5
 
6
6
  var debugMode = false;
7
7
  var visitTtl, visitorTtl;
8
+ var $ = window.jQuery || window.Zepto || window.$;
9
+ var visitToken, visitorToken;
8
10
 
9
11
  if (debugMode) {
10
12
  visitTtl = 0.2;
@@ -18,22 +20,27 @@
18
20
 
19
21
  // http://www.quirksmode.org/js/cookies.html
20
22
  function setCookie(name, value, ttl) {
23
+ var expires = "";
21
24
  if (ttl) {
22
25
  var date = new Date();
23
- date.setTime(date.getTime()+(ttl*60*1000));
24
- var expires = "; expires="+date.toGMTString();
26
+ date.setTime(date.getTime() + (ttl * 60 * 1000));
27
+ expires = "; expires=" + date.toGMTString();
25
28
  }
26
- else var expires = "";
27
- document.cookie = name+"="+value+expires+"; path=/";
29
+ document.cookie = name + "=" + value + expires + "; path=/";
28
30
  }
29
31
 
30
32
  function getCookie(name) {
33
+ var i, c;
31
34
  var nameEQ = name + "=";
32
35
  var ca = document.cookie.split(';');
33
- for(var i=0;i < ca.length;i++) {
34
- var c = ca[i];
35
- while (c.charAt(0)==' ') c = c.substring(1,c.length);
36
- if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
36
+ for (i = 0; i < ca.length; i++) {
37
+ c = ca[i];
38
+ while (c.charAt(0) === ' ') {
39
+ c = c.substring(1, c.length);
40
+ }
41
+ if (c.indexOf(nameEQ) === 0) {
42
+ return c.substring(nameEQ.length, c.length);
43
+ }
37
44
  }
38
45
  return null;
39
46
  }
@@ -45,9 +52,10 @@
45
52
  var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz';
46
53
  var length = 32;
47
54
  var string = '';
55
+ var i, randomNumber;
48
56
 
49
- for (var i = 0; i < length; i++) {
50
- var randomNumber = Math.floor(Math.random() * chars.length);
57
+ for (i = 0; i < length; i++) {
58
+ randomNumber = Math.floor(Math.random() * chars.length);
51
59
  string += chars.substring(randomNumber, randomNumber + 1);
52
60
  }
53
61
 
@@ -55,13 +63,13 @@
55
63
  }
56
64
 
57
65
  function debug(message) {
58
- console.log(message, visitToken, visitorToken);
66
+ window.console.log(message, visitToken, visitorToken);
59
67
  }
60
68
 
61
69
  // main
62
70
 
63
- var visitToken = getCookie("ahoy_visit");
64
- var visitorToken = getCookie("ahoy_visitor");
71
+ visitToken = getCookie("ahoy_visit");
72
+ visitorToken = getCookie("ahoy_visitor");
65
73
 
66
74
  if (visitToken && visitorToken) {
67
75
  // TODO keep visit alive?
@@ -99,4 +107,4 @@
99
107
  }
100
108
  }
101
109
 
102
- }());
110
+ }(window));
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.0.3
4
+ version: 0.0.4
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-02-26 00:00:00.000000000 Z
11
+ date: 2014-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: referer-parser
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: bundler
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -96,7 +110,7 @@ files:
96
110
  - app/controllers/ahoy/visits_controller.rb
97
111
  - app/models/ahoy/visit.rb
98
112
  - config/routes.rb
99
- - lib/ahoy/controller_extensions.rb
113
+ - lib/ahoy/controller.rb
100
114
  - lib/ahoy/version.rb
101
115
  - lib/ahoy_matey.rb
102
116
  - lib/generators/ahoy/install_generator.rb