Moist
Drip engine, for Ruby on Rails.
Why the name?
Because drip
was taken and moist
was available.
There is also a measurable amount of people who hate the word moist. Which results in a poor adoption strategy. In turn, fewer stars. Conclusion: recruiters won’t bother me?
Goals?
Should you use this?
Maybe, here’s the gist:
“by
Create a campaign:
::Moist::Campaign.create(name: “Abandoned cart”, slug: “cart”)
Add moist
to mailer:
class AbandonedCartMailer < ActionMailer::Base moist :you_forgot_something, campaign: :cart, step: 1, delay: 1.hour def you_forgot_something(cart) # … end
moist :selling_out_soon, campaign: :cart, step: 2, delay: 4.hours def selling_out_soon(cart) # … end end
Add to a drip campaign:
::Moist::Campaign.subscribe(cart, user: cart.user).to(:cart)
Remove from a drip campaign:
::Moist::Campaign.unsubscribe(cart, user: cart.user).from(:cart)
“
Installation
Add this line to your application’s Gemfile:
“by gem ‘moist’
“
And then execute:
“sh $ bundle
“
Bring in the initializer and migrations:
“sh $ rails g moist:setup
“
And do the migrate:
“sh $ rails db:migrate
“
Setup Moist
How to use Moist
to create an abandoned cart drip campaign.
1. First, create a Moist::Campaign
.
Moist::Campaign.create(name: "Abandoned cart
, slug: “cart”)`
The slug
used here will be referenced later. Note it.
2. Use moist
in your mailer to create steps.
You’ll need to define @moist_subscriber
and @moist_user
in each mailer. This tells Moist what Moist::Mailing
to associate with the mailer.
“by class AbandonedCartMailer < ActionMailer::Base moist :you_forgot_something, campaign: :cart, step: 1, delay: 1.hour def you_forgot_something(cart) @cart = cart @moist_subscriber = cart @moist_user = cart.user mail(subject: “You forgot something…”, to: @cart.user.email) end
moist :free_shipping_if_you_order_now, campaign: :cart, step: 2, delay: 2.days def free_shipping_if_you_order_now(cart) @cart = cart @moist_subscriber = cart @moist_user = cart.user mail(subject: “Free shipping? Yep. Complete your purchase right meow!”, to: @cart.user.email) end end
“
In these mailer methods, make sure you assign a @moist_subscriber
and a @moist_user
. If you don’t, bad things will happen.
3. Add @cart
to the campaign
Probably a background job.
“lass AbandonedCartJob < ApplicationJob TIME_TO_LIVE = 1.hour def perform Cart.where(checked_out: false).where(‘updated_at < ?’, TIME_TO_LIVE.ago).each do |cart| ::Moist::Campaign.subscribe(cart, user: cart.user).to(:cart) end end end
“
4. Run the scheduler
This manages the mailers and the drips.
“by class MoistSchedulerJob < ApplicationJob def perform ::Moist::Scheduler.run end end
“
5. Done!
All done. Some nice-to-haves:
“by class Cart has_moist_campaigns end
“
Gives you
“by @cart.moist_campaigns
“
“lass User acts_as_moist_user end
“
Gives you:
“by @user.moist_subscriptions
“
Data models
Three core concepts:
Campaign
This is just an object for reference.
CampaignSubscriber
This joins a Campaign
to a subscriber
(polymorphic anything), and a user
. In theory, a user
can have many moist_campaign_subscribers
, which would relate it to objects that belong to a user
.
This is useful if you have an Order
object and a Subscription
object that you want to create different campaigns for.
Mailing
Takes your ActionMailer moist
calls and turns them into database records. They have send_at
and sent_at
columns, in addition to information about the mailers they belong to.
Contributing
Just do it.
Todo
- Logo, duh
- Web UI examples
- Ability to pause a campaign?
- Conversion stuff
- Handle updating steps
- Use block for handling
delay
License
The gem is available as open source under the terms of the MIT License.