Selling digital products using Laravel part 8: Mailing updates and news using Mailcoach
We'd like to stay in touch with the people interested in our products by sending them emails when we got some news on an upcoming product, or when we are running a promo for existing products. To handle subscriptions and send out emails, we use our home-grown Laravel package Mailcoach. Let's take a look at how we use Mailcoach ourselves.
- Part 8: Mailing updates and news using Mailcoach (you are here)
Our digital products can be bought on spatie.be. We want each product to have it's own "face" as well, so each product has its own marketing site. Here are the ones for Front Line PHP, Media Library Pro, Mailcoach, Laravel Package Training and Laravel Beyond CRUD.
Subscribing to a list
Each of those marketing sites displays a subscription form where people can subscribe to the spatie.be email list. Here's how that looks like on the Front Line PHP site.
When creating a new account on spatie.be there's an option to subscribe to the mailing list as well.
The forms on the external marketing sites send a POST request to https://spatie.be/mailcoach/subscribe/
. They also send a tag that will be added to the subscriber. This way, we know what content this subscriber is interested in. Here's the relevant controller in the spatie/laravel-beyond-crud.com repo.
class SubscribeToEmailListController
{
public function __invoke(SubscribeToEmailListRequest $request)
{
if (! app()->environment('production')) {
flash()->error('Subscribing is only possible in production');
}
$response = Http::post("https://spatie.be/mailcoach/subscribe/" .config('services.mailcoach.subscription_uuid'), [
'email' => $request->email,
'tags' => 'laravel-beyond-crud-waiting-list',
]);
if (! $response->successful()) {
ld()->error('Something went wrong', $response, $response);
throw new Exception('Could not subscribe');
}
flash()->success('Thanks for your interest! We will keep you posted with updates on the course.');
return back();
}
}
Using segments
Using these tags, we can define Mailcoach segments to send emails to a specific part of our audience. Here's the segment that has all people that subscribed to the Mailcoach mailing list but has not bought Mailcoach yet.
When v3 of Mailcoach was released, we used that segment to send a promo code to all people that were interested in Mailcoach but didn't buy it just yet.
Send coupons automatically
We also use Mailcoach events to perform specific actions. At the moment of writing, we haven't launched our Front Line PHP course yet. To thank people for subscribing to that particular list, we send a coupon code that grants a little discount when buying one of our released products.
Here's how that's done. In EventSubscriber
we've we've added a SendCoupon
listener that will be executed whenever Mailcoach' SubscribedEvent
is fired.
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
// ...
SubscribedEvent::class => [
SendCoupon::class,
],
];
}
In SendCoupon
, we check if the new subscriber does have the tag front-line-php-waiting-list
. If so, we are going to send that subscriber the coupon.
Here's the code of SendCoupon
:
namespace App\Listeners;
use App\Models\Subscriber;
use App\Notifications\WelcomeFrontLinePhpWaitingListNotification;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Spatie\Mailcoach\Events\SubscribedEvent;
use Spatie\Mailcoach\Models\Subscriber as MailcoachSubscriber;
class SendCoupon
{
public function handle(SubscribedEvent $event): void
{
if ($event->subscriber->hasTag('front-line-php-waiting-list')) {
$this->upcastSubscriber($event->subscriber)->notify(new WelcomeFrontLinePhpWaitingListNotification());
}
}
protected function upcastSubscriber(MailcoachSubscriber $subscriber): Subscriber
{
$subscriber = Subscriber::findByUuid($subscriber->uuid);
if (! $subscriber) {
throw (new ModelNotFoundException())->setModel(Subscriber::class);
}
return $subscriber;
}
}
That upcasting bit in the code above is needed because, by default, a Subscriber
model of Mailcoach is not Notifiable
. Our local Subscriber
model extends from Mailcoach' one and is Notifiable
. In Mailcoach v4, which we'll release early next year, the Subscriber
will be Notifiable
, so this little upcasting dance can be removed.
The WelcomeFrontLinePhpWaitingListNotification
is a standard notification that sends a MailMessage
.
namespace App\Notifications;
use App\Models\Subscriber;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class WelcomeFrontLinePhpWaitingListNotification extends Notification
{
use Queueable;
public function via($notifiable): array
{
return ['mail'];
}
public function toMail(Subscriber $notifiable): MailMessage
{
return (new MailMessage)
->subject("You are now subscribed to the Front Line PHP waiting list")
->greeting('Hi!')
->line("Thank you for subscribing to the Front line PHP waiting list. In the coming weeks we'll send you a couple of previews, and of course we'll notify you as soon as Front Line PHP is available.")
->line('We would like to offer you this coupon code, which is valid for two weeks only, that grants you a 25% discount on all products in our store:')
->line('WAITING-FOR-FRONT-LINE-PHP')
->action('Redeem the coupon on our store', route('products.index'))
->line("We are very excited about PHP 8 and can't wait to share our insights and knowledge with you.");
}
}
It's pretty nice that we can use Mailcoach on our own website. I think Mailcoach is one of the better products in this category because we continuously improve it for our use case.
This series is continued in part 9: Serving ads on GitHub.
What are your thoughts on "Selling digital products using Laravel part 8: Mailing updates and news using Mailcoach"?