heya 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/LICENSE +85 -0
  4. data/README.md +418 -0
  5. data/Rakefile +14 -14
  6. data/app/mailers/heya/application_mailer.rb +0 -2
  7. data/app/mailers/heya/campaign_mailer.rb +25 -0
  8. data/app/models/heya/campaign_membership.rb +9 -0
  9. data/app/models/heya/campaign_receipt.rb +5 -0
  10. data/app/views/layouts/heya/campaign_mailer.html.erb +20 -0
  11. data/app/views/layouts/heya/campaign_mailer.text.erb +1 -0
  12. data/lib/generators/heya/campaign/USAGE +14 -0
  13. data/lib/generators/heya/campaign/campaign_generator.rb +53 -0
  14. data/lib/generators/heya/campaign/templates/application_campaign.rb.tt +3 -0
  15. data/lib/generators/heya/campaign/templates/campaign.rb.tt +7 -0
  16. data/lib/generators/heya/campaign/templates/message.html.erb.tt +1 -0
  17. data/lib/generators/heya/campaign/templates/message.md.erb.tt +1 -0
  18. data/lib/generators/heya/campaign/templates/message.text.erb.tt +1 -0
  19. data/lib/generators/heya/install/USAGE +10 -0
  20. data/lib/generators/heya/install/install_generator.rb +20 -0
  21. data/lib/generators/heya/install/templates/initializer.rb.tt +16 -0
  22. data/lib/generators/heya/install/templates/migration.rb.tt +28 -0
  23. data/lib/heya.rb +44 -1
  24. data/lib/heya/campaigns/action.rb +27 -0
  25. data/lib/heya/campaigns/actions/block.rb +24 -0
  26. data/lib/heya/campaigns/actions/email.rb +15 -0
  27. data/lib/heya/campaigns/base.rb +151 -0
  28. data/lib/heya/campaigns/queries.rb +118 -0
  29. data/lib/heya/campaigns/scheduler.rb +49 -0
  30. data/lib/heya/campaigns/step.rb +24 -0
  31. data/lib/heya/campaigns/step_action_job.rb +34 -0
  32. data/lib/heya/config.rb +17 -0
  33. data/lib/heya/engine.rb +14 -0
  34. data/lib/heya/version.rb +3 -1
  35. data/lib/tasks/heya_tasks.rake +8 -4
  36. metadata +58 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31df70e142e32c3d79397c994570de6bd19fec01fd3b04c146b452419c7ef7b6
4
- data.tar.gz: afb0e7fc1f321d35d3356a6883129e409b4ae405d2308c1c0d977ed8eaabc942
3
+ metadata.gz: 1aedd0a6d25dc8185eacb59e5e279f6dc6c2135d3980005c1d5b5c82a351c403
4
+ data.tar.gz: c6007415e758afe5d998ebbe1e9b8ae920e25e4c6abffa9da6c6a9fb1d713ae7
5
5
  SHA512:
6
- metadata.gz: 8762c62996f777c88e3942a1d12d62577bce5c33bbca4892d342a0556fb2d6f487276cd4600889761e6c49c43ae16cf6ded8be11288487727e9dab9d7544c91f
7
- data.tar.gz: 47f7a5b4bf54b2f9b6479ed0a723486be0e8bdca8d94f3c62c4c36cbf716058b6b4e830ce6c4eaa45c805b22eeaaff1d54d124f3bffd0d6aa06e6563e9f36f5c
6
+ metadata.gz: fce537c6eefe599dd9aa3b2be7fdb2c7ce0839c15a7e82256aaf168691103a57ee4e76b146d5cc8d91e7111b546ecbde3041e01e98ff59ac98ef74ce42935fb0
7
+ data.tar.gz: bceb804f1400eccc44cbacd182007160bbec6b5595613224fff5792596b2661abeeb259bc36e7222bc043cf341754fa8cffb33462828836978fb980b75d5d453
@@ -0,0 +1,11 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.0] - 2020-03-19
10
+ ### Added
11
+ - Initial release. 👋
data/LICENSE ADDED
@@ -0,0 +1,85 @@
1
+ # The Prosperity Public License 3.0.0
2
+
3
+ Contributor: Honeybadger Industries LLC
4
+
5
+ Source Code: https://github.com/honeybadger-io/heya
6
+
7
+ ## Purpose
8
+
9
+ This license allows you to use and share this software for noncommercial
10
+ purposes for free and to try this software for commercial purposes for thirty
11
+ days.
12
+
13
+ ## Agreement
14
+
15
+ In order to receive this license, you have to agree to its rules. Those rules
16
+ are both obligations under that agreement and conditions to your license.
17
+ Don't do anything with this software that triggers a rule you can't or won't
18
+ follow.
19
+
20
+ ## Notices
21
+
22
+ Make sure everyone who gets a copy of any part of this software from you, with
23
+ or without changes, also gets the text of this license and the contributor and
24
+ source code lines above.
25
+
26
+ ## Commercial Trial
27
+
28
+ Limit your use of this software for commercial purposes to a thirty-day trial
29
+ period. If you use this software for work, your company gets one trial period
30
+ for all personnel, not one trial per person.
31
+
32
+ ## Contributions Back
33
+
34
+ Developing feedback, changes, or additions that you contribute back to the
35
+ contributor on the terms of a standardized public software license such as [the
36
+ Blue Oak Model License 1.0.0](https://blueoakcouncil.org/license/1.0.0), [the
37
+ Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html), [the MIT
38
+ license](https://spdx.org/licenses/MIT.html), or [the two-clause BSD
39
+ license](https://spdx.org/licenses/BSD-2-Clause.html) doesn't count as use for
40
+ a commercial purpose.
41
+
42
+ ## Personal Uses
43
+
44
+ Personal use for research, experiment, and testing for the benefit of public
45
+ knowledge, personal study, private entertainment, hobby projects, amateur
46
+ pursuits, or religious observance, without any anticipated commercial
47
+ application, doesn't count as use for a commercial purpose.
48
+
49
+ ## Noncommercial Organizations
50
+
51
+ Use by any charitable organization, educational institution, public research
52
+ organization, public safety or health organization, environmental protection
53
+ organization, or government institution doesn't count as use for a commercial
54
+ purpose regardless of the source of funding or obligations resulting from the
55
+ funding.
56
+
57
+ ## Defense
58
+
59
+ Don't make any legal claim against anyone accusing this software, with or
60
+ without changes, alone or with other technology, of infringing any patent.
61
+
62
+ ## Copyright
63
+
64
+ The contributor licenses you to do everything with this software that would
65
+ otherwise infringe their copyright in it.
66
+
67
+ ## Patent
68
+
69
+ The contributor licenses you to do everything with this software that would
70
+ otherwise infringe any patents they can license or become able to license.
71
+
72
+ ## Reliability
73
+
74
+ The contributor can't revoke this license.
75
+
76
+ ## Excuse
77
+
78
+ You're excused for unknowingly breaking [Notices](#notices) if you take all
79
+ practical steps to comply within thirty days of learning you broke the rule.
80
+
81
+ ## No Liability
82
+
83
+ ***As far as the law allows, this software comes as is, without any warranty or
84
+ condition, and the contributor won't be liable to anyone for any damages
85
+ related to this software or this license, under any kind of legal claim.***
@@ -0,0 +1,418 @@
1
+ # Heya 👋
2
+ ![Test](https://github.com/honeybadger-io/heya/workflows/Test/badge.svg)
3
+ [![Maintainability](https://api.codeclimate.com/v1/badges/a6416e63ffc426715857/maintainability)](https://codeclimate.com/github/honeybadger-io/heya/maintainability)
4
+
5
+ Heya is a customer communication and automation framework for Ruby on Rails. It's as robust as the hosted alternatives, without the integration and compliance nightmare.
6
+
7
+ ## Why Heya?
8
+ Imagine onboarding and engaging your users with full access to their data, without maintaining a single 3rd-party integration or stressing over compliance. That's Heya: a new way to email your users.
9
+
10
+ Heya lives inside your Rails app, giving you full access to your customer data with the power of Ruby and Rails for building automated email campaigns.
11
+
12
+ If you've ever used 3rd-party email or marketing platforms, you've felt the pain of integrating, syncing customer data, and maintaining complex logic and rules--all of which is unnecessary in Heya.
13
+
14
+ Email automation becomes startlingly simple when your application framework *is* your automation tool.
15
+
16
+ ## Who is Heya for?
17
+ - SaaS developers who are marketers at heart
18
+ - SaaS marketers who are developers at heart
19
+ - Development and marketing teams who work closely together
20
+
21
+ ## Stuff we believe
22
+ - You should avoid duplicating customer data
23
+ - Segments should live as close to home as possible
24
+ - So should automation
25
+ - So should content
26
+ - Code is for everyone, not just developers
27
+ - Heya is the best way to engage your users
28
+
29
+ ## Getting started
30
+ Getting started with Heya is easy:
31
+
32
+ 1. [Install the gem](#installing-the-heya-gem)
33
+ 2. [Create a campaign](#creating-your-first-campaign)
34
+ 3. [Run the scheduler](#running-the-scheduler)
35
+
36
+ ### Installing the Heya gem
37
+ 1. Add this line to your application's Gemfile:
38
+
39
+ ```ruby
40
+ gem "heya", github: "honeybadger-io/heya"
41
+ ```
42
+
43
+ 2. Then execute:
44
+
45
+ ```bash
46
+ bundle install
47
+ rails generate heya:install
48
+ rails db:migrate
49
+ ```
50
+
51
+ This will do 3 things:
52
+
53
+ 1. Copy Heya's migration files to *db/migrate*
54
+ 2. Copy Heya's default initializer to *config/initializers/heya.rb*
55
+ 3. Run local migrations
56
+
57
+ <details><summary>Note: Heya doesn't store a copy of your user data; instead, it reads from your existing <code>User</code> model (it never writes). If you have a different user model, change the <code>user_type</code> configuration option in <em>config/initializers/heya.rb</em>.</summary>
58
+
59
+ ```ruby
60
+ # config/initializers/heya.rb
61
+ Heya.configure do |config|
62
+ config.user_type = "MyUser"
63
+ end
64
+ ```
65
+ </details>
66
+
67
+ ### Creating your first campaign
68
+ 1. Create a campaign:
69
+
70
+ ```bash
71
+ rails generate heya:campaign Onboarding welcome
72
+ ```
73
+
74
+ 2. Add a user to your campaign:
75
+
76
+ ```ruby
77
+ OnboardingCampaign.add(user)
78
+ ```
79
+
80
+ ### Running the scheduler
81
+ To start sending emails, run the scheduler periodically:
82
+
83
+ ```bash
84
+ rails heya:scheduler
85
+ ```
86
+
87
+ ## Configuration
88
+
89
+ You can use the following options to configure Heya (find this file in
90
+ *config/initializers/heya.rb*):
91
+
92
+ ```ruby
93
+ Heya.configure do |config|
94
+ # The name of the model you want to use with Heya.
95
+ config.user_type = "User"
96
+
97
+ # The default options to use when processing campaign steps.
98
+ config.campaigns.default_options = {from: "user@example.com"}
99
+
100
+ # Campaign priority. When a user is added to multiple campaigns, they are
101
+ # sent in this order. Campaigns are sent in the order that the users were
102
+ # added if no priority is configured.
103
+ config.campaigns.priority = [
104
+ "FirstCampaign",
105
+ "SecondCampaign",
106
+ "ThirdCampaign"
107
+ ]
108
+ end
109
+ ```
110
+
111
+ ## Campaigns
112
+
113
+ ### Creating campaigns
114
+ Heya stores campaigns in *app/campaigns/*, similar to how Rails stores mailers in *app/mailers/*. To create a campaign, run the following command inside your Rails project:
115
+
116
+ ```bash
117
+ rails generate heya:campaign Onboarding first second third
118
+ ```
119
+
120
+ This will do three things:
121
+
122
+ - Create the file *app/campaigns/onboarding_campaign.rb*
123
+ - Create the directory *app/views/heya/campaign_mailer/onboarding_campaign/*
124
+ - Create email templates inside of *app/views/heya/campaign_mailer/onboarding_campaign/*
125
+
126
+ Here's the campaign that the above command generates:
127
+
128
+ ```ruby
129
+ # app/campaigns/application_campaign.rb
130
+ class ApplicationCampaign < Heya::Campaigns::Base
131
+ default from: "from@example.com"
132
+ end
133
+
134
+ # app/campaigns/onboarding_campaign.rb
135
+ class OnboardingCampaign < ApplicationCampaign
136
+ step :first,
137
+ subject: "First subject"
138
+
139
+ step :second,
140
+ subject: "Second subject"
141
+
142
+ step :third,
143
+ subject: "Third subject"
144
+ end
145
+ ```
146
+
147
+ #### Steps
148
+ The `step` method defines a new step in the sequence. When you add a user to the campaign, Heya completes each step in the order that it appears.
149
+
150
+ The default time to wait between steps is *two days*, calculated from the time the user completed the previous step (or the time the user entered the campaign, in the case of the first step).
151
+
152
+ Each step has several options available (see the section [Creating messages](#creating-messages)).
153
+
154
+ ### Creating messages
155
+ Messages are defined inside Heya campaigns using the `step` method. When you add a user to a campaign, Heya completes each step in the order that it appears.
156
+
157
+ **The most important part of each step is its name, which must be unique to the campaign.** The step's name is how Heya tracks which user has received which message, so it's essential that you don't change it after the campaign is active (if you do, Heya will assume it's a new message).
158
+
159
+ Here's an example of defining a message inside a campaign:
160
+
161
+ ```ruby
162
+ class OnboardingCampaign < ApplicationCampaign
163
+ step :welcome, wait: 1.day,
164
+ subject: "Welcome to my app!"
165
+ end
166
+ ```
167
+
168
+ In the above example, Heya will send a message named `:welcome` one day after a user enters the campaign, with the subject "Welcome to my app!"
169
+
170
+ The `wait` option tells Heya how long to wait before sending each message (the default is two days). There are a few scheduling options that you can customize for each step:
171
+
172
+ | Option Name | Default | Description |
173
+ |:--|:--|:--|
174
+ | `wait` | `2.days` | The duration of time to wait before sending each message |
175
+ | `segment` | `nil` | The segment who should receive the message |
176
+ | `action` | `Heya::Campaigns::Actions::Email` | The action to perform (usually sending an email) |
177
+ | `queue` | `"heya"` | The ActiveJob queue |
178
+
179
+ Heya uses the following additional options to build the message itself:
180
+
181
+ | Option Name | Default | Description |
182
+ |:--|:--|:--|
183
+ | `subject` | **required** | The email's subject |
184
+ | `from` | Heya default | The sender's email address |
185
+
186
+ You can change the default options using the `default` method at the top of the campaign. Heya applies default options to each step which doesn't supply its own:
187
+
188
+ ```ruby
189
+ class OnboardingCampaign < ApplicationCampaign
190
+ default wait: 1.day,
191
+ queue: "onboarding",
192
+ from: "support@example.com"
193
+
194
+ # Will still be sent after one day from the
195
+ # email address support@example.com
196
+ step :welcome,
197
+ subject: "Welcome to my app!"
198
+ end
199
+ ```
200
+
201
+ ### Custom Actions
202
+
203
+ You can override the default step behavior to perform custom actions by passing
204
+ a block to the `step` method:
205
+
206
+ ```ruby
207
+ class OnboardingCampaign < ApplicationCampaign
208
+ step :first_email,
209
+ subject: "You're about to receive a txt"
210
+
211
+ step :sms do |user|
212
+ SMS.new(to: user.cell, body: "Hi, #{user.first_name}!").deliver
213
+ end
214
+
215
+ step :second_email,
216
+ subject: "Did you get it?"
217
+ end
218
+ ```
219
+
220
+ Step blocks receive two optional arguments: `user` and `step`, and are processed
221
+ in a background job alongside other actions.
222
+
223
+ ### Adding users to campaigns
224
+ Heya leaves *when* to add users to campaigns completely up to you; here's how to add a user to a campaign from anywhere in your app:
225
+
226
+ ```ruby
227
+ OnboardingCampaign.add(user)
228
+ ```
229
+
230
+ To remove a user from a campaign:
231
+
232
+ ```ruby
233
+ OnboardingCampaign.remove(user)
234
+ ```
235
+
236
+ Adding users to campaigns from Rails opens up some interesting automation possibilities--for instance, you can start or stop campaigns from `ActiveRecord` callbacks, or in response to other events that you're already tracking in your application. [See here for a list of ideas](#).
237
+
238
+ Because Heya stacks campaigns by default (meaning it will never send more than one at a time), you can also queue up several campaigns for a user, and they'll receive them in order:
239
+
240
+ ```ruby
241
+ WelcomeCampaign.add(user)
242
+ OnboardingCampaign.add(user)
243
+ EvergreenCampaign.add(user)
244
+ ```
245
+ *Note: you can customize the priority of campaigns via Heya's configuration.*
246
+
247
+ If you want to send a user two campaigns simultaneously, you can do so with the `concurrent` option:
248
+
249
+ ```ruby
250
+ FlashSaleCampaign.add(user, concurrent: true)
251
+ ```
252
+
253
+ When you remove a user from a campaign and add them back later, they'll continue where they left off. If you want them to start over from the beginning, use the `restart` option:
254
+
255
+ ```ruby
256
+ TrialConversionCampaign.add(user, restart: true)
257
+ ```
258
+
259
+ #### Automation ideas
260
+
261
+ Using `ActiveSupport::Notifications` to respond to lifecycle events (which could be sent from your Stripe controller, for instance):
262
+
263
+ ```ruby
264
+ ActiveSupport::Notifications.subscribe("user.trial_will_end") do |*args|
265
+ event = ActiveSupport::Notifications::Event.new(*args)
266
+ if event.payload[:user_id]
267
+ user = User.find(event.payload[:user_id])
268
+ TrialConversionCampaign.add(user, restart: true)
269
+ end
270
+ end
271
+ ```
272
+
273
+ Scheduling campaigns in `ActiveRecord` callbacks:
274
+
275
+ ```ruby
276
+ class User < ApplicationRecord
277
+ after_create_commit do
278
+ WelcomeCampaign.add(self)
279
+ OnboardingCampaign.add(self)
280
+ EvergreenCampaign.add(user)
281
+ end
282
+ end
283
+ ```
284
+
285
+ ### Customizing who gets what
286
+ Heya can send individual messages to certain users using the `segment` option. The following campaign will send the message to inactive users--active users will be skipped:
287
+
288
+ ```ruby
289
+ class ActivationCampaign < ApplicationCampaign
290
+ step :activate, segment: ->(user) { user.inactive? }
291
+ end
292
+ ```
293
+
294
+ When you're checking the value of a single method on the user, the segment can be simplified to the symbol version:
295
+
296
+ ```ruby
297
+ class ActivationCampaign < ApplicationCampaign
298
+ step :activate, segment: :inactive?
299
+ end
300
+ ```
301
+
302
+ #### Segmenting specific campaigns
303
+ You can also narrow entire campaigns to certain users using the `segment` method. For instance, if you have a campaign with a specific goal such as performing an action in your app, then you can send the campaign only to the users who haven't performed the action:
304
+
305
+ ```ruby
306
+ class UpgradeCampaign < ApplicationCampaign
307
+ segment { |u| !u.upgraded? }
308
+
309
+ step :one
310
+ step :two
311
+ step :three
312
+ end
313
+ ```
314
+
315
+ If they upgrade half way through the campaign, Heya will stop sending messages and remove them from the campaign.
316
+
317
+ Likewise, you can require that users meet conditions to continue receiving a campaign. Here's a campaign which sends messages only to trial users--non-trial users will be removed from the campaign:
318
+
319
+ ```ruby
320
+ class TrialCampaign < ApplicationCampaign
321
+ segment :trial?
322
+
323
+ step :one
324
+ step :two
325
+ step :three
326
+ end
327
+ ```
328
+
329
+ #### Segmenting all campaigns
330
+ Heya campaigns inherit options from parent campaigns. For example, to make sure
331
+ unsubscribed users never receive an email from Heya, create a `segment` in the
332
+ `ApplicationCampaign`, and then have all other campaigns inherit from it:
333
+
334
+ ```ruby
335
+ class ApplicationCampaign < Heya::Campaigns::Base
336
+ segment :subscribed?
337
+ end
338
+ ```
339
+
340
+ ### Campaigns FAQ
341
+ **What happens when:**
342
+ <details><summary>I reorder messages in an active campaign?</summary>
343
+
344
+ Heya sends the next *unsent* message *after the last message the user received*. When you move a message, the users who last received it will be moved with it, and continue from that point in the campaign. Heya skips messages which the user has already seen.
345
+ </details>
346
+
347
+ <details><summary>I add a message to an active campaign?</summary>
348
+
349
+ Users who have already received a message *after* the new message will *not* receive the message.
350
+ </details>
351
+
352
+ <details><summary>I remove a message from an active campaign?</summary>
353
+
354
+ Users who last received the message will be moved up to the previously received message, and continue from that point in the campaign. Heya skips messages which the user has already seen.
355
+ </details>
356
+
357
+ <details><summary>I rename a message in an active campaign?</summary>
358
+
359
+ **Renaming a message is equivalent to removing the message and adding a new one.** Users who are waiting to receive an earlier message in the campaign will receive the new message. Users who last received the old message will also receive the new one since it has replaced its position in the campaign.
360
+ </details>
361
+
362
+ <details><summary>A user skips a message based on its conditions?</summary>
363
+
364
+ Heya waits the defined wait time for every message in the campaign. If a user doesn't match the conditions, Heya skips it. If the *next* message's wait time is less than or equal to the skipped message's, it sends it immediately. If the next wait period is longer, it sends it after the new wait time has elapsed.
365
+ </details>
366
+
367
+ <details><summary>I delete an active campaign?</summary>
368
+
369
+ Heya will immediately stop sending the campaign; the campaign's data will remain until you manually delete it. If you restore the file before deleting the campaign's data, Heya will resume sending the campaign.
370
+ </details>
371
+
372
+ <details><summary>I add a user to multiple campaigns?</summary>
373
+
374
+ By default, Heya sends each user one campaign at a time. It determines the order of campaigns using the campaign `priority`. When you add a user to a higher priority campaign, the new campaign will begin immediately. Once completed, the next highest priority campaign will resume sending.
375
+
376
+ To send a campaign concurrent to other active campaigns, use the `concurrent` option.
377
+ </details>
378
+
379
+ <details><summary>I add a user to a campaign they already completed?</summary>
380
+
381
+ When you add a user to a campaign that they previously completed, Heya sends new messages which were added *to the end of the campaign*. Skipped messages will *not* be sent. To resend all messages, use the `restart` option.
382
+ </details>
383
+
384
+ **Less frequently asked questions:**
385
+ <details><summary>Can the same message be delivered twice?</summary>
386
+
387
+ Nope, not without restarting the campaign using the `restart` option (which will resend all the messages).
388
+ </details>
389
+
390
+ <details><summary>Can the same campaign be sent twice?</summary>
391
+
392
+ Yep. When you add a user to a campaign that they previously completed, Heya sends new messages which were added *to the end of the campaign*. Skipped messages will *not* be sent. To resend all messages, use the `restart` option.
393
+ </details>
394
+
395
+ <details><summary>Can I resend a campaign to a user?</summary>
396
+
397
+ Yep. Use the `restart` option to resend a campaign to a user (if they are already in the campaign, the campaign will start over from the beginning).
398
+ </details>
399
+
400
+ <details><summary>Can I send a user two campaigns at the same time?</summary>
401
+
402
+ Yep. By default, Heya sends campaigns ain order of `priority`. Use the `concurrent` option to send campaigns concurrently.
403
+ </details>
404
+
405
+ ## Roadmap
406
+ See [here](https://github.com/honeybadger-io/heya/projects/1) for things we're
407
+ considering adding to Heya.
408
+
409
+ ## Contributing
410
+ 1. Fork it.
411
+ 2. Create a topic branch `git checkout -b my_branch`
412
+ 3. Make your changes and add an entry to the [CHANGELOG](CHANGELOG.md).
413
+ 4. Commit your changes `git commit -am "Boom"`
414
+ 5. Push to your branch `git push origin my_branch`
415
+ 6. Send a [pull request](https://github.com/honeybadger-io/heya/pulls)
416
+
417
+ ## License
418
+ This package is free to use for noncommercial purposes and for commercial purposes during a trial period under the terms of the [Prosperity Public License](LICENSE).