Heya
Heya 👋 is a campaign mailer for Rails. Think of it like ActionMailer, but for timed email sequences. It can also perform other actions like sending a text message.
Install / Use
/learn @honeybadger-io/HeyaREADME
Heya 👋
Heya is a campaign mailer for Rails. Think of it like ActionMailer, but for timed email sequences. It can also perform other actions like sending a text message.
Getting started
Getting started with Heya is easy:
Prerequisites
Heya was built to work with PostgreSQL. Pull requests are welcome to support more databases.
Installing the Heya gem
-
Add this line to your application's Gemfile:
gem "heya", github: "honeybadger-io/heya" -
Then execute:
bundle install rails generate heya:install rails db:migrate
This will:
- Copy Heya's migration files to db/migrate
- Copy Heya's default initializer to config/initializers/heya.rb
- Create the file app/campaigns/application_campaign.rb
- Run local migrations
# config/initializers/heya.rb
Heya.configure do |config|
config.user_type = "MyUser"
end
</details>
Creating your first campaign
-
Create a campaign:
rails generate heya:campaign Onboarding welcome:0 -
Add a user to your campaign:
OnboardingCampaign.add(user)
Add the following to your User model to send them the campaign
when they first sign up:
after_create_commit do
OnboardingCampaign.add(self)
end
Running the scheduler
To start queuing emails, run the scheduler task periodically:
rails heya:scheduler
Heya uses ActiveJob to send emails in the background. Make sure your
ActiveJob backend is configured to process the heya queue. For example,
here's how you might start Sidekiq:
bundle exec sidekiq -q default -q heya
You can change Heya's default queue using the queue option:
# app/campaigns/application_campaign.rb
class ApplicationCampaign < Heya::Campaigns::Base
default queue: "custom"
end
Bonus: tips for working with email in Rails
<details> <summary>Use <a href="http://mailcatcher.me">MailCatcher</a> to see emails sent from your dev environment</summary># config/environments/development.rb
Rails.application.configure do
# ..
# Use MailCatcher to inspect emails
# http://mailcatcher.me
# Usage:
# gem install mailcatcher
# mailcatcher
# # => Starting MailCatcher
# # => ==> smtp://127.0.0.1:1025
# # => ==> http://127.0.0.1:1080
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {host: "localhost", port: 1025}
end
</details>
<details>
<summary>Use <a href="https://github.com/codetriage/maildown">Maildown</a> to
write your emails in Markdown</summary>
$ bundle add maildown
$ rails generate heya:campaign Onboarding welcome
create app/campaigns/application_campaign.rb
create app/campaigns/onboarding_campaign.rb
create app/views/heya/campaign_mailer/onboarding_campaign/welcome.md.erb
☝️ Notice how only one template was generated; Maildown automatically builds the HTML and text variants from the markdown file.
</details> <details> <summary>Use <a href="https://guides.rubyonrails.org/action_mailer_basics.html#previewing-emails">ActionMailer::Preview</a> to preview emails as you write them</summary>Heya's campaign generator generates previews for campaigns at
(test|spec)/mailers/previews/*_campaign_preview.rb. To see them, open
http://localhost:3000/rails/mailers/. If you didn't use the generator, you
can still build your own preview:
# test/mailers/previews/onboarding_campaign_preview.rb
class OnboardingCampaignPreview < ActionMailer::Preview
def welcome
OnboardingCampaign.welcome(user)
end
private
def user
User.where(id: params[:user_id]).first || User.first
end
end
</details>
Configuration
You can use the following options to configure Heya (find this file in config/initializers/heya.rb):
Heya.configure do |config|
# The name of the model you want to use with Heya.
config.user_type = "User"
# The default options to use when processing campaign steps.
config.campaigns.default_options = {from: "user@example.com"}
# Campaign priority. When a user is added to multiple campaigns, they are
# sent in this order. Campaigns are sent in the order that the users were
# added if no priority is configured.
config.campaigns.priority = [
"FirstCampaign",
"SecondCampaign",
"ThirdCampaign"
]
end
Campaigns
Creating campaigns
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:
rails generate heya:campaign Onboarding first second third
This will:
- Create the file app/campaigns/onboarding_campaign.rb
- Create the directory app/views/heya/campaign_mailer/onboarding_campaign/
- Create email templates inside of app/views/heya/campaign_mailer/onboarding_campaign/
- Create an ActionMailer preview at (test|spec)/mailers/previews/onboarding_campaign_preview.rb
Here's the campaign that the above command generates:
# app/campaigns/application_campaign.rb
class ApplicationCampaign < Heya::Campaigns::Base
default from: "from@example.com"
end
# app/campaigns/onboarding_campaign.rb
class OnboardingCampaign < ApplicationCampaign
step :first,
subject: "First subject"
step :second,
subject: "Second subject"
step :third,
subject: "Third subject"
end
Steps
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.
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).
Each step has several options available (see the section Creating messages).
Creating messages
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.
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).
Here's an example of defining a message inside a campaign:
class OnboardingCampaign < ApplicationCampaign
step :welcome, wait: 1.day,
subject: "Welcome to my app!"
end
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!"
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:
| Option Name | Default | Description |
| :---------- | :-------------------------------- | :------------------------------------------------------- |
| wait | 2.days | The duration of time to wait before sending each message |
| segment | nil | The segment who should receive the message |
| action | Heya::Campaigns::Actions::Email | The action to perform (usually sending an email) |
| queue | "heya" | The ActiveJob queue |
Heya uses the following additional options to build the message itself:
| Option Name | Default | Description |
| ----------- | ------------ | -------------------------------------- |
| subject | required | The email's subject |
| from | Heya default | The sender's email address |
| layout | Heya default | The email's layout file |
| to | See below | The recipient's name & email address |
| bcc | nil | BCC when sending emails |
| headers | {} | Headers to include when sending emails |
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:
class OnboardingCampaign < ApplicationCampaign
default wait: 1.day,
queue: "onboarding",
from: "support@example.com",
layout: "onboarding"
# Will still be sent after one day from the
# email address support@example.com
step :welcome,
subject: "Welcome to my app!"
end
Customizing the to field
You can customize the to field by passing a callable object, which Heya will
invoke with the user. For instance:
class OnboardingCampaign < ApplicationCampaign
step :welcome,
subject: "Welcome to my app!",
to: -> (user) { ActionMailer::Base.email_address_with_name(user.email, user.nickname) }
end
It is recommended to rely on ActionMailer::Base.email_address_with_name so
that sanitization is correctly applied.
If the to param is not provided, Heya will default to:
user#first_nameuser#name
If the user object doesn't respond to these methods, it will fallback to a
simple user.email in the to field.
Quality control option
You may wish to apply quali
