redis_analytics 0.7.1 → 1.0.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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/app/views/layouts/redis_analytics/application.html.erb +3 -3
  4. data/coverage/index.html +423 -381
  5. data/lib/redis_analytics/configuration.rb +73 -73
  6. data/lib/redis_analytics/engine.rb +7 -0
  7. data/lib/redis_analytics/filter.rb +22 -22
  8. data/lib/redis_analytics/helpers.rb +58 -58
  9. data/lib/redis_analytics/metrics.rb +73 -73
  10. data/lib/redis_analytics/version.rb +3 -3
  11. data/lib/redis_analytics/visit.rb +96 -96
  12. data/test/dummy/config/environments/production.rb +1 -1
  13. data/test/dummy/config/routes.rb +1 -1
  14. data/test/dummy/log/development.log +1185 -0
  15. data/test/dummy/log/production.log +5172 -0
  16. data/test/dummy/public/assets/application-c900658d554ff9f314a2e1b97cd68997.js.gz +0 -0
  17. data/test/dummy/public/assets/manifest-567012ae8b6f03148f7121062750991f.json +1 -0
  18. data/test/dummy/public/assets/redis_analytics/redis_analytics-82322234eccfd3d7c55a2034ee41ab2a.js +10785 -0
  19. data/test/dummy/public/assets/redis_analytics/redis_analytics-82322234eccfd3d7c55a2034ee41ab2a.js.gz +0 -0
  20. data/test/dummy/public/assets/redis_analytics/redis_analytics-f13abe0904b7483ea8c8c08029e97be3.css +64 -0
  21. data/test/dummy/public/assets/redis_analytics/redis_analytics-f13abe0904b7483ea8c8c08029e97be3.css.gz +0 -0
  22. data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  23. data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  24. data/test/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  25. data/test/dummy/tmp/cache/assets/development/sprockets/3b2603753f496fe7b73a04ce200ea6c0 +0 -0
  26. data/test/dummy/tmp/cache/assets/development/sprockets/4b838eac074ecce8b8ae19c261677ab6 +0 -0
  27. data/test/dummy/tmp/cache/assets/development/sprockets/63afa0e9c559fa85d5c63b6f37728141 +0 -0
  28. data/test/dummy/tmp/cache/assets/development/sprockets/6d0077b1948c42a8892f40120649d217 +0 -0
  29. data/test/dummy/tmp/cache/assets/development/sprockets/a317f594a79c3dd49a6f88b49aabc1b5 +0 -0
  30. data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  31. data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  32. data/test/dummy/tmp/cache/assets/development/sprockets/f069f087fa68223029e7fb8547e5bc3b +0 -0
  33. data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  34. data/test/dummy/tmp/cache/assets/production/sprockets/006eb7cc017cf18c3ea32cab97f0cc3c +0 -0
  35. data/test/dummy/tmp/cache/assets/production/sprockets/192691b9e0bedebfde12633bb3629d0b +0 -0
  36. data/test/dummy/tmp/cache/assets/production/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  37. data/test/dummy/tmp/cache/assets/production/sprockets/3b2603753f496fe7b73a04ce200ea6c0 +0 -0
  38. data/test/dummy/tmp/cache/assets/production/sprockets/4b838eac074ecce8b8ae19c261677ab6 +0 -0
  39. data/test/dummy/tmp/cache/assets/production/sprockets/5cf60638cb580f41112a5a83eb3b72ef +0 -0
  40. data/test/dummy/tmp/cache/assets/production/sprockets/63afa0e9c559fa85d5c63b6f37728141 +0 -0
  41. data/test/dummy/tmp/cache/assets/production/sprockets/6c2f18f7338d56feecce32780357521c +0 -0
  42. data/test/dummy/tmp/cache/assets/production/sprockets/6d0077b1948c42a8892f40120649d217 +0 -0
  43. data/test/dummy/tmp/cache/assets/production/sprockets/7751914469530dae0646d92467e9d72e +0 -0
  44. data/test/dummy/tmp/cache/assets/production/sprockets/8d62150b658b3a8b6fed7e8951f52392 +0 -0
  45. data/test/dummy/tmp/cache/assets/production/sprockets/8ea331810c31cbe1ba34b91a02f769e7 +0 -0
  46. data/test/dummy/tmp/cache/assets/production/sprockets/953bc37b1ee0915247dba29773960202 +0 -0
  47. data/test/dummy/tmp/cache/assets/production/sprockets/9b54afa4ef026f4c288feeec49f2f526 +0 -0
  48. data/test/dummy/tmp/cache/assets/production/sprockets/a29d0dc527ff5ce1252ccf6370514620 +0 -0
  49. data/test/dummy/tmp/cache/assets/production/sprockets/a317f594a79c3dd49a6f88b49aabc1b5 +0 -0
  50. data/test/dummy/tmp/cache/assets/production/sprockets/b01583a39abd5ce0a3d2b2967c6f75bd +0 -0
  51. data/test/dummy/tmp/cache/assets/production/sprockets/cfdf466647e83eb93e0d6630e4b51a25 +0 -0
  52. data/test/dummy/tmp/cache/assets/production/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  53. data/test/dummy/tmp/cache/assets/production/sprockets/d7491740e7757fe2ec57fd6d25461e5c +0 -0
  54. data/test/dummy/tmp/cache/assets/production/sprockets/df16db3bfcc56fafc73b853b7999be1f +0 -0
  55. data/test/dummy/tmp/cache/assets/production/sprockets/e7bd439b274a2155050b47e5a64ea72d +0 -0
  56. data/test/dummy/tmp/cache/assets/production/sprockets/f069f087fa68223029e7fb8547e5bc3b +0 -0
  57. data/test/dummy/tmp/cache/assets/production/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  58. data/test/dummy/tmp/cache/assets/production/sprockets/f9a412f49281cc7e6512f0787f7ba05f +0 -0
  59. data/vendor/assets/javascripts/redis_analytics/{engine.js → redis_analytics.js} +6 -1
  60. data/vendor/assets/stylesheets/redis_analytics/{engine.css → redis_analytics.css} +3 -1
  61. metadata +43 -8
  62. data/app/views/redis_analytics/application/_footer.html.erb~ +0 -3
  63. data/app/views/redis_analytics/visits/_unique_visits_line.html.erb~ +0 -26
  64. data/app/views/redis_analytics/visits/index.html.erb~ +0 -71
  65. data/test/dummy/public/assets/manifest-5bcba723c313582b1d428fc3bf592b29.json +0 -1
@@ -1,101 +1,101 @@
1
- module RedisAnalytics
2
- module Configuration
3
- # Redis connection instance
4
- attr_accessor :redis_connection
1
+ module RedisAnalytics
2
+ module Configuration
3
+ # Redis connection instance
4
+ attr_accessor :redis_connection
5
5
 
6
- # Redis namespace for keys
7
- attr_writer :redis_namespace
6
+ # Redis namespace for keys
7
+ attr_writer :redis_namespace
8
8
 
9
- # Name of the cookie which tracks first visitors
10
- attr_writer :first_visit_cookie_name
9
+ # Name of the cookie which tracks first visitors
10
+ attr_writer :first_visit_cookie_name
11
11
 
12
- # Name of the cookie which tracks current visits
13
- attr_writer :current_visit_cookie_name
12
+ # Name of the cookie which tracks current visits
13
+ attr_writer :current_visit_cookie_name
14
14
 
15
- # Minutes the visit should timeout after (if no hit is received)
16
- attr_writer :visit_timeout
15
+ # Minutes the visit should timeout after (if no hit is received)
16
+ attr_writer :visit_timeout
17
17
 
18
- # Endpoint for dashboard
19
- attr_writer :dashboard_endpoint
18
+ # Endpoint for dashboard
19
+ attr_writer :dashboard_endpoint
20
20
 
21
- # Endpoint for api
22
- attr_writer :api_endpoint
21
+ # Endpoint for api
22
+ attr_writer :api_endpoint
23
23
 
24
- attr_writer :path_filters
24
+ attr_writer :path_filters
25
25
 
26
- attr_writer :filters
26
+ attr_writer :filters
27
27
 
28
- # Path to the Geo IP Database file
29
- attr_writer :geo_ip_data_path
28
+ # Path to the Geo IP Database file
29
+ attr_writer :geo_ip_data_path
30
30
 
31
- # Redis namespace for keys
32
- def redis_namespace
33
- @redis_namespace ||= 'ra'
34
- end
35
-
36
- # Minutes the visit should timeout after (if no hit is received)
37
- def visit_timeout
38
- @visit_timeout ||= 30 # minutes
39
- end
31
+ # Redis namespace for keys
32
+ def redis_namespace
33
+ @redis_namespace ||= 'ra'
34
+ end
40
35
 
41
- # Name of the cookie which tracks first visitors (unknown visitors)
42
- def first_visit_cookie_name
43
- @first_visit_cookie_name ||= '_rucn'
44
- end
36
+ # Minutes the visit should timeout after (if no hit is received)
37
+ def visit_timeout
38
+ @visit_timeout ||= 30 # minutes
39
+ end
45
40
 
46
- # Name of the cookie which tracks visits
47
- def current_visit_cookie_name
48
- @current_visit_cookie_name ||= '_vcn'
49
- end
41
+ # Name of the cookie which tracks first visitors (unknown visitors)
42
+ def first_visit_cookie_name
43
+ @first_visit_cookie_name ||= '_rucn'
44
+ end
50
45
 
51
- def filters
52
- @filters ||= []
53
- end
46
+ # Name of the cookie which tracks visits
47
+ def current_visit_cookie_name
48
+ @current_visit_cookie_name ||= '_vcn'
49
+ end
54
50
 
55
- def path_filters
56
- @path_filters ||= []
57
- end
51
+ def filters
52
+ @filters ||= []
53
+ end
58
54
 
59
- def add_filter(&proc)
60
- filters << RedisAnalytics::Filter.new(proc)
61
- end
55
+ def path_filters
56
+ @path_filters ||= []
57
+ end
62
58
 
63
- def add_path_filter(path)
64
- path_filters << RedisAnalytics::PathFilter.new(path)
65
- end
59
+ def add_filter(&proc)
60
+ filters << RedisAnalytics::Filter.new(proc)
61
+ end
66
62
 
67
- def geo_ip_data_path
68
- @geo_ip_data_path = ::File.expand_path(::File.join(::File.dirname(__FILE__),'..','..')) + "/bin/GeoIP.dat"
69
- end
63
+ def add_path_filter(path)
64
+ path_filters << RedisAnalytics::PathFilter.new(path)
65
+ end
70
66
 
71
- def visitor_recency_slices
72
- @visitor_recency_slices ||= [1, 7, 30]
73
- end
67
+ def geo_ip_data_path
68
+ @geo_ip_data_path = ::File.expand_path(::File.join(::File.dirname(__FILE__),'..','..')) + "/bin/GeoIP.dat"
69
+ end
74
70
 
75
- def default_range
76
- @default_range = :day
77
- end
71
+ def visitor_recency_slices
72
+ @visitor_recency_slices ||= [1, 7, 30]
73
+ end
78
74
 
79
- def redis_key_timestamps # [format, expire in seconds or nil]
80
- ['%Y', '%Y_%m', '%Y_%m_%d', '%Y_%m_%d_%H', '%Y_%m_%d_%H_%M']
81
- end
75
+ def default_range
76
+ @default_range = :day
77
+ end
82
78
 
83
- def time_range_formats
84
- [[:year, :month, "%b"], [:week, :day, "%a"], [:day, :hour, "%l%P"]]
85
- end
79
+ def redis_key_timestamps # [format, expire in seconds or nil]
80
+ ['%Y', '%Y_%m', '%Y_%m_%d', '%Y_%m_%d_%H', '%Y_%m_%d_%H_%M']
81
+ end
86
82
 
87
- def configure
88
- yield self
89
- end
83
+ def time_range_formats
84
+ [[:year, :month, "%b"], [:week, :day, "%a"], [:day, :hour, "%l%P"]]
85
+ end
90
86
 
91
- def api_endpoint
92
- @api_endpoint || dashboard_endpoint + '/api'
93
- end
87
+ def configure
88
+ yield self
89
+ end
94
90
 
95
- def dashboard_endpoint
96
- @dashboard_endpoint || '/redis_analytics'
97
- end
91
+ def api_endpoint
92
+ @api_endpoint || dashboard_endpoint + '/api'
93
+ end
98
94
 
95
+ def dashboard_endpoint
96
+ @dashboard_endpoint || '/redis_analytics'
99
97
  end
98
+
100
99
  end
100
+ end
101
101
 
@@ -13,6 +13,13 @@ module RedisAnalytics
13
13
  initializer "redis_analytics.view_helpers" do |app|
14
14
  ActionController::Base.send :include, RedisAnalytics::Helpers
15
15
  end
16
+
17
+ initializer "redis_analytics.precompile.hook", group: :all do |app|
18
+ app.config.assets.precompile += %w[
19
+ redis_analytics/redis_analytics.js
20
+ redis_analytics/redis_analytics.css
21
+ ]
22
+ end
16
23
  end
17
24
  end
18
25
  end
@@ -1,32 +1,32 @@
1
- module RedisAnalytics
2
- class Filter
3
- attr_reader :filter_proc
1
+ module RedisAnalytics
2
+ class Filter
3
+ attr_reader :filter_proc
4
4
 
5
- def initialize(filter_proc)
6
- @filter_proc = filter_proc
7
- end
8
-
9
- def matches?(request, response)
10
- filter_proc.call(request, response)
11
- end
5
+ def initialize(filter_proc)
6
+ @filter_proc = filter_proc
7
+ end
12
8
 
9
+ def matches?(request, response)
10
+ filter_proc.call(request, response)
13
11
  end
14
12
 
15
- class PathFilter
16
- attr_reader :filter_path
13
+ end
14
+
15
+ class PathFilter
16
+ attr_reader :filter_path
17
17
 
18
- def initialize(filter_path)
19
- @filter_path = filter_path
20
- end
18
+ def initialize(filter_path)
19
+ @filter_path = filter_path
20
+ end
21
21
 
22
- def matches?(request_path)
23
- if filter_path.is_a?(String)
24
- request_path == filter_path
25
- elsif filter_path.is_a?(Regexp)
26
- request_path =~ filter_path
27
- end
22
+ def matches?(request_path)
23
+ if filter_path.is_a?(String)
24
+ request_path == filter_path
25
+ elsif filter_path.is_a?(Regexp)
26
+ request_path =~ filter_path
28
27
  end
29
28
  end
30
-
31
29
  end
32
30
 
31
+ end
32
+
@@ -1,74 +1,74 @@
1
- module RedisAnalytics
2
- module Helpers
1
+ module RedisAnalytics
2
+ module Helpers
3
3
 
4
- FORMAT_SPECIFIER = [['%Y', 365], ['%m', 30], ['%d', 24], ['%H', 60], ['%M', 60]]
4
+ FORMAT_SPECIFIER = [['%Y', 365], ['%m', 30], ['%d', 24], ['%H', 60], ['%M', 60]]
5
5
 
6
- GRANULARITY = ['yearly', 'monthly', 'dayly', 'hourly', 'minutely']
6
+ GRANULARITY = ['yearly', 'monthly', 'dayly', 'hourly', 'minutely']
7
7
 
8
- private
9
- def method_missing(meth, *args, &block)
10
- if meth.to_s =~ /^(minute|hour|dai|day|month|year)ly_([a-z_0-9]+)$/
11
- granularity = ($1 == 'dai' ? 'day' : $1) + 'ly'
12
- metric_name = $2
13
- data(granularity, metric_name, *args)
14
- else
15
- super
16
- end
8
+ private
9
+ def method_missing(meth, *args, &block)
10
+ if meth.to_s =~ /^(minute|hour|dai|day|month|year)ly_([a-z_0-9]+)$/
11
+ granularity = ($1 == 'dai' ? 'day' : $1) + 'ly'
12
+ metric_name = $2
13
+ data(granularity, metric_name, *args)
14
+ else
15
+ super
17
16
  end
17
+ end
18
18
 
19
- def metric_type(metric_name)
20
- RedisAnalytics.redis_connection.hget("#{RedisAnalytics.redis_namespace}:#METRICS", metric_name)
21
- end
19
+ def metric_type(metric_name)
20
+ RedisAnalytics.redis_connection.hget("#{RedisAnalytics.redis_namespace}:#METRICS", metric_name)
21
+ end
22
22
 
23
- def data(granularity, metric_name, from_date, options = {})
24
- aggregate = options[:aggregate] || false
25
- x = granularity[0..-3]
23
+ def data(granularity, metric_name, from_date, options = {})
24
+ aggregate = options[:aggregate] || false
25
+ x = granularity[0..-3]
26
26
 
27
- to_date = (options[:to_date] || Time.now).send("end_of_#{x}")
28
- i = from_date.send("beginning_of_#{x}")
27
+ to_date = (options[:to_date] || Time.now).send("end_of_#{x}")
28
+ i = from_date.send("beginning_of_#{x}")
29
29
 
30
- union = []
31
- time = []
32
- begin
33
- slice_key = i.strftime(FORMAT_SPECIFIER[0..GRANULARITY.index(granularity)].map{|x| x[0]}.join('_'))
34
- union << "#{RedisAnalytics.redis_namespace}:#{metric_name}:#{slice_key}"
35
- time << slice_key.split('_')
36
- i += 1.send(x)
37
- end while i <= to_date
38
- seq = get_next_seq
39
- if metric_type(metric_name) == 'String'
40
- if aggregate
41
- union_key = "#{RedisAnalytics.redis_namespace}:#{seq}"
42
- RedisAnalytics.redis_connection.zunionstore(union_key, union)
43
- RedisAnalytics.redis_connection.expire(union_key, 100)
44
- return Hash[RedisAnalytics.redis_connection.zrange(union_key, 0, -1, :with_scores => true)]
45
- else
46
- return time.zip(union.map{|x| Hash[RedisAnalytics.redis_connection.zrange(x, 0, -1, :with_scores => true)]})
47
- end
48
- elsif metric_type(metric_name) == 'Fixnum'
49
- if aggregate
50
- return RedisAnalytics.redis_connection.mget(*union).map(&:to_i).inject(:+)
51
- else
52
- return time.zip(RedisAnalytics.redis_connection.mget(*union).map(&:to_i))
53
- end
30
+ union = []
31
+ time = []
32
+ begin
33
+ slice_key = i.strftime(FORMAT_SPECIFIER[0..GRANULARITY.index(granularity)].map{|x| x[0]}.join('_'))
34
+ union << "#{RedisAnalytics.redis_namespace}:#{metric_name}:#{slice_key}"
35
+ time << slice_key.split('_')
36
+ i += 1.send(x)
37
+ end while i <= to_date
38
+ seq = get_next_seq
39
+ if metric_type(metric_name) == 'String'
40
+ if aggregate
41
+ union_key = "#{RedisAnalytics.redis_namespace}:#{seq}"
42
+ RedisAnalytics.redis_connection.zunionstore(union_key, union)
43
+ RedisAnalytics.redis_connection.expire(union_key, 100)
44
+ return Hash[RedisAnalytics.redis_connection.zrange(union_key, 0, -1, :with_scores => true)]
45
+ else
46
+ return time.zip(union.map{|x| Hash[RedisAnalytics.redis_connection.zrange(x, 0, -1, :with_scores => true)]})
47
+ end
48
+ elsif metric_type(metric_name) == 'Fixnum'
49
+ if aggregate
50
+ return RedisAnalytics.redis_connection.mget(*union).map(&:to_i).inject(:+)
54
51
  else
55
- if Metrics.public_instance_methods.any?{|m| m.to_s =~ /^#{metric_name}_ratio_per_(hit|visit)$/}
56
- aggregate ? {} : time.zip([{}] * time.length)
57
- elsif Metrics.public_instance_methods.any?{|m| m.to_s =~ /^#{metric_name}_count_per_(hit|visit)$/}
58
- aggregate ? 0 : time.zip([0] * time.length)
59
- else
60
- aggregate ? 0 : time.zip([0] * time.length)
61
- end
52
+ return time.zip(RedisAnalytics.redis_connection.mget(*union).map(&:to_i))
53
+ end
54
+ else
55
+ if Metrics.public_instance_methods.any?{|m| m.to_s =~ /^#{metric_name}_ratio_per_(hit|visit)$/}
56
+ aggregate ? {} : time.zip([{}] * time.length)
57
+ elsif Metrics.public_instance_methods.any?{|m| m.to_s =~ /^#{metric_name}_count_per_(hit|visit)$/}
58
+ aggregate ? 0 : time.zip([0] * time.length)
59
+ else
60
+ aggregate ? 0 : time.zip([0] * time.length)
62
61
  end
63
62
  end
63
+ end
64
64
 
65
- def get_next_seq
66
- seq = RedisAnalytics.redis_connection.incr("#{RedisAnalytics.redis_namespace}:#SEQUENCER")
67
- end
65
+ def get_next_seq
66
+ seq = RedisAnalytics.redis_connection.incr("#{RedisAnalytics.redis_namespace}:#SEQUENCER")
67
+ end
68
68
 
69
- def time_range
70
- (request.cookies["_rarng"] || RedisAnalytics.default_range).to_sym
71
- end
69
+ def time_range
70
+ (request.cookies["_rarng"] || RedisAnalytics.default_range).to_sym
72
71
  end
73
72
  end
73
+ end
74
74
 
@@ -1,95 +1,95 @@
1
- module RedisAnalytics
2
- module Metrics
1
+ module RedisAnalytics
2
+ module Metrics
3
3
 
4
- attr_reader :visit_time_count_per_visit
5
- attr_reader :visits_count_per_visit, :first_visits_count_per_visit, :repeat_visits_count_per_visit
6
- attr_reader :unique_visits_ratio_per_visit
7
- attr_reader :page_views_count_per_hit, :second_page_views_count_per_hit
4
+ attr_reader :visit_time_count_per_visit
5
+ attr_reader :visits_count_per_visit, :first_visits_count_per_visit, :repeat_visits_count_per_visit
6
+ attr_reader :unique_visits_ratio_per_visit
7
+ attr_reader :page_views_count_per_hit, :second_page_views_count_per_hit
8
8
 
9
- # Developers can override or define new public methods here
10
- # Methods should start with track and end with count or types
11
- # Return types should be Fixnum or String resp.
12
- # If you return nil or an error nothing will be tracked
9
+ # Developers can override or define new public methods here
10
+ # Methods should start with track and end with count or types
11
+ # Return types should be Fixnum or String resp.
12
+ # If you return nil or an error nothing will be tracked
13
13
 
14
- def browser_ratio_per_visit
15
- user_agent.name.to_s
16
- end
14
+ def browser_ratio_per_visit
15
+ user_agent.name.to_s
16
+ end
17
17
 
18
- def platform_ratio_per_visit
19
- user_agent.platform.to_s
20
- end
18
+ def platform_ratio_per_visit
19
+ user_agent.platform.to_s
20
+ end
21
21
 
22
- def country_ratio_per_visit
23
- if defined?(GeoIP)
24
- begin
25
- g = GeoIP.new(RedisAnalytics.geo_ip_data_path)
26
- geo_country_code = g.country(@rack_request.ip).to_hash[:country_code2]
27
- if geo_country_code and geo_country_code =~ /^[A-Z]{2}$/
28
- return geo_country_code
29
- end
30
- rescue Exception => e
31
- warn "Unable to fetch country info #{e}"
22
+ def country_ratio_per_visit
23
+ if defined?(GeoIP)
24
+ begin
25
+ g = GeoIP.new(RedisAnalytics.geo_ip_data_path)
26
+ geo_country_code = g.country(@rack_request.ip).to_hash[:country_code2]
27
+ if geo_country_code and geo_country_code =~ /^[A-Z]{2}$/
28
+ return geo_country_code
32
29
  end
30
+ rescue Exception => e
31
+ warn "Unable to fetch country info #{e}"
33
32
  end
34
33
  end
34
+ end
35
35
 
36
- def recency_ratio_per_visit
37
- # tracking for visitor recency
38
- if @last_visit_time # from first_visit_cookie
39
- days_since_last_visit = ((@t.to_i - @last_visit_time.to_i)/(24*3600)).round
40
- if days_since_last_visit <= 1
41
- return 'd'
42
- elsif days_since_last_visit <= 7
43
- return 'w'
44
- elsif days_since_last_visit <= 30
45
- return 'm'
46
- else
47
- return 'o'
48
- end
36
+ def recency_ratio_per_visit
37
+ # tracking for visitor recency
38
+ if @last_visit_time # from first_visit_cookie
39
+ days_since_last_visit = ((@t.to_i - @last_visit_time.to_i)/(24*3600)).round
40
+ if days_since_last_visit <= 1
41
+ return 'd'
42
+ elsif days_since_last_visit <= 7
43
+ return 'w'
44
+ elsif days_since_last_visit <= 30
45
+ return 'm'
46
+ else
47
+ return 'o'
49
48
  end
50
49
  end
50
+ end
51
51
 
52
- def device_ratio_per_visit
53
- return ((user_agent.mobile? or user_agent.tablet?) ? 'mobile' : 'desktop')
54
- end
52
+ def device_ratio_per_visit
53
+ return ((user_agent.mobile? or user_agent.tablet?) ? 'mobile' : 'desktop')
54
+ end
55
55
 
56
- def referrer_ratio_per_visit
57
- if @rack_request.referrer
58
- ['google', 'bing', 'yahoo', 'cleartrip', 'github'].each do |referrer|
59
- # this will track x.google.mysite.com as google so its buggy, fix the regex
60
- if m = @rack_request.referrer.match(/^(https?:\/\/)?([a-zA-Z0-9\.\-]+\.)?(#{referrer})\.([a-zA-Z\.]+)(:[0-9]+)?(\/.*)?$/)
61
- "REFERRER => #{m.to_a[3]}"
62
- referrer = m.to_a[3]
63
- else
64
- referrer = 'other'
65
- end
56
+ def referrer_ratio_per_visit
57
+ if @rack_request.referrer
58
+ ['google', 'bing', 'yahoo', 'cleartrip', 'github'].each do |referrer|
59
+ # this will track x.google.mysite.com as google so its buggy, fix the regex
60
+ if m = @rack_request.referrer.match(/^(https?:\/\/)?([a-zA-Z0-9\.\-]+\.)?(#{referrer})\.([a-zA-Z\.]+)(:[0-9]+)?(\/.*)?$/)
61
+ "REFERRER => #{m.to_a[3]}"
62
+ referrer = m.to_a[3]
63
+ else
64
+ referrer = 'other'
66
65
  end
67
- else
68
- referrer = 'organic'
69
66
  end
70
- return referrer
71
- end
72
-
73
- # track the ratio of URL's visits
74
- def url_ratio_per_hit
75
- return @rack_request.path
76
- end
77
-
78
- # track the landing pages ratio
79
- def landing_page_ratio_per_hit
80
- return @rack_request.path if @page_view_seq_no.to_i == 0
67
+ else
68
+ referrer = 'organic'
81
69
  end
70
+ return referrer
71
+ end
82
72
 
83
- # track the landing pages ratio
84
- def http_response_ratio_per_hit
85
- return @rack_response.status.to_s
86
- end
73
+ # track the ratio of URL's visits
74
+ def url_ratio_per_hit
75
+ return @rack_request.path
76
+ end
77
+
78
+ # track the landing pages ratio
79
+ def landing_page_ratio_per_hit
80
+ return @rack_request.path if @page_view_seq_no.to_i == 0
81
+ end
87
82
 
88
- private
89
- def user_agent
90
- Browser.new(:ua => @rack_request.user_agent, :accept_language => 'en-us')
91
- end
83
+ # track the landing pages ratio
84
+ def http_response_ratio_per_hit
85
+ return @rack_response.status.to_s
86
+ end
92
87
 
88
+ private
89
+ def user_agent
90
+ Browser.new(:ua => @rack_request.user_agent, :accept_language => 'en-us')
93
91
  end
92
+
94
93
  end
94
+ end
95
95