Blog

Building a Subscription Form with Laravel Volt & Mailcoach

Sound like gibberish? Laravel Livewire is a framework to build dynamic interfaces with PHP.
Volt is an alternative, functional API to create single-file Livewire components.

Setting Up

If you want to follow along from scratch, set up a fresh Laravel application first.

laravel new mailcoach-volt

Next, we’ll install our dependencies: Laravel Volt and the Mailcoach SDK. Volt has an install command that needs to be run, and we’ll publish the SDK’s configuration file.

composer require livewire/volt spatie/laravel-mailcoach-sdk
php artisan volt:install
php artisan vendor:publish --tag="mailcoach-sdk-config"

We’ll add an additional email_list_uuid setting to the newly created config/mailcoach-sdk.php, and the necessary variables to your .env file and .env.example files.

<?php

return [
    'api_token' => env('MAILCOACH_API_TOKEN'),
    'endpoint' => env('MAILCOACH_API_ENDPOINT'),
    'email_list_uuid' => env('MAILCOACH_EMAIL_LIST_UUID'),
];
MAILCOACH_API_TOKEN=
MAILCOACH_API_ENDPOINT=
MAILCOACH_EMAIL_LIST_UUID=

You can find your API token & endpoint in your team settings under Profile > Team > API Tokens, and your list UUID in your list’s settings under Lists > List > Settings > General > Usage in Mailcoach API.

Our First Volt Component

Like many Laravel features, Volt comes with a make command. We’ll use it to create a subscribe component.

php artisan make:volt subscribe

The make command sets up an empty component in resources/views/livewire/subscribe.php. Our first Volt component!

<?php

use function Livewire\Volt\{state};

//

?>

<div>
    //
</div>

First, we’ll set up our template. Our form needs an email input and a submit button. Feel free to add more inputs if you want users to provide more details like first name, last name…

<?php

use function Livewire\Volt\{state};

//

?>

<div>
    <form>
        <label>Email <input type="email" required></label>
        <button>Submit</button>
    </form>
</div>

Next, we’ll hook up our email input with Livewire so we can access the value on the server. We’ll also set up a dummy submit handler.

<?php

use function Livewire\Volt\{state};

state(['email']);

$submit = function () {
    // @todo Subscribe user to list
}

?>

<div>
    <form wire:submit="submit">
        <label>Email <input type="email" wire:model="email" required></label>
        <button>Submit</button>
    </form>
</div>

Above, wire:model will bind the value of our email state to the input. wire:submit registers a submit handler on the form.

On to our submit handler. We’re going to use the Mailcoach SDK to subscribe the user to our email list. We’ll pass our list UUID from the configuration, and pass the user’s email address.

$submit = function () {
    Mailcoach::createSubscriber(
        config('mailcoach-sdk.email_list_uuid'),
        ['email' => $this->email],
    );
}

We’ll also want to provide feedback to the user: a message when they’re subscribed or when something went wrong. First, we’ll introduce more state variables to display the messages in the template. Then we’ll wrap our Mailcoach call in a try/catch and act accordingly.

<?php

use Spatie\MailcoachSdk\Facades\Mailcoach;
use Illuminate\Support\Facades\Auth;

use function Livewire\Volt\{state};

state(['email', 'success', 'error']);

$submit = function () {
    try {
        Mailcoach::createSubscriber(
            emailListUuid: config('mailcoach-sdk.email_list_uuid'),
            attributes: [
                'email' => $this->email,
                'first_name' => $this->firstName,
                'last_name' => $this->lastName,
            ],
        )->confirm();
    } catch (Exception $exception) {
        $this->error = true;
    }

    $this->success = true;
}; ?>

<div>
    @if($success)
        <p>Thanks for subscribing!</p>
    @elseif($error)
        <p>Whoops, something went wrong. Please try again later!</p>
    @else
        <form wire:submit="submit">
            <label>Email <input type="email" wire:model="email" required></label>
            <button>Submit</button>
        </form>
    @endif
</div>

And there we have it, the Volt component is ready to fuel our campaigns!

Ready to get started?