helios-tracker 0.0.0 → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +233 -0
- data/README.md +197 -0
- data/app/controllers/concerns/helios_tracker_concern.rb +17 -0
- data/app/controllers/helios_tracker/api/all_users_controller.rb +21 -0
- data/app/controllers/helios_tracker/api/all_visits_controller.rb +21 -0
- data/app/controllers/helios_tracker/api/base_controller.rb +38 -0
- data/app/controllers/helios_tracker/api/blocked_emails_controller.rb +21 -0
- data/config/routes.rb +7 -0
- data/lib/generators/helios_tracker/install_generator.rb +118 -0
- data/lib/generators/helios_tracker/templates/add_hmid_to_visits.rb.erb +6 -0
- data/lib/generators/helios_tracker/templates/create_blocked_emails.rb.erb +12 -0
- data/lib/generators/helios_tracker/templates/helios_tracker.rb.erb +69 -0
- data/lib/helios-tracker.rb +1 -0
- data/lib/helios_tracker/configuration.rb +124 -0
- data/lib/helios_tracker/version.rb +1 -1
- data/lib/helios_tracker.rb +27 -0
- metadata +21 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bfbf5eff1c6c46819373a06aed86d64e3d0ed9b267fee8832c22ceabd5f0d618
|
|
4
|
+
data.tar.gz: 0c80b7f065b45b086bbfabfa91d3993bab8372cffc6638e100ab9070b5c59375
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 54e55ca996db4f656a856434275b31c9884f91721f999752e49af7c59cd76351430ccee6e857c899914b8ad049030c398b71f79ba2f0e244f3f762b30dda297c
|
|
7
|
+
data.tar.gz: 594d5ae967a43ce5dad2f644f9decd463b47c68af82675cff271a3d9a23b1bddbcd0fbf107611ed9b7c87b2b71745a04fb81c002cc7894b9319282373dececb6
|
data/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
helios-tracker-*.gem
|
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
helios-tracker (0.0.0)
|
|
5
|
+
ffaker (~> 2.16)
|
|
6
|
+
rails (> 5.1)
|
|
7
|
+
universal-track-manager (~> 0.8)
|
|
8
|
+
|
|
9
|
+
GEM
|
|
10
|
+
remote: https://rubygems.org/
|
|
11
|
+
specs:
|
|
12
|
+
action_text-trix (2.1.18)
|
|
13
|
+
railties
|
|
14
|
+
actioncable (8.1.3)
|
|
15
|
+
actionpack (= 8.1.3)
|
|
16
|
+
activesupport (= 8.1.3)
|
|
17
|
+
nio4r (~> 2.0)
|
|
18
|
+
websocket-driver (>= 0.6.1)
|
|
19
|
+
zeitwerk (~> 2.6)
|
|
20
|
+
actionmailbox (8.1.3)
|
|
21
|
+
actionpack (= 8.1.3)
|
|
22
|
+
activejob (= 8.1.3)
|
|
23
|
+
activerecord (= 8.1.3)
|
|
24
|
+
activestorage (= 8.1.3)
|
|
25
|
+
activesupport (= 8.1.3)
|
|
26
|
+
mail (>= 2.8.0)
|
|
27
|
+
actionmailer (8.1.3)
|
|
28
|
+
actionpack (= 8.1.3)
|
|
29
|
+
actionview (= 8.1.3)
|
|
30
|
+
activejob (= 8.1.3)
|
|
31
|
+
activesupport (= 8.1.3)
|
|
32
|
+
mail (>= 2.8.0)
|
|
33
|
+
rails-dom-testing (~> 2.2)
|
|
34
|
+
actionpack (8.1.3)
|
|
35
|
+
actionview (= 8.1.3)
|
|
36
|
+
activesupport (= 8.1.3)
|
|
37
|
+
nokogiri (>= 1.8.5)
|
|
38
|
+
rack (>= 2.2.4)
|
|
39
|
+
rack-session (>= 1.0.1)
|
|
40
|
+
rack-test (>= 0.6.3)
|
|
41
|
+
rails-dom-testing (~> 2.2)
|
|
42
|
+
rails-html-sanitizer (~> 1.6)
|
|
43
|
+
useragent (~> 0.16)
|
|
44
|
+
actiontext (8.1.3)
|
|
45
|
+
action_text-trix (~> 2.1.15)
|
|
46
|
+
actionpack (= 8.1.3)
|
|
47
|
+
activerecord (= 8.1.3)
|
|
48
|
+
activestorage (= 8.1.3)
|
|
49
|
+
activesupport (= 8.1.3)
|
|
50
|
+
globalid (>= 0.6.0)
|
|
51
|
+
nokogiri (>= 1.8.5)
|
|
52
|
+
actionview (8.1.3)
|
|
53
|
+
activesupport (= 8.1.3)
|
|
54
|
+
builder (~> 3.1)
|
|
55
|
+
erubi (~> 1.11)
|
|
56
|
+
rails-dom-testing (~> 2.2)
|
|
57
|
+
rails-html-sanitizer (~> 1.6)
|
|
58
|
+
activejob (8.1.3)
|
|
59
|
+
activesupport (= 8.1.3)
|
|
60
|
+
globalid (>= 0.3.6)
|
|
61
|
+
activemodel (8.1.3)
|
|
62
|
+
activesupport (= 8.1.3)
|
|
63
|
+
activerecord (8.1.3)
|
|
64
|
+
activemodel (= 8.1.3)
|
|
65
|
+
activesupport (= 8.1.3)
|
|
66
|
+
timeout (>= 0.4.0)
|
|
67
|
+
activestorage (8.1.3)
|
|
68
|
+
actionpack (= 8.1.3)
|
|
69
|
+
activejob (= 8.1.3)
|
|
70
|
+
activerecord (= 8.1.3)
|
|
71
|
+
activesupport (= 8.1.3)
|
|
72
|
+
marcel (~> 1.0)
|
|
73
|
+
activesupport (8.1.3)
|
|
74
|
+
base64
|
|
75
|
+
bigdecimal
|
|
76
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
77
|
+
connection_pool (>= 2.2.5)
|
|
78
|
+
drb
|
|
79
|
+
i18n (>= 1.6, < 2)
|
|
80
|
+
json
|
|
81
|
+
logger (>= 1.4.2)
|
|
82
|
+
minitest (>= 5.1)
|
|
83
|
+
securerandom (>= 0.3)
|
|
84
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
|
85
|
+
uri (>= 0.13.1)
|
|
86
|
+
base64 (0.3.0)
|
|
87
|
+
bigdecimal (4.1.2)
|
|
88
|
+
builder (3.3.0)
|
|
89
|
+
concurrent-ruby (1.3.6)
|
|
90
|
+
connection_pool (3.0.2)
|
|
91
|
+
crass (1.0.6)
|
|
92
|
+
date (3.5.1)
|
|
93
|
+
drb (2.2.3)
|
|
94
|
+
erb (6.0.4)
|
|
95
|
+
erubi (1.13.1)
|
|
96
|
+
ffaker (2.25.0)
|
|
97
|
+
globalid (1.3.0)
|
|
98
|
+
activesupport (>= 6.1)
|
|
99
|
+
i18n (1.14.8)
|
|
100
|
+
concurrent-ruby (~> 1.0)
|
|
101
|
+
io-console (0.8.2)
|
|
102
|
+
irb (1.18.0)
|
|
103
|
+
pp (>= 0.6.0)
|
|
104
|
+
prism (>= 1.3.0)
|
|
105
|
+
rdoc (>= 4.0.0)
|
|
106
|
+
reline (>= 0.4.2)
|
|
107
|
+
json (2.19.5)
|
|
108
|
+
logger (1.7.0)
|
|
109
|
+
loofah (2.25.1)
|
|
110
|
+
crass (~> 1.0.2)
|
|
111
|
+
nokogiri (>= 1.12.0)
|
|
112
|
+
mail (2.9.0)
|
|
113
|
+
logger
|
|
114
|
+
mini_mime (>= 0.1.1)
|
|
115
|
+
net-imap
|
|
116
|
+
net-pop
|
|
117
|
+
net-smtp
|
|
118
|
+
marcel (1.1.0)
|
|
119
|
+
mini_mime (1.1.5)
|
|
120
|
+
minitest (6.0.6)
|
|
121
|
+
drb (~> 2.0)
|
|
122
|
+
prism (~> 1.5)
|
|
123
|
+
net-imap (0.6.4)
|
|
124
|
+
date
|
|
125
|
+
net-protocol
|
|
126
|
+
net-pop (0.1.2)
|
|
127
|
+
net-protocol
|
|
128
|
+
net-protocol (0.2.2)
|
|
129
|
+
timeout
|
|
130
|
+
net-smtp (0.5.1)
|
|
131
|
+
net-protocol
|
|
132
|
+
nio4r (2.7.5)
|
|
133
|
+
nokogiri (1.19.3-aarch64-linux-gnu)
|
|
134
|
+
racc (~> 1.4)
|
|
135
|
+
nokogiri (1.19.3-aarch64-linux-musl)
|
|
136
|
+
racc (~> 1.4)
|
|
137
|
+
nokogiri (1.19.3-arm-linux-gnu)
|
|
138
|
+
racc (~> 1.4)
|
|
139
|
+
nokogiri (1.19.3-arm-linux-musl)
|
|
140
|
+
racc (~> 1.4)
|
|
141
|
+
nokogiri (1.19.3-arm64-darwin)
|
|
142
|
+
racc (~> 1.4)
|
|
143
|
+
nokogiri (1.19.3-x86_64-darwin)
|
|
144
|
+
racc (~> 1.4)
|
|
145
|
+
nokogiri (1.19.3-x86_64-linux-gnu)
|
|
146
|
+
racc (~> 1.4)
|
|
147
|
+
nokogiri (1.19.3-x86_64-linux-musl)
|
|
148
|
+
racc (~> 1.4)
|
|
149
|
+
pp (0.6.3)
|
|
150
|
+
prettyprint
|
|
151
|
+
prettyprint (0.2.0)
|
|
152
|
+
prism (1.9.0)
|
|
153
|
+
psych (5.3.1)
|
|
154
|
+
date
|
|
155
|
+
stringio
|
|
156
|
+
racc (1.8.1)
|
|
157
|
+
rack (3.2.6)
|
|
158
|
+
rack-session (2.1.2)
|
|
159
|
+
base64 (>= 0.1.0)
|
|
160
|
+
rack (>= 3.0.0)
|
|
161
|
+
rack-test (2.2.0)
|
|
162
|
+
rack (>= 1.3)
|
|
163
|
+
rackup (2.3.1)
|
|
164
|
+
rack (>= 3)
|
|
165
|
+
rails (8.1.3)
|
|
166
|
+
actioncable (= 8.1.3)
|
|
167
|
+
actionmailbox (= 8.1.3)
|
|
168
|
+
actionmailer (= 8.1.3)
|
|
169
|
+
actionpack (= 8.1.3)
|
|
170
|
+
actiontext (= 8.1.3)
|
|
171
|
+
actionview (= 8.1.3)
|
|
172
|
+
activejob (= 8.1.3)
|
|
173
|
+
activemodel (= 8.1.3)
|
|
174
|
+
activerecord (= 8.1.3)
|
|
175
|
+
activestorage (= 8.1.3)
|
|
176
|
+
activesupport (= 8.1.3)
|
|
177
|
+
bundler (>= 1.15.0)
|
|
178
|
+
railties (= 8.1.3)
|
|
179
|
+
rails-dom-testing (2.3.0)
|
|
180
|
+
activesupport (>= 5.0.0)
|
|
181
|
+
minitest
|
|
182
|
+
nokogiri (>= 1.6)
|
|
183
|
+
rails-html-sanitizer (1.7.0)
|
|
184
|
+
loofah (~> 2.25)
|
|
185
|
+
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
|
186
|
+
railties (8.1.3)
|
|
187
|
+
actionpack (= 8.1.3)
|
|
188
|
+
activesupport (= 8.1.3)
|
|
189
|
+
irb (~> 1.13)
|
|
190
|
+
rackup (>= 1.0.0)
|
|
191
|
+
rake (>= 12.2)
|
|
192
|
+
thor (~> 1.0, >= 1.2.2)
|
|
193
|
+
tsort (>= 0.2)
|
|
194
|
+
zeitwerk (~> 2.6)
|
|
195
|
+
rake (13.4.2)
|
|
196
|
+
rdoc (7.2.0)
|
|
197
|
+
erb
|
|
198
|
+
psych (>= 4.0.0)
|
|
199
|
+
tsort
|
|
200
|
+
reline (0.6.3)
|
|
201
|
+
io-console (~> 0.5)
|
|
202
|
+
securerandom (0.4.1)
|
|
203
|
+
stringio (3.2.0)
|
|
204
|
+
thor (1.5.0)
|
|
205
|
+
timeout (0.6.1)
|
|
206
|
+
tsort (0.2.0)
|
|
207
|
+
tzinfo (2.0.6)
|
|
208
|
+
concurrent-ruby (~> 1.0)
|
|
209
|
+
universal-track-manager (0.8.0.1)
|
|
210
|
+
rails (> 5.1)
|
|
211
|
+
uri (1.1.1)
|
|
212
|
+
useragent (0.16.11)
|
|
213
|
+
websocket-driver (0.8.0)
|
|
214
|
+
base64
|
|
215
|
+
websocket-extensions (>= 0.1.0)
|
|
216
|
+
websocket-extensions (0.1.5)
|
|
217
|
+
zeitwerk (2.7.5)
|
|
218
|
+
|
|
219
|
+
PLATFORMS
|
|
220
|
+
aarch64-linux-gnu
|
|
221
|
+
aarch64-linux-musl
|
|
222
|
+
arm-linux-gnu
|
|
223
|
+
arm-linux-musl
|
|
224
|
+
arm64-darwin
|
|
225
|
+
x86_64-darwin
|
|
226
|
+
x86_64-linux-gnu
|
|
227
|
+
x86_64-linux-musl
|
|
228
|
+
|
|
229
|
+
DEPENDENCIES
|
|
230
|
+
helios-tracker!
|
|
231
|
+
|
|
232
|
+
BUNDLED WITH
|
|
233
|
+
2.6.9
|
data/README.md
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Helios Tracker
|
|
2
|
+
|
|
3
|
+
A Rails engine that exposes your app's user, visit, and email-suppression data as JSON API endpoints for [Helios Crusader](https://heliosflow.ai/) to consume.
|
|
4
|
+
|
|
5
|
+
Helios pulls from these endpoints daily to track signups, logins, click-throughs, and blocked emails — automatically moving targets from cold to warm to hot based on engagement.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
- Rails >= 5.1
|
|
10
|
+
- Ruby >= 2.7
|
|
11
|
+
- [Universal Track Manager](https://github.com/jasonfb/universal_track_manager) (installed automatically)
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
Add to your Gemfile:
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
gem "helios-tracker"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Then run:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
bundle install
|
|
25
|
+
rails generate helios_tracker:install
|
|
26
|
+
rails db:migrate
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The install generator will:
|
|
30
|
+
|
|
31
|
+
1. Install and configure Universal Track Manager (visit tracking)
|
|
32
|
+
2. Add `include UniversalTrackManagerConcern` to your `ApplicationController`
|
|
33
|
+
3. Create a `blocked_emails` migration
|
|
34
|
+
4. Generate `config/initializers/helios_tracker.rb`
|
|
35
|
+
5. Mount the engine in your routes
|
|
36
|
+
|
|
37
|
+
If Universal Track Manager is already installed, the generator will detect it and skip that step.
|
|
38
|
+
|
|
39
|
+
### Generator Options
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
# Specify your User model class (default: "User")
|
|
43
|
+
rails generate helios_tracker:install --user-class=Account
|
|
44
|
+
|
|
45
|
+
# Skip UTM installation if already set up
|
|
46
|
+
rails generate helios_tracker:install --skip-utm
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Configuration
|
|
50
|
+
|
|
51
|
+
Set your API key in your environment (`.env`, credentials, or server config):
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
HELIOS_TRACKER_API_KEY=your_secret_key_here
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Then edit `config/initializers/helios_tracker.rb`:
|
|
58
|
+
|
|
59
|
+
```ruby
|
|
60
|
+
HeliosTracker.configure do |config|
|
|
61
|
+
# ---- Users ----
|
|
62
|
+
|
|
63
|
+
config.user_class_name = "User"
|
|
64
|
+
|
|
65
|
+
# Return users updated since query_start.
|
|
66
|
+
# Receives (query_start, params). Must return an ActiveRecord relation.
|
|
67
|
+
config.user_scope = ->(query_start, params) {
|
|
68
|
+
User.where.not(email: "")
|
|
69
|
+
.where("updated_at > ?", query_start)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# Map API field names to model attributes or lambdas.
|
|
73
|
+
# :email is required. All others are optional.
|
|
74
|
+
config.user_fields = {
|
|
75
|
+
email: :email,
|
|
76
|
+
created_at: :created_at,
|
|
77
|
+
source_ip: :source_ip,
|
|
78
|
+
login_count: :login_count,
|
|
79
|
+
accounts_owned_count: ->(user) { user.accounts_owned_count },
|
|
80
|
+
free_accounts_count: ->(user) { user.free_accounts_count },
|
|
81
|
+
unsubscribe_nonce: :unsubscribe_nonce,
|
|
82
|
+
first_unconfirmed_visit_id: :first_unconfirmed_visit_id,
|
|
83
|
+
login_attempt_count: :login_attempt_count,
|
|
84
|
+
app_open_days_count: :app_open_days_count,
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# ---- Visits ----
|
|
88
|
+
|
|
89
|
+
config.visit_scope = ->(query_start, params) {
|
|
90
|
+
UniversalTrackManager::Visit.where.not(hmid: nil)
|
|
91
|
+
.where("updated_at > ?", query_start)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
# :hmid is required.
|
|
95
|
+
config.visit_fields = {
|
|
96
|
+
hmid: :hmid,
|
|
97
|
+
visited_download_page: ->(visit) { visit.visited_download_page? },
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# ---- Blocked Emails ----
|
|
101
|
+
|
|
102
|
+
config.blocked_email_class_name = "BlockedEmail"
|
|
103
|
+
|
|
104
|
+
config.blocked_email_scope = ->(query_start, params) {
|
|
105
|
+
BlockedEmail.where("created_at > ?", query_start)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
config.blocked_email_fields = {
|
|
109
|
+
email: :email,
|
|
110
|
+
source: :source,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Field Mapping
|
|
117
|
+
|
|
118
|
+
Each field in `user_fields`, `visit_fields`, and `blocked_email_fields` can be either:
|
|
119
|
+
|
|
120
|
+
- **A symbol** — calls that method on the record (e.g., `:email` calls `user.email`)
|
|
121
|
+
- **A lambda** — receives the record and returns a value (e.g., `->(user) { user.accounts.count }`)
|
|
122
|
+
|
|
123
|
+
Fields you don't include in the hash are silently omitted from the API response.
|
|
124
|
+
|
|
125
|
+
### Scoping with Lambdas
|
|
126
|
+
|
|
127
|
+
The `user_scope`, `visit_scope`, and `blocked_email_scope` lambdas receive two arguments:
|
|
128
|
+
|
|
129
|
+
| Argument | Description |
|
|
130
|
+
|---------------|-------------------------------------------------------|
|
|
131
|
+
| `query_start` | A `YYYY-MM-DD` date string sent by Helios |
|
|
132
|
+
| `params` | The full request params (includes `domain_name`, etc.) |
|
|
133
|
+
|
|
134
|
+
Use these to filter your records however your app requires:
|
|
135
|
+
|
|
136
|
+
```ruby
|
|
137
|
+
# Multi-domain example
|
|
138
|
+
config.user_scope = ->(query_start, params) {
|
|
139
|
+
domain = Domain.find_by(name: params[:domain_name])
|
|
140
|
+
User.where.not(email: "")
|
|
141
|
+
.where(domain_id: domain&.id)
|
|
142
|
+
.where("updated_at > ?", query_start)
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## API Endpoints
|
|
147
|
+
|
|
148
|
+
All endpoints require authentication via `HELIOS_TRACKER_API_KEY`, passed as either:
|
|
149
|
+
|
|
150
|
+
- **Header:** `Authorization: Bearer <API_KEY>`
|
|
151
|
+
- **Query parameter:** `?api_key=<API_KEY>`
|
|
152
|
+
|
|
153
|
+
### GET /api/all_users.json
|
|
154
|
+
|
|
155
|
+
Returns users updated since `query_start`.
|
|
156
|
+
|
|
157
|
+
| Parameter | Required | Description |
|
|
158
|
+
|------------- |----------|--------------------------------------|
|
|
159
|
+
| `query_start`| yes | `YYYY-MM-DD` — records from this date onward |
|
|
160
|
+
| `domain_name`| no | Domain filter (if your app is multi-domain) |
|
|
161
|
+
| `api_key` | yes | Shared API key |
|
|
162
|
+
|
|
163
|
+
### GET /api/all_visits.json
|
|
164
|
+
|
|
165
|
+
Returns visits with a non-null `hmid` since `query_start`.
|
|
166
|
+
|
|
167
|
+
| Parameter | Required | Description |
|
|
168
|
+
|------------- |----------|--------------------------------------|
|
|
169
|
+
| `query_start`| yes | `YYYY-MM-DD` — visits from this date onward |
|
|
170
|
+
| `api_key` | yes | Shared API key |
|
|
171
|
+
|
|
172
|
+
### GET /api/blocked_emails.json
|
|
173
|
+
|
|
174
|
+
Returns suppressed emails (bounces, unsubscribes) since `query_start`.
|
|
175
|
+
|
|
176
|
+
| Parameter | Required | Description |
|
|
177
|
+
|------------- |----------|--------------------------------------|
|
|
178
|
+
| `query_start`| yes | `YYYY-MM-DD` — blocks from this date onward |
|
|
179
|
+
| `api_key` | yes | Shared API key |
|
|
180
|
+
|
|
181
|
+
## How It Works
|
|
182
|
+
|
|
183
|
+
Helios calls your endpoints once per day (9:00 AM UTC). Each call includes a `query_start` date — your scopes should return records created or updated on or after that date.
|
|
184
|
+
|
|
185
|
+
**Important for window-based fields:** `login_count`, `accounts_owned_count`, and `app_open_days_count` should return only counts within the `query_start..now` window. Helios accumulates these across successive pulls. Returning lifetime totals will result in double-counting.
|
|
186
|
+
|
|
187
|
+
Helios handles duplicates gracefully (find-or-create logic), so returning the same records on a re-request is safe.
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
MIT License. See [LICENSE](LICENSE) for details.
|
|
192
|
+
|
|
193
|
+
## Links
|
|
194
|
+
|
|
195
|
+
- [Helios Flow](https://heliosflow.ai/)
|
|
196
|
+
- [Universal Track Manager](https://github.com/jasonfb/universal_track_manager)
|
|
197
|
+
- [Source Code](https://github.com/heliosdev-shop/helios-tracker)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module HeliosTrackerConcern
|
|
2
|
+
extend ActiveSupport::Concern
|
|
3
|
+
|
|
4
|
+
included do
|
|
5
|
+
before_action :track_hmid
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def track_hmid
|
|
11
|
+
return unless params['hmid'].present?
|
|
12
|
+
return unless session['visit_id'].present?
|
|
13
|
+
|
|
14
|
+
visit = UniversalTrackManager::Visit.find_by(id: session['visit_id'])
|
|
15
|
+
visit&.update(hmid: params['hmid'])
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module HeliosTracker
|
|
4
|
+
module Api
|
|
5
|
+
class AllUsersController < BaseController
|
|
6
|
+
def index
|
|
7
|
+
return unless require_query_start!
|
|
8
|
+
|
|
9
|
+
config = HeliosTracker.config
|
|
10
|
+
|
|
11
|
+
if config.user_scope.nil?
|
|
12
|
+
render json: { error: 'HeliosTracker.user_scope is not configured' }, status: :internal_server_error
|
|
13
|
+
return
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
users = config.user_scope.call(query_start, params)
|
|
17
|
+
render json: users.map { |user| config.serialize_record(user, config.user_fields) }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module HeliosTracker
|
|
4
|
+
module Api
|
|
5
|
+
class AllVisitsController < BaseController
|
|
6
|
+
def index
|
|
7
|
+
return unless require_query_start!
|
|
8
|
+
|
|
9
|
+
config = HeliosTracker.config
|
|
10
|
+
|
|
11
|
+
if config.visit_scope.nil?
|
|
12
|
+
render json: { error: 'HeliosTracker.visit_scope is not configured' }, status: :internal_server_error
|
|
13
|
+
return
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
visits = config.visit_scope.call(query_start, params)
|
|
17
|
+
render json: visits.map { |visit| config.serialize_record(visit, config.visit_fields) }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module HeliosTracker
|
|
4
|
+
module Api
|
|
5
|
+
class BaseController < ActionController::API
|
|
6
|
+
before_action :authenticate_api!
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def authenticate_api!
|
|
11
|
+
api_key = ENV['HELIOS_TRACKER_API_KEY']
|
|
12
|
+
|
|
13
|
+
if api_key.blank?
|
|
14
|
+
raise "No HELIOS_TRACKER_API_KEY set in environment. Set this in your .env or production config."
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
header_token = request.headers['Authorization']&.sub(/^Bearer\s+/, '')
|
|
18
|
+
|
|
19
|
+
if header_token != api_key && params[:api_key] != api_key
|
|
20
|
+
render json: { error: 'Unauthorized' }, status: :unauthorized
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def query_start
|
|
25
|
+
params[:query_start]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def require_query_start!
|
|
29
|
+
if query_start.blank?
|
|
30
|
+
render json: { error: 'No `query_start` date specified' }, status: :bad_request
|
|
31
|
+
false
|
|
32
|
+
else
|
|
33
|
+
true
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module HeliosTracker
|
|
4
|
+
module Api
|
|
5
|
+
class BlockedEmailsController < BaseController
|
|
6
|
+
def index
|
|
7
|
+
return unless require_query_start!
|
|
8
|
+
|
|
9
|
+
config = HeliosTracker.config
|
|
10
|
+
|
|
11
|
+
if config.blocked_email_scope.nil?
|
|
12
|
+
render json: []
|
|
13
|
+
return
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
records = config.blocked_email_scope.call(query_start, params)
|
|
17
|
+
render json: records.map { |record| config.serialize_record(record, config.blocked_email_fields) }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
require 'rails/generators'
|
|
2
|
+
require 'rails/generators/migration'
|
|
3
|
+
|
|
4
|
+
module HeliosTracker
|
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
|
6
|
+
include Rails::Generators::Migration
|
|
7
|
+
|
|
8
|
+
source_root File.expand_path('templates', __dir__)
|
|
9
|
+
|
|
10
|
+
class_option :user_class, type: :string, default: "User",
|
|
11
|
+
desc: "The name of your User model class"
|
|
12
|
+
|
|
13
|
+
class_option :skip_utm, type: :boolean, default: false,
|
|
14
|
+
desc: "Skip Universal Track Manager installation"
|
|
15
|
+
|
|
16
|
+
def self.next_migration_number(path)
|
|
17
|
+
# Find the highest existing migration number and increment by 1,
|
|
18
|
+
# avoiding collisions with UTM migrations created in the same second.
|
|
19
|
+
existing = Dir.glob("#{path}/[0-9]*_*.rb").map { |f| File.basename(f).split("_", 2).first.to_i }
|
|
20
|
+
candidate = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
|
21
|
+
[candidate, *existing].max + 1
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def install_universal_track_manager
|
|
25
|
+
if options[:skip_utm]
|
|
26
|
+
say "Skipping Universal Track Manager installation (--skip-utm)", :yellow
|
|
27
|
+
return
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
if File.exist?("config/initializers/universal_track_manager.rb")
|
|
31
|
+
say "Universal Track Manager initializer already exists, skipping UTM install", :yellow
|
|
32
|
+
else
|
|
33
|
+
say "Installing Universal Track Manager...", :green
|
|
34
|
+
generate "universal_track_manager:install"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def add_utm_concern_to_application_controller
|
|
39
|
+
if options[:skip_utm]
|
|
40
|
+
say "Skipping UTM concern injection (--skip-utm)", :yellow
|
|
41
|
+
return
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
app_controller = "app/controllers/application_controller.rb"
|
|
45
|
+
if File.exist?(app_controller)
|
|
46
|
+
content = File.read(app_controller)
|
|
47
|
+
if content.include?("UniversalTrackManagerConcern")
|
|
48
|
+
say "UniversalTrackManagerConcern already included in ApplicationController", :yellow
|
|
49
|
+
else
|
|
50
|
+
inject_into_class app_controller, "ApplicationController",
|
|
51
|
+
" include UniversalTrackManagerConcern\n"
|
|
52
|
+
say "Added UniversalTrackManagerConcern to ApplicationController", :green
|
|
53
|
+
end
|
|
54
|
+
else
|
|
55
|
+
say "Could not find #{app_controller} — please add `include UniversalTrackManagerConcern` manually", :red
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def add_helios_tracker_concern_to_application_controller
|
|
60
|
+
app_controller = "app/controllers/application_controller.rb"
|
|
61
|
+
if File.exist?(app_controller)
|
|
62
|
+
content = File.read(app_controller)
|
|
63
|
+
if content.include?("HeliosTrackerConcern")
|
|
64
|
+
say "HeliosTrackerConcern already included in ApplicationController", :yellow
|
|
65
|
+
else
|
|
66
|
+
inject_into_class app_controller, "ApplicationController",
|
|
67
|
+
" include HeliosTrackerConcern\n"
|
|
68
|
+
say "Added HeliosTrackerConcern to ApplicationController", :green
|
|
69
|
+
end
|
|
70
|
+
else
|
|
71
|
+
say "Could not find #{app_controller} — please add `include HeliosTrackerConcern` manually", :red
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def create_add_hmid_to_visits_migration
|
|
76
|
+
migration_template "add_hmid_to_visits.rb.erb",
|
|
77
|
+
"db/migrate/add_hmid_to_visits.rb"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def create_blocked_emails_migration
|
|
81
|
+
migration_template "create_blocked_emails.rb.erb",
|
|
82
|
+
"db/migrate/create_blocked_emails.rb"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def create_initializer
|
|
86
|
+
@user_class = options[:user_class]
|
|
87
|
+
template "helios_tracker.rb.erb", "config/initializers/helios_tracker.rb"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def mount_engine_routes
|
|
91
|
+
route_file = "config/routes.rb"
|
|
92
|
+
content = File.read(route_file)
|
|
93
|
+
if content.include?("mount HeliosTracker::Engine")
|
|
94
|
+
say "HeliosTracker engine already mounted in routes", :yellow
|
|
95
|
+
else
|
|
96
|
+
route "mount HeliosTracker::Engine, at: '/'"
|
|
97
|
+
say "Mounted HeliosTracker::Engine at '/' in routes", :green
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def print_post_install
|
|
102
|
+
say ""
|
|
103
|
+
say "=" * 60, :green
|
|
104
|
+
say "Helios Tracker installed successfully!", :green
|
|
105
|
+
say "=" * 60, :green
|
|
106
|
+
say ""
|
|
107
|
+
say "Next steps:", :yellow
|
|
108
|
+
say " 1. Run `rails db:migrate`"
|
|
109
|
+
say " 2. Set HELIOS_TRACKER_API_KEY in your environment (.env or production config)"
|
|
110
|
+
say " 3. Edit config/initializers/helios_tracker.rb to configure your user scope and fields"
|
|
111
|
+
say " 4. Your API endpoints are now available at:"
|
|
112
|
+
say " GET /api/all_users.json"
|
|
113
|
+
say " GET /api/all_visits.json"
|
|
114
|
+
say " GET /api/blocked_emails.json"
|
|
115
|
+
say ""
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class CreateBlockedEmails < ActiveRecord::Migration<%= "[#{ActiveRecord::Migration.current_version}]" %>
|
|
2
|
+
def change
|
|
3
|
+
create_table :blocked_emails, id: :uuid do |t|
|
|
4
|
+
t.string :email, null: false
|
|
5
|
+
t.string :source, null: false
|
|
6
|
+
t.timestamps
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
add_index :blocked_emails, :email
|
|
10
|
+
add_index :blocked_emails, :created_at
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
HeliosTracker.configure do |config|
|
|
2
|
+
# -----------------------------------------------------------------------
|
|
3
|
+
# User Configuration
|
|
4
|
+
# -----------------------------------------------------------------------
|
|
5
|
+
|
|
6
|
+
# The name of your User model class
|
|
7
|
+
config.user_class_name = "<%= @user_class %>"
|
|
8
|
+
|
|
9
|
+
# A lambda that returns users to expose via GET /api/all_users.json
|
|
10
|
+
# Receives (query_start, params) — query_start is a YYYY-MM-DD string.
|
|
11
|
+
# Must return an ActiveRecord relation.
|
|
12
|
+
config.user_scope = ->(query_start, params) {
|
|
13
|
+
<%= @user_class %>.where.not(email: "")
|
|
14
|
+
.where("updated_at > ?", query_start)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
# Map API response field names to your model's attributes or lambdas.
|
|
18
|
+
# :email is required by the Helios API. All other fields are optional —
|
|
19
|
+
# simply remove any lines you don't need.
|
|
20
|
+
config.user_fields = {
|
|
21
|
+
email: :email,
|
|
22
|
+
created_at: :created_at,
|
|
23
|
+
# source_ip: :source_ip,
|
|
24
|
+
# first_unconfirmed_visit_id: :first_unconfirmed_visit_id,
|
|
25
|
+
# login_attempt_count: :login_attempt_count,
|
|
26
|
+
# login_count: :login_count,
|
|
27
|
+
# accounts_owned_count: ->(user) { user.accounts_owned_count },
|
|
28
|
+
# free_accounts_count: ->(user) { user.free_accounts_count },
|
|
29
|
+
# unsubscribe_nonce: :unsubscribe_nonce,
|
|
30
|
+
# app_open_days_count: :app_open_days_count,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# -----------------------------------------------------------------------
|
|
34
|
+
# Visit Configuration (requires Universal Track Manager)
|
|
35
|
+
# -----------------------------------------------------------------------
|
|
36
|
+
|
|
37
|
+
# A lambda that returns visits to expose via GET /api/all_visits.json
|
|
38
|
+
# Visits with a nil hmid are skipped by Helios, so filter them out here.
|
|
39
|
+
config.visit_scope = ->(query_start, params) {
|
|
40
|
+
UniversalTrackManager::Visit.where.not(hmid: nil)
|
|
41
|
+
.where("updated_at > ?", query_start)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# Map API response field names to your visit model's attributes or lambdas.
|
|
45
|
+
# :hmid is required by the Helios API.
|
|
46
|
+
config.visit_fields = {
|
|
47
|
+
hmid: :hmid,
|
|
48
|
+
# visited_download_page: ->(visit) { visit.visited_download_page? },
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# -----------------------------------------------------------------------
|
|
52
|
+
# Blocked Emails Configuration
|
|
53
|
+
# -----------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
# The class used for blocked/suppressed emails
|
|
56
|
+
config.blocked_email_class_name = "BlockedEmail"
|
|
57
|
+
|
|
58
|
+
# A lambda that returns blocked emails via GET /api/blocked_emails.json
|
|
59
|
+
config.blocked_email_scope = ->(query_start, params) {
|
|
60
|
+
BlockedEmail.where("created_at > ?", query_start)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
config.blocked_email_fields = {
|
|
64
|
+
email: :email,
|
|
65
|
+
source: :source,
|
|
66
|
+
created_at: :created_at,
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "helios_tracker"
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
module HeliosTracker
|
|
2
|
+
class Configuration
|
|
3
|
+
# Required: the User class name as a string, e.g. "User"
|
|
4
|
+
attr_accessor :user_class_name
|
|
5
|
+
|
|
6
|
+
# Required: a lambda that receives (query_start, params) and returns an
|
|
7
|
+
# ActiveRecord relation of user records to expose via the API.
|
|
8
|
+
#
|
|
9
|
+
# Example:
|
|
10
|
+
# config.user_scope = ->(query_start, params) {
|
|
11
|
+
# User.where.not(email: "")
|
|
12
|
+
# .where("updated_at > ?", query_start)
|
|
13
|
+
# }
|
|
14
|
+
attr_accessor :user_scope
|
|
15
|
+
|
|
16
|
+
# Optional: a lambda that receives (query_start, params) and returns an
|
|
17
|
+
# ActiveRecord relation of visit records. Defaults to UTM visits with hmid.
|
|
18
|
+
#
|
|
19
|
+
# Example:
|
|
20
|
+
# config.visit_scope = ->(query_start, params) {
|
|
21
|
+
# UniversalTrackManager::Visit.where.not(hmid: nil)
|
|
22
|
+
# .where("updated_at > ?", query_start)
|
|
23
|
+
# }
|
|
24
|
+
attr_accessor :visit_scope
|
|
25
|
+
|
|
26
|
+
# Optional: a lambda that receives (query_start, params) and returns an
|
|
27
|
+
# ActiveRecord relation of blocked email records.
|
|
28
|
+
#
|
|
29
|
+
# Example:
|
|
30
|
+
# config.blocked_email_scope = ->(query_start, params) {
|
|
31
|
+
# BlockedEmail.where("created_at > ?", query_start)
|
|
32
|
+
# }
|
|
33
|
+
attr_accessor :blocked_email_scope
|
|
34
|
+
|
|
35
|
+
# Optional user fields — map API field names to model attributes or lambdas.
|
|
36
|
+
# :email is always required and included automatically.
|
|
37
|
+
#
|
|
38
|
+
# Example:
|
|
39
|
+
# config.user_fields = {
|
|
40
|
+
# email: :email,
|
|
41
|
+
# created_at: :created_at,
|
|
42
|
+
# source_ip: ->(user) { user.try(:source_ip) },
|
|
43
|
+
# first_unconfirmed_visit_id: :first_unconfirmed_visit_id,
|
|
44
|
+
# login_attempt_count: :login_attempt_count,
|
|
45
|
+
# login_count: :login_count,
|
|
46
|
+
# accounts_owned_count: ->(user) { user.accounts_owned_count },
|
|
47
|
+
# free_accounts_count: ->(user) { user.free_accounts_count },
|
|
48
|
+
# unsubscribe_nonce: :unsubscribe_nonce,
|
|
49
|
+
# app_open_days_count: :app_open_days_count,
|
|
50
|
+
# }
|
|
51
|
+
attr_accessor :user_fields
|
|
52
|
+
|
|
53
|
+
# Optional visit fields — map API field names to model attributes or lambdas.
|
|
54
|
+
# :hmid is always required and included automatically.
|
|
55
|
+
#
|
|
56
|
+
# Example:
|
|
57
|
+
# config.visit_fields = {
|
|
58
|
+
# hmid: :hmid,
|
|
59
|
+
# visited_download_page: ->(visit) { visit.visited_download_page? },
|
|
60
|
+
# }
|
|
61
|
+
attr_accessor :visit_fields
|
|
62
|
+
|
|
63
|
+
# Optional blocked email fields — map API field names to model attributes or lambdas.
|
|
64
|
+
# :email and :source are always required and included automatically.
|
|
65
|
+
#
|
|
66
|
+
# Example:
|
|
67
|
+
# config.blocked_email_fields = {
|
|
68
|
+
# email: :email,
|
|
69
|
+
# source: :source,
|
|
70
|
+
# created_at: :created_at,
|
|
71
|
+
# }
|
|
72
|
+
attr_accessor :blocked_email_fields
|
|
73
|
+
|
|
74
|
+
# Optional: the class name for blocked emails, e.g. "BlockedEmail"
|
|
75
|
+
attr_accessor :blocked_email_class_name
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def initialize
|
|
79
|
+
@user_class_name = "User"
|
|
80
|
+
@blocked_email_class_name = nil
|
|
81
|
+
|
|
82
|
+
@user_fields = {
|
|
83
|
+
email: :email,
|
|
84
|
+
created_at: :created_at,
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@visit_fields = {
|
|
88
|
+
hmid: :hmid,
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@blocked_email_fields = {
|
|
92
|
+
email: :email,
|
|
93
|
+
source: :source,
|
|
94
|
+
created_at: :created_at,
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Default scopes
|
|
98
|
+
@user_scope = nil
|
|
99
|
+
@visit_scope = nil
|
|
100
|
+
@blocked_email_scope = nil
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def user_class
|
|
104
|
+
@user_class_name.constantize
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def blocked_email_class
|
|
108
|
+
return nil unless @blocked_email_class_name
|
|
109
|
+
@blocked_email_class_name.constantize
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Serialize a single record using a fields hash.
|
|
113
|
+
# Fields can be symbols (attribute names) or lambdas.
|
|
114
|
+
def serialize_record(record, fields)
|
|
115
|
+
fields.each_with_object({}) do |(key, mapping), hash|
|
|
116
|
+
hash[key] = if mapping.respond_to?(:call)
|
|
117
|
+
mapping.call(record)
|
|
118
|
+
else
|
|
119
|
+
record.public_send(mapping)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require "helios_tracker/version"
|
|
2
|
+
require "helios_tracker/configuration"
|
|
3
|
+
|
|
4
|
+
# UTM's entry point (universal-track-manager.rb) loads models before defining
|
|
5
|
+
# the module, which breaks on Rails 8+. We pre-define the module so models
|
|
6
|
+
# can reference UniversalTrackManager:: constants, then load the full entry
|
|
7
|
+
# point which brings in models, concerns, and finally reopens the module
|
|
8
|
+
# to add .configure and friends.
|
|
9
|
+
module UniversalTrackManager; end unless defined?(UniversalTrackManager)
|
|
10
|
+
require "universal-track-manager"
|
|
11
|
+
|
|
12
|
+
module HeliosTracker
|
|
13
|
+
class << self
|
|
14
|
+
attr_accessor :configuration
|
|
15
|
+
|
|
16
|
+
def configure
|
|
17
|
+
self.configuration ||= Configuration.new
|
|
18
|
+
yield(configuration)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def config
|
|
22
|
+
configuration || Configuration.new
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
require "helios_tracker/engine" if defined?(Rails::Engine)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: helios-tracker
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jason Fleetwood-Boldt
|
|
@@ -39,19 +39,19 @@ dependencies:
|
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '2.16'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: universal-track-manager
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
47
|
+
version: '0.8'
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '
|
|
54
|
+
version: '0.8'
|
|
55
55
|
description: Tracks click rates, signups, logins, and daily app interactions via REST
|
|
56
56
|
API. Targets automatically move from cold to warm or warm to hot as they engage
|
|
57
57
|
— increasing Crusader send frequency in real time.
|
|
@@ -60,9 +60,25 @@ executables: []
|
|
|
60
60
|
extensions: []
|
|
61
61
|
extra_rdoc_files: []
|
|
62
62
|
files:
|
|
63
|
+
- ".gitignore"
|
|
63
64
|
- ".ruby-version"
|
|
64
65
|
- Gemfile
|
|
66
|
+
- Gemfile.lock
|
|
67
|
+
- README.md
|
|
68
|
+
- app/controllers/concerns/helios_tracker_concern.rb
|
|
69
|
+
- app/controllers/helios_tracker/api/all_users_controller.rb
|
|
70
|
+
- app/controllers/helios_tracker/api/all_visits_controller.rb
|
|
71
|
+
- app/controllers/helios_tracker/api/base_controller.rb
|
|
72
|
+
- app/controllers/helios_tracker/api/blocked_emails_controller.rb
|
|
65
73
|
- config/database.yml
|
|
74
|
+
- config/routes.rb
|
|
75
|
+
- lib/generators/helios_tracker/install_generator.rb
|
|
76
|
+
- lib/generators/helios_tracker/templates/add_hmid_to_visits.rb.erb
|
|
77
|
+
- lib/generators/helios_tracker/templates/create_blocked_emails.rb.erb
|
|
78
|
+
- lib/generators/helios_tracker/templates/helios_tracker.rb.erb
|
|
79
|
+
- lib/helios-tracker.rb
|
|
80
|
+
- lib/helios_tracker.rb
|
|
81
|
+
- lib/helios_tracker/configuration.rb
|
|
66
82
|
- lib/helios_tracker/engine.rb
|
|
67
83
|
- lib/helios_tracker/version.rb
|
|
68
84
|
homepage: https://heliosflow.ai?utm_source=rubygems.org&utm_campaign=rubygems_link
|
|
@@ -80,7 +96,7 @@ post_install_message: |
|
|
|
80
96
|
rails db:migrate
|
|
81
97
|
|
|
82
98
|
Then set your API key in your environment:
|
|
83
|
-
|
|
99
|
+
HELIOS_TRACKER_API_KEY=your_secret_key_here
|
|
84
100
|
|
|
85
101
|
Edit config/initializers/helios_tracker.rb to configure
|
|
86
102
|
your user scope, fields, and visit tracking.
|