Ahoy
:fire: Simple, powerful analytics for Rails
Visits are stored in your database so you can easily combine them with other data.
You get:
- traffic source - referrer, referring domain, landing page, search keyword
- location - country, region, and city
- technology - browser, OS, and device type
- utm parameters - source, medium, term, content, campaign
Track events in:
- JavaScript
- Ruby
- Native apps
And store them wherever you’d like - your database, logs, external services, or all of them.
:postbox: To track emails, check out Ahoy Email.
No Ruby? Check out Ahoy.js.
Installation
Add this line to your application’s Gemfile:
gem 'ahoy_matey'
And run the generator. This creates a model to store visits.
rails generate ahoy:install
rake db:migrate
Lastly, include the javascript file in app/assets/javascripts/application.js
after jQuery.
//= require jquery
//= require ahoy
We recommend using traditional analytics services like Google Analytics as well.
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.
Explore your visits with queries like:
Visit.group(:search_keyword).count
Visit.group(:country).count
Visit.group(:referring_domain).count
Chartkick and Groupdate make it super easy to visualize the data.
<%= 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.
Let’s associate orders with visits.
class Order < ActiveRecord::Base
visitable
end
When a visitor places an order, the visit_id
column is automatically set.
:tada: Magic!
See where orders are coming from with simple joins:
Order.joins(:visit).group("referring_domain").count
Order.joins(:visit).group("city").count
Order.joins(:visit).group("device_type").count
Users
Ahoy automatically attaches the current_user
to the current_visit
.
With Devise, it will attach the user even if he / she signs in after the visit starts.
With other authentication frameworks, add this to the end of your sign in method:
if current_visit and !current_visit.user
current_visit.user = current_user
current_visit.save!
end
To see the visits for a given user, create an association:
class User < ActiveRecord::Base
has_many :visits
end
And use:
user = User.first
user.visits
UTM Parameters
Use UTM parameters to track campaigns. This is great for emails and social media. Just add them to your links and Ahoy will pick them up.
http://datakick.org/?utm_medium=email&utm_campaign=newsletter&utm_source=newsletter-2014-03
or
http://datakick.org/?utm_medium=twitter&utm_campaign=social&utm_source=tweet123
Native Apps
When a user launches the app, create a visit. Send a POST
request to /ahoy/visits
with:
- platform -
iOS
,Android
, etc. - app_version -
1.0.0
- os_version -
7.0.6
- visitor_token - if you have one
The endpoint will return a JSON response like:
{
"visit_token": "8tx2ziymkwa1WlppnkqxyaBaRlXrEQ3K",
"visitor_token": "hYBIV0rBfrIUAiArWweiECt4N9pyiygN"
}
Send the visit token in the Ahoy-Visit
header for all requests.
After 4 hours, create another visit and use the updated visit token.
Events
Each event has a name
and properties
.
There are three ways to track events.
JavaScript
ahoy.track("Viewed book", {title: "The World is Flat"});
or track all views and clicks with:
ahoy.trackAll();
Ruby
ahoy.track "Viewed book", title: "Hot, Flat, and Crowded"
Native Apps
Send a POST
request to /ahoy/events
with:
- name
- properties
- user token (depends on your authentication framework)
Ahoy-Visit
header
Requests should have Content-Type: application/json
.
Storing Events
You choose how to store events.
ActiveRecord
Create an Ahoy::Event
model to store events.
rails generate ahoy:events:active_record
rake db:migrate
Custom
Create your own subscribers in config/initializers/ahoy.rb
.
class LogSubscriber
def track(name, properties, = {})
data = {
name: name,
properties: properties,
time: [:time].to_i,
visit_id: [:visit].try(:id),
user_id: [:user].try(:id),
ip: [:controller].try(:request).try(:remote_ip)
}
Rails.logger.info data.to_json
end
end
# and add it
Ahoy.subscribers << LogSubscriber.new
Add as many subscribers as you’d like.
Development
Ahoy is built with developers in mind. You can run the following code in your browser’s console.
Force a new visit
ahoy.reset(); // then reload the page
Log messages
ahoy.debug();
Turn off logging
ahoy.debug(false);
More
- Excludes bots
- Degrades gracefully when cookies are disabled
- Don’t need a field? Just remove it from the migration
- Visits are 4 hours by default
Doorkeeper
To attach the user with Doorkeeper, be sure you have a current_resource_owner
method in ApplicationController
.
class ApplicationController < ActionController::Base
private
def current_resource_owner
User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
end
end
Reference
To track visits across multiple subdomains, add this before the javascript files.
var ahoy = {"domain": "yourdomain.com"};
Change the platform on the web
var ahoy = {"platform": "Mobile Web"}
Track additional values
class Visit < ActiveRecord::Base
ahoy_visit
before_create :set_gclid
def set_gclid
self.gclid = landing_params["gclid"]
end
end
Use a method besides current_user
Ahoy.user_method = :true_user
or use a Proc
Ahoy.user_method = proc {|controller| controller.current_user }
Customize visitable
visitable :sign_up_visit, class_name: "Visit"
Track view
ahoy.trackView();
Track clicks
ahoy.trackClicks();
Track all Rails actions
class ApplicationController < ActionController::Base
after_filter :track_action
protected
def track_action
ahoy.track "Hit action", request.filtered_parameters
end
end
Use a different model for visits
Ahoy.visit_model = UserVisit
# fix for Rails reloader in development
ActionDispatch::Reloader.to_prepare do
Ahoy.visit_model = UserVisit
end
Use a different model for events
Ahoy.subscribers << Ahoy::Subscribers::ActiveRecord.new(model: Event)
Upgrading
In 0.1.6
, a big improvement was made to browser
and os
. Update existing visits with:
Visit.find_each do |visit|
visit.set_technology
visit.save! if visit.changed?
end
TODO
- better readme
- simple dashboard
- turn off modules
History
View the changelog
Contributing
Everyone is encouraged to help improve this project. Here are a few ways you can help:
- Report bugs
- Fix bugs and submit pull requests
- Write, clarify, or fix documentation
- Suggest or add new features