mitamirri 0.13.8 → 2.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (236) hide show
  1. data/Capfile +4 -0
  2. data/Gemfile +29 -0
  3. data/README.rdoc +6 -55
  4. data/Rakefile +34 -21
  5. data/VERSION +1 -1
  6. data/app/controllers/admin/tracking/reports_controller.rb +78 -0
  7. data/app/controllers/admin/tracking/trackable_sessions_controller.rb +7 -0
  8. data/app/controllers/application_controller.rb +1 -8
  9. data/app/controllers/trackable_actions_controller.rb +0 -2
  10. data/app/helpers/application_helper.rb +21 -0
  11. data/app/helpers/layout_helper.rb +18 -0
  12. data/app/models/content_report.rb +35 -0
  13. data/app/models/content_stat.rb +4 -0
  14. data/app/models/destination.rb +4 -0
  15. data/app/models/intersite_traffic_report.rb +47 -0
  16. data/app/models/keyword_stat.rb +4 -0
  17. data/app/models/lead.rb +3 -0
  18. data/app/models/lead_stat.rb +5 -0
  19. data/app/models/leads_report.rb +32 -0
  20. data/app/models/location_stat.rb +37 -0
  21. data/app/models/referrer_stat.rb +4 -0
  22. data/app/models/report.rb +83 -0
  23. data/app/models/stat_base.rb +11 -0
  24. data/app/models/trackable_action.rb +114 -91
  25. data/app/models/trackable_base.rb +12 -0
  26. data/app/models/trackable_location.rb +7 -13
  27. data/app/models/trackable_session.rb +255 -171
  28. data/app/models/trackable_stat.rb +45 -27
  29. data/app/models/traffic_explorer_report.rb +92 -0
  30. data/app/models/traffic_summary_report.rb +142 -0
  31. data/app/models/user_agent_stat.rb +4 -0
  32. data/app/models/visit.rb +6 -0
  33. data/app/models/visit_stat.rb +5 -0
  34. data/app/models/visitor.rb +4 -0
  35. data/app/models/visitor_profile_report.rb +23 -0
  36. data/app/views/admin/tracking/reports/_content.html.erb +28 -0
  37. data/app/views/admin/tracking/reports/_conversion_rate.html.erb +30 -0
  38. data/app/views/admin/tracking/reports/_criteria.html.erb +33 -0
  39. data/app/views/admin/tracking/reports/_entrance_pages.html.erb +29 -0
  40. data/app/views/admin/tracking/reports/_exit_pages.html.erb +28 -0
  41. data/app/views/admin/tracking/reports/_explorer_criteria.html.erb +22 -0
  42. data/app/views/admin/tracking/reports/_explorer_summary.html.erb +22 -0
  43. data/app/views/admin/tracking/reports/_intersite_destinations.html.erb +28 -0
  44. data/app/views/admin/tracking/reports/_intersite_referrals.html.erb +30 -0
  45. data/app/views/admin/tracking/reports/_leads.html.erb +30 -0
  46. data/app/views/admin/tracking/reports/_locations.html.erb +47 -0
  47. data/app/views/admin/tracking/reports/_recent_visits.html.erb +33 -0
  48. data/app/views/admin/tracking/reports/_referring_keywords.html.erb +28 -0
  49. data/app/views/admin/tracking/reports/_referring_sites.html.erb +28 -0
  50. data/app/views/admin/tracking/reports/_traffic_summary.html.erb +26 -0
  51. data/app/views/admin/tracking/reports/_user_agents.html.erb +28 -0
  52. data/app/views/{trackable_sessions/_visits_graph.html.erb → admin/tracking/reports/_visits_by_kind.html.erb} +3 -3
  53. data/app/views/admin/tracking/reports/content.html.erb +12 -0
  54. data/app/views/admin/tracking/reports/explorer.html.erb +13 -0
  55. data/app/views/admin/tracking/reports/index.html.erb +16 -0
  56. data/app/views/admin/tracking/reports/intersite.html.erb +11 -0
  57. data/app/views/admin/tracking/reports/leads.html.erb +11 -0
  58. data/app/views/admin/tracking/reports/summary.html.erb +16 -0
  59. data/app/views/admin/tracking/reports/visitor_profile.html.erb +11 -0
  60. data/app/views/{trackable_sessions → admin/tracking/trackable_sessions}/show.html.erb +5 -4
  61. data/app/views/layouts/application.html.erb +51 -18
  62. data/config.ru +4 -0
  63. data/config/application.rb +13 -0
  64. data/config/boot.rb +13 -110
  65. data/config/cucumber.yml +10 -0
  66. data/config/deploy.rb +40 -0
  67. data/config/environment.rb +4 -23
  68. data/config/environments/development.rb +24 -13
  69. data/config/environments/production.rb +41 -20
  70. data/config/environments/test.rb +28 -24
  71. data/config/initializers/formats.rb +19 -0
  72. data/config/initializers/metric_fu.rb +9 -0
  73. data/config/initializers/secret_token.rb +7 -0
  74. data/config/initializers/session_store.rb +3 -10
  75. data/config/locales/en.yml +1 -1
  76. data/config/mongoid.yml +19 -0
  77. data/config/routes.rb +16 -10
  78. data/features/access_reports.feature +26 -0
  79. data/features/step_definitions/reports_steps.rb +9 -0
  80. data/features/step_definitions/web_steps.rb +219 -0
  81. data/features/support/env.rb +32 -0
  82. data/features/support/hooks.rb +1 -0
  83. data/features/support/paths.rb +33 -0
  84. data/features/traffic_summary_report.feature +43 -0
  85. data/init.rb +0 -7
  86. data/lib/mitamirri.rb +9 -12
  87. data/lib/mitamirri/engine.rb +7 -0
  88. data/lib/mitamirri/helper.rb +13 -29
  89. data/lib/mitamirri/railtie.rb +10 -0
  90. data/lib/tasks/cucumber.rake +60 -0
  91. data/lib/tasks/rcov.rake +44 -0
  92. data/mitamirri.gemspec +228 -100
  93. data/public/404.html +26 -0
  94. data/public/422.html +26 -0
  95. data/public/500.html +26 -0
  96. data/{config/database.yml → public/favicon.ico} +0 -0
  97. data/public/images/icons/add.png +0 -0
  98. data/public/images/icons/collapsed.gif +0 -0
  99. data/public/images/icons/delete.png +0 -0
  100. data/public/images/icons/drag.png +0 -0
  101. data/public/images/icons/edit.png +0 -0
  102. data/public/images/icons/expanded.gif +0 -0
  103. data/public/images/icons/help_icon.png +0 -0
  104. data/public/images/icons/link_icon.png +0 -0
  105. data/public/images/icons/move.png +0 -0
  106. data/public/images/icons/move_white.png +0 -0
  107. data/public/images/icons/note.png +0 -0
  108. data/public/images/icons/note_white.png +0 -0
  109. data/public/images/icons/notification_icon_sprite.png +0 -0
  110. data/public/images/icons/spinner.gif +0 -0
  111. data/public/images/icons/view.png +0 -0
  112. data/public/images/icons/warning.png +0 -0
  113. data/public/images/icons/warning_2.png +0 -0
  114. data/public/images/icons/warning_box.png +0 -0
  115. data/public/images/icons/warning_icon.png +0 -0
  116. data/public/images/icons/warning_white.png +0 -0
  117. data/public/images/layout/arrow_asc.png +0 -0
  118. data/public/images/layout/arrow_desc.png +0 -0
  119. data/public/images/layout/back.png +0 -0
  120. data/public/images/layout/black_bar.png +0 -0
  121. data/public/images/layout/branding.png +0 -0
  122. data/public/images/layout/breadcrumb_bg.png +0 -0
  123. data/public/images/layout/button_bg.png +0 -0
  124. data/public/images/layout/content_left_bg.png +0 -0
  125. data/public/images/layout/content_right_bg.png +0 -0
  126. data/public/images/layout/footer_bg.png +0 -0
  127. data/public/images/layout/h1_bg.png +0 -0
  128. data/public/images/layout/h2_bg.png +0 -0
  129. data/public/images/layout/h2_bg_for_table.png +0 -0
  130. data/public/images/layout/header_bg_grey.png +0 -0
  131. data/public/images/layout/header_bg_purple.png +0 -0
  132. data/public/images/layout/legend_bg.png +0 -0
  133. data/public/images/layout/menu_box_bg.png +0 -0
  134. data/public/images/layout/shadow_border.png +0 -0
  135. data/public/images/layout/shadow_border_2.png +0 -0
  136. data/public/images/layout/shadow_border_3.png +0 -0
  137. data/public/images/layout/shadow_border_4.png +0 -0
  138. data/public/images/layout/tab.png +0 -0
  139. data/public/images/layout/tab_active.png +0 -0
  140. data/public/images/layout/table_header.png +0 -0
  141. data/public/images/layout/text_field_bg.jpg +0 -0
  142. data/public/images/layout/text_field_error_bg.png +0 -0
  143. data/public/images/layout/th_bg.png +0 -0
  144. data/public/images/layout/th_bg_selected.png +0 -0
  145. data/public/images/menu_icons/content_report.png +0 -0
  146. data/public/images/menu_icons/content_report_on.png +0 -0
  147. data/public/images/menu_icons/funnel.png +0 -0
  148. data/public/images/menu_icons/funnel_on.png +0 -0
  149. data/public/images/menu_icons/intersite_traffic.png +0 -0
  150. data/public/images/menu_icons/intersite_traffic_on.png +0 -0
  151. data/public/images/menu_icons/leads.png +0 -0
  152. data/public/images/menu_icons/leads_on.png +0 -0
  153. data/public/images/menu_icons/traffic_explorer.png +0 -0
  154. data/public/images/menu_icons/traffic_explorer_on.png +0 -0
  155. data/public/images/menu_icons/traffic_summary.png +0 -0
  156. data/public/images/menu_icons/traffic_summary_on.png +0 -0
  157. data/public/images/menu_icons/visitor_profile.png +0 -0
  158. data/public/images/menu_icons/visitor_profile_on.png +0 -0
  159. data/public/index.html +8 -0
  160. data/public/javascripts/application.js +2 -0
  161. data/public/javascripts/controls.js +965 -0
  162. data/public/javascripts/dragdrop.js +974 -0
  163. data/public/javascripts/effects.js +1123 -0
  164. data/public/javascripts/prototype.js +6001 -0
  165. data/public/javascripts/rails.js +175 -0
  166. data/public/robots.txt +5 -0
  167. data/public/stylesheets/.gitkeep +0 -0
  168. data/public/stylesheets/application.css +876 -0
  169. data/public/stylesheets/core.css +1146 -0
  170. data/public/stylesheets/core_ie.css +52 -0
  171. data/public/stylesheets/csshover3.htc +14 -0
  172. data/public/stylesheets/mitamirri.css +37 -724
  173. data/public/stylesheets/mitamirri_print.css +3 -0
  174. data/script/cucumber +10 -0
  175. data/script/rails +6 -0
  176. data/spec/blueprints.rb +13 -0
  177. data/spec/helpers/application_helper_spec.rb +23 -35
  178. data/spec/{lib → models}/content_report_spec.rb +12 -8
  179. data/spec/{lib → models}/intersite_traffic_report_spec.rb +6 -9
  180. data/spec/{lib → models}/leads_report_spec.rb +11 -12
  181. data/spec/models/location_stat_spec.rb +18 -0
  182. data/spec/models/trackable_action_spec.rb +46 -14
  183. data/spec/models/trackable_base_spec.rb +27 -0
  184. data/spec/models/trackable_session_spec.rb +181 -57
  185. data/spec/{lib/session_report_spec.rb → models/traffic_explorer_report_spec.rb} +8 -25
  186. data/spec/spec_helper.rb +8 -28
  187. data/{lib/mitamirri/tasks.rb → tasks/mitamirri.rake} +6 -7
  188. data/vendor/plugins/.gitkeep +0 -0
  189. metadata +316 -77
  190. data/.gitignore +0 -26
  191. data/app/controllers/trackable_sessions_controller.rb +0 -100
  192. data/app/views/trackable_sessions/_keywords_graph.html.erb +0 -24
  193. data/app/views/trackable_sessions/_print_buttons.html.erb +0 -3
  194. data/app/views/trackable_sessions/_sessions.html.erb +0 -26
  195. data/app/views/trackable_sessions/_top_referrers.html.erb +0 -24
  196. data/app/views/trackable_sessions/_traffic_summary_all.html.erb +0 -64
  197. data/app/views/trackable_sessions/_traffic_summary_by_kind.html.erb +0 -48
  198. data/app/views/trackable_sessions/content.html.erb +0 -119
  199. data/app/views/trackable_sessions/explorer.html.erb +0 -67
  200. data/app/views/trackable_sessions/export.xls.erb +0 -5
  201. data/app/views/trackable_sessions/index.html.erb +0 -47
  202. data/app/views/trackable_sessions/intersite.html.erb +0 -97
  203. data/app/views/trackable_sessions/leads.html.erb +0 -98
  204. data/app/views/trackable_sessions/visitor_profile.html.erb +0 -114
  205. data/config/initializers/backtrace_silencers.rb +0 -7
  206. data/config/initializers/database.rb +0 -1
  207. data/config/initializers/inflections.rb +0 -10
  208. data/config/initializers/mime_types.rb +0 -5
  209. data/config/initializers/new_rails_defaults.rb +0 -21
  210. data/db/development.sqlite3 +0 -0
  211. data/db/migrate/20100810173533_create_trackable_sessions.rb +0 -23
  212. data/db/migrate/20100810173605_create_trackable_actions.rb +0 -20
  213. data/db/test.sqlite3 +0 -1
  214. data/lib/mitamirri/content_report.rb +0 -75
  215. data/lib/mitamirri/intersite_traffic_report.rb +0 -122
  216. data/lib/mitamirri/leads_report.rb +0 -90
  217. data/lib/mitamirri/session_report.rb +0 -219
  218. data/lib/mitamirri/stat_report.rb +0 -216
  219. data/lib/mitamirri/visitor_profile_report.rb +0 -127
  220. data/script/about +0 -4
  221. data/script/console +0 -3
  222. data/script/dbconsole +0 -3
  223. data/script/destroy +0 -3
  224. data/script/generate +0 -3
  225. data/script/performance/benchmarker +0 -3
  226. data/script/performance/profiler +0 -3
  227. data/script/plugin +0 -3
  228. data/script/runner +0 -3
  229. data/script/server +0 -3
  230. data/spec/controllers/trackable_actions_controller_spec.rb +0 -5
  231. data/spec/controllers/trackable_sessions_controller_spec.rb +0 -5
  232. data/spec/custom_matchers.rb +0 -23
  233. data/spec/lib/stat_report_spec.rb +0 -106
  234. data/spec/rcov.opts +0 -4
  235. data/spec/schema.rb +0 -34
  236. data/spec/spec.opts +0 -4
@@ -0,0 +1,4 @@
1
+ class KeywordStat < StatBase
2
+ attr_accessor :keyword
3
+ attr_accessor :count
4
+ end
@@ -0,0 +1,3 @@
1
+ class Lead < StatBase
2
+ attr_accessor :stats
3
+ end
@@ -0,0 +1,5 @@
1
+ class LeadStat < StatBase
2
+ attr_accessor :leads
3
+ attr_accessor :conversion_rate
4
+ attr_accessor :date
5
+ end
@@ -0,0 +1,32 @@
1
+ class LeadsReport < Report
2
+
3
+ # Initialization =================================================================================
4
+
5
+ def ready?
6
+ self.site && self.time_period && self.visit_kind
7
+ end
8
+
9
+ def wants_traffic_kind?
10
+ true
11
+ end
12
+
13
+ # Stats for Visualization ========================================================================
14
+
15
+ def leads(args)
16
+ _leads = []
17
+ _leads << Lead.new(:stats => lead_stats(args))
18
+ _leads
19
+ end
20
+
21
+ def lead_stats(args)
22
+ _lead_stats = []
23
+ dates_by_week.each do |date|
24
+ _total_sessions = TrackableSession.search_without_date(args).for_week(date).count
25
+ _total_conversions = TrackableSession.search_without_date(args).for_week(date).with_conversions.count
26
+ _conversion_rate = (_total_conversions.to_f / _total_sessions) * 100
27
+ _lead_stats << LeadStat.new(:date => date, :leads => _total_conversions, :conversion_rate => sprintf("%0.1f",_conversion_rate).to_f)
28
+ end
29
+ _lead_stats
30
+ end
31
+
32
+ end
@@ -0,0 +1,37 @@
1
+ class LocationStat < StatBase
2
+ attr_accessor :name
3
+ attr_accessor :latitude
4
+ attr_accessor :longitude
5
+ attr_accessor :count
6
+
7
+ def initialize(args)
8
+ super
9
+ geocode
10
+ end
11
+
12
+ def geocode
13
+ if _location = TrackableLocation.where(:location => self.name).first
14
+ self.latitude = _location.latitude
15
+ self.longitude = _location.longitude
16
+ else
17
+ begin
18
+ _coords = Geokit::Geocoders::MultiGeocoder.geocode(self.name)
19
+ rescue
20
+ end
21
+ if _coords && _coords.success
22
+ self.latitude = _coords.lat
23
+ self.longitude = _coords.lng
24
+ TrackableLocation.create(:location => self.name, :latitude => self.latitude, :longitude => self.longitude)
25
+ end
26
+ end
27
+ end
28
+
29
+ def geocoded?
30
+ self.latitude && self.longitude
31
+ end
32
+
33
+ def sanitized_name
34
+ self.name.gsub("'","\\\\'")
35
+ end
36
+
37
+ end
@@ -0,0 +1,4 @@
1
+ class ReferrerStat < StatBase
2
+ attr_accessor :referrer
3
+ attr_accessor :count
4
+ end
@@ -0,0 +1,83 @@
1
+ class Report
2
+
3
+ attr_accessor :site
4
+ attr_accessor :time_period
5
+ attr_accessor :visit_kind
6
+ attr_accessor :action_kind
7
+
8
+ def initialize(args)
9
+ args.each{|k,v| self.send("#{k}=", v.downcase) if self.respond_to?(k)}
10
+ self.time_period ||= 'past 3 months'
11
+ self.visit_kind ||= 'all'
12
+ self.visit_kind = 'all' if self.visit_kind == 'total'
13
+ end
14
+
15
+ def dates
16
+ return @dates if @dates
17
+ @dates = []
18
+ case self.time_period.downcase
19
+ when 'past month'
20
+ _increment = 1
21
+ when 'past 3 months'
22
+ _increment = 2
23
+ when 'past 6 months'
24
+ _increment = 5
25
+ when 'past 12 months'
26
+ _increment = 11
27
+ else 'all time'
28
+ _increment = 24
29
+ end
30
+
31
+ (1.._increment).each{ |i| @dates << (Time.zone.now - i.months).beginning_of_month }
32
+ @dates.reverse!
33
+ @dates << Time.zone.now.end_of_month
34
+ @dates
35
+ end
36
+
37
+ def dates_by_week
38
+ return @dates_by_week if @dates_by_week
39
+ @dates_by_week = []
40
+ case self.time_period.downcase
41
+ when 'past month'
42
+ _increment = 4
43
+ when 'past 3 months'
44
+ _increment = 12
45
+ when 'past 6 months'
46
+ _increment = 24
47
+ when 'past 12 months'
48
+ _increment = 52
49
+ else
50
+ _increment = 52
51
+ end
52
+
53
+ (1.._increment).each{ |i| @dates_by_week << (Time.zone.now - i.weeks).end_of_week }
54
+ @dates_by_week.reverse!
55
+ @dates_by_week << Time.zone.now.end_of_week
56
+ @dates_by_week
57
+ end
58
+
59
+ def start_date
60
+ self.dates.first
61
+ end
62
+
63
+ def end_date
64
+ self.dates.last.end_of_month
65
+ end
66
+
67
+ def multiple_sites?
68
+ self.site.downcase == 'all sites'
69
+ end
70
+
71
+ def recent_sessions
72
+ self.sessions[0..24]
73
+ end
74
+
75
+ def sessions
76
+ @sessions ||= TrackableSession.search(:action_kind => self.action_kind, :visit_kind => self.visit_kind, :site => self.site, :time_period => self.time_period.downcase)
77
+ end
78
+
79
+ def wants_traffic_kind?
80
+ false
81
+ end
82
+
83
+ end
@@ -0,0 +1,11 @@
1
+ class StatBase
2
+
3
+ def initialize(args)
4
+ args.each{ |k,v| self.send("#{k}=", v) if self.respond_to?(k) }
5
+ end
6
+
7
+ def short_date
8
+ self.date.to_s(:concise)
9
+ end
10
+
11
+ end
@@ -1,46 +1,61 @@
1
- class TrackableAction
2
-
3
- include MongoMapper::Document
4
-
5
- # MongoMapper Setup ==============================================================================
6
-
7
- belongs_to :trackable_session
8
-
9
- key :trackable_session_id, ObjectId
10
- key :kind, String, :index => true
11
- key :label, String, :index => true
12
- key :referrer, String
13
- key :url, String, :index => true
14
- key :relative_url, String
15
- key :site, String, :index => true
16
- key :new_visit, Boolean
17
- timestamps!
18
-
1
+ class TrackableAction < TrackableBase
2
+
3
+ # Mongoid Config =================================================================================
4
+
5
+ include Mongoid::Document
6
+ include Mongoid::Timestamps
7
+
8
+ field :kind
9
+ field :label
10
+ field :referrer
11
+ field :url
12
+ field :relative_url
13
+ field :site
14
+ field :new_visit, :type => Boolean
15
+
16
+ index :kind, :unique => false
17
+ index :label, :unique => false
18
+ index :url, :unique => false
19
+ index :site, :unique => false
20
+
21
+ referenced_in :trackable_session
22
+
19
23
  # Scopes =========================================================================================
20
24
 
21
- scope :by_kind, lambda { |k| { :conditions => { :kind => k } } }
22
- scope :by_label, lambda { |l| { :conditions => { :label => l } } }
23
- scope :clicks, :conditions => {:kind => 'click'}
24
- scope :clickthroughs, :conditions => {:kind => 'clickthrough'}
25
- scope :conversions, :conditions => {:kind => 'conversion'}
26
- scope :leads, :conditions => {:kind => 'conversion'}
27
- scope :for_site, lambda { |s| { :conditions => { :site => s } } }
28
- scope :for_month, lambda { |d| { :conditions => { :created_at => { '$gte' => d.beginning_of_month, '$lte' => d.end_of_month } } } }
29
- scope :for_week, lambda { |d| { :conditions => { :created_at => { '$gte' => d.beginning_of_week, '$lte' => d.end_of_week } } } }
30
- scope :for_date_range, lambda { |start_date,end_date| { :conditions => { :created_at => { '$gte' => start_date.beginning_of_month, '$lte' => end_date.end_of_month } } } }
31
- scope :mouseovers, :conditions => {:kind => 'mouseover'}
32
- scope :scrolls, :conditions => {:kind => 'scroll'}
33
- scope :views, :conditions => {:kind => 'view'}
34
-
25
+ scope :by_kind, lambda { |k| { :where => { :kind => k } } }
26
+ scope :by_label, lambda { |l| { :where => { :label => l } } }
27
+ scope :clicks, :where => {:kind => 'click'}
28
+ scope :clickthroughs, :where => {:kind => 'clickthrough'}
29
+ scope :conversions, :where => {:kind => 'conversion'}
30
+ scope :leads, :where => {:kind => 'conversion'}
31
+ scope :for_site, lambda { |s| { :where => { :site => s } } }
32
+ scope :for_month, lambda { |d| { :where => { :created_at => { '$gte' => d.beginning_of_month, '$lte' => d.end_of_month } } } }
33
+ scope :for_week, lambda { |d| { :where => { :created_at => { '$gte' => d.beginning_of_week, '$lte' => d.end_of_week } } } }
34
+ scope :for_date_range, lambda { |start_date,end_date| { :where => { :created_at => { '$gte' => start_date.beginning_of_month, '$lte' => end_date.end_of_month } } } }
35
+ scope :mouseovers, :where => {:kind => 'mouseover'}
36
+ scope :scrolls, :where => {:kind => 'scroll'}
37
+ scope :views, :where => {:kind => 'view'}
38
+
35
39
  # Constants ======================================================================================
36
40
 
37
41
  KINDS = ['clicks', 'leads', 'scrolls', 'mouseovers', 'clickthroughs']
38
42
 
39
43
  # Class Methods ==================================================================================
40
44
 
45
+ # Create a tracked action from the specified arguments. The action finds an existing session or creates a new one.
46
+ #
47
+ # ==== Attributes
48
+ #
49
+ # * +:params+ - {:site => 'foo.com', :referrer => 'cnn.com/foo', :url => '/cnn'}
50
+ # * +:creation_date+ - action's creation date (used for testing)
51
+ #
52
+ # ==== Examples
53
+ #
54
+ # TrackableAction.create_from_params( :site => 'foo.com' )
41
55
  def self.create_from_params(params, creation_date = Time.zone.now)
42
56
  _referring_site = nil
43
57
  _relative_url = nil
58
+ # Some govt URLs break URI.parse, so wrap in a begin/rescue block
44
59
  begin
45
60
  if ! params[:referrer].blank? && params[:referrer] != '/'
46
61
  _referring_site = URI.parse(params[:referrer]).host
@@ -49,10 +64,10 @@ class TrackableAction
49
64
  _relative_url = URI.parse(params[:url]).path.downcase
50
65
  rescue
51
66
  end
52
-
53
- unless trackable_session = TrackableSession.find_by_session_id(params[:session_id])
67
+
68
+ unless trackable_session = TrackableSession.where(:session_id => params[:session_id]).first
54
69
  trackable_session = TrackableSession.create(
55
- :session_id => params[:session_id],
70
+ :session_id => params[:session_id],
56
71
  :referrer => _referring_site,
57
72
  :referring_keywords => params[:referring_keywords],
58
73
  :ip_address => params[:remote_ip],
@@ -66,7 +81,7 @@ class TrackableAction
66
81
  :created_at => creation_date
67
82
  )
68
83
  end
69
- _action = TrackableAction.create(
84
+ _action = trackable_session.trackable_actions.create(
70
85
  :kind => params[:kind],
71
86
  :label => params[:label],
72
87
  :referrer => params[:referrer],
@@ -79,7 +94,7 @@ class TrackableAction
79
94
  trackable_session.touch(params[:kind], params[:destination], _relative_url)
80
95
  _action
81
96
  end
82
-
97
+
83
98
  def self.create_test_data!(count = 1000, destructive = true)
84
99
 
85
100
  if destructive
@@ -87,15 +102,15 @@ class TrackableAction
87
102
  TrackableSession.delete_all
88
103
  TrackableAction.delete_all
89
104
  end
90
-
91
- 1..count.times do
105
+
106
+ 1..count.times do
92
107
  params = {
93
108
  :remote_ip => "127.0.0.#{rand(128)}",
94
109
  :site => ['www.test1.com', 'www.test2.com', 'www.test3.com'].rand,
95
110
  :initial_referrer => ['','','','','','http://www.google.com','http://www.bing.com','http://www.yahoo.com','http://www.seologic.com','http://www.idolhands.com','http://www.findcounseling.com','http://www.emeritus.com'].rand,
96
111
  :session_id => "#{rand(10000)}#{('a'..'z').to_a.rand}"
97
112
  }
98
-
113
+
99
114
  created_at = Time.zone.now - rand(6).months - rand(30).days
100
115
  (1..rand(10)).each do |i|
101
116
  params[:kind] = ['view','view','mouseover','click','view','view','scroll','view','click','conversion'].rand
@@ -105,88 +120,96 @@ class TrackableAction
105
120
  params[:label] = params[:kind].titleize
106
121
  TrackableAction.create_from_params(params, created_at + i.minutes)
107
122
  end
108
- end
123
+ end
109
124
  "Created #{count} sample sessions."
110
125
  end
111
126
 
112
- # Returns a list of kinds that have already been tracked.
127
+ # Returns a list of kinds for all actions that have already been tracked, used to populate report filters.
113
128
  def self.kinds
114
- _kinds = []
115
- KINDS.each{ |kind| _kinds << kind unless self.send(kind).count.zero? }
116
- _kinds
129
+ TrackableAction.all.map{|ta| ta.kind}.uniq.sort - ['view']
117
130
  end
118
-
131
+
132
+ # Returns a histogram for visited pages in the specified site(s).
133
+ #
134
+ # ==== Attributes
135
+ #
136
+ # * +:action_kind+ - kind of action: 'clicks', 'leads', 'scrolls', 'mouseovers', 'clickthroughs'
137
+ # * +:site+ - name of a site
138
+ # * +:time_period+ - date range as a string: 'past 3 months', 'past 6 months', 'past 12 months'
139
+ # * +:visit_kind+ - kind of visit as a string: 'direct', 'natural', 'paid', 'search'
140
+ #
141
+ # ==== Examples
142
+ #
143
+ # TrackableAction.pages_histogram( :site => 'foo.com' )
119
144
  def self.pages_histogram(args)
120
- TrackableAction.collection.group("function(x) { return { url: x.url }; }", TrackableAction.search(args).to_hash, { :count => 0}, "function(x,y){y.count++}", true).inject({}){|h,k| h[URI.parse(k['url']).path] ||= 0; h[URI.parse(k['url']).path] += k['count']; h}.sort{|a,b| a[1] <=> b[1]}.reverse
145
+ conditions = TrackableAction.search(args).selector
146
+ TrackableAction.collection.group(:keyf => "function(x) { return { url: x.url }; }", :cond => conditions, :initial => { :count => 0}, :reduce => "function(x,y){y.count++}").inject({}){|h,k| k['url'] ||= '/'; h[URI.parse(k['url']).path] ||= 0; h[URI.parse(k['url']).path] += k['count']; h}.sort{|a,b| a[1] <=> b[1]}.reverse
121
147
  end
122
148
 
149
+ # Returns a scope based on time period, site, and visit kind. Null arguments returns all.
150
+ #
151
+ # ==== Attributes
152
+ #
153
+ # * +:action_kind+ - kind of action: 'clicks', 'leads', 'scrolls', 'mouseovers', 'clickthroughs'
154
+ # * +:site+ - name of a site
155
+ # * +:time_period+ - date range as a string: 'past 3 months', 'past 6 months', 'past 12 months'
156
+ # * +:visit_kind+ - kind of visit as a string: 'direct', 'natural', 'paid', 'search'
157
+ #
158
+ # ==== Examples
159
+ #
160
+ # TrackableAction.pages_histogram( :site => 'foo.com' )
123
161
  def self.search(args = {})
124
162
  args[:site] ||= 'all sites'
125
163
  args[:action_kind] ||= 'views'
126
- [:site, :action_kind, :time_period].each{|a| args[a] = args[a].downcase if args[a]}
127
- case args[:time_period]
128
- when 'past 3 months'
129
- args[:start_date] = (Time.zone.now - 2.months).beginning_of_month
130
- args[:end_date] = Time.zone.now
131
- when 'past 6 months'
132
- args[:start_date] = (Time.zone.now - 5.months).beginning_of_month
133
- args[:end_date] = Time.zone.now
134
- when 'past 12 months'
135
- args[:start_date] = (Time.zone.now - 11.months).beginning_of_month
136
- args[:end_date] = Time.zone.now
137
- else
138
- args[:start_date] = TrackableAction.first.created_at
139
- args[:end_date] = Time.zone.now
140
- end
141
- if args[:time_period]
142
- if args[:site] == 'all sites'
143
- TrackableAction.send("#{args[:action_kind]}").for_date_range(args[:start_date], args[:end_date])
144
- else
145
- TrackableAction.for_site(args[:site]).send("#{args[:action_kind]}").for_date_range(args[:start_date], args[:end_date])
146
- end
147
- else
148
- if args[:site] == 'all sites'
149
- TrackableAction.send("#{args[:action_kind]}")
150
- else
151
- TrackableAction.for_site(args[:site]).send("#{args[:action_kind]}")
152
- end
153
- end
164
+ args[:action_kind] == 'views' unless TrackableAction::KINDS.include?(args[:action_kind])
165
+ [:site, :action_kind, :time_period, :visit_kind].each{|a| args[a] = args[a].downcase if args[a]}
166
+ (args[:start_date], args[:end_date]) = dates_from_time_period(args[:time_period])
167
+
168
+ sessions = TrackableSession.search(args).map{|s| s.id.to_s}
169
+ actions = TrackableAction.where(:trackable_session_id.in => sessions)
170
+ actions = actions.send("#{args[:action_kind]}")
171
+ actions
154
172
  end
155
-
156
- # Can't combine date conditions, so this is needed for reports
173
+
174
+ # Returns a scope based on action kind, site, and visit kind only.
175
+ #
176
+ # ==== Attributes
177
+ #
178
+ # * +:action_kind+ - kind of action: 'clicks', 'leads', 'scrolls', 'mouseovers', 'clickthroughs'
179
+ # * +:site+ - name of a site
180
+ # * +:visit_kind+ - kind of visit as a string: 'direct', 'natural', 'paid', 'search'
181
+ #
182
+ # ==== Examples
183
+ #
184
+ # TrackableAction.search_without_date( :site => 'foo.com' )
157
185
  def self.search_without_date(args = {})
158
- args[:site] ||= 'all sites'
159
- args[:action_kind] ||= 'views'
160
- [:site, :action_kind, :visit_kind].each{|a| args[a] = args[a].downcase}
161
- if args[:site] == 'all sites'
162
- TrackableAction.send("#{args[:action_kind]}")
163
- else
164
- TrackableAction.for_site(args[:site]).send("#{args[:action_kind]}")
165
- end
186
+ args = args.clone
187
+ args.delete(:time_period)
188
+ self.search(args)
166
189
  end
167
-
190
+
168
191
  # Instance Methods ===============================================================================
169
192
 
170
193
  def click?
171
194
  self.kind == 'click'
172
195
  end
173
-
196
+
174
197
  def clickthrough?
175
198
  self.kind == 'clickthrough'
176
199
  end
177
-
200
+
178
201
  def conversion?
179
202
  self.kind == 'conversion'
180
203
  end
181
-
204
+
182
205
  def mouseover?
183
206
  self.kind == 'mouseover'
184
207
  end
185
-
208
+
186
209
  def scroll?
187
210
  self.kind == 'scroll'
188
211
  end
189
-
212
+
190
213
  def view?
191
214
  self.kind == 'view'
192
215
  end