ahoy_matey 1.5.3 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +88 -0
- data/CONTRIBUTING.md +42 -0
- data/LICENSE.txt +1 -1
- data/README.md +369 -380
- data/app/controllers/ahoy/base_controller.rb +15 -15
- data/app/controllers/ahoy/events_controller.rb +8 -2
- data/app/controllers/ahoy/visits_controller.rb +8 -1
- data/app/jobs/ahoy/geocode_job.rb +10 -0
- data/app/jobs/ahoy/geocode_v2_job.rb +28 -0
- data/config/routes.rb +1 -1
- data/lib/ahoy.rb +68 -86
- data/lib/ahoy/base_store.rb +97 -0
- data/lib/ahoy/controller.rb +26 -17
- data/lib/ahoy/database_store.rb +89 -0
- data/lib/ahoy/engine.rb +7 -7
- data/lib/ahoy/helper.rb +40 -0
- data/lib/ahoy/model.rb +5 -27
- data/lib/ahoy/{properties.rb → query_methods.rb} +25 -9
- data/lib/ahoy/tracker.rb +101 -42
- data/lib/ahoy/utils.rb +7 -0
- data/lib/ahoy/version.rb +1 -1
- data/lib/ahoy/visit_properties.rb +99 -37
- data/lib/generators/ahoy/activerecord_generator.rb +41 -0
- data/lib/generators/ahoy/base_generator.rb +13 -0
- data/lib/generators/ahoy/install_generator.rb +44 -0
- data/lib/generators/ahoy/mongoid_generator.rb +16 -0
- data/lib/generators/ahoy/templates/active_record_event_model.rb.tt +10 -0
- data/lib/generators/ahoy/templates/active_record_migration.rb.tt +62 -0
- data/lib/generators/ahoy/templates/active_record_visit_model.rb.tt +6 -0
- data/lib/generators/ahoy/templates/base_store_initializer.rb.tt +20 -0
- data/lib/generators/ahoy/templates/database_store_initializer.rb.tt +5 -0
- data/lib/generators/ahoy/{stores/templates/mongoid_event_model.rb → templates/mongoid_event_model.rb.tt} +4 -2
- data/lib/generators/ahoy/{stores/templates/mongoid_visit_model.rb → templates/mongoid_visit_model.rb.tt} +15 -9
- data/vendor/assets/javascripts/ahoy.js +336 -113
- metadata +54 -144
- data/.gitignore +0 -17
- data/Gemfile +0 -6
- data/Rakefile +0 -8
- data/ahoy_matey.gemspec +0 -38
- data/lib/ahoy/deckhands/location_deckhand.rb +0 -49
- data/lib/ahoy/deckhands/request_deckhand.rb +0 -52
- data/lib/ahoy/deckhands/technology_deckhand.rb +0 -47
- data/lib/ahoy/deckhands/traffic_source_deckhand.rb +0 -22
- data/lib/ahoy/deckhands/utm_parameter_deckhand.rb +0 -23
- data/lib/ahoy/geocode_job.rb +0 -13
- data/lib/ahoy/logger_silencer.rb +0 -75
- data/lib/ahoy/stores/active_record_store.rb +0 -60
- data/lib/ahoy/stores/active_record_token_store.rb +0 -113
- data/lib/ahoy/stores/base_store.rb +0 -88
- data/lib/ahoy/stores/bunny_store.rb +0 -33
- data/lib/ahoy/stores/fluentd_store.rb +0 -17
- data/lib/ahoy/stores/kafka_store.rb +0 -40
- data/lib/ahoy/stores/kinesis_firehose_store.rb +0 -42
- data/lib/ahoy/stores/log_store.rb +0 -53
- data/lib/ahoy/stores/mongoid_store.rb +0 -63
- data/lib/ahoy/subscribers/active_record.rb +0 -19
- data/lib/ahoy/throttle.rb +0 -17
- data/lib/generators/ahoy/stores/active_record_events_generator.rb +0 -53
- data/lib/generators/ahoy/stores/active_record_generator.rb +0 -16
- data/lib/generators/ahoy/stores/active_record_visits_generator.rb +0 -43
- data/lib/generators/ahoy/stores/bunny_generator.rb +0 -15
- data/lib/generators/ahoy/stores/custom_generator.rb +0 -15
- data/lib/generators/ahoy/stores/fluentd_generator.rb +0 -15
- data/lib/generators/ahoy/stores/kafka_generator.rb +0 -15
- data/lib/generators/ahoy/stores/kinesis_firehose_generator.rb +0 -15
- data/lib/generators/ahoy/stores/log_generator.rb +0 -15
- data/lib/generators/ahoy/stores/mongoid_events_generator.rb +0 -19
- data/lib/generators/ahoy/stores/mongoid_generator.rb +0 -14
- data/lib/generators/ahoy/stores/mongoid_visits_generator.rb +0 -27
- data/lib/generators/ahoy/stores/templates/active_record_event_model.rb +0 -12
- data/lib/generators/ahoy/stores/templates/active_record_events_migration.rb +0 -19
- data/lib/generators/ahoy/stores/templates/active_record_initializer.rb +0 -3
- data/lib/generators/ahoy/stores/templates/active_record_visit_model.rb +0 -4
- data/lib/generators/ahoy/stores/templates/active_record_visits_migration.rb +0 -57
- data/lib/generators/ahoy/stores/templates/bunny_initializer.rb +0 -9
- data/lib/generators/ahoy/stores/templates/custom_initializer.rb +0 -10
- data/lib/generators/ahoy/stores/templates/fluentd_initializer.rb +0 -3
- data/lib/generators/ahoy/stores/templates/kafka_initializer.rb +0 -9
- data/lib/generators/ahoy/stores/templates/kinesis_firehose_initializer.rb +0 -17
- data/lib/generators/ahoy/stores/templates/log_initializer.rb +0 -3
- data/lib/generators/ahoy/stores/templates/mongoid_initializer.rb +0 -3
- data/test/properties/mysql_json_test.rb +0 -18
- data/test/properties/mysql_text_test.rb +0 -19
- data/test/properties/postgresql_hstore_test.rb +0 -18
- data/test/properties/postgresql_json_test.rb +0 -18
- data/test/properties/postgresql_jsonb_test.rb +0 -18
- data/test/properties/postgresql_text_test.rb +0 -19
- data/test/test_helper.rb +0 -99
- data/test/visit_properties_test.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d90d64ae8641aa0bae1bc44acf29379a585ebbad0bbb87325380508d5a8ffcc7
|
4
|
+
data.tar.gz: 7c01ce8cbd2e92e3555479b251889d171b54be9d5c369fca51f413fdc912ab01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe62cce407d17f736b616f11a742fefe338cdedd2457665cb3e578bafe0bd6fbb889dd315382dcb70d563a35dd5c5e05de908c069e12d21ab92e0cee637e42d7
|
7
|
+
data.tar.gz: f399c7708f6c1071c72db3d9164ab77bd3377fdc0eab7064707fb1202b240156be03669070763bf2f13bcf0bfcac134286eb9e9f9fb988d78267c71da9603386
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,90 @@
|
|
1
|
+
## 3.0.1
|
2
|
+
|
3
|
+
- Made `Ahoy::Tracker` work outside of requests
|
4
|
+
- Fixed storage of `false` values with customized store
|
5
|
+
- Fixed error with `user_method` and `Rails::InfoController`
|
6
|
+
- Gracefully handle `ActionDispatch::RemoteIp::IpSpoofAttackError`
|
7
|
+
|
8
|
+
## 3.0.0
|
9
|
+
|
10
|
+
- Made Device Detector the default user agent parser
|
11
|
+
- Made v2 the default bot detection version
|
12
|
+
- Removed a large number of dependencies
|
13
|
+
- Removed search keyword detection (most search engines today prevent this)
|
14
|
+
- Removed support for Rails < 5
|
15
|
+
|
16
|
+
## 2.2.1
|
17
|
+
|
18
|
+
- Updated Ahoy.js to 0.3.4
|
19
|
+
- Fixed v2 bot detection
|
20
|
+
- Added latitude and longitude to installation
|
21
|
+
|
22
|
+
## 2.2.0
|
23
|
+
|
24
|
+
- Added `amp_event` helper
|
25
|
+
- Improved bot detection for Device Detector
|
26
|
+
|
27
|
+
## 2.1.0
|
28
|
+
|
29
|
+
- Added option for IP masking
|
30
|
+
- Added option to use anonymity sets instead of cookies
|
31
|
+
- Added `user_agent_parser` option
|
32
|
+
- Fixed `visitable` for Rails 4.2
|
33
|
+
- Removed `search_keyword` from new installs
|
34
|
+
|
35
|
+
## 2.0.2
|
36
|
+
|
37
|
+
- Fixed error on duplicate records
|
38
|
+
- Fixed message when visit not found for geocoding
|
39
|
+
- Better compatibility with GeoLite2
|
40
|
+
- Better browser compatibility for Ahoy.js
|
41
|
+
|
42
|
+
## 2.0.1
|
43
|
+
|
44
|
+
- Added `Ahoy.server_side_visits = :when_needed` to automatically create visits server-side when needed for events and `visitable`
|
45
|
+
- Better handling of visit duration and expiration in JavaScript
|
46
|
+
|
47
|
+
## 2.0.0
|
48
|
+
|
49
|
+
- Removed dependency on jQuery
|
50
|
+
- Use `navigator.sendBeacon` by default in supported browsers
|
51
|
+
- Added `geocode` event
|
52
|
+
- Added `where_event` method for querying events
|
53
|
+
- Added support for `visitable` and `where_props` to Mongoid
|
54
|
+
- Added `preserve_callbacks` option
|
55
|
+
- Use `json` for MySQL by default
|
56
|
+
- Fixed log silencing
|
57
|
+
|
58
|
+
Breaking changes
|
59
|
+
|
60
|
+
- Simpler interface for data stores
|
61
|
+
- Renamed `track_visits_immediately` to `server_side_visits` and enabled by default
|
62
|
+
- Renamed `mount` option to `api` and disabled by default
|
63
|
+
- Enabled `protect_from_forgery` by default
|
64
|
+
- Removed deprecated options
|
65
|
+
- Removed throttling
|
66
|
+
- Removed most built-in stores
|
67
|
+
- Removed support for Rails < 4.2
|
68
|
+
|
69
|
+
## 1.6.1
|
70
|
+
|
71
|
+
- Added `gin` index on properties for events
|
72
|
+
- Fixed `visitable` options when name not provided
|
73
|
+
|
74
|
+
## 1.6.0
|
75
|
+
|
76
|
+
- Added support for Rails 5.1
|
77
|
+
|
78
|
+
## 1.5.5
|
79
|
+
|
80
|
+
- Added support for Rails API
|
81
|
+
- Added NATS and NSQ stores
|
82
|
+
|
83
|
+
## 1.5.4
|
84
|
+
|
85
|
+
- Fixed issue with duplicate events
|
86
|
+
- Added support for PostGIS for `where_properties`
|
87
|
+
|
1
88
|
## 1.5.3
|
2
89
|
|
3
90
|
- Fixed error with Rails 5 and Mongoid 6
|
@@ -36,6 +123,7 @@
|
|
36
123
|
- Detect database for `rails g ahoy:stores:active_record` for easier installation
|
37
124
|
- Use `safely` as default exception handler
|
38
125
|
- Fixed issue with log silencer
|
126
|
+
- Use multi-column indexes on `ahoy_events` table creation
|
39
127
|
|
40
128
|
## 1.3.1
|
41
129
|
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# Contributing
|
2
|
+
|
3
|
+
First, thanks for wanting to contribute. You’re awesome! :heart:
|
4
|
+
|
5
|
+
## Help
|
6
|
+
|
7
|
+
We’re not able to provide support through GitHub Issues. If you’re looking for help with your code, try posting on [Stack Overflow](https://stackoverflow.com/).
|
8
|
+
|
9
|
+
All features should be documented. If you don’t see a feature in the docs, assume it doesn’t exist.
|
10
|
+
|
11
|
+
## Bugs
|
12
|
+
|
13
|
+
Think you’ve discovered a bug?
|
14
|
+
|
15
|
+
1. Search existing issues to see if it’s been reported.
|
16
|
+
2. Try the `master` branch to make sure it hasn’t been fixed.
|
17
|
+
|
18
|
+
```rb
|
19
|
+
gem "ahoy_matey", github: "ankane/ahoy"
|
20
|
+
```
|
21
|
+
|
22
|
+
If the above steps don’t help, create an issue. Include:
|
23
|
+
|
24
|
+
- Detailed steps to reproduce
|
25
|
+
- Complete backtraces for exceptions
|
26
|
+
|
27
|
+
## New Features
|
28
|
+
|
29
|
+
If you’d like to discuss a new feature, create an issue and start the title with `[Idea]`.
|
30
|
+
|
31
|
+
## Pull Requests
|
32
|
+
|
33
|
+
Fork the project and create a pull request. A few tips:
|
34
|
+
|
35
|
+
- Keep changes to a minimum. If you have multiple features or fixes, submit multiple pull requests.
|
36
|
+
- Follow the existing style. The code should read like it’s written by a single person.
|
37
|
+
|
38
|
+
Feel free to open an issue to get feedback on your idea before spending too much time on it.
|
39
|
+
|
40
|
+
---
|
41
|
+
|
42
|
+
This contributing guide is released under [CCO](https://creativecommons.org/publicdomain/zero/1.0/) (public domain). Use it for your own project without attribution.
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
# Ahoy
|
2
2
|
|
3
|
-
|
3
|
+
:fire: Simple, powerful analytics for Rails
|
4
|
+
|
5
|
+
Track visits and events in Ruby, JavaScript, and native apps. Data is stored in your database by default so you can easily combine it with other data.
|
6
|
+
|
7
|
+
:postbox: To track emails, check out [Ahoy Email](https://github.com/ankane/ahoy_email), and for A/B testing, check out [Field Test](https://github.com/ankane/field_test)
|
4
8
|
|
5
9
|
:tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
|
6
10
|
|
7
|
-
|
11
|
+
[![Build Status](https://travis-ci.org/ankane/ahoy.svg?branch=master)](https://travis-ci.org/ankane/ahoy)
|
8
12
|
|
9
13
|
## Installation
|
10
14
|
|
@@ -14,159 +18,124 @@ Add this line to your application’s Gemfile:
|
|
14
18
|
gem 'ahoy_matey'
|
15
19
|
```
|
16
20
|
|
17
|
-
And
|
18
|
-
|
19
|
-
```javascript
|
20
|
-
//= require jquery
|
21
|
-
//= require ahoy
|
22
|
-
```
|
23
|
-
|
24
|
-
## Choose a Data Store
|
25
|
-
|
26
|
-
Ahoy supports a number of data stores out of the box. You can start with one of them and customize as needed, or create your own store from scratch.
|
27
|
-
|
28
|
-
- [PostgreSQL, MySQL, or SQLite](#postgresql-mysql-or-sqlite)
|
29
|
-
- [MongoDB](#mongodb)
|
30
|
-
- [Kafka](#kafka)
|
31
|
-
- [Fluentd](#fluentd)
|
32
|
-
- [RabbitMQ](#rabbitmq)
|
33
|
-
- [Amazon Kinesis Firehose](#amazon-kinesis-firehose)
|
34
|
-
- [Logs](#logs)
|
35
|
-
- [Custom](#custom)
|
36
|
-
|
37
|
-
### PostgreSQL, MySQL, or SQLite
|
38
|
-
|
39
|
-
Run:
|
21
|
+
And run:
|
40
22
|
|
41
23
|
```sh
|
42
|
-
|
43
|
-
|
24
|
+
bundle install
|
25
|
+
rails generate ahoy:install
|
26
|
+
rails db:migrate
|
44
27
|
```
|
45
28
|
|
46
|
-
|
29
|
+
Restart your web server, open a page in your browser, and a visit will be created :tada:
|
47
30
|
|
48
|
-
|
49
|
-
|
31
|
+
Track your first event from a controller with:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
ahoy.track "My first event", language: "Ruby"
|
50
35
|
```
|
51
36
|
|
52
|
-
###
|
37
|
+
### JavaScript, Native Apps, & AMP
|
53
38
|
|
54
|
-
|
39
|
+
Enable the API in `config/initializers/ahoy.rb`:
|
55
40
|
|
56
41
|
```ruby
|
57
|
-
|
42
|
+
Ahoy.api = true
|
58
43
|
```
|
59
44
|
|
60
|
-
And
|
45
|
+
And restart your web server.
|
46
|
+
|
47
|
+
### JavaScript
|
48
|
+
|
49
|
+
For Rails 6 / Webpacker, run:
|
61
50
|
|
62
51
|
```sh
|
63
|
-
|
52
|
+
yarn add ahoy.js
|
64
53
|
```
|
65
54
|
|
66
|
-
|
55
|
+
And add to `app/javascript/packs/application.js`:
|
67
56
|
|
68
|
-
|
57
|
+
```javascript
|
58
|
+
import ahoy from "ahoy.js";
|
59
|
+
```
|
69
60
|
|
70
|
-
|
61
|
+
For Rails 5 / Sprockets, add to `app/assets/javascripts/application.js`:
|
71
62
|
|
72
|
-
```
|
73
|
-
|
63
|
+
```javascript
|
64
|
+
//= require ahoy
|
74
65
|
```
|
75
66
|
|
76
|
-
|
67
|
+
Track an event with:
|
77
68
|
|
78
|
-
```
|
79
|
-
|
69
|
+
```javascript
|
70
|
+
ahoy.track("My second event", {language: "JavaScript"});
|
80
71
|
```
|
81
72
|
|
82
|
-
|
73
|
+
### GDPR Compliance
|
83
74
|
|
84
|
-
|
75
|
+
Ahoy provides a number of options to help with GDPR compliance. See the [GDPR section](#gdpr-compliance-1) for more info.
|
85
76
|
|
86
|
-
|
87
|
-
|
88
|
-
```ruby
|
89
|
-
gem 'bunny'
|
90
|
-
```
|
77
|
+
## How It Works
|
91
78
|
|
92
|
-
|
79
|
+
### Visits
|
93
80
|
|
94
|
-
|
95
|
-
rails generate ahoy:stores:bunny
|
96
|
-
```
|
81
|
+
When someone visits your website, Ahoy creates a visit with lots of useful information.
|
97
82
|
|
98
|
-
|
83
|
+
- **traffic source** - referrer, referring domain, landing page
|
84
|
+
- **location** - country, region, city, latitude, longitude
|
85
|
+
- **technology** - browser, OS, device type
|
86
|
+
- **utm parameters** - source, medium, term, content, campaign
|
99
87
|
|
100
|
-
|
88
|
+
Use the `current_visit` method to access it.
|
101
89
|
|
102
|
-
|
90
|
+
Prevent certain Rails actions from creating visits with:
|
103
91
|
|
104
92
|
```ruby
|
105
|
-
|
93
|
+
skip_before_action :track_ahoy_visit
|
106
94
|
```
|
107
95
|
|
108
|
-
|
96
|
+
This is typically useful for APIs. If your entire Rails app is an API, you can use:
|
109
97
|
|
110
|
-
```
|
111
|
-
|
98
|
+
```ruby
|
99
|
+
Ahoy.api_only = true
|
112
100
|
```
|
113
101
|
|
114
|
-
|
102
|
+
You can also defer visit tracking to JavaScript. This is useful for preventing bots (that aren’t detected by their user agent) and users with cookies disabled from creating a new visit on each request. `:when_needed` will create visits server-side only when needed by events, and `false` will disable server-side creation completely, discarding events without a visit.
|
115
103
|
|
116
|
-
|
117
|
-
|
118
|
-
```sh
|
119
|
-
rails generate ahoy:stores:log
|
104
|
+
```ruby
|
105
|
+
Ahoy.server_side_visits = :when_needed
|
120
106
|
```
|
121
107
|
|
122
|
-
|
108
|
+
### Events
|
123
109
|
|
124
|
-
|
110
|
+
Each event has a `name` and `properties`. There are several ways to track events.
|
125
111
|
|
126
|
-
|
127
|
-
|
112
|
+
#### Ruby
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
ahoy.track "Viewed book", title: "Hot, Flat, and Crowded"
|
128
116
|
```
|
129
117
|
|
130
|
-
|
118
|
+
Track actions automatically with:
|
131
119
|
|
132
120
|
```ruby
|
133
|
-
class
|
134
|
-
|
135
|
-
end
|
121
|
+
class ApplicationController < ActionController::Base
|
122
|
+
after_action :track_action
|
136
123
|
|
137
|
-
|
124
|
+
protected
|
125
|
+
|
126
|
+
def track_action
|
127
|
+
ahoy.track "Ran action", request.path_parameters
|
138
128
|
end
|
139
129
|
end
|
140
130
|
```
|
141
131
|
|
142
|
-
See the [ActiveRecordTokenStore](https://github.com/ankane/ahoy/blob/master/lib/ahoy/stores/active_record_token_store.rb) for an example.
|
143
|
-
|
144
|
-
## How It Works
|
145
|
-
|
146
|
-
### Visits
|
147
|
-
|
148
|
-
When someone visits your website, Ahoy creates a visit with lots of useful information.
|
149
|
-
|
150
|
-
- **traffic source** - referrer, referring domain, landing page, search keyword
|
151
|
-
- **location** - country, region, and city
|
152
|
-
- **technology** - browser, OS, and device type
|
153
|
-
- **utm parameters** - source, medium, term, content, campaign
|
154
|
-
|
155
|
-
Use the `current_visit` method to access it.
|
156
|
-
|
157
|
-
### Events
|
158
|
-
|
159
|
-
Each event has a `name` and `properties`.
|
160
|
-
|
161
|
-
There are three ways to track events.
|
162
|
-
|
163
132
|
#### JavaScript
|
164
133
|
|
165
134
|
```javascript
|
166
135
|
ahoy.track("Viewed book", {title: "The World is Flat"});
|
167
136
|
```
|
168
137
|
|
169
|
-
|
138
|
+
Track events automatically with:
|
170
139
|
|
171
140
|
```javascript
|
172
141
|
ahoy.trackAll();
|
@@ -174,140 +143,155 @@ ahoy.trackAll();
|
|
174
143
|
|
175
144
|
See [Ahoy.js](https://github.com/ankane/ahoy.js) for a complete list of features.
|
176
145
|
|
177
|
-
#### Ruby
|
178
|
-
|
179
|
-
```ruby
|
180
|
-
ahoy.track "Viewed book", title: "Hot, Flat, and Crowded"
|
181
|
-
```
|
182
|
-
|
183
146
|
#### Native Apps
|
184
147
|
|
185
|
-
|
148
|
+
For Android, check out [Ahoy Android](https://github.com/instacart/ahoy-android). For other platforms, see the [API spec](#api-spec).
|
186
149
|
|
187
|
-
|
150
|
+
#### AMP
|
188
151
|
|
189
|
-
|
152
|
+
```erb
|
153
|
+
<head>
|
154
|
+
<script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script>
|
155
|
+
</head>
|
156
|
+
<body>
|
157
|
+
<%= amp_event "Viewed article", title: "Analytics with Rails" %>
|
158
|
+
</body>
|
159
|
+
```
|
190
160
|
|
191
|
-
|
161
|
+
### Associated Models
|
192
162
|
|
193
|
-
|
163
|
+
Say we want to associate orders with visits. Just add `visitable` to the model.
|
194
164
|
|
195
165
|
```ruby
|
196
|
-
|
166
|
+
class Order < ApplicationRecord
|
167
|
+
visitable :ahoy_visit
|
168
|
+
end
|
197
169
|
```
|
198
170
|
|
199
|
-
|
171
|
+
When a visitor places an order, the `ahoy_visit_id` column is automatically set :tada:
|
200
172
|
|
201
|
-
|
173
|
+
See where orders are coming from with simple joins:
|
202
174
|
|
203
175
|
```ruby
|
204
|
-
|
205
|
-
|
206
|
-
|
176
|
+
Order.joins(:ahoy_visit).group("referring_domain").count
|
177
|
+
Order.joins(:ahoy_visit).group("city").count
|
178
|
+
Order.joins(:ahoy_visit).group("device_type").count
|
207
179
|
```
|
208
180
|
|
209
|
-
|
210
|
-
|
211
|
-
Exclude visits and events from being tracked with:
|
181
|
+
Here’s what the migration to add the `ahoy_visit_id` column should look like:
|
212
182
|
|
213
183
|
```ruby
|
214
|
-
class
|
215
|
-
def
|
216
|
-
|
184
|
+
class AddVisitIdToOrders < ActiveRecord::Migration[6.0]
|
185
|
+
def change
|
186
|
+
add_column :orders, :ahoy_visit_id, :bigint
|
217
187
|
end
|
218
188
|
end
|
219
189
|
```
|
220
190
|
|
221
|
-
|
222
|
-
|
223
|
-
### Track Additional Values
|
191
|
+
Customize the column with:
|
224
192
|
|
225
193
|
```ruby
|
226
|
-
|
227
|
-
def track_visit(options)
|
228
|
-
super do |visit|
|
229
|
-
visit.gclid = visit_properties.landing_params["gclid"]
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
def track_event(name, properties, options)
|
234
|
-
super do |event|
|
235
|
-
event.ip = request.ip
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
194
|
+
visitable :sign_up_visit
|
239
195
|
```
|
240
196
|
|
241
|
-
|
197
|
+
### Users
|
242
198
|
|
243
|
-
|
199
|
+
Ahoy automatically attaches the `current_user` to the visit. With [Devise](https://github.com/plataformatec/devise), it attaches the user even if he or she signs in after the visit starts.
|
244
200
|
|
245
|
-
|
201
|
+
With other authentication frameworks, add this to the end of your sign in method:
|
246
202
|
|
247
203
|
```ruby
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
204
|
+
ahoy.authenticate(user)
|
205
|
+
```
|
206
|
+
|
207
|
+
To see the visits for a given user, create an association:
|
208
|
+
|
209
|
+
```ruby
|
210
|
+
class User < ApplicationRecord
|
211
|
+
has_many :visits, class_name: "Ahoy::Visit"
|
252
212
|
end
|
253
213
|
```
|
254
214
|
|
255
|
-
|
215
|
+
And use:
|
216
|
+
|
217
|
+
```ruby
|
218
|
+
User.find(123).visits
|
219
|
+
```
|
256
220
|
|
257
|
-
|
221
|
+
#### Custom User Method
|
258
222
|
|
259
|
-
|
223
|
+
Use a method besides `current_user`
|
260
224
|
|
261
225
|
```ruby
|
262
|
-
|
226
|
+
Ahoy.user_method = :true_user
|
263
227
|
```
|
264
228
|
|
265
|
-
|
229
|
+
or use a proc
|
230
|
+
|
231
|
+
```ruby
|
232
|
+
Ahoy.user_method = ->(controller) { controller.true_user }
|
233
|
+
```
|
266
234
|
|
267
|
-
|
235
|
+
#### Doorkeeper
|
236
|
+
|
237
|
+
To attach the user with [Doorkeeper](https://github.com/doorkeeper-gem/doorkeeper), be sure you have a `current_resource_owner` method in `ApplicationController`.
|
268
238
|
|
269
239
|
```ruby
|
270
|
-
class
|
271
|
-
|
272
|
-
CustomVisit
|
273
|
-
end
|
240
|
+
class ApplicationController < ActionController::Base
|
241
|
+
private
|
274
242
|
|
275
|
-
def
|
276
|
-
|
243
|
+
def current_resource_owner
|
244
|
+
User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
|
277
245
|
end
|
278
246
|
end
|
279
247
|
```
|
280
248
|
|
281
|
-
|
249
|
+
#### Knock
|
282
250
|
|
283
|
-
|
251
|
+
To attach the user with [Knock](https://github.com/nsarno/knock), either include `Knock::Authenticable`in `ApplicationController`:
|
284
252
|
|
285
|
-
|
253
|
+
```ruby
|
254
|
+
class ApplicationController < ActionController::API
|
255
|
+
include Knock::Authenticable
|
256
|
+
end
|
257
|
+
```
|
286
258
|
|
287
|
-
|
288
|
-
|
259
|
+
Or include it in Ahoy:
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
Ahoy::BaseController.include Knock::Authenticable
|
289
263
|
```
|
290
264
|
|
291
|
-
|
265
|
+
And use:
|
292
266
|
|
293
|
-
```
|
294
|
-
|
267
|
+
```ruby
|
268
|
+
Ahoy.user_method = ->(controller) { controller.send(:authenticate_entity, "user") }
|
295
269
|
```
|
296
270
|
|
297
|
-
|
271
|
+
### Exclusions
|
272
|
+
|
273
|
+
Bots are excluded from tracking by default. To include them, use:
|
298
274
|
|
299
275
|
```ruby
|
300
|
-
|
301
|
-
|
276
|
+
Ahoy.track_bots = true
|
277
|
+
```
|
302
278
|
|
303
|
-
|
279
|
+
Add your own rules with:
|
304
280
|
|
305
|
-
|
306
|
-
|
307
|
-
|
281
|
+
```ruby
|
282
|
+
Ahoy.exclude_method = lambda do |controller, request|
|
283
|
+
request.ip == "192.168.1.1"
|
308
284
|
end
|
309
285
|
```
|
310
286
|
|
287
|
+
### Visit Duration
|
288
|
+
|
289
|
+
By default, a new visit is created after 4 hours of inactivity. Change this with:
|
290
|
+
|
291
|
+
```ruby
|
292
|
+
Ahoy.visit_duration = 30.minutes
|
293
|
+
```
|
294
|
+
|
311
295
|
### Multiple Subdomains
|
312
296
|
|
313
297
|
To track visits across multiple subdomains, use:
|
@@ -316,103 +300,136 @@ To track visits across multiple subdomains, use:
|
|
316
300
|
Ahoy.cookie_domain = :all
|
317
301
|
```
|
318
302
|
|
319
|
-
###
|
303
|
+
### Geocoding
|
304
|
+
|
305
|
+
Disable geocoding with:
|
320
306
|
|
321
|
-
|
307
|
+
```ruby
|
308
|
+
Ahoy.geocode = false
|
309
|
+
```
|
322
310
|
|
323
|
-
Change
|
311
|
+
Change the job queue with:
|
324
312
|
|
325
313
|
```ruby
|
326
|
-
Ahoy.
|
314
|
+
Ahoy.job_queue = :low_priority
|
327
315
|
```
|
328
316
|
|
329
|
-
|
317
|
+
#### Geocoding Performance
|
330
318
|
|
331
|
-
|
319
|
+
To avoid calls to a remote API, download the [GeoLite2 City database](https://dev.maxmind.com/geoip/geoip2/geolite2/) and configure Geocoder to use it.
|
332
320
|
|
333
|
-
|
321
|
+
Add this line to your application’s Gemfile:
|
334
322
|
|
335
323
|
```ruby
|
336
|
-
|
337
|
-
def change
|
338
|
-
add_column :orders, :visit_id, :integer
|
339
|
-
end
|
340
|
-
end
|
324
|
+
gem 'maxminddb'
|
341
325
|
```
|
342
326
|
|
343
|
-
|
344
|
-
|
345
|
-
Then, add `visitable` to the model.
|
327
|
+
And create an initializer at `config/initializers/geocoder.rb` with:
|
346
328
|
|
347
329
|
```ruby
|
348
|
-
|
349
|
-
|
350
|
-
|
330
|
+
Geocoder.configure(
|
331
|
+
ip_lookup: :geoip2,
|
332
|
+
geoip2: {
|
333
|
+
file: Rails.root.join("lib", "GeoLite2-City.mmdb")
|
334
|
+
}
|
335
|
+
)
|
351
336
|
```
|
352
337
|
|
353
|
-
|
338
|
+
If you use Heroku, you can use an unofficial buildpack like [this one](https://github.com/temedica/heroku-buildpack-maxmind-geolite2) to avoid including the database in your repo.
|
354
339
|
|
355
|
-
|
340
|
+
### Token Generation
|
341
|
+
|
342
|
+
Ahoy uses random UUIDs for visit and visitor tokens by default, but you can use your own generator like [Druuid](https://github.com/recurly/druuid).
|
356
343
|
|
357
344
|
```ruby
|
358
|
-
|
345
|
+
Ahoy.token_generator = -> { Druuid.gen }
|
359
346
|
```
|
360
347
|
|
361
|
-
###
|
348
|
+
### Throttling
|
362
349
|
|
363
|
-
|
350
|
+
You can use [Rack::Attack](https://github.com/kickstarter/rack-attack) to throttle requests to the API.
|
364
351
|
|
365
352
|
```ruby
|
366
|
-
class
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
353
|
+
class Rack::Attack
|
354
|
+
throttle("ahoy/ip", limit: 20, period: 1.minute) do |req|
|
355
|
+
if req.path.start_with?("/ahoy/")
|
356
|
+
req.ip
|
357
|
+
end
|
371
358
|
end
|
372
359
|
end
|
373
360
|
```
|
374
361
|
|
375
|
-
###
|
362
|
+
### Exceptions
|
376
363
|
|
377
|
-
|
364
|
+
Exceptions are rescued so analytics do not break your app. Ahoy uses [Safely](https://github.com/ankane/safely) to try to report them to a service by default. To customize this, use:
|
378
365
|
|
379
366
|
```ruby
|
380
|
-
|
367
|
+
Safely.report_exception_method = ->(e) { Rollbar.error(e) }
|
381
368
|
```
|
382
369
|
|
383
|
-
|
370
|
+
## GDPR Compliance
|
371
|
+
|
372
|
+
Ahoy provides a number of options to help with [GDPR compliance](https://en.wikipedia.org/wiki/General_Data_Protection_Regulation).
|
384
373
|
|
385
|
-
|
374
|
+
Update `config/initializers/ahoy.rb` with:
|
386
375
|
|
387
376
|
```ruby
|
388
|
-
Ahoy
|
377
|
+
class Ahoy::Store < Ahoy::DatabaseStore
|
378
|
+
def authenticate(data)
|
379
|
+
# disables automatic linking of visits and users
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
Ahoy.mask_ips = true
|
384
|
+
Ahoy.cookies = false
|
389
385
|
```
|
390
386
|
|
391
|
-
|
387
|
+
This:
|
388
|
+
|
389
|
+
- Masks IP addresses
|
390
|
+
- Switches from cookies to anonymity sets
|
391
|
+
- Disables automatic linking of visits and users
|
392
|
+
|
393
|
+
If you use JavaScript tracking, also set:
|
394
|
+
|
395
|
+
```javascript
|
396
|
+
ahoy.configure({cookies: false});
|
397
|
+
```
|
398
|
+
|
399
|
+
### IP Masking
|
400
|
+
|
401
|
+
Ahoy can mask IPs with the same approach [Google Analytics uses for IP anonymization](https://support.google.com/analytics/answer/2763052). This means:
|
402
|
+
|
403
|
+
- For IPv4, the last octet is set to 0 (`8.8.4.4` becomes `8.8.4.0`)
|
404
|
+
- For IPv6, the last 80 bits are set to zeros (`2001:4860:4860:0:0:0:0:8844` becomes `2001:4860:4860::`)
|
392
405
|
|
393
406
|
```ruby
|
394
|
-
Ahoy.
|
407
|
+
Ahoy.mask_ips = true
|
395
408
|
```
|
396
409
|
|
397
|
-
|
410
|
+
IPs are masked before geolocation is performed.
|
398
411
|
|
399
|
-
|
412
|
+
To mask previously collected IPs, use:
|
400
413
|
|
401
414
|
```ruby
|
402
|
-
Ahoy.
|
415
|
+
Ahoy::Visit.find_each do |visit|
|
416
|
+
visit.update_column :ip, Ahoy.mask_ip(visit.ip)
|
417
|
+
end
|
403
418
|
```
|
404
419
|
|
405
|
-
|
420
|
+
### Anonymity Sets & Cookies
|
406
421
|
|
407
|
-
|
422
|
+
Ahoy can switch from cookies to [anonymity sets](https://privacypatterns.org/patterns/Anonymity-set). Instead of cookies, visitors with the same IP mask and user agent are grouped together in an anonymity set.
|
408
423
|
|
409
424
|
```ruby
|
410
|
-
|
425
|
+
Ahoy.cookies = false
|
411
426
|
```
|
412
427
|
|
428
|
+
Previously set cookies are automatically deleted.
|
429
|
+
|
413
430
|
## Development
|
414
431
|
|
415
|
-
Ahoy is built with developers in mind.
|
432
|
+
Ahoy is built with developers in mind. You can run the following code in your browser’s console.
|
416
433
|
|
417
434
|
Force a new visit
|
418
435
|
|
@@ -432,266 +449,238 @@ Turn off logging
|
|
432
449
|
ahoy.debug(false);
|
433
450
|
```
|
434
451
|
|
435
|
-
Debug
|
452
|
+
Debug API requests in Ruby
|
436
453
|
|
437
454
|
```ruby
|
438
455
|
Ahoy.quiet = false
|
439
456
|
```
|
440
457
|
|
441
|
-
##
|
442
|
-
|
443
|
-
How you explore the data depends on the data store used.
|
444
|
-
|
445
|
-
For SQL databases, you can use [Blazer](https://github.com/ankane/blazer) to easily generate charts and dashboards.
|
458
|
+
## Data Stores
|
446
459
|
|
447
|
-
|
460
|
+
Data tracked by Ahoy is sent to your data store. Ahoy ships with a data store that uses your Rails database by default. You can find it in `config/initializers/ahoy.rb`:
|
448
461
|
|
449
462
|
```ruby
|
450
|
-
|
451
|
-
|
452
|
-
Visit.group(:referring_domain).count
|
453
|
-
```
|
454
|
-
|
455
|
-
[Chartkick](http://chartkick.com/) and [Groupdate](https://github.com/ankane/groupdate) make it easy to visualize the data.
|
456
|
-
|
457
|
-
```erb
|
458
|
-
<%= line_chart Visit.group_by_day(:started_at).count %>
|
463
|
+
class Ahoy::Store < Ahoy::DatabaseStore
|
464
|
+
end
|
459
465
|
```
|
460
466
|
|
461
|
-
|
467
|
+
There are four events data stores can subscribe to:
|
462
468
|
|
463
469
|
```ruby
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
470
|
+
class Ahoy::Store < Ahoy::BaseStore
|
471
|
+
def track_visit(data)
|
472
|
+
# new visit
|
473
|
+
end
|
468
474
|
|
469
|
-
|
475
|
+
def track_event(data)
|
476
|
+
# new event
|
477
|
+
end
|
470
478
|
|
471
|
-
|
472
|
-
|
473
|
-
|
479
|
+
def geocode(data)
|
480
|
+
# visit geocoded
|
481
|
+
end
|
482
|
+
|
483
|
+
def authenticate(data)
|
484
|
+
# user authenticates
|
485
|
+
end
|
474
486
|
end
|
475
487
|
```
|
476
488
|
|
477
|
-
|
489
|
+
Data stores are designed to be highly customizable so you can scale as you grow. Check out [examples](docs/Data-Store-Examples.md) for Kafka, RabbitMQ, Fluentd, NATS, NSQ, and Amazon Kinesis Firehose.
|
478
490
|
|
479
|
-
|
480
|
-
user = User.first
|
481
|
-
user.visits
|
482
|
-
```
|
483
|
-
|
484
|
-
### Create Funnels
|
491
|
+
### Track Additional Data
|
485
492
|
|
486
493
|
```ruby
|
487
|
-
|
488
|
-
|
489
|
-
|
494
|
+
class Ahoy::Store < Ahoy::DatabaseStore
|
495
|
+
def track_visit(data)
|
496
|
+
data[:accept_language] = request.headers["Accept-Language"]
|
497
|
+
super(data)
|
498
|
+
end
|
499
|
+
end
|
490
500
|
```
|
491
501
|
|
492
|
-
|
502
|
+
Two useful methods you can use are `request` and `controller`.
|
493
503
|
|
494
|
-
|
504
|
+
You can pass additional visit data from JavaScript with:
|
495
505
|
|
496
|
-
|
497
|
-
|
498
|
-
```ruby
|
499
|
-
Ahoy::Event.where(name: "Viewed product").where_properties(product_id: 123).count
|
506
|
+
```javascript
|
507
|
+
ahoy.configure({visitParams: {referral_code: 123}});
|
500
508
|
```
|
501
509
|
|
502
|
-
|
510
|
+
And use:
|
503
511
|
|
504
512
|
```ruby
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
513
|
+
class Ahoy::Store < Ahoy::DatabaseStore
|
514
|
+
def track_visit(data)
|
515
|
+
data[:referral_code] = request.parameters[:referral_code]
|
516
|
+
super(data)
|
509
517
|
end
|
510
518
|
end
|
511
519
|
```
|
512
520
|
|
513
|
-
|
514
|
-
|
515
|
-
### Visits
|
516
|
-
|
517
|
-
When a user launches the app, create a visit.
|
518
|
-
|
519
|
-
Generate a `visit_token` and `visitor_token` as [UUIDs](http://en.wikipedia.org/wiki/Universally_unique_identifier).
|
520
|
-
|
521
|
-
Send these values in the `Ahoy-Visit` and `Ahoy-Visitor` headers with all requests.
|
522
|
-
|
523
|
-
Send a `POST` request to `/ahoy/visits` with:
|
524
|
-
|
525
|
-
- platform - `iOS`, `Android`, etc.
|
526
|
-
- app_version - `1.0.0`
|
527
|
-
- os_version - `7.0.6`
|
528
|
-
|
529
|
-
After 4 hours of inactivity, create another visit and use the updated visit id.
|
530
|
-
|
531
|
-
### Events
|
521
|
+
### Use Different Models
|
532
522
|
|
533
|
-
|
523
|
+
```ruby
|
524
|
+
class Ahoy::Store < Ahoy::DatabaseStore
|
525
|
+
def visit_model
|
526
|
+
MyVisit
|
527
|
+
end
|
534
528
|
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
- user token (depends on your authentication framework)
|
529
|
+
def event_model
|
530
|
+
MyEvent
|
531
|
+
end
|
532
|
+
end
|
533
|
+
```
|
541
534
|
|
542
|
-
|
535
|
+
## Explore the Data
|
543
536
|
|
544
|
-
|
537
|
+
[Blazer](https://github.com/ankane/blazer) is a great tool for exploring your data.
|
545
538
|
|
546
|
-
|
539
|
+
With ActiveRecord, you can do:
|
547
540
|
|
548
541
|
```ruby
|
549
|
-
Ahoy.
|
542
|
+
Ahoy::Visit.group(:search_keyword).count
|
543
|
+
Ahoy::Visit.group(:country).count
|
544
|
+
Ahoy::Visit.group(:referring_domain).count
|
550
545
|
```
|
551
546
|
|
552
|
-
|
547
|
+
[Chartkick](https://www.chartkick.com/) and [Groupdate](https://github.com/ankane/groupdate) make it easy to visualize the data.
|
553
548
|
|
554
|
-
|
549
|
+
```erb
|
550
|
+
<%= line_chart Ahoy::Visit.group_by_day(:started_at).count %>
|
551
|
+
```
|
555
552
|
|
556
|
-
|
553
|
+
### Querying Events
|
557
554
|
|
558
|
-
|
555
|
+
Ahoy provides two methods on the event model to make querying easier.
|
559
556
|
|
560
|
-
|
557
|
+
To query on both name and properties, you can use:
|
561
558
|
|
562
559
|
```ruby
|
563
|
-
|
564
|
-
add_column :ahoy_events, :properties, :jsonb
|
560
|
+
Ahoy::Event.where_event("Viewed product", product_id: 123).count
|
565
561
|
```
|
566
562
|
|
567
|
-
|
568
|
-
|
569
|
-
Sync the new column.
|
563
|
+
Or just query properties with:
|
570
564
|
|
571
565
|
```ruby
|
572
|
-
Ahoy::Event.
|
573
|
-
Ahoy::Event.where(id: events.map(&:id)).update_all("properties = properties_json::jsonb")
|
574
|
-
end
|
566
|
+
Ahoy::Event.where_props(product_id: 123).count
|
575
567
|
```
|
576
568
|
|
577
|
-
|
569
|
+
### Funnels
|
570
|
+
|
571
|
+
It’s easy to create funnels.
|
578
572
|
|
579
573
|
```ruby
|
580
|
-
|
574
|
+
viewed_store_ids = Ahoy::Event.where(name: "Viewed store").distinct.pluck(:user_id)
|
575
|
+
added_item_ids = Ahoy::Event.where(user_id: viewed_store_ids, name: "Added item to cart").distinct.pluck(:user_id)
|
576
|
+
viewed_checkout_ids = Ahoy::Event.where(user_id: added_item_ids, name: "Viewed checkout").distinct.pluck(:user_id)
|
581
577
|
```
|
582
578
|
|
583
|
-
|
579
|
+
The same approach also works with visitor tokens.
|
584
580
|
|
585
|
-
|
581
|
+
## Tutorials
|
586
582
|
|
587
|
-
|
588
|
-
class Ahoy::Store < Ahoy::Stores::ActiveRecordTokenStore
|
589
|
-
uses_deprecated_subscribers
|
590
|
-
end
|
591
|
-
```
|
583
|
+
- [Tracking Metrics with Ahoy and Blazer](https://gorails.com/episodes/internal-metrics-with-ahoy-and-blazer)
|
592
584
|
|
593
|
-
|
585
|
+
## API Spec
|
594
586
|
|
595
|
-
|
596
|
-
module Ahoy
|
597
|
-
class Event < ActiveRecord::Base
|
598
|
-
self.table_name = "ahoy_events"
|
587
|
+
### Visits
|
599
588
|
|
600
|
-
|
601
|
-
belongs_to :user, polymorphic: true
|
589
|
+
Generate visit and visitor tokens as [UUIDs](https://en.wikipedia.org/wiki/Universally_unique_identifier), and include these values in the `Ahoy-Visit` and `Ahoy-Visitor` headers with all requests.
|
602
590
|
|
603
|
-
|
604
|
-
end
|
605
|
-
end
|
606
|
-
```
|
591
|
+
Send a `POST` request to `/ahoy/visits` with `Content-Type: application/json` and a body like:
|
607
592
|
|
608
|
-
|
593
|
+
```json
|
594
|
+
{
|
595
|
+
"visit_token": "<visit-token>",
|
596
|
+
"visitor_token": "<visitor-token>",
|
597
|
+
"platform": "iOS",
|
598
|
+
"app_version": "1.0.0",
|
599
|
+
"os_version": "11.2.6"
|
600
|
+
}
|
601
|
+
```
|
609
602
|
|
610
|
-
|
603
|
+
After 4 hours of inactivity, create another visit (use the same visitor token).
|
611
604
|
|
612
|
-
|
605
|
+
### Events
|
613
606
|
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
607
|
+
Send a `POST` request to `/ahoy/events` with `Content-Type: application/json` and a body like:
|
608
|
+
|
609
|
+
```json
|
610
|
+
{
|
611
|
+
"visit_token": "<visit-token>",
|
612
|
+
"visitor_token": "<visitor-token>",
|
613
|
+
"events": [
|
614
|
+
{
|
615
|
+
"id": "<optional-random-id>",
|
616
|
+
"name": "Viewed item",
|
617
|
+
"properties": {
|
618
|
+
"item_id": 123
|
619
|
+
},
|
620
|
+
"time": "2018-01-01T00:00:00-07:00"
|
621
|
+
}
|
622
|
+
]
|
623
|
+
}
|
618
624
|
```
|
619
625
|
|
620
|
-
|
626
|
+
## Upgrading
|
621
627
|
|
622
|
-
|
628
|
+
### 3.0
|
623
629
|
|
624
|
-
If you
|
630
|
+
If you installed Ahoy before 2.1 and want to keep legacy user agent parsing and bot detection, add to your Gemfile:
|
625
631
|
|
626
632
|
```ruby
|
627
|
-
|
628
|
-
|
629
|
-
# code copied from the track method in your subscriber
|
630
|
-
end
|
631
|
-
end
|
633
|
+
gem "browser", "~> 2.0"
|
634
|
+
gem "user_agent_parser"
|
632
635
|
```
|
633
636
|
|
634
|
-
|
635
|
-
|
636
|
-
Ahoy no longer tracks the `$authenticate` event automatically.
|
637
|
-
|
638
|
-
To restore this behavior, use:
|
637
|
+
And add to `config/initializers/ahoy.rb`:
|
639
638
|
|
640
639
|
```ruby
|
641
|
-
|
642
|
-
def authenticate(user)
|
643
|
-
super
|
644
|
-
ahoy.track "$authenticate"
|
645
|
-
end
|
646
|
-
end
|
640
|
+
Ahoy.user_agent_parser = :legacy
|
647
641
|
```
|
648
642
|
|
649
|
-
|
643
|
+
### 2.2
|
650
644
|
|
651
|
-
|
652
|
-
|
653
|
-
Skip this step if you do not use these options.
|
645
|
+
Ahoy now ships with better bot detection if you use Device Detector. This should be more accurate but can significantly reduce the number of visits recorded. For existing installs, it’s opt-in to start. To use it, add to `config/initializers/ahoy.rb`:
|
654
646
|
|
655
647
|
```ruby
|
656
|
-
|
657
|
-
def user
|
658
|
-
# logic from Ahoy.user_method goes here
|
659
|
-
controller.true_user
|
660
|
-
end
|
661
|
-
|
662
|
-
def exclude?
|
663
|
-
# logic from Ahoy.track_bots and Ahoy.exclude_method goes here
|
664
|
-
bot? || request.ip == "192.168.1.1"
|
665
|
-
end
|
666
|
-
end
|
648
|
+
Ahoy.bot_detection_version = 2
|
667
649
|
```
|
668
650
|
|
669
|
-
|
670
|
-
|
671
|
-
### 0.3.0
|
651
|
+
### 2.1
|
672
652
|
|
673
|
-
|
653
|
+
Ahoy recommends [Device Detector](https://github.com/podigee/device_detector) for user agent parsing and makes it the default for new installations. To switch, add to `config/initializers/ahoy.rb`:
|
674
654
|
|
675
|
-
|
655
|
+
```ruby
|
656
|
+
Ahoy.user_agent_parser = :device_detector
|
657
|
+
```
|
676
658
|
|
677
|
-
|
659
|
+
Backfill existing records with:
|
678
660
|
|
679
661
|
```ruby
|
680
|
-
Visit.find_each do |visit|
|
681
|
-
visit.
|
682
|
-
|
662
|
+
Ahoy::Visit.find_each do |visit|
|
663
|
+
client = DeviceDetector.new(visit.user_agent)
|
664
|
+
device_type =
|
665
|
+
case client.device_type
|
666
|
+
when "smartphone"
|
667
|
+
"Mobile"
|
668
|
+
when "tv"
|
669
|
+
"TV"
|
670
|
+
else
|
671
|
+
client.device_type.try(:titleize)
|
672
|
+
end
|
673
|
+
|
674
|
+
visit.browser = client.name
|
675
|
+
visit.os = client.os_name
|
676
|
+
visit.device_type = device_type
|
677
|
+
visit.save(validate: false) if visit.changed?
|
683
678
|
end
|
684
679
|
```
|
685
680
|
|
686
|
-
|
687
|
-
|
688
|
-
- real-time dashboard of visits and events
|
689
|
-
- more events for append only stores
|
690
|
-
- turn off modules
|
691
|
-
|
692
|
-
## No Ruby?
|
681
|
+
### 2.0
|
693
682
|
|
694
|
-
|
683
|
+
See the [upgrade guide](docs/Ahoy-2-Upgrade.md)
|
695
684
|
|
696
685
|
## History
|
697
686
|
|