Use Visit instead of Ahoy::Visit

Andrew Kane committed Mar 19, 2014
commit 157c92f79ef6b54e8231a07e74c5619879454174
Showing 9 changed files with 138 additions and 95 deletions
README.md +24 -8
@@ @@ -4,7 +4,7 @@
:exclamation: Not ready for production just yet
- In under a minute, start learning more about your visitors.
+ You get:
- traffic source - referrer, referring domain, landing page, search keyword
- location - country, region, and city
@@ @@ -41,15 +41,31 @@ Lastly, include the javascript file in `app/assets/javascripts/application.js` a
//= require ahoy
```
- ## What You Get
+ ## How It Works
When someone visits your website, Ahoy creates a visit with lots of useful information.
Use the `current_visit` method to access it.
- The information is great on it’s own, but super powerful when combined with other models.
+ Explore your visits with queries like:
- You can store the visit id on any model. For instance, when someone places an order:
+ ```ruby
+ Visit.group(:search_keyword).count
+ Visit.group(:country).count
+ Visit.group(:referring_domain).count
+ ```
+
+ [Chartkick](http://chartkick.com/) and [Groupdate](https://github.com/ankane/groupdate) make it super easy to visualize the data.
+
+ ```erb
+ <%= line_chart Visit.group_by_day(:created_at).count %>
+ ```
+
+ ## The Power
+
+ This information is great on its own, but super powerful when combined with other models.
+
+ You can associate the visit with any model. For instance, when someone places an order:
```ruby
Order.create(
@@ @@ -58,15 +74,15 @@ Order.create(
)
```
- To get the visit for the order, use:
+ When you want to explore where most orders are coming from, create an association:
```ruby
class Order < ActiveRecord::Base
- belongs_to :visit, class_name: "Ahoy::Visit"
+ belongs_to :visit
end
```
- When you want to explore where most orders are coming from, you can do a number of queries.
+ And query away:
```ruby
Order.joins(:visit).group("referring_domain").count
@@ @@ -84,7 +100,7 @@ To see the visits for a given user, create an association:
```ruby
class User < ActiveRecord::Base
- has_many :visits, class_name: "Ahoy::Visit"
+ has_many :visits
end
```
app/controllers/ahoy/visits_controller.rb +1 -6
@@ @@ -4,7 +4,7 @@ module Ahoy
def create
visit =
- Ahoy::Visit.new do |v|
+ Ahoy.visit_model.new do |v|
v.visit_token = params[:visit_token]
v.visitor_token = params[:visitor_token]
v.ip = request.remote_ip
@@ @@ -14,11 +14,6 @@ module Ahoy
v.user = current_user if respond_to?(:current_user)
end
- visit.set_traffic_source
- visit.set_technology
- visit.set_location
- visit.set_utm_parameters
-
visit.save!
render json: {id: visit.id}
end
app/models/ahoy/visit.rb +0 -71
@@ @@ -1,71 +0,0 @@
- module Ahoy
- class Visit < ActiveRecord::Base
- belongs_to :user, polymorphic: true
-
- def set_traffic_source
- referring_uri = Addressable::URI.parse(referrer) rescue nil
- self.referring_domain = referring_uri.try(:host)
- search_keyword = RefererParser::Referer.new(referrer).search_term rescue nil
- self.search_keyword = search_keyword.present? ? search_keyword : nil
- end
-
- def set_utm_parameters
- landing_uri = Addressable::URI.parse(landing_page) rescue nil
- if landing_uri
- query_values = landing_uri.query_values || {}
- %w[utm_source utm_medium utm_term utm_content utm_campaign].each do |name|
- self[name] = query_values[name]
- end
- end
- end
-
- def set_technology
- browser = Browser.new(ua: user_agent)
-
- self.browser = browser.name
-
- # TODO add more
- self.os =
- if browser.android?
- "Android"
- elsif browser.ios?
- "iOS"
- elsif browser.windows_phone?
- "Windows Phone"
- elsif browser.blackberry?
- "Blackberry"
- elsif browser.chrome_os?
- "Chrome OS"
- elsif browser.mac?
- "Mac"
- elsif browser.windows?
- "Windows"
- elsif browser.linux?
- "Linux"
- end
-
- self.device_type =
- if browser.tv?
- "TV"
- elsif browser.console?
- "Console"
- elsif browser.tablet?
- "Tablet"
- elsif browser.mobile?
- "Mobile"
- else
- "Desktop"
- end
- end
-
- def set_location
- location = Geocoder.search(ip).first rescue nil
- if location
- self.country = location.country.presence
- self.region = location.state.presence
- self.city = location.city.presence
- end
- end
-
- end
- end
ahoy/controller.rb b/lib/ahoy/controller.rb +1 -1
@@ @@ -9,7 +9,7 @@ module Ahoy
def current_visit
if cookies[:ahoy_visit]
- @current_visit ||= Ahoy::Visit.where(visit_token: cookies[:ahoy_visit]).first
+ @current_visit ||= Ahoy.visit_model.where(visit_token: cookies[:ahoy_visit]).first
end
end
ahoy/engine.rb b/lib/ahoy/engine.rb +10 -0
@@ @@ -0,0 +1,10 @@
+ module Ahoy
+ class Engine < ::Rails::Engine
+ isolate_namespace Ahoy
+
+ initializer "ahoy" do |app|
+ Ahoy.visit_model ||= Visit
+ end
+
+ end
+ end
ahoy/model.rb b/lib/ahoy/model.rb +83 -0
@@ @@ -0,0 +1,83 @@
+ module Ahoy
+ module Model
+
+ def ahoy_visit
+ class_eval do
+
+ belongs_to :user, polymorphic: true
+
+ before_create :set_traffic_source
+ before_create :set_utm_parameters
+ before_create :set_technology
+ before_create :set_location
+
+ def set_traffic_source
+ referring_uri = Addressable::URI.parse(referrer) rescue nil
+ self.referring_domain = referring_uri.try(:host)
+ search_keyword = RefererParser::Referer.new(referrer).search_term rescue nil
+ self.search_keyword = search_keyword.present? ? search_keyword : nil
+ end
+
+ def set_utm_parameters
+ landing_uri = Addressable::URI.parse(landing_page) rescue nil
+ if landing_uri
+ query_values = landing_uri.query_values || {}
+ %w[utm_source utm_medium utm_term utm_content utm_campaign].each do |name|
+ self[name] = query_values[name]
+ end
+ end
+ end
+
+ def set_technology
+ browser = Browser.new(ua: user_agent)
+
+ self.browser = browser.name
+
+ # TODO add more
+ self.os =
+ if browser.android?
+ "Android"
+ elsif browser.ios?
+ "iOS"
+ elsif browser.windows_phone?
+ "Windows Phone"
+ elsif browser.blackberry?
+ "Blackberry"
+ elsif browser.chrome_os?
+ "Chrome OS"
+ elsif browser.mac?
+ "Mac"
+ elsif browser.windows?
+ "Windows"
+ elsif browser.linux?
+ "Linux"
+ end
+
+ self.device_type =
+ if browser.tv?
+ "TV"
+ elsif browser.console?
+ "Console"
+ elsif browser.tablet?
+ "Tablet"
+ elsif browser.mobile?
+ "Mobile"
+ else
+ "Desktop"
+ end
+ end
+
+ def set_location
+ location = Geocoder.search(ip).first rescue nil
+ if location
+ self.country = location.country.presence
+ self.region = location.state.presence
+ self.city = location.city.presence
+ end
+ end
+
+ end # end class_eval
+ end
+
+ end
+ end
ahoy_matey.rb b/lib/ahoy_matey.rb +7 -6
@@ @@ -1,23 +1,24 @@
- require "ahoy/version"
- require "ahoy/controller"
require "addressable/uri"
require "browser"
require "geocoder"
require "referer-parser"
+ require "ahoy/version"
+ require "ahoy/controller"
+ require "ahoy/model"
+ require "ahoy/engine"
module Ahoy
- class Engine < ::Rails::Engine
- isolate_namespace Ahoy
- end
+ mattr_accessor :visit_model
end
ActionController::Base.send :include, Ahoy::Controller
+ ActiveRecord::Base.send(:extend, Ahoy::Model) if defined?(ActiveRecord)
if defined?(Warden)
Warden::Manager.after_authentication do |user, auth, opts|
request = Rack::Request.new(auth.env)
if request.cookies["ahoy_visit"]
- visit = Ahoy::Visit.where(visit_token: request.cookies["ahoy_visit"]).first
+ visit = Ahoy.visit_model.where(visit_token: request.cookies["ahoy_visit"]).first
if visit
visit.user = user
visit.save!
generators/ahoy/install_generator.rb b/lib/generators/ahoy/install_generator.rb +9 -0
@@ @@ -24,6 +24,15 @@ module Ahoy
def copy_migration
migration_template "install.rb", "db/migrate/install_ahoy.rb"
end
+
+ def generate_model
+ invoke "active_record:model", ["Visit"], migration: false
+ end
+
+ def inject_ahoy_content
+ inject_into_class "app/models/visit.rb", "Visit", " ahoy_visit\n"
+ end
+
end
end
end
generators/ahoy/templates/install.rb b/lib/generators/ahoy/templates/install.rb +3 -3
@@ @@ -1,6 +1,6 @@
class <%= migration_class_name %> < ActiveRecord::Migration
def change
- create_table :ahoy_visits do |t|
+ create_table :visits do |t|
# cookies
t.string :visit_token
t.string :visitor_token
@@ @@ -39,7 +39,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration
t.timestamp :created_at
end
- add_index :ahoy_visits, [:visit_token], unique: true
- add_index :ahoy_visits, [:user_id, :user_type]
+ add_index :visits, [:visit_token], unique: true
+ add_index :visits, [:user_id, :user_type]
end
end