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 | |