app/models/trackable_action.rb in mitamirri-0.13.8 vs app/models/trackable_action.rb in mitamirri-2.0.8

- old
+ new

@@ -1,60 +1,75 @@ -class TrackableAction +class TrackableAction < TrackableBase - include MongoMapper::Document + # Mongoid Config ================================================================================= - # MongoMapper Setup ============================================================================== - - belongs_to :trackable_session + include Mongoid::Document + include Mongoid::Timestamps - key :trackable_session_id, ObjectId - key :kind, String, :index => true - key :label, String, :index => true - key :referrer, String - key :url, String, :index => true - key :relative_url, String - key :site, String, :index => true - key :new_visit, Boolean - timestamps! - + field :kind + field :label + field :referrer + field :url + field :relative_url + field :site + field :new_visit, :type => Boolean + + index :kind, :unique => false + index :label, :unique => false + index :url, :unique => false + index :site, :unique => false + + referenced_in :trackable_session + # Scopes ========================================================================================= - scope :by_kind, lambda { |k| { :conditions => { :kind => k } } } - scope :by_label, lambda { |l| { :conditions => { :label => l } } } - scope :clicks, :conditions => {:kind => 'click'} - scope :clickthroughs, :conditions => {:kind => 'clickthrough'} - scope :conversions, :conditions => {:kind => 'conversion'} - scope :leads, :conditions => {:kind => 'conversion'} - scope :for_site, lambda { |s| { :conditions => { :site => s } } } - scope :for_month, lambda { |d| { :conditions => { :created_at => { '$gte' => d.beginning_of_month, '$lte' => d.end_of_month } } } } - scope :for_week, lambda { |d| { :conditions => { :created_at => { '$gte' => d.beginning_of_week, '$lte' => d.end_of_week } } } } - scope :for_date_range, lambda { |start_date,end_date| { :conditions => { :created_at => { '$gte' => start_date.beginning_of_month, '$lte' => end_date.end_of_month } } } } - scope :mouseovers, :conditions => {:kind => 'mouseover'} - scope :scrolls, :conditions => {:kind => 'scroll'} - scope :views, :conditions => {:kind => 'view'} - + scope :by_kind, lambda { |k| { :where => { :kind => k } } } + scope :by_label, lambda { |l| { :where => { :label => l } } } + scope :clicks, :where => {:kind => 'click'} + scope :clickthroughs, :where => {:kind => 'clickthrough'} + scope :conversions, :where => {:kind => 'conversion'} + scope :leads, :where => {:kind => 'conversion'} + scope :for_site, lambda { |s| { :where => { :site => s } } } + scope :for_month, lambda { |d| { :where => { :created_at => { '$gte' => d.beginning_of_month, '$lte' => d.end_of_month } } } } + scope :for_week, lambda { |d| { :where => { :created_at => { '$gte' => d.beginning_of_week, '$lte' => d.end_of_week } } } } + scope :for_date_range, lambda { |start_date,end_date| { :where => { :created_at => { '$gte' => start_date.beginning_of_month, '$lte' => end_date.end_of_month } } } } + scope :mouseovers, :where => {:kind => 'mouseover'} + scope :scrolls, :where => {:kind => 'scroll'} + scope :views, :where => {:kind => 'view'} + # Constants ====================================================================================== KINDS = ['clicks', 'leads', 'scrolls', 'mouseovers', 'clickthroughs'] # Class Methods ================================================================================== + # Create a tracked action from the specified arguments. The action finds an existing session or creates a new one. + # + # ==== Attributes + # + # * +:params+ - {:site => 'foo.com', :referrer => 'cnn.com/foo', :url => '/cnn'} + # * +:creation_date+ - action's creation date (used for testing) + # + # ==== Examples + # + # TrackableAction.create_from_params( :site => 'foo.com' ) def self.create_from_params(params, creation_date = Time.zone.now) _referring_site = nil _relative_url = nil + # Some govt URLs break URI.parse, so wrap in a begin/rescue block begin if ! params[:referrer].blank? && params[:referrer] != '/' _referring_site = URI.parse(params[:referrer]).host _referring_site = nil if _referring_site == params[:site] end _relative_url = URI.parse(params[:url]).path.downcase rescue end - - unless trackable_session = TrackableSession.find_by_session_id(params[:session_id]) + + unless trackable_session = TrackableSession.where(:session_id => params[:session_id]).first trackable_session = TrackableSession.create( - :session_id => params[:session_id], + :session_id => params[:session_id], :referrer => _referring_site, :referring_keywords => params[:referring_keywords], :ip_address => params[:remote_ip], :site => params[:site].downcase, :session_id => params[:session_id], @@ -64,11 +79,11 @@ :user_agent => params[:user_agent], :views_count => 0, :created_at => creation_date ) end - _action = TrackableAction.create( + _action = trackable_session.trackable_actions.create( :kind => params[:kind], :label => params[:label], :referrer => params[:referrer], :url => params[:url], :relative_url => _relative_url, @@ -77,117 +92,125 @@ :created_at => creation_date ) trackable_session.touch(params[:kind], params[:destination], _relative_url) _action end - + def self.create_test_data!(count = 1000, destructive = true) if destructive TrackableStat.delete_all TrackableSession.delete_all TrackableAction.delete_all end - - 1..count.times do + + 1..count.times do params = { :remote_ip => "127.0.0.#{rand(128)}", :site => ['www.test1.com', 'www.test2.com', 'www.test3.com'].rand, :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, :session_id => "#{rand(10000)}#{('a'..'z').to_a.rand}" } - + created_at = Time.zone.now - rand(6).months - rand(30).days (1..rand(10)).each do |i| params[:kind] = ['view','view','mouseover','click','view','view','scroll','view','click','conversion'].rand params[:referrer] = i == 1 ? params[:initial_referrer] : "/" params[:referring_keywords] = i == 1 ? ['foo','bar','trouble','braids'].rand : nil params[:url] = "http://#{params[:site]}#{['/','/about','/tour','/contact','/services'].rand}" params[:label] = params[:kind].titleize TrackableAction.create_from_params(params, created_at + i.minutes) end - end + end "Created #{count} sample sessions." end - # Returns a list of kinds that have already been tracked. + # Returns a list of kinds for all actions that have already been tracked, used to populate report filters. def self.kinds - _kinds = [] - KINDS.each{ |kind| _kinds << kind unless self.send(kind).count.zero? } - _kinds + TrackableAction.all.map{|ta| ta.kind}.uniq.sort - ['view'] end - + + # Returns a histogram for visited pages in the specified site(s). + # + # ==== Attributes + # + # * +:action_kind+ - kind of action: 'clicks', 'leads', 'scrolls', 'mouseovers', 'clickthroughs' + # * +:site+ - name of a site + # * +:time_period+ - date range as a string: 'past 3 months', 'past 6 months', 'past 12 months' + # * +:visit_kind+ - kind of visit as a string: 'direct', 'natural', 'paid', 'search' + # + # ==== Examples + # + # TrackableAction.pages_histogram( :site => 'foo.com' ) def self.pages_histogram(args) - 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 + conditions = TrackableAction.search(args).selector + 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 end + # Returns a scope based on time period, site, and visit kind. Null arguments returns all. + # + # ==== Attributes + # + # * +:action_kind+ - kind of action: 'clicks', 'leads', 'scrolls', 'mouseovers', 'clickthroughs' + # * +:site+ - name of a site + # * +:time_period+ - date range as a string: 'past 3 months', 'past 6 months', 'past 12 months' + # * +:visit_kind+ - kind of visit as a string: 'direct', 'natural', 'paid', 'search' + # + # ==== Examples + # + # TrackableAction.pages_histogram( :site => 'foo.com' ) def self.search(args = {}) args[:site] ||= 'all sites' args[:action_kind] ||= 'views' - [:site, :action_kind, :time_period].each{|a| args[a] = args[a].downcase if args[a]} - case args[:time_period] - when 'past 3 months' - args[:start_date] = (Time.zone.now - 2.months).beginning_of_month - args[:end_date] = Time.zone.now - when 'past 6 months' - args[:start_date] = (Time.zone.now - 5.months).beginning_of_month - args[:end_date] = Time.zone.now - when 'past 12 months' - args[:start_date] = (Time.zone.now - 11.months).beginning_of_month - args[:end_date] = Time.zone.now - else - args[:start_date] = TrackableAction.first.created_at - args[:end_date] = Time.zone.now - end - if args[:time_period] - if args[:site] == 'all sites' - TrackableAction.send("#{args[:action_kind]}").for_date_range(args[:start_date], args[:end_date]) - else - TrackableAction.for_site(args[:site]).send("#{args[:action_kind]}").for_date_range(args[:start_date], args[:end_date]) - end - else - if args[:site] == 'all sites' - TrackableAction.send("#{args[:action_kind]}") - else - TrackableAction.for_site(args[:site]).send("#{args[:action_kind]}") - end - end + args[:action_kind] == 'views' unless TrackableAction::KINDS.include?(args[:action_kind]) + [:site, :action_kind, :time_period, :visit_kind].each{|a| args[a] = args[a].downcase if args[a]} + (args[:start_date], args[:end_date]) = dates_from_time_period(args[:time_period]) + + sessions = TrackableSession.search(args).map{|s| s.id.to_s} + actions = TrackableAction.where(:trackable_session_id.in => sessions) + actions = actions.send("#{args[:action_kind]}") + actions end - - # Can't combine date conditions, so this is needed for reports + + # Returns a scope based on action kind, site, and visit kind only. + # + # ==== Attributes + # + # * +:action_kind+ - kind of action: 'clicks', 'leads', 'scrolls', 'mouseovers', 'clickthroughs' + # * +:site+ - name of a site + # * +:visit_kind+ - kind of visit as a string: 'direct', 'natural', 'paid', 'search' + # + # ==== Examples + # + # TrackableAction.search_without_date( :site => 'foo.com' ) def self.search_without_date(args = {}) - args[:site] ||= 'all sites' - args[:action_kind] ||= 'views' - [:site, :action_kind, :visit_kind].each{|a| args[a] = args[a].downcase} - if args[:site] == 'all sites' - TrackableAction.send("#{args[:action_kind]}") - else - TrackableAction.for_site(args[:site]).send("#{args[:action_kind]}") - end + args = args.clone + args.delete(:time_period) + self.search(args) end - + # Instance Methods =============================================================================== def click? self.kind == 'click' end - + def clickthrough? self.kind == 'clickthrough' end - + def conversion? self.kind == 'conversion' end - + def mouseover? self.kind == 'mouseover' end - + def scroll? self.kind == 'scroll' end - + def view? self.kind == 'view' end end