ahoy_email 1.1.1 → 2.0.0
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/CHANGELOG.md +15 -0
- data/README.md +159 -147
- data/app/controllers/ahoy/messages_controller.rb +24 -49
- data/config/routes.rb +3 -0
- data/lib/ahoy_email.rb +33 -9
- data/lib/ahoy_email/mailer.rb +45 -17
- data/lib/ahoy_email/message_subscriber.rb +12 -0
- data/lib/ahoy_email/processor.rb +16 -45
- data/lib/ahoy_email/redis_subscriber.rb +79 -0
- data/lib/ahoy_email/tracker.rb +9 -3
- data/lib/ahoy_email/utils.rb +35 -0
- data/lib/ahoy_email/version.rb +1 -1
- data/lib/generators/ahoy/messages/activerecord_generator.rb +40 -0
- data/lib/generators/ahoy/messages/mongoid_generator.rb +21 -0
- data/lib/generators/{ahoy_email/templates/install.rb.tt → ahoy/messages/templates/migration.rb.tt} +1 -1
- data/lib/generators/ahoy/messages/templates/model_encrypted.rb.tt +8 -0
- data/lib/generators/ahoy/messages/templates/mongoid.rb.tt +12 -0
- data/lib/generators/ahoy/messages/templates/mongoid_encrypted.rb.tt +16 -0
- data/lib/generators/ahoy/messages_generator.rb +41 -0
- metadata +12 -88
- data/lib/generators/ahoy_email/install_generator.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d178d2bd4a2631bad0bce962cd35daecc019034270530f350596d14172e46ca0
|
4
|
+
data.tar.gz: af5eb88ec75a4100c5215a71e39fb825d7c7e4823fd601c3cd6473b7409db3dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bcc3ac25d9a8323a4da3a4331a338ca377a375033886c9e447945654897ea3b89e178ffe7a4e02336838ba27e1b8f8dda0aef0f5261f1adb8c66167dbe758f98
|
7
|
+
data.tar.gz: b433434716662eb90d9309c6dfdefe61752496777206e43d1d1d9ddadfee9aa664cf1daa1272d4df62a393d6e979e62932194829dd68b84720fd47661fada6e0
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## 2.0.0 (2021-03-06)
|
2
|
+
|
3
|
+
- Made `to` field encrypted by default for new installations
|
4
|
+
- Added click analytics for Redis
|
5
|
+
- Added send events to subscribers
|
6
|
+
- Removed support for Rails < 5.2
|
7
|
+
|
8
|
+
Breaking changes
|
9
|
+
|
10
|
+
- The `track` method has been broken into `has_history` for message history, `utm_params` for UTM tagging, and `track_clicks` for click analytics
|
11
|
+
- Message history is no longer enabled by default
|
12
|
+
- Open tracking has been removed
|
13
|
+
- `:message` is no longer included in click events
|
14
|
+
- Users are shown a link expired page when signature verification fails instead of being redirected to the homepage when `AhoyEmail.invalid_redirect_url` is not set
|
15
|
+
|
1
16
|
## 1.1.1 (2021-03-06)
|
2
17
|
|
3
18
|
- Added support for classes for subscribers
|
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
First-party email analytics for Rails
|
4
4
|
|
5
|
+
**Ahoy Email 2.0 was recently released** - see [how to upgrade](#upgrading)
|
6
|
+
|
5
7
|
:fire: For web and native app analytics, check out [Ahoy](https://github.com/ankane/ahoy)
|
6
8
|
|
7
9
|
:bullettrain_side: To manage unsubscribes, check out [Mailkick](https://github.com/ankane/mailkick)
|
@@ -16,48 +18,65 @@ Add this line to your application’s Gemfile:
|
|
16
18
|
gem 'ahoy_email'
|
17
19
|
```
|
18
20
|
|
19
|
-
And run the generator. This creates a model to store messages.
|
20
|
-
|
21
|
-
```sh
|
22
|
-
rails generate ahoy_email:install
|
23
|
-
rails db:migrate
|
24
|
-
```
|
25
|
-
|
26
21
|
## Getting Started
|
27
22
|
|
28
|
-
There are three main features:
|
23
|
+
There are three main features, which can be used independently:
|
29
24
|
|
30
25
|
- [Message history](#message-history)
|
31
26
|
- [UTM tagging](#utm-tagging)
|
32
|
-
- [
|
27
|
+
- [Click analytics](#click-analytics)
|
33
28
|
|
34
29
|
## Message History
|
35
30
|
|
36
|
-
|
31
|
+
To encrypt email addresses, install [Lockbox](https://github.com/ankane/lockbox) and [Blind Index](https://github.com/ankane/blind_index) and run:
|
32
|
+
|
33
|
+
```sh
|
34
|
+
rails generate ahoy:messages
|
35
|
+
rails db:migrate
|
36
|
+
```
|
37
|
+
|
38
|
+
If you prefer not to encrypt data, run:
|
39
|
+
|
40
|
+
```sh
|
41
|
+
rails generate ahoy:messages --unencrypted
|
42
|
+
rails db:migrate
|
43
|
+
```
|
44
|
+
|
45
|
+
Then, add to mailers:
|
37
46
|
|
38
47
|
```ruby
|
39
48
|
class CouponMailer < ApplicationMailer
|
40
|
-
|
49
|
+
has_history
|
41
50
|
end
|
42
51
|
```
|
43
52
|
|
44
|
-
|
53
|
+
Use the `Ahoy::Message` model to query messages:
|
45
54
|
|
46
55
|
```ruby
|
47
|
-
|
56
|
+
Ahoy::Message.last
|
48
57
|
```
|
49
58
|
|
50
|
-
|
59
|
+
Use only and except to limit actions
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
class CouponMailer < ApplicationMailer
|
63
|
+
has_history only: [:welcome]
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
To store history for all mailers, create `config/initializers/ahoy_email.rb` with:
|
51
68
|
|
52
|
-
|
69
|
+
```ruby
|
70
|
+
AhoyEmail.default_options[:message] = true
|
71
|
+
```
|
53
72
|
|
54
|
-
|
73
|
+
### Users
|
55
74
|
|
56
|
-
You can pass a specific user with:
|
75
|
+
By default, Ahoy Email tries `@user` then `params[:user]` then `User.find_by(email: message.to)` to find the user. You can pass a specific user with:
|
57
76
|
|
58
77
|
```ruby
|
59
78
|
class CouponMailer < ApplicationMailer
|
60
|
-
|
79
|
+
has_history user: -> { params[:some_user] }
|
61
80
|
end
|
62
81
|
```
|
63
82
|
|
@@ -77,11 +96,9 @@ And run:
|
|
77
96
|
user.messages
|
78
97
|
```
|
79
98
|
|
80
|
-
### Extra
|
99
|
+
### Extra Data
|
81
100
|
|
82
|
-
|
83
|
-
|
84
|
-
Create a migration to add extra attributes to the `ahoy_messages` table. For example:
|
101
|
+
Add extra data to messages. Create a migration like:
|
85
102
|
|
86
103
|
```ruby
|
87
104
|
class AddCouponIdToAhoyMessages < ActiveRecord::Migration[6.1]
|
@@ -91,11 +108,11 @@ class AddCouponIdToAhoyMessages < ActiveRecord::Migration[6.1]
|
|
91
108
|
end
|
92
109
|
```
|
93
110
|
|
94
|
-
|
111
|
+
And use:
|
95
112
|
|
96
113
|
```ruby
|
97
114
|
class CouponMailer < ApplicationMailer
|
98
|
-
|
115
|
+
has_history extra: {coupon_id: 1}
|
99
116
|
end
|
100
117
|
```
|
101
118
|
|
@@ -103,23 +120,53 @@ You can use a proc as well.
|
|
103
120
|
|
104
121
|
```ruby
|
105
122
|
class CouponMailer < ApplicationMailer
|
106
|
-
|
123
|
+
has_history extra: -> { {coupon_id: params[:coupon].id} }
|
107
124
|
end
|
108
125
|
```
|
109
126
|
|
110
|
-
|
127
|
+
### Options
|
111
128
|
|
112
|
-
|
129
|
+
Set global options
|
113
130
|
|
114
|
-
|
115
|
-
|
116
|
-
|
131
|
+
```ruby
|
132
|
+
AhoyEmail.default_options[:user] = -> { params[:admin] }
|
133
|
+
```
|
117
134
|
|
118
|
-
|
135
|
+
Use a different model
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
AhoyEmail.message_model = -> { UserMessage }
|
139
|
+
```
|
140
|
+
|
141
|
+
Or fully customize how messages are tracked
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
AhoyEmail.track_method = lambda do |data|
|
145
|
+
# your code
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
149
|
+
### Data Retention
|
150
|
+
|
151
|
+
Delete older data with:
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
Ahoy::Message.where("created_at < ?", 1.year.ago).in_batches.delete_all
|
155
|
+
```
|
156
|
+
|
157
|
+
Delete data for a specific user with:
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
Ahoy::Message.where(user_id: 1).in_batches.delete_all
|
161
|
+
```
|
162
|
+
|
163
|
+
## UTM Tagging
|
164
|
+
|
165
|
+
Use UTM tagging to attribute visits or conversions to an email campaign. Add UTM parameters to links with:
|
119
166
|
|
120
167
|
```ruby
|
121
168
|
class CouponMailer < ApplicationMailer
|
122
|
-
|
169
|
+
utm_params
|
123
170
|
end
|
124
171
|
```
|
125
172
|
|
@@ -133,7 +180,15 @@ You can customize them with:
|
|
133
180
|
|
134
181
|
```ruby
|
135
182
|
class CouponMailer < ApplicationMailer
|
136
|
-
|
183
|
+
utm_params utm_campaign: -> { "coupon#{params[:coupon].id}" }
|
184
|
+
end
|
185
|
+
```
|
186
|
+
|
187
|
+
Use only and except to limit actions
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
class CouponMailer < ApplicationMailer
|
191
|
+
utm_params only: [:welcome]
|
137
192
|
end
|
138
193
|
```
|
139
194
|
|
@@ -143,40 +198,56 @@ Skip specific links with:
|
|
143
198
|
<%= link_to "Go", some_url, data: {skip_utm_params: true} %>
|
144
199
|
```
|
145
200
|
|
146
|
-
##
|
201
|
+
## Click Analytics
|
147
202
|
|
148
|
-
|
203
|
+
You can track click-through rate to see how well campaigns are performing. Stats can be stored in any data store, and there’s a built-in integration with Redis.
|
149
204
|
|
150
|
-
|
205
|
+
#### Redis
|
151
206
|
|
152
|
-
|
207
|
+
Add this line to your application’s Gemfile:
|
153
208
|
|
154
209
|
```ruby
|
155
|
-
|
156
|
-
|
157
|
-
add_column :ahoy_messages, :token, :string
|
158
|
-
add_index :ahoy_messages, :token
|
210
|
+
gem 'redis'
|
211
|
+
```
|
159
212
|
|
160
|
-
|
161
|
-
add_column :ahoy_messages, :opened_at, :timestamp
|
213
|
+
And create `config/initializers/ahoy_email.rb` with:
|
162
214
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
215
|
+
```ruby
|
216
|
+
# pass your Redis client if you already have one
|
217
|
+
AhoyEmail.subscribers << AhoyEmail::RedisSubscriber.new(redis: Redis.new)
|
218
|
+
AhoyEmail.api = true
|
167
219
|
```
|
168
220
|
|
169
|
-
|
221
|
+
#### Other
|
222
|
+
|
223
|
+
Create `config/initializers/ahoy_email.rb` with:
|
170
224
|
|
171
225
|
```ruby
|
226
|
+
class EmailSubscriber
|
227
|
+
def track_send(data)
|
228
|
+
# your code
|
229
|
+
end
|
230
|
+
|
231
|
+
def track_click(data)
|
232
|
+
# your code
|
233
|
+
end
|
234
|
+
|
235
|
+
def stats(campaign = nil)
|
236
|
+
# optional, for AhoyEmail.stats
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
AhoyEmail.subscribers << EmailSubscriber
|
172
241
|
AhoyEmail.api = true
|
173
|
-
|
242
|
+
````
|
174
243
|
|
175
|
-
|
244
|
+
### Setup
|
245
|
+
|
246
|
+
Add to mailers you want to track
|
176
247
|
|
177
248
|
```ruby
|
178
249
|
class CouponMailer < ApplicationMailer
|
179
|
-
|
250
|
+
track_clicks campaign: "my-campaign"
|
180
251
|
end
|
181
252
|
```
|
182
253
|
|
@@ -184,7 +255,7 @@ Use only and except to limit actions
|
|
184
255
|
|
185
256
|
```ruby
|
186
257
|
class CouponMailer < ApplicationMailer
|
187
|
-
|
258
|
+
track_clicks campaign: "my-campaign", only: [:welcome]
|
188
259
|
end
|
189
260
|
```
|
190
261
|
|
@@ -192,28 +263,10 @@ Or make it conditional
|
|
192
263
|
|
193
264
|
```ruby
|
194
265
|
class CouponMailer < ApplicationMailer
|
195
|
-
|
266
|
+
track_clicks campaign: "my-campaign", if: -> { params[:user].opted_in? }
|
196
267
|
end
|
197
268
|
```
|
198
269
|
|
199
|
-
### How It Works
|
200
|
-
|
201
|
-
For opens, an invisible pixel is added right before the `</body>` tag in HTML emails. If the recipient has images enabled in their email client, the pixel is loaded and the open time recorded.
|
202
|
-
|
203
|
-
For clicks, a redirect is added to links to track clicks in HTML emails.
|
204
|
-
|
205
|
-
```
|
206
|
-
https://chartkick.com
|
207
|
-
```
|
208
|
-
|
209
|
-
becomes
|
210
|
-
|
211
|
-
```
|
212
|
-
https://yoursite.com/ahoy/messages/rAnDoMtOkEn/click?url=https%3A%2F%2Fchartkick.com&signature=...
|
213
|
-
```
|
214
|
-
|
215
|
-
A signature is added to prevent [open redirects](https://www.owasp.org/index.php/Open_redirect).
|
216
|
-
|
217
270
|
Skip specific links with:
|
218
271
|
|
219
272
|
```erb
|
@@ -232,108 +285,67 @@ You can specify the domain to use with:
|
|
232
285
|
AhoyEmail.default_options[:url_options] = {host: "mydomain.com"}
|
233
286
|
```
|
234
287
|
|
235
|
-
###
|
288
|
+
### Stats
|
236
289
|
|
237
|
-
|
290
|
+
Get stats for all campaigns
|
238
291
|
|
239
292
|
```ruby
|
240
|
-
|
241
|
-
def open(event)
|
242
|
-
# your code
|
243
|
-
end
|
244
|
-
|
245
|
-
def click(event)
|
246
|
-
# your code
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
AhoyEmail.subscribers << EmailSubscriber.new
|
293
|
+
AhoyEmail.stats
|
251
294
|
```
|
252
295
|
|
253
|
-
|
296
|
+
Get stats for a specific campaign
|
254
297
|
|
255
298
|
```ruby
|
256
|
-
|
257
|
-
def open(event)
|
258
|
-
event[:controller].ahoy.track "Email opened", message_id: event[:message].id
|
259
|
-
end
|
260
|
-
|
261
|
-
def click(event)
|
262
|
-
event[:controller].ahoy.track "Email clicked", message_id: event[:message].id, url: event[:url]
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
AhoyEmail.subscribers << EmailSubscriber.new
|
299
|
+
AhoyEmail.stats("my-campaign")
|
267
300
|
```
|
268
301
|
|
269
|
-
##
|
270
|
-
|
271
|
-
We recommend encrypting the `to` field (as well as the `subject` if it’s sensitive). [Lockbox](https://github.com/ankane/lockbox) is great for this. Use [Blind Index](https://github.com/ankane/blind_index) if you need to query by the `to` field.
|
302
|
+
## Upgrading
|
272
303
|
|
273
|
-
|
304
|
+
### 2.0
|
274
305
|
|
275
|
-
|
276
|
-
class Ahoy::Message < ApplicationRecord
|
277
|
-
self.table_name = "ahoy_messages"
|
278
|
-
belongs_to :user, polymorphic: true, optional: true
|
306
|
+
Ahoy Email 2.0 brings a number of changes. Here are a few to be aware of:
|
279
307
|
|
280
|
-
|
281
|
-
blind_index :to
|
282
|
-
end
|
283
|
-
```
|
308
|
+
- The `to` field is encrypted by default for new installations. If you’d like to encrypt an existing installation, install [Lockbox](https://github.com/ankane/lockbox) and [Blind Index](https://github.com/ankane/blind_index) and follow the Lockbox instructions for [migrating existing data](https://github.com/ankane/lockbox#migrating-existing-data).
|
284
309
|
|
285
|
-
|
286
|
-
|
287
|
-
Delete older data with:
|
310
|
+
For the model, create `app/models/ahoy/message.rb` with:
|
288
311
|
|
289
|
-
```ruby
|
290
|
-
Ahoy::Message
|
291
|
-
|
292
|
-
|
293
|
-
Delete data for a specific user with:
|
294
|
-
|
295
|
-
```ruby
|
296
|
-
Ahoy::Message.where(user_id: 1).in_batches.delete_all
|
297
|
-
```
|
312
|
+
```ruby
|
313
|
+
class Ahoy::Message < ActiveRecord::Base
|
314
|
+
self.table_name = "ahoy_messages"
|
298
315
|
|
299
|
-
|
316
|
+
belongs_to :user, polymorphic: true, optional: true
|
300
317
|
|
301
|
-
|
318
|
+
encrypts :to, migrating: true
|
319
|
+
blind_index :to, migrating: true
|
320
|
+
end
|
321
|
+
```
|
302
322
|
|
303
|
-
|
304
|
-
AhoyEmail.default_options[:user] = -> { params[:admin] }
|
305
|
-
```
|
323
|
+
- The `track` method has been broken into:
|
306
324
|
|
307
|
-
|
325
|
+
- `has_history` for message history
|
326
|
+
- `utm_params` for UTM tagging
|
327
|
+
- `track_clicks` for click analytics
|
308
328
|
|
309
|
-
|
310
|
-
AhoyEmail.message_model = -> { UserMessage }
|
311
|
-
```
|
329
|
+
- Message history is no longer enabled by default. Add `has_history` to individual mailers, or create an initializer with:
|
312
330
|
|
313
|
-
|
331
|
+
```ruby
|
332
|
+
AhoyEmail.default_options[:message] = true
|
333
|
+
```
|
314
334
|
|
315
|
-
|
316
|
-
AhoyEmail.track_method = lambda do |data|
|
317
|
-
# your code
|
318
|
-
end
|
319
|
-
```
|
335
|
+
- For privacy, open tracking has been removed.
|
320
336
|
|
321
|
-
|
337
|
+
- For clicks, we encourage you to try [aggregate analytics](#click-analytics) to measure the performance of campaigns. You can use a library like [Rollup](https://github.com/ankane/rollup) to aggregate existing data, then drop the `token` and `clicked_at` columns.
|
322
338
|
|
323
|
-
|
339
|
+
To keep individual analytics, use `has_history` and `track_clicks campaign: false` and create an initializer with:
|
324
340
|
|
325
|
-
```ruby
|
326
|
-
|
327
|
-
|
341
|
+
```ruby
|
342
|
+
AhoyEmail.save_token = true
|
343
|
+
AhoyEmail.subscribers << AhoyEmail::MessageSubscriber
|
344
|
+
```
|
328
345
|
|
329
|
-
|
346
|
+
If you use a custom subscriber, `:message` is no longer included in click events. You can use `:token` to query the message if needed.
|
330
347
|
|
331
|
-
|
332
|
-
field :mailer, type: String
|
333
|
-
field :subject, type: String
|
334
|
-
field :sent_at, type: Time
|
335
|
-
end
|
336
|
-
```
|
348
|
+
- Users are shown a link expired page when signature verification fails instead of being redirected to the homepage when `AhoyEmail.invalid_redirect_url` is not set
|
337
349
|
|
338
350
|
## History
|
339
351
|
|