spatie/laravel-newsletter
Laravel package to manage newsletter subscriptions across providers. Supports Mailcoach, MailChimp, and MailerLite, with a unified API for subscribing/unsubscribing and list management. Includes configurable integration via config/newsletter.php.
Installation:
composer require spatie/laravel-newsletter
php artisan vendor:publish --tag="newsletter-config"
Configure config/newsletter.php with your preferred driver (mailcoach, mailchimp, or mailerlite) and credentials.
Example for Mailcoach:
'driver' => Spatie\Newsletter\Drivers\MailcoachDriver::class,
'driver_arguments' => [
'api_key' => env('MAILCOACH_API_KEY'),
'endpoint' => env('MAILCOACH_ENDPOINT'),
],
'lists' => [
'subscribers' => [
'id' => env('MAILCOACH_LIST_UUID'),
],
],
First Use Case: Subscribe a user to your default list:
use Spatie\Newsletter\Facades\Newsletter;
Newsletter::subscribe('user@example.com');
Subscription Management:
Newsletter::subscribe('user@example.com');
Newsletter::subscribe('user@example.com', ['first_name' => 'John', 'last_name' => 'Doe']);
Newsletter::subscribe('user@example.com', ['FNAME' => 'John', 'LNAME' => 'Doe']);
Newsletter::subscribe('user@example.com', listName: 'promotions');
Updating Subscribers:
Newsletter::subscribeOrUpdate('user@example.com', ['first_name' => 'UpdatedName']);
Unsubscription:
Newsletter::unsubscribe('user@example.com');
Or for a specific list:
Newsletter::unsubscribe('user@example.com', 'promotions');
Deletion (use sparingly; removes all history):
Newsletter::delete('user@example.com');
Checking Subscriptions:
if (Newsletter::hasMember('user@example.com')) {
// Handle existing subscriber
}
MailChimp-Specific: Group Management:
Newsletter::subscribeOrUpdate(
'user@example.com',
['FNAME' => 'John', 'LAND' => 'US'],
'subscribers',
['interests' => ['group_id_1' => true, 'group_id_2' => false]]
);
Laravel Events: Trigger newsletter actions in Registered or ProfileUpdated events:
public function handle(Registered $event) {
Newsletter::subscribe($event->user->email, [
'first_name' => $event->user->first_name,
]);
}
Forms: Use in registration/login forms or profile settings:
<form method="POST" action="/subscribe">
@csrf
<input type="email" name="email" required>
<button type="submit">Subscribe</button>
</form>
API Endpoints: Expose subscription management via API:
Route::post('/subscribe', function (Request $request) {
Newsletter::subscribe($request->email, $request->attributes);
return response()->json(['status' => 'subscribed']);
});
Testing: Use the NullDriver for local development/testing:
'driver' => Spatie\Newsletter\Drivers\NullDriver::class,
Driver-Specific Fields:
attributes or fields.merge_vars (e.g., FNAME, LNAME).List IDs:
Unsubscription vs. Deletion:
unsubscribe() marks users as inactive but retains history.delete() permanently removes users and history.unsubscribe() unless you explicitly need deletion.Rate Limits:
NullDriver Quirks:
getMember() return false (not null).=== false) when checking responses.API Errors:
Newsletter::getApi()->getLastError();
Configuration Issues:
NEWSLETTER_DRIVER and NEWSLETTER_* env vars are set.php artisan config:clear after updates.Custom Drivers:
Extend Spatie\Newsletter\Drivers\Driver to support other providers:
class CustomDriver implements Driver {
public function subscribe(string $email, array $attributes = []): void {
// Custom logic
}
// Implement other methods...
}
Register in config/newsletter.php:
'driver' => App\Newsletter\Drivers\CustomDriver::class,
Middleware: Add subscription checks in middleware:
public function handle(Request $request, Closure $next) {
if (!Newsletter::isSubscribed($request->user->email)) {
abort(403);
}
return $next($request);
}
Service Providers:
Bind custom logic to the Newsletter facade:
public function boot() {
Newsletter::extend(function ($app) {
return new CustomDriver();
});
}
lists/members batch operations) for large datasets.$cached = Cache::remember("subscribed_{$email}", now()->addHours(1), function () use ($email) {
return Newsletter::hasMember($email);
});
interests to be pre-configured in lists for group management.How can I help you explore Laravel packages today?