Managing your mailing list with MailChimp and Laravel 5

 Every website needs subscription system to keep track of it's users,  as a developers we usually need to integrate Email Marketing Programs in our application, for this we usually create backend to subscribe, unsubscribe and create campaign, In this tutorial we will use Laravel 5 and Mailchimp to make emailing process easier.

Prerequisites

For this tutorial, you need MailChimp account, follow the process if you don't have one.

1- Create MailChimp account.

2- After signing up, go to list section and create the new list.

3- After creating the new list, select your list, got to settings->List name and defaults and copy your list id.

3- Now go to your profile at top right corner, click it and select the account from the dropdown menu.

4- Go to Extras->API Keys and click Create A Key.

5- Copy your API key, we will use key and list id later.

We will use .env file to store our API key and list id.

What we are going to build

We are going to build a simple application for subscribing users to the mailing list and send a custom campaign to users in our mailing list.

laravel-mailchimp-demo1

laravel-mailchimp-2

Directory Structure

We will have simple laravel 5.1 directory structure with one additional directory Devartisans, you can name it whatever you want.

LaravelRoot
|	app
|	|	Devartisans
|	|	|	Subscriber
|	|	|		Mailchimp.php
|	|	Http
|	|	|	Controllers
|	|	|		SubscriptionController.php   
|	bootstrap
|	config
|	database
|	public
|	resources
|	|	views
|	|	|	subscription
|	|	|	|	create.blade.php
|	|	|	|	index.blade.php
|	|	master.blade.php
|	storage
|	test
|	vendor
|	.env
|	composer.json

Getting our dependencies

Assuming you have composer installed globally, Open terminal, navigate to your project root and run the following command -

compsoer require mailchimp/mailchimp

Setup required Routes

We are going to add four routes, two routes will handle our subscription system and other two will be responsible for creating and sending a campaign.

Our home route('/') is responsible for showing subscription form.

<?php 

Route::get('/', function() {
	return view('subscription.index');
});

Route::post('/subscribe', [ 'uses' => 'SubscriptionController@subscribe', 'as' => 'subscriber.subscribe']);

Route::get('/campaign', ['uses' => 'SubscriptionController@createCampaign', 'as' => 'subscriber.campaign.create']);
Route::post('/campaign', ['uses' => 'SubscriptionController@sendCampaign', 'as' => 'subscriber.campaign.send']);

Creating Controllers

Now that our routing part is done, we need to create a controller to handle our request, Let's create our SubscriptionController  class to handle our subscription process.

To keep our controllers clean, we are going to create a dedicated class for our MailChimp related logic.

app/Http/Controllers/SubscriptionController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Devartisans\Subscriber\Mailchimp as SubscriptionHandler;
class SubscriptionController extends Controller
{
	protected $subscriptionHandler;

	public function __construct()
	{
		$this->subscriptionHandler = new SubscriptionHandler($this);
	}

	public function subscribe( Request $request )
	{
		
		return $this->subscriptionHandler->subscribe($request);
	}

	public function subscription_failed($message )
	{
		return redirect()->back()->with('message', $message);
	}

	public function subscription_succeed( $message )
	{
		return redirect()->back()->with('message', $message);
	}

	public function createCampaign(Request $request)
	{
		return view('subscription.create');
	}
	public function sendCampaign(Request $request)
	{
		$status = $this->subscriptionHandler->sendCampaign($request->all());

		if(! $status)
		{
			return redirect()->back()->with('message', 'Could not send campaign');
		}
		return redirect()->back()->with('message', 'campaign sent successfully');

	}
}

app/Devartisans/Subscriber/Mailchimp.php

<?php 

namespace App\Devartisans\Subscriber;

use Mailchimp as ListProvider;
use Illuminate\Http\Request;
use Validator;
use App\User;

class Mailchimp {

	protected $mailchimp;
	protected $listener;
	protected $listid;

	public function __construct($listener)
	{
		$this->mailchimp = new ListProvider(getenv('MAILCHIMP_API_KEY'));
		$this->lsitid = getenv('MAILCHIMP_LIST_ID');
		$this->listener = $listener;

	}

	public function saveNewSubscriber(array $data )
	{
		return User::create([ 'email' => $data['email'] ]);
	}

	protected function validate(Request $request)
	{
		return Validator::make($request->all(), [
			'email' => 'required|email|max:255|unique:users'
			]);
	}

	public function subscribe(Request $request)
	{

		if ($this->validate($request)->fails())
		{
			return $this->listener->subscription_failed('You have already subscribed to our mailing list');
		}

		$subscriberAdded = $this->saveNewSubscriber($request->all());

		if( $subscriberAdded )
		{
			$addedToProviderList = $this->subscribeToList($request->get('email'));
			
			if($addedToProviderList)
			{
				return $this->listener->subscription_succeed('Thank you for subscribing');
			}
		}


	}

	public function subscribeToList($email)
	{
		try {
			$status = $this->mailchimp->lists->subscribe(
				$this->listid,
				compact('email'),
                null, // merge vars
                'html', // email type
                false, // requires double optin
                false, // update existing members
                true
                );

		}
		catch(Exception $e)
		{
			return false;
            // if 214 then already subscribed
            //var_dump($e->getCode());
		}
	}

	public function unsubscribeFromList($email)
	{
		return $this->mailchimp->lists->unsubscribe(
			$this->listid,
			compact('email'),
            false, //delete permanently
            false, //send goodbye emails
            false //send unsubscribe notification email
            );
	}

	public function sendCampaign(array $data)
	{
		$html = $data['body'];
		$options = [
		'list_id'   => $this->listid,
		'subject' => $data['subject'],
		'from_name' => $data['mail_from'],
		'from_email' => 'satish@devartisans.com',
		'to_name' => $data['mail_to']
		];

		$content = [
		'html' => $html,
		'text' => strip_tags($html)
		];

		$campaign = $this->mailchimp->campaigns->create('regular', $options, $content);
		return $this->mailchimp->campaigns->send($campaign['id']);
	}

}

We can refactor it even further but for the sake of this tutorial, we will keep everything in these two files.

Creating Views

We have two views index.blade.php and create.blade.php, first one contains our subscription form and other one  will keep our form for creating the campaign.

resources/views/master.blade.php

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="_token" content="{{ csrf_token() }}"/>
    <title>Laravel With Mailchimp</title>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
    <style>
        body {
            padding-top : 70px;
        }
    </style>
</head>
<body>
    <div class="container">
        @yield('content')
    </div>

    <script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>

resources/views/subscription/index.blade.php

@extends('master')

@section('content')

<div class="container">
	@if(session()->has('message'))
	<div class="alert alert-success alert-dismissible" role="alert">
		<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
		{{ session()->get('message') }}
	</div>
	@endif
	<div class="panel panel-default">
		<div class="panel-heading">
			<span>Subscribe with us</span>
		</div>
		<div class="panel-body">
			<form action="{{ route('subscriber.subscribe')}}" method="POST">
				<input type="hidden" name="_token" value="{{ csrf_token() }}">
				<div class="row">
					<div class="col-lg-6 col-lg-offset-3">
						<div class="input-group">
							<input type="text" class="form-control" placeholder="your@email.com" name="email" id="email">
							<span class="input-group-btn">
								<button class="btn btn-default" type="submit">Subscribe</button>
							</span>
						</div>
					</div>
				</div>
			</form>
		</div>
	</div>		
</div>

@stop

Resources/views/subscription/create.blade.php

@extends('master')

@section('content')

<div class="container">
	@if(session()->has('message'))
	<div class="alert alert-success alert-dismissible" role="alert">
		<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
		{{ session()->get('message') }}
	</div>
	@endif
	<div class="panel panel-default">
		<div class="panel-heading">
			<h4>Create Campaign</h4>
		</div>
		<div class="panel-body">
			<div class="col-md-12">

				<form action="{{ route('subscriber.campaign.send')}}" method="POST">
					<input type="hidden" name="_token" value="{{ csrf_token() }}">	

					<div class="form-group">
						<label for="mail_to">To :</label>
						<input type="text" class="form-control" name="mail_to" id="mail_to">
					</div>

					<div class="form-group">
						<label for="mail_from">From : </label>
						<input type="text" class="form-control" name="mail_from" id="mail_from">
					</div>

					<div class="form-group">
						<label for="subject">Subject</label>
						<input type="text" class="form-control" name="subject" id="subject">
					</div>

					<div class="form-group">
						<label for="body">Body</label>
						<textarea rows="10" class="form-control" name="body" id="body"></textarea>
					</div>

					<div class="form-group">
						<button type="submit" class="btn btn-default">Send Campaign</button>
					</div>

				</form>
			</div>
		</div>
	</div>
</div>

@stop

Note - We are using master page here to keep our views clean.

Now we should be able to subscribe a user to our mailing list as well as send campaign to our list. check out MailChimp API to see all the available options.

If you are getting an error make sure you have proper namespacing in SubscriptionController.php and Mailchimp.php, if you are using windows, you need to configure some options to be able to send e-mails from the local machine.

If you have any question, please ask us in comment section or create new thread in forum.

Something to say? Tell us in comment section.