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