ahoy_matey 1.6.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE.md +7 -0
- data/CHANGELOG.md +22 -0
- data/CONTRIBUTING.md +40 -0
- data/LICENSE.txt +1 -1
- data/README.md +210 -489
- data/Rakefile +1 -0
- data/ahoy_matey.gemspec +6 -8
- data/app/controllers/ahoy/base_controller.rb +2 -6
- data/app/controllers/ahoy/events_controller.rb +7 -1
- data/app/controllers/ahoy/visits_controller.rb +7 -1
- data/app/jobs/ahoy/geocode_job.rb +10 -0
- data/app/jobs/ahoy/geocode_v2_job.rb +29 -0
- data/config/routes.rb +1 -1
- data/docs/Ahoy-2-Upgrade.md +147 -0
- data/docs/Data-Store-Examples.md +240 -0
- data/lib/ahoy.rb +30 -88
- data/lib/ahoy/base_store.rb +72 -0
- data/lib/ahoy/controller.rb +4 -10
- data/lib/ahoy/database_store.rb +72 -0
- data/lib/ahoy/engine.rb +5 -7
- data/lib/ahoy/model.rb +4 -26
- data/lib/ahoy/{properties.rb → query_methods.rb} +18 -4
- data/lib/ahoy/tracker.rb +60 -38
- data/lib/ahoy/version.rb +1 -1
- data/lib/ahoy/visit_properties.rb +65 -39
- data/lib/generators/ahoy/activerecord_generator.rb +58 -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 +20 -0
- data/lib/generators/ahoy/templates/active_record_event_model.rb +10 -0
- data/lib/generators/ahoy/{stores/templates/active_record_visits_migration.rb → templates/active_record_migration.rb} +19 -21
- data/lib/generators/ahoy/templates/active_record_visit_model.rb +6 -0
- data/lib/generators/ahoy/templates/base_store_initializer.rb +17 -0
- data/lib/generators/ahoy/templates/database_store_initializer.rb +5 -0
- data/lib/generators/ahoy/{stores/templates → templates}/mongoid_event_model.rb +4 -2
- data/lib/generators/ahoy/{stores/templates → templates}/mongoid_visit_model.rb +7 -3
- data/test/query_methods/mongoid_test.rb +23 -0
- data/test/{properties → query_methods}/mysql_json_test.rb +1 -1
- data/test/{properties → query_methods}/mysql_text_test.rb +1 -1
- data/test/{properties → query_methods}/postgresql_hstore_test.rb +1 -1
- data/test/{properties → query_methods}/postgresql_json_test.rb +1 -1
- data/test/{properties → query_methods}/postgresql_jsonb_test.rb +1 -1
- data/test/{properties → query_methods}/postgresql_text_test.rb +1 -1
- data/test/test_helper.rb +4 -3
- data/vendor/assets/javascripts/ahoy.js +551 -325
- metadata +67 -112
- 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 -61
- data/lib/ahoy/stores/active_record_token_store.rb +0 -114
- 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 -42
- 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/stores/nats_store.rb +0 -34
- data/lib/ahoy/stores/nsq_store.rb +0 -36
- 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 -59
- data/lib/generators/ahoy/stores/active_record_generator.rb +0 -16
- data/lib/generators/ahoy/stores/active_record_visits_generator.rb +0 -49
- 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/nats_generator.rb +0 -15
- data/lib/generators/ahoy/stores/nsq_generator.rb +0 -15
- 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 -20
- 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/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/lib/generators/ahoy/stores/templates/nats_initializer.rb +0 -9
- data/lib/generators/ahoy/stores/templates/nsq_initializer.rb +0 -9
- data/test/visit_properties_test.rb +0 -44
data/Rakefile
CHANGED
data/ahoy_matey.gemspec
CHANGED
@@ -9,7 +9,6 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Andrew Kane"]
|
10
10
|
spec.email = ["andrew@chartkick.com"]
|
11
11
|
spec.summary = "Simple, powerful visit tracking for Rails"
|
12
|
-
spec.description = "Simple, powerful visit tracking for Rails"
|
13
12
|
spec.homepage = "https://github.com/ankane/ahoy"
|
14
13
|
spec.license = "MIT"
|
15
14
|
|
@@ -18,21 +17,20 @@ Gem::Specification.new do |spec|
|
|
18
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
18
|
spec.require_paths = ["lib"]
|
20
19
|
|
21
|
-
spec.add_dependency "railties"
|
20
|
+
spec.add_dependency "railties", ">= 4.2"
|
22
21
|
spec.add_dependency "addressable"
|
23
|
-
spec.add_dependency "browser", "~> 2.0"
|
24
22
|
spec.add_dependency "geocoder"
|
25
|
-
spec.add_dependency "
|
23
|
+
spec.add_dependency "browser", "~> 2.0"
|
24
|
+
spec.add_dependency "referer-parser", ">= 0.3"
|
26
25
|
spec.add_dependency "user_agent_parser"
|
27
26
|
spec.add_dependency "request_store"
|
28
|
-
spec.add_dependency "
|
29
|
-
spec.add_dependency "safely_block", ">= 0.1.1"
|
30
|
-
spec.add_dependency "rack-attack", "< 6"
|
27
|
+
spec.add_dependency "safely_block", ">= 0.2.1"
|
31
28
|
|
32
|
-
spec.add_development_dependency "bundler"
|
29
|
+
spec.add_development_dependency "bundler"
|
33
30
|
spec.add_development_dependency "rake"
|
34
31
|
spec.add_development_dependency "minitest"
|
35
32
|
spec.add_development_dependency "activerecord"
|
36
33
|
spec.add_development_dependency "pg"
|
37
34
|
spec.add_development_dependency "mysql2"
|
35
|
+
spec.add_development_dependency "mongoid"
|
38
36
|
end
|
@@ -1,18 +1,14 @@
|
|
1
1
|
module Ahoy
|
2
2
|
class BaseController < ApplicationController
|
3
|
-
|
4
|
-
filters = _process_action_callbacks.map(&:filter) - [:load_authlogic]
|
3
|
+
filters = _process_action_callbacks.map(&:filter) - Ahoy.preserve_callbacks
|
5
4
|
if Rails::VERSION::MAJOR >= 5
|
6
5
|
skip_before_action(*filters, raise: false)
|
7
6
|
skip_after_action(*filters, raise: false)
|
8
7
|
skip_around_action(*filters, raise: false)
|
9
8
|
before_action :verify_request_size
|
10
|
-
|
9
|
+
else
|
11
10
|
skip_action_callback *filters
|
12
11
|
before_action :verify_request_size
|
13
|
-
else
|
14
|
-
skip_filter *filters
|
15
|
-
before_filter :verify_request_size
|
16
12
|
end
|
17
13
|
|
18
14
|
if respond_to?(:protect_from_forgery)
|
@@ -8,8 +8,14 @@ module Ahoy
|
|
8
8
|
elsif params[:events]
|
9
9
|
request.params[:events]
|
10
10
|
else
|
11
|
+
data =
|
12
|
+
if params[:events_json]
|
13
|
+
request.params[:events_json]
|
14
|
+
else
|
15
|
+
request.body.read
|
16
|
+
end
|
11
17
|
begin
|
12
|
-
ActiveSupport::JSON.decode(
|
18
|
+
ActiveSupport::JSON.decode(data)
|
13
19
|
rescue ActiveSupport::JSON.parse_error
|
14
20
|
# do nothing
|
15
21
|
[]
|
@@ -2,7 +2,13 @@ module Ahoy
|
|
2
2
|
class VisitsController < BaseController
|
3
3
|
def create
|
4
4
|
ahoy.track_visit
|
5
|
-
render json: {
|
5
|
+
render json: {
|
6
|
+
visit_token: ahoy.visit_token,
|
7
|
+
visitor_token: ahoy.visitor_token,
|
8
|
+
# legacy
|
9
|
+
visit_id: ahoy.visit_token,
|
10
|
+
visitor_id: ahoy.visitor_token
|
11
|
+
}
|
6
12
|
end
|
7
13
|
end
|
8
14
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Ahoy
|
2
|
+
class GeocodeV2Job < ActiveJob::Base
|
3
|
+
queue_as { Ahoy.job_queue }
|
4
|
+
|
5
|
+
def perform(visit_token, ip)
|
6
|
+
location =
|
7
|
+
begin
|
8
|
+
Geocoder.search(ip).first
|
9
|
+
rescue => e
|
10
|
+
$stderr.puts e.message
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
|
14
|
+
if location
|
15
|
+
data = {
|
16
|
+
visit_token: visit_token,
|
17
|
+
country: location.try(:country).presence,
|
18
|
+
region: location.try(:state).presence,
|
19
|
+
city: location.try(:city).presence,
|
20
|
+
postal_code: location.try(:postal_code).presence,
|
21
|
+
latitude: location.try(:latitude).presence,
|
22
|
+
longitude: location.try(:longitude).presence
|
23
|
+
}
|
24
|
+
|
25
|
+
Ahoy::Tracker.new(visit_token: visit_token).geocode(data)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/config/routes.rb
CHANGED
@@ -0,0 +1,147 @@
|
|
1
|
+
# Ahoy 2 Upgrade
|
2
|
+
|
3
|
+
Ahoy 2.0 brings a number of exciting changes:
|
4
|
+
|
5
|
+
- jQuery is no longer required
|
6
|
+
- Uses `navigator.sendBeacon` by default in supported browsers
|
7
|
+
- Simpler interface for data stores
|
8
|
+
|
9
|
+
## How to Upgrade
|
10
|
+
|
11
|
+
Update your Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'ahoy_matey', '~> 2'
|
15
|
+
```
|
16
|
+
|
17
|
+
And run:
|
18
|
+
|
19
|
+
```sh
|
20
|
+
bundle install
|
21
|
+
```
|
22
|
+
|
23
|
+
Add to `config/initializers/ahoy.rb`:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
Ahoy.api = true
|
27
|
+
Ahoy.server_side_visits = false
|
28
|
+
```
|
29
|
+
|
30
|
+
If you use `visitable`, add `class_name` to each instance:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
visitable class_name: "Visit"
|
34
|
+
```
|
35
|
+
|
36
|
+
Then follow the instructions for your data store.
|
37
|
+
|
38
|
+
- [ActiveRecordTokenStore](#activerecordtokenstore)
|
39
|
+
- [ActiveRecordStore](#activerecordstore)
|
40
|
+
- [MongoidStore](#mongoidstore)
|
41
|
+
- [Others](#others)
|
42
|
+
|
43
|
+
## Data Stores
|
44
|
+
|
45
|
+
### ActiveRecordTokenStore
|
46
|
+
|
47
|
+
In `config/initializers/ahoy.rb`, replace `Ahoy::Store` with:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
class Ahoy::Store < Ahoy::DatabaseStore
|
51
|
+
def visit_model
|
52
|
+
Visit
|
53
|
+
end
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
### ActiveRecordStore
|
58
|
+
|
59
|
+
Add [uuidtools](https://github.com/sporkmonger/uuidtools) to your Gemfile.
|
60
|
+
|
61
|
+
In `config/initializers/ahoy.rb`, replace `Ahoy::Store` with:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
class Ahoy::Store < Ahoy::DatabaseStore
|
65
|
+
def track_visit(data)
|
66
|
+
data[:id] = ensure_uuid(data.delete(:visit_token))
|
67
|
+
data[:visitor_id] = ensure_uuid(data.delete(:visitor_token))
|
68
|
+
super(data)
|
69
|
+
end
|
70
|
+
|
71
|
+
def track_event(data)
|
72
|
+
data[:id] = ensure_uuid(data.delete(:event_id))
|
73
|
+
super(data)
|
74
|
+
end
|
75
|
+
|
76
|
+
def visit
|
77
|
+
@visit ||= visit_model.find_by(id: ensure_uuid(ahoy.visit_token)) if ahoy.visit_token
|
78
|
+
end
|
79
|
+
|
80
|
+
def visit_model
|
81
|
+
Visit
|
82
|
+
end
|
83
|
+
|
84
|
+
UUID_NAMESPACE = UUIDTools::UUID.parse("a82ae811-5011-45ab-a728-569df7499c5f")
|
85
|
+
|
86
|
+
def ensure_uuid(id)
|
87
|
+
UUIDTools::UUID.parse(id).to_s
|
88
|
+
rescue
|
89
|
+
UUIDTools::UUID.sha1_create(UUID_NAMESPACE, id).to_s
|
90
|
+
end
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
### MongoidStore
|
95
|
+
|
96
|
+
In `config/initializers/ahoy.rb`, replace `Ahoy::Store` with:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
class Ahoy::Store < Ahoy::DatabaseStore
|
100
|
+
def track_visit(data)
|
101
|
+
data[:_id] = binary_uuid(data.delete(:visit_token))
|
102
|
+
data[:visitor_id] = binary_uuid(data.delete(:visitor_token))
|
103
|
+
super(data)
|
104
|
+
end
|
105
|
+
|
106
|
+
def track_event(data)
|
107
|
+
data[:_id] = binary_uuid(data.delete(:event_id))
|
108
|
+
super(data)
|
109
|
+
end
|
110
|
+
|
111
|
+
def geocode(data)
|
112
|
+
visit_model.where(id: binary_uuid(ahoy.visit_token)).find_one_and_update({"$set": data}, {upsert: true})
|
113
|
+
end
|
114
|
+
|
115
|
+
def visit
|
116
|
+
@visit ||= visit_model.where(id: binary_uuid(ahoy.visit_token)).first if ahoy.visit_token
|
117
|
+
end
|
118
|
+
|
119
|
+
def visit_model
|
120
|
+
Visit
|
121
|
+
end
|
122
|
+
|
123
|
+
def binary_uuid(token)
|
124
|
+
token = token.delete("-")
|
125
|
+
if defined?(::BSON)
|
126
|
+
::BSON::Binary.new(token, :uuid)
|
127
|
+
elsif defined?(::Moped::BSON)
|
128
|
+
::Moped::BSON::Binary.new(:uuid, token)
|
129
|
+
else
|
130
|
+
token
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
```
|
135
|
+
|
136
|
+
### Others
|
137
|
+
|
138
|
+
Check out the [data store examples](Data-Store-Examples.md).
|
139
|
+
|
140
|
+
## Throttling
|
141
|
+
|
142
|
+
Throttling was removed due to limited practical usefulness. See [instructions for adding it back](../README.md#throttling) if you need it.
|
143
|
+
|
144
|
+
## Options
|
145
|
+
|
146
|
+
- The `mount` option was renamed to `api`
|
147
|
+
- The `track_visits_immediately` option was renamed to `server_side_visits`
|
@@ -0,0 +1,240 @@
|
|
1
|
+
# Data Store Examples
|
2
|
+
|
3
|
+
- [Kafka](#kafka)
|
4
|
+
- [RabbitMQ](#rabbitmq)
|
5
|
+
- [Fluentd](#fluentd)
|
6
|
+
- [NATS](#nats)
|
7
|
+
- [NSQ](#nsq)
|
8
|
+
- [Amazon Kinesis Firehose](#amazon-kinesis-firehose)
|
9
|
+
|
10
|
+
### Kafka
|
11
|
+
|
12
|
+
Add [ruby-kafka](https://github.com/zendesk/ruby-kafka) to your Gemfile.
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
class Ahoy::Store < Ahoy::BaseStore
|
16
|
+
def track_visit(data)
|
17
|
+
post("ahoy_visits", data)
|
18
|
+
end
|
19
|
+
|
20
|
+
def track_event(data)
|
21
|
+
post("ahoy_events", data)
|
22
|
+
end
|
23
|
+
|
24
|
+
def geocode(data)
|
25
|
+
post("ahoy_geocode", data)
|
26
|
+
end
|
27
|
+
|
28
|
+
def authenticate(data)
|
29
|
+
post("ahoy_auth", data)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def post(topic, data)
|
35
|
+
producer.produce(data.to_json, topic: topic)
|
36
|
+
end
|
37
|
+
|
38
|
+
def producer
|
39
|
+
@producer ||= begin
|
40
|
+
client =
|
41
|
+
Kafka.new(
|
42
|
+
seed_brokers: ENV["KAFKA_URL"] || "localhost:9092",
|
43
|
+
logger: Rails.logger
|
44
|
+
)
|
45
|
+
producer = client.async_producer(delivery_interval: 3)
|
46
|
+
at_exit { producer.shutdown }
|
47
|
+
producer
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
### RabbitMQ
|
54
|
+
|
55
|
+
Add [bunny](https://github.com/ruby-amqp/bunny) to your Gemfile.
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
class Ahoy::Store < Ahoy::BaseStore
|
59
|
+
def track_visit(data)
|
60
|
+
post("ahoy_visits", data)
|
61
|
+
end
|
62
|
+
|
63
|
+
def track_event(data)
|
64
|
+
post("ahoy_events", data)
|
65
|
+
end
|
66
|
+
|
67
|
+
def geocode(data)
|
68
|
+
post("ahoy_geocode", data)
|
69
|
+
end
|
70
|
+
|
71
|
+
def authenticate(data)
|
72
|
+
post("ahoy_auth", data)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def post(topic, message)
|
78
|
+
channel.queue(topic, durable: true).publish(message.to_json)
|
79
|
+
end
|
80
|
+
|
81
|
+
def channel
|
82
|
+
@channel ||= begin
|
83
|
+
conn = Bunny.new
|
84
|
+
conn.start
|
85
|
+
conn.create_channel
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
91
|
+
### Fluentd
|
92
|
+
|
93
|
+
Add [fluent-logger](https://github.com/fluent/fluent-logger-ruby) to your Gemfile.
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
class Ahoy::Store < Ahoy::BaseStore
|
97
|
+
def track_visit(data)
|
98
|
+
post("ahoy_visits", data)
|
99
|
+
end
|
100
|
+
|
101
|
+
def track_event(data)
|
102
|
+
post("ahoy_events", data)
|
103
|
+
end
|
104
|
+
|
105
|
+
def geocode(data)
|
106
|
+
post("ahoy_geocode", data)
|
107
|
+
end
|
108
|
+
|
109
|
+
def authenticate(data)
|
110
|
+
post("ahoy_auth", data)
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def post(topic, message)
|
116
|
+
logger.post(topic, message)
|
117
|
+
end
|
118
|
+
|
119
|
+
def logger
|
120
|
+
@logger ||= Fluent::Logger::FluentLogger.new("ahoy", host: "localhost", port: 24224)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
### NATS
|
126
|
+
|
127
|
+
Add [nats-pure](https://github.com/nats-io/pure-ruby-nats) to your Gemfile.
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
class Ahoy::Store < Ahoy::BaseStore
|
131
|
+
def track_visit(data)
|
132
|
+
post("ahoy_visits", data)
|
133
|
+
end
|
134
|
+
|
135
|
+
def track_event(data)
|
136
|
+
post("ahoy_events", data)
|
137
|
+
end
|
138
|
+
|
139
|
+
def geocode(data)
|
140
|
+
post("ahoy_geocode", data)
|
141
|
+
end
|
142
|
+
|
143
|
+
def authenticate(data)
|
144
|
+
post("ahoy_auth", data)
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def post(topic, data)
|
150
|
+
client.publish(topic, data.to_json)
|
151
|
+
end
|
152
|
+
|
153
|
+
def client
|
154
|
+
@client ||= begin
|
155
|
+
require "nats/io/client"
|
156
|
+
client = NATS::IO::Client.new
|
157
|
+
client.connect(servers: (ENV["NATS_URL"] || "nats://127.0.0.1:4222").split(","))
|
158
|
+
client
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
```
|
163
|
+
|
164
|
+
### NSQ
|
165
|
+
|
166
|
+
Add [nsq-ruby](https://github.com/wistia/nsq-ruby) to your Gemfile.
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
class Ahoy::Store < Ahoy::BaseStore
|
170
|
+
def track_visit(data)
|
171
|
+
post("ahoy_visits", data)
|
172
|
+
end
|
173
|
+
|
174
|
+
def track_event(data)
|
175
|
+
post("ahoy_events", data)
|
176
|
+
end
|
177
|
+
|
178
|
+
def geocode(data)
|
179
|
+
post("ahoy_geocode", data)
|
180
|
+
end
|
181
|
+
|
182
|
+
def authenticate(data)
|
183
|
+
post("ahoy_auth", data)
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
def post(topic, data)
|
189
|
+
client.write_to_topic(topic, data.to_json)
|
190
|
+
end
|
191
|
+
|
192
|
+
def client
|
193
|
+
@client ||= begin
|
194
|
+
require "nsq"
|
195
|
+
client = Nsq::Producer.new(
|
196
|
+
nsqd: ENV["NSQ_URL"] || "127.0.0.1:4150"
|
197
|
+
)
|
198
|
+
at_exit { client.terminate }
|
199
|
+
client
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
```
|
204
|
+
|
205
|
+
### Amazon Kinesis Firehose
|
206
|
+
|
207
|
+
Add [aws-sdk-firehose](https://github.com/aws/aws-sdk-ruby) to your Gemfile.
|
208
|
+
|
209
|
+
```ruby
|
210
|
+
class Ahoy::Store < Ahoy::BaseStore
|
211
|
+
def track_visit(data)
|
212
|
+
post("ahoy_visits", data)
|
213
|
+
end
|
214
|
+
|
215
|
+
def track_event(data)
|
216
|
+
post("ahoy_events", data)
|
217
|
+
end
|
218
|
+
|
219
|
+
def geocode(data)
|
220
|
+
post("ahoy_geocode", data)
|
221
|
+
end
|
222
|
+
|
223
|
+
def authenticate(data)
|
224
|
+
post("ahoy_auth", data)
|
225
|
+
end
|
226
|
+
|
227
|
+
private
|
228
|
+
|
229
|
+
def post(topic, data)
|
230
|
+
client.put_record(
|
231
|
+
delivery_stream_name: topic,
|
232
|
+
record: {data: "#{data.to_json}\n"}
|
233
|
+
)
|
234
|
+
end
|
235
|
+
|
236
|
+
def client
|
237
|
+
@client ||= Aws::Firehose::Client.new
|
238
|
+
end
|
239
|
+
end
|
240
|
+
```
|