ahoy_matey 1.5.5 → 4.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +184 -34
  3. data/CONTRIBUTING.md +42 -0
  4. data/LICENSE.txt +1 -1
  5. data/README.md +464 -407
  6. data/app/controllers/ahoy/base_controller.rb +23 -15
  7. data/app/controllers/ahoy/events_controller.rb +8 -2
  8. data/app/controllers/ahoy/visits_controller.rb +8 -1
  9. data/app/jobs/ahoy/geocode_job.rb +11 -0
  10. data/app/jobs/ahoy/geocode_v2_job.rb +31 -0
  11. data/config/routes.rb +1 -1
  12. data/lib/ahoy/base_store.rb +101 -0
  13. data/lib/ahoy/controller.rb +23 -16
  14. data/lib/ahoy/database_store.rb +94 -0
  15. data/lib/ahoy/engine.rb +14 -7
  16. data/lib/ahoy/helper.rb +40 -0
  17. data/lib/ahoy/model.rb +5 -27
  18. data/lib/ahoy/query_methods.rb +88 -0
  19. data/lib/ahoy/tracker.rb +105 -51
  20. data/lib/ahoy/utils.rb +7 -0
  21. data/lib/ahoy/version.rb +1 -1
  22. data/lib/ahoy/visit_properties.rb +99 -37
  23. data/lib/ahoy.rb +83 -93
  24. data/lib/ahoy_matey.rb +1 -1
  25. data/lib/generators/ahoy/activerecord_generator.rb +67 -0
  26. data/lib/generators/ahoy/base_generator.rb +13 -0
  27. data/lib/generators/ahoy/install_generator.rb +44 -0
  28. data/lib/generators/ahoy/mongoid_generator.rb +16 -0
  29. data/lib/generators/ahoy/templates/active_record_event_model.rb.tt +10 -0
  30. data/lib/generators/ahoy/templates/active_record_migration.rb.tt +62 -0
  31. data/lib/generators/ahoy/templates/active_record_visit_model.rb.tt +6 -0
  32. data/lib/generators/ahoy/templates/base_store_initializer.rb.tt +25 -0
  33. data/lib/generators/ahoy/templates/database_store_initializer.rb.tt +10 -0
  34. data/lib/generators/ahoy/{stores/templates/mongoid_event_model.rb → templates/mongoid_event_model.rb.tt} +4 -2
  35. data/lib/generators/ahoy/{stores/templates/mongoid_visit_model.rb → templates/mongoid_visit_model.rb.tt} +15 -9
  36. data/vendor/assets/javascripts/ahoy.js +271 -133
  37. metadata +37 -273
  38. data/.gitignore +0 -17
  39. data/Gemfile +0 -6
  40. data/Rakefile +0 -8
  41. data/ahoy_matey.gemspec +0 -38
  42. data/lib/ahoy/deckhands/location_deckhand.rb +0 -49
  43. data/lib/ahoy/deckhands/request_deckhand.rb +0 -52
  44. data/lib/ahoy/deckhands/technology_deckhand.rb +0 -47
  45. data/lib/ahoy/deckhands/traffic_source_deckhand.rb +0 -22
  46. data/lib/ahoy/deckhands/utm_parameter_deckhand.rb +0 -23
  47. data/lib/ahoy/geocode_job.rb +0 -13
  48. data/lib/ahoy/logger_silencer.rb +0 -75
  49. data/lib/ahoy/properties.rb +0 -58
  50. data/lib/ahoy/stores/active_record_store.rb +0 -61
  51. data/lib/ahoy/stores/active_record_token_store.rb +0 -114
  52. data/lib/ahoy/stores/base_store.rb +0 -88
  53. data/lib/ahoy/stores/bunny_store.rb +0 -33
  54. data/lib/ahoy/stores/fluentd_store.rb +0 -17
  55. data/lib/ahoy/stores/kafka_store.rb +0 -40
  56. data/lib/ahoy/stores/kinesis_firehose_store.rb +0 -42
  57. data/lib/ahoy/stores/log_store.rb +0 -53
  58. data/lib/ahoy/stores/mongoid_store.rb +0 -63
  59. data/lib/ahoy/stores/nats_store.rb +0 -34
  60. data/lib/ahoy/stores/nsq_store.rb +0 -36
  61. data/lib/ahoy/subscribers/active_record.rb +0 -19
  62. data/lib/ahoy/throttle.rb +0 -17
  63. data/lib/generators/ahoy/stores/active_record_events_generator.rb +0 -53
  64. data/lib/generators/ahoy/stores/active_record_generator.rb +0 -16
  65. data/lib/generators/ahoy/stores/active_record_visits_generator.rb +0 -43
  66. data/lib/generators/ahoy/stores/bunny_generator.rb +0 -15
  67. data/lib/generators/ahoy/stores/custom_generator.rb +0 -15
  68. data/lib/generators/ahoy/stores/fluentd_generator.rb +0 -15
  69. data/lib/generators/ahoy/stores/kafka_generator.rb +0 -15
  70. data/lib/generators/ahoy/stores/kinesis_firehose_generator.rb +0 -15
  71. data/lib/generators/ahoy/stores/log_generator.rb +0 -15
  72. data/lib/generators/ahoy/stores/mongoid_events_generator.rb +0 -19
  73. data/lib/generators/ahoy/stores/mongoid_generator.rb +0 -14
  74. data/lib/generators/ahoy/stores/mongoid_visits_generator.rb +0 -27
  75. data/lib/generators/ahoy/stores/nats_generator.rb +0 -15
  76. data/lib/generators/ahoy/stores/nsq_generator.rb +0 -15
  77. data/lib/generators/ahoy/stores/templates/active_record_event_model.rb +0 -12
  78. data/lib/generators/ahoy/stores/templates/active_record_events_migration.rb +0 -19
  79. data/lib/generators/ahoy/stores/templates/active_record_initializer.rb +0 -3
  80. data/lib/generators/ahoy/stores/templates/active_record_visit_model.rb +0 -4
  81. data/lib/generators/ahoy/stores/templates/active_record_visits_migration.rb +0 -57
  82. data/lib/generators/ahoy/stores/templates/bunny_initializer.rb +0 -9
  83. data/lib/generators/ahoy/stores/templates/custom_initializer.rb +0 -10
  84. data/lib/generators/ahoy/stores/templates/fluentd_initializer.rb +0 -3
  85. data/lib/generators/ahoy/stores/templates/kafka_initializer.rb +0 -9
  86. data/lib/generators/ahoy/stores/templates/kinesis_firehose_initializer.rb +0 -17
  87. data/lib/generators/ahoy/stores/templates/log_initializer.rb +0 -3
  88. data/lib/generators/ahoy/stores/templates/mongoid_initializer.rb +0 -3
  89. data/lib/generators/ahoy/stores/templates/nats_initializer.rb +0 -9
  90. data/lib/generators/ahoy/stores/templates/nsq_initializer.rb +0 -9
  91. data/test/properties/mysql_json_test.rb +0 -18
  92. data/test/properties/mysql_text_test.rb +0 -19
  93. data/test/properties/postgresql_hstore_test.rb +0 -18
  94. data/test/properties/postgresql_json_test.rb +0 -18
  95. data/test/properties/postgresql_jsonb_test.rb +0 -18
  96. data/test/properties/postgresql_text_test.rb +0 -19
  97. data/test/test_helper.rb +0 -99
  98. data/test/visit_properties_test.rb +0 -44
data/lib/ahoy.rb CHANGED
@@ -1,69 +1,49 @@
1
+ # stdlib
2
+ require "ipaddr"
3
+
4
+ # dependencies
1
5
  require "active_support"
2
6
  require "active_support/core_ext"
3
- require "addressable/uri"
4
- require "browser"
5
- require "geocoder"
6
- require "referer-parser"
7
- require "user_agent_parser"
8
- require "request_store"
9
- require "uuidtools"
10
7
  require "safely/core"
11
8
 
12
- require "ahoy/version"
13
- require "ahoy/tracker"
14
- require "ahoy/controller"
15
- require "ahoy/model"
16
- require "ahoy/visit_properties"
17
- require "ahoy/properties"
18
- require "ahoy/deckhands/location_deckhand"
19
- require "ahoy/deckhands/request_deckhand"
20
- require "ahoy/deckhands/technology_deckhand"
21
- require "ahoy/deckhands/traffic_source_deckhand"
22
- require "ahoy/deckhands/utm_parameter_deckhand"
23
- require "ahoy/stores/base_store"
24
- require "ahoy/stores/active_record_store"
25
- require "ahoy/stores/active_record_token_store"
26
- require "ahoy/stores/log_store"
27
- require "ahoy/stores/fluentd_store"
28
- require "ahoy/stores/mongoid_store"
29
- require "ahoy/stores/kafka_store"
30
- require "ahoy/stores/nats_store"
31
- require "ahoy/stores/nsq_store"
32
- require "ahoy/stores/kinesis_firehose_store"
33
- require "ahoy/stores/bunny_store"
34
- require "ahoy/engine" if defined?(Rails)
35
- require "ahoy/warden" if defined?(Warden)
36
-
37
- # background jobs
38
- begin
39
- require "active_job"
40
- rescue LoadError
41
- # do nothing
42
- end
43
- require "ahoy/geocode_job" if defined?(ActiveJob)
9
+ # modules
10
+ require_relative "ahoy/utils"
11
+ require_relative "ahoy/base_store"
12
+ require_relative "ahoy/controller"
13
+ require_relative "ahoy/database_store"
14
+ require_relative "ahoy/helper"
15
+ require_relative "ahoy/model"
16
+ require_relative "ahoy/query_methods"
17
+ require_relative "ahoy/tracker"
18
+ require_relative "ahoy/version"
19
+ require_relative "ahoy/visit_properties"
44
20
 
45
- # deprecated
46
- require "ahoy/subscribers/active_record"
21
+ require_relative "ahoy/engine" if defined?(Rails)
47
22
 
48
23
  module Ahoy
49
- UUID_NAMESPACE = UUIDTools::UUID.parse("a82ae811-5011-45ab-a728-569df7499c5f")
50
-
51
24
  mattr_accessor :visit_duration
52
25
  self.visit_duration = 4.hours
53
26
 
54
27
  mattr_accessor :visitor_duration
55
28
  self.visitor_duration = 2.years
56
29
 
30
+ mattr_accessor :cookies
31
+ self.cookies = true
32
+
33
+ # TODO deprecate in favor of cookie_options
57
34
  mattr_accessor :cookie_domain
58
35
 
59
- mattr_accessor :track_visits_immediately
60
- self.track_visits_immediately = false
36
+ mattr_accessor :cookie_options
37
+ self.cookie_options = {}
38
+
39
+ mattr_accessor :server_side_visits
40
+ self.server_side_visits = true
61
41
 
62
42
  mattr_accessor :quiet
63
43
  self.quiet = true
64
44
 
65
45
  mattr_accessor :geocode
66
- self.geocode = true
46
+ self.geocode = false
67
47
 
68
48
  mattr_accessor :max_content_length
69
49
  self.max_content_length = 8192
@@ -71,71 +51,81 @@ module Ahoy
71
51
  mattr_accessor :max_events_per_request
72
52
  self.max_events_per_request = 10
73
53
 
74
- mattr_accessor :mount
75
- self.mount = true
76
-
77
- mattr_accessor :throttle
78
- self.throttle = true
79
-
80
- mattr_accessor :throttle_limit
81
- self.throttle_limit = 20
82
-
83
- mattr_accessor :throttle_period
84
- self.throttle_period = 1.minute
85
-
86
54
  mattr_accessor :job_queue
87
55
  self.job_queue = :ahoy
88
56
 
57
+ mattr_accessor :api
58
+ self.api = false
59
+
89
60
  mattr_accessor :api_only
90
61
  self.api_only = false
91
62
 
92
63
  mattr_accessor :protect_from_forgery
93
- self.protect_from_forgery = false
94
-
95
- def self.ensure_uuid(id)
96
- valid = UUIDTools::UUID.parse(id) rescue nil
97
- if valid
98
- id
99
- else
100
- UUIDTools::UUID.sha1_create(UUID_NAMESPACE, id).to_s
101
- end
102
- end
64
+ self.protect_from_forgery = true
103
65
 
104
- # deprecated
66
+ mattr_accessor :preserve_callbacks
67
+ self.preserve_callbacks = [:load_authlogic, :activate_authlogic]
105
68
 
106
- mattr_accessor :domain
107
- mattr_accessor :visit_model
108
69
  mattr_accessor :user_method
109
- mattr_accessor :exclude_method
70
+ self.user_method = lambda do |controller|
71
+ (controller.respond_to?(:current_user, true) && controller.send(:current_user)) || (controller.respond_to?(:current_resource_owner, true) && controller.send(:current_resource_owner)) || nil
72
+ end
110
73
 
111
- mattr_accessor :subscribers
112
- self.subscribers = []
74
+ mattr_accessor :exclude_method
113
75
 
114
76
  mattr_accessor :track_bots
115
77
  self.track_bots = false
116
- end
117
78
 
118
- if defined?(Rails)
119
- ActiveSupport.on_load(:action_controller) do
120
- ActionController::Base.send :include, Ahoy::Controller
121
- ActionController::API.send :include, Ahoy::Controller if defined?(ActionController::API)
79
+ mattr_accessor :bot_detection_version
80
+ self.bot_detection_version = 2
81
+
82
+ mattr_accessor :token_generator
83
+ self.token_generator = -> { SecureRandom.uuid }
84
+
85
+ mattr_accessor :mask_ips
86
+ self.mask_ips = false
87
+
88
+ mattr_accessor :user_agent_parser
89
+ self.user_agent_parser = :device_detector
90
+
91
+ mattr_accessor :logger
92
+
93
+ def self.log(message)
94
+ logger.info { "[ahoy] #{message}" } if logger
95
+ end
96
+
97
+ def self.mask_ip(ip)
98
+ addr = IPAddr.new(ip)
99
+ if addr.ipv4?
100
+ # set last octet to 0
101
+ addr.mask(24).to_s
102
+ else
103
+ # set last 80 bits to zeros
104
+ addr.mask(48).to_s
105
+ end
122
106
  end
123
107
 
124
- ActiveSupport.on_load(:active_record) do
125
- ActiveRecord::Base.send(:extend, Ahoy::Model)
108
+ def self.instance
109
+ Thread.current[:ahoy]
126
110
  end
127
111
 
128
- # ensure logger silence will not be added by activerecord-session_store
129
- # otherwise, we get SystemStackError: stack level too deep
130
- begin
131
- require "active_record/session_store/extension/logger_silencer"
132
- rescue LoadError
133
- require "ahoy/logger_silencer"
134
- Logger.send :include, Ahoy::LoggerSilencer
135
-
136
- begin
137
- require "syslog/logger"
138
- Syslog::Logger.send :include, Ahoy::LoggerSilencer
139
- rescue LoadError; end
112
+ def self.instance=(value)
113
+ Thread.current[:ahoy] = value
140
114
  end
141
115
  end
116
+
117
+ ActiveSupport.on_load(:action_controller) do
118
+ include Ahoy::Controller
119
+ end
120
+
121
+ ActiveSupport.on_load(:active_record) do
122
+ extend Ahoy::Model
123
+ end
124
+
125
+ ActiveSupport.on_load(:action_view) do
126
+ include Ahoy::Helper
127
+ end
128
+
129
+ ActiveSupport.on_load(:mongoid) do
130
+ Mongoid::Document::ClassMethods.include(Ahoy::Model)
131
+ end
data/lib/ahoy_matey.rb CHANGED
@@ -1 +1 @@
1
- require "ahoy"
1
+ require_relative "ahoy"
@@ -0,0 +1,67 @@
1
+ require "rails/generators"
2
+ require "rails/generators/active_record"
3
+
4
+ module Ahoy
5
+ module Generators
6
+ class ActiverecordGenerator < Rails::Generators::Base
7
+ include ActiveRecord::Generators::Migration
8
+ source_root File.join(__dir__, "templates")
9
+
10
+ class_option :database, type: :string, aliases: "-d"
11
+
12
+ def copy_templates
13
+ template "database_store_initializer.rb", "config/initializers/ahoy.rb"
14
+ template "active_record_visit_model.rb", "app/models/ahoy/visit.rb"
15
+ template "active_record_event_model.rb", "app/models/ahoy/event.rb"
16
+ migration_template "active_record_migration.rb", "db/migrate/create_ahoy_visits_and_events.rb", migration_version: migration_version
17
+ puts "\nAlmost set! Last, run:\n\n rails db:migrate"
18
+ end
19
+
20
+ def properties_type
21
+ case adapter
22
+ when /postg/i # postgres, postgis
23
+ "jsonb"
24
+ when /mysql/i
25
+ "json"
26
+ else
27
+ "text"
28
+ end
29
+ end
30
+
31
+ # requires database connection to check for MariaDB
32
+ def serialize_properties?
33
+ properties_type == "text" || (properties_type == "json" && ActiveRecord::Base.connection.try(:mariadb?))
34
+ end
35
+
36
+ # use connection_config instead of connection.adapter
37
+ # so database connection isn't needed
38
+ def adapter
39
+ if ActiveRecord::VERSION::STRING.to_f >= 6.1
40
+ ActiveRecord::Base.connection_db_config.adapter.to_s
41
+ else
42
+ ActiveRecord::Base.connection_config[:adapter].to_s
43
+ end
44
+ end
45
+
46
+ def rails52?
47
+ ActiveRecord::VERSION::STRING.to_f >= 5.2
48
+ end
49
+
50
+ def migration_version
51
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
52
+ end
53
+
54
+ def primary_key_type
55
+ ", id: :#{key_type}" if key_type
56
+ end
57
+
58
+ def foreign_key_type
59
+ ", type: :#{key_type}" if key_type
60
+ end
61
+
62
+ def key_type
63
+ Rails.configuration.generators.options.dig(:active_record, :primary_key_type)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,13 @@
1
+ require "rails/generators"
2
+
3
+ module Ahoy
4
+ module Generators
5
+ class BaseGenerator < Rails::Generators::Base
6
+ source_root File.join(__dir__, "templates")
7
+
8
+ def copy_templates
9
+ template "base_store_initializer.rb", "config/initializers/ahoy.rb"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,44 @@
1
+ require "rails/generators"
2
+
3
+ module Ahoy
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.join(__dir__, "templates")
7
+
8
+ def copy_templates
9
+ activerecord = defined?(ActiveRecord)
10
+ mongoid = defined?(Mongoid)
11
+
12
+ selection =
13
+ if activerecord && mongoid
14
+ puts <<-MSG
15
+
16
+ Which data store would you like to use?
17
+ 1. ActiveRecord (default)
18
+ 2. Mongoid
19
+ 3. Neither
20
+ MSG
21
+
22
+ ask(">")
23
+ elsif activerecord
24
+ "1"
25
+ elsif mongoid
26
+ "2"
27
+ else
28
+ "3"
29
+ end
30
+
31
+ case selection
32
+ when "", "1"
33
+ invoke "ahoy:activerecord"
34
+ when "2"
35
+ invoke "ahoy:mongoid"
36
+ when "3"
37
+ invoke "ahoy:base"
38
+ else
39
+ abort "Error: must enter a number [1-3]"
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,16 @@
1
+ require "rails/generators"
2
+
3
+ module Ahoy
4
+ module Generators
5
+ class MongoidGenerator < Rails::Generators::Base
6
+ source_root File.join(__dir__, "templates")
7
+
8
+ def copy_templates
9
+ template "database_store_initializer.rb", "config/initializers/ahoy.rb"
10
+ template "mongoid_visit_model.rb", "app/models/ahoy/visit.rb"
11
+ template "mongoid_event_model.rb", "app/models/ahoy/event.rb"
12
+ puts "\nAlmost set! Last, run:\n\n rake db:mongoid:create_indexes"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ class Ahoy::Event < ApplicationRecord
2
+ include Ahoy::QueryMethods
3
+
4
+ self.table_name = "ahoy_events"
5
+
6
+ belongs_to :visit
7
+ belongs_to :user, optional: true<% if serialize_properties? %>
8
+
9
+ serialize :properties, JSON<% end %>
10
+ end
@@ -0,0 +1,62 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
2
+ def change
3
+ create_table :ahoy_visits<%= primary_key_type %> do |t|
4
+ t.string :visit_token
5
+ t.string :visitor_token
6
+
7
+ # the rest are recommended but optional
8
+ # simply remove any you don't want
9
+
10
+ # user
11
+ t.references :user<%= foreign_key_type %>
12
+
13
+ # standard
14
+ t.string :ip
15
+ t.text :user_agent
16
+ t.text :referrer
17
+ t.string :referring_domain
18
+ t.text :landing_page
19
+
20
+ # technology
21
+ t.string :browser
22
+ t.string :os
23
+ t.string :device_type
24
+
25
+ # location
26
+ t.string :country
27
+ t.string :region
28
+ t.string :city
29
+ t.float :latitude
30
+ t.float :longitude
31
+
32
+ # utm parameters
33
+ t.string :utm_source
34
+ t.string :utm_medium
35
+ t.string :utm_term
36
+ t.string :utm_content
37
+ t.string :utm_campaign
38
+
39
+ # native apps
40
+ t.string :app_version
41
+ t.string :os_version
42
+ t.string :platform
43
+
44
+ t.datetime :started_at
45
+ end
46
+
47
+ add_index :ahoy_visits, :visit_token, unique: true
48
+
49
+ create_table :ahoy_events<%= primary_key_type %> do |t|
50
+ t.references :visit<%= foreign_key_type %>
51
+ t.references :user<%= foreign_key_type %>
52
+
53
+ t.string :name
54
+ t.<%= properties_type %> :properties
55
+ t.datetime :time
56
+ end
57
+
58
+ add_index :ahoy_events, [:name, :time]<% if properties_type == "jsonb" %><% if rails52? %>
59
+ add_index :ahoy_events, :properties, using: :gin, opclass: :jsonb_path_ops<% else %>
60
+ add_index :ahoy_events, "properties jsonb_path_ops", using: "gin"<% end %><% end %>
61
+ end
62
+ end
@@ -0,0 +1,6 @@
1
+ class Ahoy::Visit < ApplicationRecord
2
+ self.table_name = "ahoy_visits"
3
+
4
+ has_many :events, class_name: "Ahoy::Event"
5
+ belongs_to :user, optional: true
6
+ end
@@ -0,0 +1,25 @@
1
+ class Ahoy::Store < Ahoy::BaseStore
2
+ def track_visit(data)
3
+ # do
4
+ end
5
+
6
+ def track_event(data)
7
+ # something
8
+ end
9
+
10
+ def geocode(data)
11
+ # amazing
12
+ end
13
+
14
+ def authenticate(data)
15
+ # !!!
16
+ end
17
+ end
18
+
19
+ # set to true for JavaScript tracking
20
+ Ahoy.api = false
21
+
22
+ # set to true for geocoding (and add the geocoder gem to your Gemfile)
23
+ # we recommend configuring local geocoding as well
24
+ # see https://github.com/ankane/ahoy#geocoding
25
+ Ahoy.geocode = false
@@ -0,0 +1,10 @@
1
+ class Ahoy::Store < Ahoy::DatabaseStore
2
+ end
3
+
4
+ # set to true for JavaScript tracking
5
+ Ahoy.api = false
6
+
7
+ # set to true for geocoding (and add the geocoder gem to your Gemfile)
8
+ # we recommend configuring local geocoding as well
9
+ # see https://github.com/ankane/ahoy#geocoding
10
+ Ahoy.geocode = false
@@ -2,11 +2,13 @@ class Ahoy::Event
2
2
  include Mongoid::Document
3
3
 
4
4
  # associations
5
- belongs_to :visit
6
- belongs_to :user
5
+ belongs_to :visit, class_name: "Ahoy::Visit", index: true
6
+ belongs_to :user, index: true, optional: true
7
7
 
8
8
  # fields
9
9
  field :name, type: String
10
10
  field :properties, type: Hash
11
11
  field :time, type: Time
12
+
13
+ index({name: 1, time: 1})
12
14
  end
@@ -1,11 +1,13 @@
1
- class Visit
1
+ class Ahoy::Visit
2
2
  include Mongoid::Document
3
3
 
4
4
  # associations
5
- belongs_to :user
5
+ has_many :events, class_name: "Ahoy::Event"
6
+ belongs_to :user, index: true, optional: true
6
7
 
7
8
  # required
8
- field :visitor_id, type: <%= @visitor_id_type %>
9
+ field :visit_token, type: String
10
+ field :visitor_token, type: String
9
11
 
10
12
  # the rest are recommended but optional
11
13
  # simply remove the columns you don't want
@@ -14,23 +16,20 @@ class Visit
14
16
  field :ip, type: String
15
17
  field :user_agent, type: String
16
18
  field :referrer, type: String
17
- field :landing_page, type: String
18
-
19
- # traffic source
20
19
  field :referring_domain, type: String
21
- field :search_keyword, type: String
20
+ field :landing_page, type: String
22
21
 
23
22
  # technology
24
23
  field :browser, type: String
25
24
  field :os, type: String
26
25
  field :device_type, type: String
27
- field :screen_height, type: Integer
28
- field :screen_width, type: Integer
29
26
 
30
27
  # location
31
28
  field :country, type: String
32
29
  field :region, type: String
33
30
  field :city, type: String
31
+ field :latitude, type: Float
32
+ field :longitude, type: Float
34
33
 
35
34
  # utm parameters
36
35
  field :utm_source, type: String
@@ -39,5 +38,12 @@ class Visit
39
38
  field :utm_content, type: String
40
39
  field :utm_campaign, type: String
41
40
 
41
+ # native apps
42
+ field :app_version, type: String
43
+ field :os_version, type: String
44
+ field :platform, type: String
45
+
42
46
  field :started_at, type: Time
47
+
48
+ index({visit_token: 1}, {unique: true})
43
49
  end