mitamirri 0.13.8

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 (90) hide show
  1. data/.document +5 -0
  2. data/.gitignore +26 -0
  3. data/README.rdoc +117 -0
  4. data/Rakefile +26 -0
  5. data/VERSION +1 -0
  6. data/app/controllers/application_controller.rb +10 -0
  7. data/app/controllers/trackable_actions_controller.rb +10 -0
  8. data/app/controllers/trackable_sessions_controller.rb +100 -0
  9. data/app/helpers/application_helper.rb +2 -0
  10. data/app/models/trackable_action.rb +193 -0
  11. data/app/models/trackable_location.rb +19 -0
  12. data/app/models/trackable_session.rb +352 -0
  13. data/app/models/trackable_stat.rb +64 -0
  14. data/app/views/layouts/application.html.erb +20 -0
  15. data/app/views/trackable_sessions/_keywords_graph.html.erb +24 -0
  16. data/app/views/trackable_sessions/_print_buttons.html.erb +3 -0
  17. data/app/views/trackable_sessions/_sessions.html.erb +26 -0
  18. data/app/views/trackable_sessions/_top_referrers.html.erb +24 -0
  19. data/app/views/trackable_sessions/_traffic_summary_all.html.erb +64 -0
  20. data/app/views/trackable_sessions/_traffic_summary_by_kind.html.erb +48 -0
  21. data/app/views/trackable_sessions/_visits_graph.html.erb +25 -0
  22. data/app/views/trackable_sessions/content.html.erb +119 -0
  23. data/app/views/trackable_sessions/explorer.html.erb +67 -0
  24. data/app/views/trackable_sessions/export.xls.erb +5 -0
  25. data/app/views/trackable_sessions/index.html.erb +47 -0
  26. data/app/views/trackable_sessions/intersite.html.erb +97 -0
  27. data/app/views/trackable_sessions/leads.html.erb +98 -0
  28. data/app/views/trackable_sessions/show.html.erb +113 -0
  29. data/app/views/trackable_sessions/visitor_profile.html.erb +114 -0
  30. data/config/boot.rb +110 -0
  31. data/config/database.yml +0 -0
  32. data/config/environment.rb +24 -0
  33. data/config/environments/development.rb +17 -0
  34. data/config/environments/production.rb +28 -0
  35. data/config/environments/test.rb +31 -0
  36. data/config/initializers/backtrace_silencers.rb +7 -0
  37. data/config/initializers/database.rb +1 -0
  38. data/config/initializers/inflections.rb +10 -0
  39. data/config/initializers/mime_types.rb +5 -0
  40. data/config/initializers/new_rails_defaults.rb +21 -0
  41. data/config/initializers/session_store.rb +15 -0
  42. data/config/locales/en.yml +5 -0
  43. data/config/routes.rb +11 -0
  44. data/db/development.sqlite3 +0 -0
  45. data/db/migrate/20100810173533_create_trackable_sessions.rb +23 -0
  46. data/db/migrate/20100810173605_create_trackable_actions.rb +20 -0
  47. data/db/test.sqlite3 +1 -0
  48. data/doc/README_FOR_APP +2 -0
  49. data/init.rb +8 -0
  50. data/lib/mitamirri/content_report.rb +75 -0
  51. data/lib/mitamirri/helper.rb +106 -0
  52. data/lib/mitamirri/intersite_traffic_report.rb +122 -0
  53. data/lib/mitamirri/leads_report.rb +90 -0
  54. data/lib/mitamirri/session_report.rb +219 -0
  55. data/lib/mitamirri/stat_report.rb +216 -0
  56. data/lib/mitamirri/tasks.rb +27 -0
  57. data/lib/mitamirri/visitor_profile_report.rb +127 -0
  58. data/lib/mitamirri.rb +15 -0
  59. data/log/development.log +0 -0
  60. data/log/production.log +0 -0
  61. data/log/server.log +0 -0
  62. data/log/test.log +0 -0
  63. data/mitamirri.gemspec +125 -0
  64. data/public/stylesheets/mitamirri.css +736 -0
  65. data/script/about +4 -0
  66. data/script/console +3 -0
  67. data/script/dbconsole +3 -0
  68. data/script/destroy +3 -0
  69. data/script/generate +3 -0
  70. data/script/performance/benchmarker +3 -0
  71. data/script/performance/profiler +3 -0
  72. data/script/plugin +3 -0
  73. data/script/runner +3 -0
  74. data/script/server +3 -0
  75. data/spec/controllers/trackable_actions_controller_spec.rb +5 -0
  76. data/spec/controllers/trackable_sessions_controller_spec.rb +5 -0
  77. data/spec/custom_matchers.rb +23 -0
  78. data/spec/helpers/application_helper_spec.rb +57 -0
  79. data/spec/lib/content_report_spec.rb +37 -0
  80. data/spec/lib/intersite_traffic_report_spec.rb +51 -0
  81. data/spec/lib/leads_report_spec.rb +46 -0
  82. data/spec/lib/session_report_spec.rb +107 -0
  83. data/spec/lib/stat_report_spec.rb +106 -0
  84. data/spec/models/trackable_action_spec.rb +42 -0
  85. data/spec/models/trackable_session_spec.rb +154 -0
  86. data/spec/rcov.opts +4 -0
  87. data/spec/schema.rb +34 -0
  88. data/spec/spec.opts +4 -0
  89. data/spec/spec_helper.rb +32 -0
  90. metadata +155 -0
@@ -0,0 +1,90 @@
1
+ module Mitamirri
2
+
3
+ class LeadsReport
4
+
5
+ # Search params
6
+ attr_accessor :site
7
+ attr_accessor :time_period
8
+ attr_accessor :start_date
9
+ attr_accessor :end_date
10
+
11
+ # Stat attributes
12
+
13
+ # Initialization
14
+
15
+ def initialize(args = {})
16
+ args.each{|k,v| self.send("#{k}=",v) if self.respond_to?(k)}
17
+ self.time_period = args[:time_period] || 'past 6 months'
18
+ self.start_date = self.dates.first
19
+ self.end_date = self.dates.last
20
+ end
21
+
22
+ # Generate an array of dates spanning the appropriate time period.
23
+ def dates
24
+ return @dates if @dates
25
+ @dates = []
26
+ case self.time_period.downcase
27
+ when 'past month'
28
+ _increment = 4
29
+ when 'past 3 months'
30
+ _increment = 12
31
+ when 'past 6 months'
32
+ _increment = 24
33
+ when 'past 12 months'
34
+ _increment = 52
35
+ else 'all time'
36
+ _increment = 104
37
+ end
38
+
39
+ (1.._increment).each{ |i| @dates << (Time.zone.now - i.weeks).beginning_of_week }
40
+ @dates.reverse!
41
+ @dates << Time.zone.now
42
+ @dates
43
+ end
44
+
45
+ # Graphing objects
46
+
47
+ def leads(args)
48
+ _leads = []
49
+ _leads << Lead.new(:stats => lead_stats(args))
50
+ _leads
51
+ end
52
+
53
+ def lead_stats(args)
54
+ _lead_stats = []
55
+ dates.each do |date|
56
+ _total_sessions = TrackableSession.search_without_date(args).for_week(date).count
57
+ _total_conversions = TrackableSession.search_without_date(args).for_week(date).with_conversions.count
58
+ _conversion_rate = (_total_conversions.to_f / _total_sessions) * 100
59
+ _lead_stats << LeadStat.new(:date => date, :leads => _total_conversions, :conversion_rate => sprintf("%0.1f",_conversion_rate).to_f)
60
+ end
61
+ _lead_stats
62
+ end
63
+
64
+ # Inner stat classes
65
+
66
+ class Lead
67
+ attr_accessor :stats
68
+ def initialize(args)
69
+ args.each{ |k,v| self.send("#{k}=", v) }
70
+ end
71
+ end
72
+
73
+ class LeadStat
74
+ attr_accessor :date
75
+ attr_accessor :leads
76
+ attr_accessor :conversion_rate
77
+
78
+ def initialize(args)
79
+ args.each{ |k,v| self.send("#{k}=", v) }
80
+ end
81
+
82
+ def short_date
83
+ self.date.to_s(:concise)
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+
90
+ end
@@ -0,0 +1,219 @@
1
+ module Mitamirri
2
+
3
+ class SessionReport
4
+
5
+ # Search params
6
+ attr_accessor :action_kind
7
+ attr_accessor :site
8
+ attr_accessor :time_period
9
+ attr_accessor :visit_kind
10
+
11
+ # Initialization
12
+
13
+ def initialize(args = {})
14
+ args.each{|k,v| self.send("#{k}=",v) if self.respond_to?(k)}
15
+ self.time_period = args[:time_period] || 'past 6 months'
16
+ self.sessions
17
+ end
18
+
19
+ def criteria
20
+ _criteria = self.sessions.to_hash
21
+ _criteria.delete(:sort)
22
+ _criteria
23
+ end
24
+
25
+ def sessions
26
+ @sessions ||= TrackableSession.search(
27
+ :action_kind => self.action_kind,
28
+ :site => self.site,
29
+ :time_period => self.time_period,
30
+ :visit_kind => self.visit_kind
31
+ )
32
+ end
33
+
34
+ # Generate an array of dates spanning the appropriate time period.
35
+ def dates
36
+ return @dates if @dates
37
+ @dates = []
38
+ case self.time_period
39
+ when 'past month'
40
+ _increment = 1
41
+ when 'past 3 months'
42
+ _increment = 2
43
+ when 'past 6 months'
44
+ _increment = 5
45
+ when 'past 12 months'
46
+ _increment = 11
47
+ else 'all time'
48
+ _increment = 24
49
+ end
50
+
51
+ (1.._increment).each{ |i| @dates << (Time.zone.now - i.months).beginning_of_month }
52
+ @dates.reverse!
53
+ @dates << Time.zone.now.end_of_month
54
+ @dates
55
+ end
56
+
57
+ # Graphing data
58
+ def self.keywords_by_frequency(args)
59
+ TrackableSession.keywords_histogram(args).inject([]){|a,v| a << KeywordStat.new(:keyword => v[0], :count => v[1]); a}.sort{|a,b| a.count <=> b.count}.reverse[0..24]
60
+ end
61
+
62
+ def self.top_referrers(args)
63
+ TrackableSession.referrers_histogram(args).inject([]){|a,v| a << ReferrerStat.new(:referrer => v[0], :count => v[1]); a}.sort{|a,b| a.count <=> b.count}.reverse[0..24]
64
+ end
65
+
66
+ def visits(args)
67
+ _visits = []
68
+ _visits << Visit.new(:kind => "#{args[:visit_kind].titleize} Visits", :stats => visit_stats(args))
69
+ _visits
70
+ end
71
+
72
+ def visit_stats(args)
73
+ _visit_stats = []
74
+ dates.each do |date|
75
+ _visit_stats << VisitStat.new(:date => date, :visits => TrackableSession.search_without_date(args).for_month(date).count)
76
+ end
77
+ _visit_stats
78
+ end
79
+
80
+ # Statistics
81
+
82
+ def average_pages_per_visit
83
+ sprintf("%.1f", total_pageviews / total_visits.to_f)
84
+ end
85
+
86
+ def average_time_on_site
87
+ average = total_duration / total_visits.to_f
88
+ average > 60 ? sprintf("%.1f minutes", average / 60.0) : sprintf("%.1f seconds", average)
89
+ end
90
+
91
+ def bounce_rate
92
+ bounce_rate = total_bounces / total_visits.to_f
93
+ sprintf("%.1f%", bounce_rate * 100)
94
+ end
95
+
96
+ def conversion_rate
97
+ conversion_rate = total_conversions / total_visits.to_f
98
+ sprintf("%.1f%", conversion_rate * 100)
99
+ end
100
+
101
+ def total_bounces
102
+ @total_bounces ||= self.sessions.bounces.count
103
+ end
104
+
105
+ def total_clickthroughs
106
+ @total_clickthroughs ||= self.sessions.with_clickthroughs.count
107
+ end
108
+
109
+ def total_clickthroughs_percentage
110
+ sprintf("%.1f%", (total_clickthroughs / total_visits.to_f) * 100)
111
+ end
112
+
113
+ def total_conversions
114
+ @total_conversions ||= self.sessions.with_conversions.count
115
+ end
116
+
117
+ def total_direct_visits
118
+ @total_direct_visits ||= self.sessions.direct_visits.count
119
+ end
120
+
121
+ def total_duration
122
+ @total_duration ||= TrackableSession.collection.group(["site"], self.criteria, {:duration => 0}, "function(doc,prev) { prev.duration += doc.duration}", true).map{|x| x['duration']}.sum.to_i
123
+ end
124
+
125
+ def total_new_visits
126
+ @total_new_visits ||= self.sessions.new_visits.count
127
+ end
128
+
129
+ def total_return_visits
130
+ @total_return_visits ||= total_visits - total_new_visits
131
+ end
132
+
133
+ def total_organic_visits
134
+ @total_organic_visits ||= self.sessions.organic_visits.count
135
+ end
136
+
137
+ def total_pageviews
138
+ @total_pageviews ||= TrackableSession.collection.group(["site"], self.criteria, {:views_count => 0}, "function(doc,prev) { prev.views_count += doc.views_count}", true).map{|x| x['views_count']}.sum.to_i
139
+ end
140
+
141
+ def total_ppc_visits
142
+ @total_ppc_visits ||= self.sessions.ppc_visits.count
143
+ end
144
+
145
+ def total_search_visits
146
+ @total_search_visits ||= self.sessions.search_visits.count
147
+ end
148
+
149
+ def total_direct_visits_percentage
150
+ sprintf("%.1f%", (total_direct_visits / total_visits.to_f) * 100)
151
+ end
152
+
153
+ def total_organic_visits_percentage
154
+ sprintf("%.1f%", (total_organic_visits / total_visits.to_f) * 100)
155
+ end
156
+
157
+ def total_new_visits_percentage
158
+ sprintf("%.1f%", (total_new_visits / total_visits.to_f) * 100)
159
+ end
160
+
161
+ def total_ppc_visits_percentage
162
+ sprintf("%.1f%", (total_ppc_visits / total_visits.to_f) * 100)
163
+ end
164
+
165
+ def total_return_visits_percentage
166
+ sprintf("%.1f%", (total_return_visits / total_visits.to_f) * 100)
167
+ end
168
+
169
+ def total_search_visits_percentage
170
+ sprintf("%.1f%", (total_search_visits / total_visits.to_f) * 100)
171
+ end
172
+
173
+ def total_visits
174
+ @total_visits ||= self.sessions.count
175
+ end
176
+
177
+ # Inner stat classes
178
+ class KeywordStat
179
+ attr_accessor :keyword
180
+ attr_accessor :count
181
+ def initialize(args)
182
+ args.each{ |k,v| self.send("#{k}=", v) }
183
+ end
184
+ end
185
+
186
+ class ReferrerStat
187
+ attr_accessor :referrer
188
+ attr_accessor :count
189
+ def initialize(args)
190
+ args.each{ |k,v| self.send("#{k}=", v) }
191
+ end
192
+ end
193
+
194
+ class Visit
195
+ attr_accessor :kind
196
+ attr_accessor :date
197
+ attr_accessor :stats
198
+ def initialize(args)
199
+ args.each{ |k,v| self.send("#{k}=", v) }
200
+ end
201
+ end
202
+
203
+ class VisitStat
204
+ attr_accessor :date
205
+ attr_accessor :visits
206
+
207
+ def initialize(args)
208
+ args.each{ |k,v| self.send("#{k}=", v) }
209
+ end
210
+
211
+ def short_date
212
+ self.date.to_s(:month_year)
213
+ end
214
+
215
+ end
216
+
217
+ end
218
+
219
+ end
@@ -0,0 +1,216 @@
1
+ module Mitamirri
2
+
3
+ class StatReport
4
+
5
+ # Search params
6
+ attr_accessor :action_kind
7
+ attr_accessor :site
8
+ attr_accessor :time_period
9
+ attr_accessor :visit_kind
10
+
11
+ # Initialization
12
+
13
+ def initialize(args = {})
14
+ args.each{|k,v| self.send("#{k}=",v) if self.respond_to?(k)}
15
+ self.time_period = args[:time_period] || 'past 6 months'
16
+ self.stats
17
+ end
18
+
19
+ def stats
20
+ if self.site && self.site.downcase != 'all sites'
21
+ @stats ||= TrackableStat.by_site(self.site).for_date_range(dates.first, dates.last.end_of_month)
22
+ else
23
+ @stats ||= TrackableStat.for_date_range(dates.first, dates.last.end_of_month)
24
+ end
25
+ end
26
+
27
+ # Generate an array of dates spanning the appropriate time period.
28
+ def dates
29
+ return @dates if @dates
30
+ @dates = []
31
+ case self.time_period
32
+ when 'past month'
33
+ _increment = 1
34
+ when 'past 3 months'
35
+ _increment = 2
36
+ when 'past 6 months'
37
+ _increment = 5
38
+ when 'past 12 months'
39
+ _increment = 11
40
+ else 'all time'
41
+ _increment = 24
42
+ end
43
+
44
+ (1.._increment).each{ |i| @dates << (Time.zone.now - i.months).beginning_of_month }
45
+ @dates.reverse!
46
+ @dates << Time.zone.now.end_of_month
47
+ @dates
48
+ end
49
+
50
+ # Graphing data
51
+ def self.keywords_by_frequency(args)
52
+ TrackableSession.keywords_histogram(args).inject([]){|a,v| a << KeywordStat.new(:keyword => v[0], :count => v[1]); a}.sort{|a,b| a.count <=> b.count}.reverse[0..24]
53
+ end
54
+
55
+ def self.top_referrers(args)
56
+ TrackableSession.referrers_histogram(args).inject([]){|a,v| a << ReferrerStat.new(:referrer => v[0], :count => v[1]); a}.sort{|a,b| a.count <=> b.count}.reverse[0..24]
57
+ end
58
+
59
+ def visits(args)
60
+ _visits = []
61
+ _visits << Visit.new(:kind => 'All', :stats => visit_stats(args))
62
+ _visits << Visit.new(:kind => 'Direct Traffic', :stats => visit_stats(args.merge(:visit_kind => 'direct')))
63
+ _visits << Visit.new(:kind => 'Referring Sites', :stats => visit_stats(args.merge(:visit_kind => 'natural')))
64
+ _visits << Visit.new(:kind => 'Organic Search', :stats => visit_stats(args.merge(:visit_kind => 'search')))
65
+ _visits << Visit.new(:kind => 'Paid Search', :stats => visit_stats(args.merge(:visit_kind => 'paid')))
66
+ _visits
67
+ end
68
+
69
+ def visit_stats(args)
70
+ _visit_stats = []
71
+ dates.each do |date|
72
+ _visit_stats << VisitStat.new(:date => date, :visits => TrackableSession.search_without_date(args).for_month(date).count)
73
+ end
74
+ _visit_stats
75
+ end
76
+
77
+ # Statistics
78
+
79
+ def average_pages_per_visit
80
+ sprintf("%.1f", total_pageviews / total_visits.to_f)
81
+ end
82
+
83
+ def average_time_on_site
84
+ average = total_duration / total_visits.to_f
85
+ average > 60 ? sprintf("%.1f minutes", average / 60.0) : sprintf("%.1f seconds", average)
86
+ end
87
+
88
+ def bounce_rate
89
+ bounce_rate = total_bounces / total_visits.to_f
90
+ sprintf("%.1f%", bounce_rate * 100)
91
+ end
92
+
93
+ def conversion_rate
94
+ conversion_rate = total_conversions / total_visits.to_f
95
+ sprintf("%.1f%", conversion_rate * 100)
96
+ end
97
+
98
+ def total_bounces
99
+ @total_bounces ||= stats.fields(:bounces).map{|s| s.bounces}.sum
100
+ end
101
+
102
+ def total_clickthroughs
103
+ @total_clickthroughs ||= stats.fields(:clickthroughs).map{|s| s.clickthroughs}.sum
104
+ end
105
+
106
+ def total_clickthroughs_percentage
107
+ sprintf("%.1f%", (total_clickthroughs / total_visits.to_f) * 100)
108
+ end
109
+
110
+ def total_conversions
111
+ @total_conversions ||= stats.fields(:conversions).map{|s| s.conversions}.sum
112
+ end
113
+
114
+ def total_direct_visits
115
+ @total_direct_visits ||= stats.fields(:direct_visits).map{|s| s.direct_visits}.sum
116
+ end
117
+
118
+ def total_direct_visits_percentage
119
+ sprintf("%.1f%", (total_direct_visits / total_visits.to_f) * 100)
120
+ end
121
+
122
+ def total_duration
123
+ @total_duration ||= stats.fields(:duration).map{|s| s.duration}.sum
124
+ end
125
+
126
+ def total_new_visits
127
+ @total_new_visits ||= stats.fields(:new_visits).map{|s| s.new_visits}.sum
128
+ end
129
+
130
+ def total_new_visits_percentage
131
+ sprintf("%.1f%", (total_new_visits / total_visits.to_f) * 100)
132
+ end
133
+
134
+ def total_organic_visits
135
+ @total_organic_visits ||= stats.fields(:organic_visits).map{|s| s.organic_visits}.sum
136
+ end
137
+
138
+ def total_organic_visits_percentage
139
+ sprintf("%.1f%", (total_organic_visits / total_visits.to_f) * 100)
140
+ end
141
+
142
+ def total_pageviews
143
+ @total_pageviews ||= stats.fields(:pageviews).map{|s| s.pageviews}.sum
144
+ end
145
+
146
+ def total_ppc_visits
147
+ @total_ppc_visits ||= stats.fields(:ppc_visits).map{|s| s.ppc_visits}.sum
148
+ end
149
+
150
+ def total_ppc_visits_percentage
151
+ sprintf("%.1f%", (total_ppc_visits / total_visits.to_f) * 100)
152
+ end
153
+
154
+ def total_return_visits
155
+ @total_return_visits ||= stats.fields(:return_visits).map{|s| s.return_visits}.sum
156
+ end
157
+
158
+ def total_return_visits_percentage
159
+ sprintf("%.1f%", (total_return_visits / total_visits.to_f) * 100)
160
+ end
161
+
162
+ def total_search_visits
163
+ @total_search_visits ||= stats.fields(:search_visits).map{|s| s.search_visits}.sum
164
+ end
165
+
166
+ def total_search_visits_percentage
167
+ sprintf("%.1f%", (total_search_visits / total_visits.to_f) * 100)
168
+ end
169
+
170
+ def total_visits
171
+ @total_visits ||= stats.fields(:visits).map{|s| s.visits}.sum
172
+ end
173
+
174
+ # Inner stat classes
175
+ class KeywordStat
176
+ attr_accessor :keyword
177
+ attr_accessor :count
178
+ def initialize(args)
179
+ args.each{ |k,v| self.send("#{k}=", v) }
180
+ end
181
+ end
182
+
183
+ class ReferrerStat
184
+ attr_accessor :referrer
185
+ attr_accessor :count
186
+ def initialize(args)
187
+ args.each{ |k,v| self.send("#{k}=", v) }
188
+ end
189
+ end
190
+
191
+ class Visit
192
+ attr_accessor :kind
193
+ attr_accessor :date
194
+ attr_accessor :stats
195
+ def initialize(args)
196
+ args.each{ |k,v| self.send("#{k}=", v) }
197
+ end
198
+ end
199
+
200
+ class VisitStat
201
+ attr_accessor :date
202
+ attr_accessor :visits
203
+
204
+ def initialize(args)
205
+ args.each{ |k,v| self.send("#{k}=", v) }
206
+ end
207
+
208
+ def short_date
209
+ self.date.to_s(:month_year)
210
+ end
211
+
212
+ end
213
+
214
+ end
215
+
216
+ end
@@ -0,0 +1,27 @@
1
+ # require 'mitamirri/tasks' to add tasks to the host application.
2
+
3
+ namespace :mitamirri do
4
+
5
+ desc "Sync migrations and other files from Mitamirri."
6
+ task :install do
7
+ dir = Gem.searcher.find('mitamirri').full_gem_path
8
+ system "rsync -ruv #{dir}/public/stylesheets public/"
9
+ system "rsync -ruv #{dir}/config/initializers/database.rb config/initializers/"
10
+ puts
11
+ puts "Mitamarri file sync complete."
12
+ puts "Run rake mitamirri:override to install local views and controllers to override default behaviour."
13
+ puts
14
+ end
15
+
16
+ desc "Copy default view and controller files from Mitamirri to the host application."
17
+ task :override do
18
+ dir = Gem.searcher.find('mitamirri').full_gem_path
19
+ system "rsync -ruv #{dir}/app/controllers/trackable_actions_controller.rb app/controllers/"
20
+ system "rsync -ruv #{dir}/app/controllers/trackable_sessions_controller.rb app/controllers/"
21
+ system "rsync -ruv #{dir}/app/views/trackable_sessions app/views/"
22
+ puts
23
+ puts "Mitamarri views and controllers copied and ready to override."
24
+ puts
25
+ end
26
+
27
+ end
@@ -0,0 +1,127 @@
1
+ module Mitamirri
2
+
3
+ class VisitorProfileReport
4
+
5
+ # Search params
6
+ attr_accessor :action_kind
7
+ attr_accessor :site
8
+ attr_accessor :time_period
9
+ attr_accessor :visit_kind
10
+
11
+ # Initialization
12
+
13
+ def initialize(args = {})
14
+ args.each{|k,v| self.send("#{k}=",v) if self.respond_to?(k)}
15
+ self.time_period = args[:time_period] || 'past 6 months'
16
+ self.sessions
17
+ end
18
+
19
+ def criteria
20
+ _criteria = self.sessions.to_hash
21
+ _criteria.delete(:sort)
22
+ _criteria
23
+ end
24
+
25
+ def sessions
26
+ @sessions ||= TrackableSession.search(
27
+ :action_kind => self.action_kind,
28
+ :site => self.site,
29
+ :time_period => self.time_period,
30
+ :visit_kind => self.visit_kind
31
+ )
32
+ end
33
+
34
+ # Generate an array of dates spanning the appropriate time period.
35
+ def dates
36
+ return @dates if @dates
37
+ @dates = []
38
+ case self.time_period
39
+ when 'past month'
40
+ _increment = 1
41
+ when 'past 3 months'
42
+ _increment = 2
43
+ when 'past 6 months'
44
+ _increment = 5
45
+ when 'past 12 months'
46
+ _increment = 11
47
+ else 'all time'
48
+ _increment = 24
49
+ end
50
+
51
+ (1.._increment).each{ |i| @dates << (Time.zone.now - i.months).beginning_of_month }
52
+ @dates.reverse!
53
+ @dates << Time.zone.now.end_of_month
54
+ @dates
55
+ end
56
+
57
+ # Graphing data
58
+
59
+ def locations_by_frequency(args)
60
+ TrackableSession.locations_histogram(args).inject([]){|a,v| a << LocationStat.new(:name => v[0], :count => v[1]); a}.sort{|a,b| a.count <=> b.count}.reverse[0..24]
61
+ end
62
+
63
+ def user_agents_by_frequency(args)
64
+ TrackableSession.user_agents_histogram(args).inject([]){|a,v| a << UserAgentStat.new(:user_agent => v[0], :count => v[1]); a}.sort{|a,b| a.count <=> b.count}.reverse[0..24]
65
+ end
66
+
67
+ # Inner stat classes
68
+
69
+ class Visitor
70
+ attr_accessor :user_agent_stats
71
+ attr_accessor :location_stats
72
+ def initialize(args)
73
+ args.each{ |k,v| self.send("#{k}=", v) }
74
+ end
75
+ end
76
+
77
+ class UserAgentStat
78
+ attr_accessor :user_agent
79
+ attr_accessor :count
80
+ def initialize(args)
81
+ args.each{ |k,v| self.send("#{k}=", v) }
82
+ end
83
+ end
84
+
85
+ class LocationStat
86
+
87
+ attr_accessor :name
88
+ attr_accessor :latitude
89
+ attr_accessor :longitude
90
+ attr_accessor :count
91
+
92
+ def initialize(args)
93
+ args.each{ |k,v| self.send("#{k}=", v) }
94
+ geocode
95
+ end
96
+
97
+ def geocode
98
+ if _location = TrackableLocation.where(:location => self.name).first
99
+ self.latitude = _location.latitude
100
+ self.longitude = _location.longitude
101
+ else
102
+ begin
103
+ _coords = Geokit::Geocoders::MultiGeocoder.geocode(self.name)
104
+ rescue
105
+ end
106
+ if _coords && _coords.success
107
+ self.latitude = _coords.lat
108
+ self.longitude = _coords.lng
109
+ TrackableLocation.create(:location => self.name, :latitude => self.latitude, :longitude => self.longitude)
110
+ end
111
+ end
112
+ end
113
+
114
+ def geocoded?
115
+ self.latitude && self.longitude
116
+ end
117
+
118
+ def sanitized_name
119
+ self.name.gsub(/'/,"\\'")
120
+ end
121
+
122
+ end
123
+
124
+
125
+ end
126
+
127
+ end
data/lib/mitamirri.rb ADDED
@@ -0,0 +1,15 @@
1
+ module Mitamirri
2
+ require 'mitamirri'
3
+ require 'mitamirri/session_report'
4
+
5
+ # Detects the ability of the host application to output reports to PDF format.
6
+ def self.pdf_output_enabled?
7
+ @pdf_output_enabled ||= false
8
+ begin
9
+ @pdf_output_enabled = Rails.configuration.middleware.include?('PDFKit::Middleware')
10
+ rescue
11
+ end
12
+ @pdf_output_enabled
13
+ end
14
+
15
+ end
File without changes
File without changes
data/log/server.log ADDED
File without changes
data/log/test.log ADDED
File without changes