Mailing lists are great for capturing contact details for your audience, and are essential for most web-based businesses. MailChimp is a leading provider for creating mailing lists and has a fantastic REST API which we can use to manage our lists amongst many other things. In order to capture the details of our audience we need a sign-up form (just like the one on this site) - there are lots of options for this, such as embedding one of MailChimp's out of the box forms. However, if we want to customise our form and build it into existing functionality of our site we can use the API's List methods (see https://apidocs.mailchimp.com/api/2.0/#lists-methods).

In this tutorial we will use the MailChimp PHP SDK along with the Slim framework to build a simple custom AJAX sign-up form. If you are not familiar with the Slim Framework it would be worth taking a quick look at http://www.slimframework.com/. Also the code used below is available at https://github.com/gaw508/tutorials/tree/master/mailchimp-php-sdk-custom-signup-form-tutorial

Setting Up

The first step is to create a free MailChimp account (http://mailchimp.com/), if you haven't done so already. Once you've set up your account you will also need to create a list, which will be the one we use in the sign up form. There two pieces of info we need from MailChimp before we move on, an API key and the list ID for your new list.

  • To get your MailChimp API key, go to account then click on the extras menu and choose API keys. Go ahead a create a key here and make a note of your key for later.

  • To get the List ID for your new list, go to your list, then choose settings and List name and campaign defaults. Alongside your list name is a List ID, which is a 10 character long string. Make a note of this for later too.

Now we have setup MailChimp it's time to get stuck into the code.

  • First, create your new project directory and run composer require slim/slim mailchimp/mailchimp which will create a composer.json file and install the Slim framework and the MailChimp PHP SDK under the vendor/ directory.

  • Next you'll want to set up a few new files so your project now looks like this:

    project/
        templates/
            newsletter-form.php    // this is the html template for your signup form
    
        vendor/    // composer dependencies
    
        web/    // your web server's document root should point here
            .htaccess    // configuration for rewrites for an apache web server
            index.php    // the access point of your application
    
        composer.json    // composer config
        composer.lock    // composer config
  • Next you need to setup your slim routes in web/index.php

    <?php
    
    require_once dirname(__DIR__) . '/vendor/autoload.php';
    
    $app = new \Slim\Slim(array(
        'templates.path' => dirname(__DIR__) . '/templates'
    ));
    
    $app->get('/', function () use ($app) {
        $app->render('home.php');
    });
    
    $app->post('/newsletter/subscribe', function () use ($app) {
    
    });
    
    $app->run();
    • Here we first autoload our composer dependencies and then instantiate Slim with our templates directory

    • We then set up two routes, one for our html page, the other for our newsletter subscription. The html route renders our newsletter-form.php template. We'll set up the subscription endpoint later.

    • Then we run slim.
  • Finally you'll need add a rewrite to your web/.htaccess file

    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [QSA,L]

Creating a Form

Next we need to create the form by writing the html and css - we will use bootstrap here for ease, but feel free to style the form however you wish. We will then write some simple JavaScript (using jQuery) to submit an AJAX request for the signup form.

Our html template will be located in templates/newsletter-form.php and we will write our JS in here too for simplicity.

<!DOCTYPE html>
<html>
<head>
    <title>Mailchimp PHP API Signup Form Tutorial</title>
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
</head>
<body>
<div class="container">
    <h1>Mailchimp PHP API Signup Form Tutorial</h1>

    <form id="subscribe-form" method="post">
        <div class="subscribe-feedback"></div>

        <div class="form-group">
            <label>First Name</label>
            <input class="form-control" name="first_name">
        </div>

        <div class="form-group">
            <label>Email Address</label>
            <input class="form-control" name="email_address">
        </div>

        <div class="form-group">
            <button class="btn btn-success subscribe-submit" type="submit">Subscribe</button>
        </div>
    </form>
</div>

<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script>
    $('#subscribe-form').submit(function() {
        $('.subscribe-submit').prop('disabled', true);

        $.ajax({
            url: '/newsletter/subscribe',
            method: 'POST',
            data: {
                first_name: $('input[name=first_name]').val(),
                email_address: $('input[name=email_address]').val()
            },
            dataType: 'json'
        })
            .done(function(data) {
                    $('.subscribe-feedback').html(
                        '<div class="alert alert-warning">' + data.message + '</div>'
                    );
                    $('input[name=first_name]').val('');
                    $('input[name=email_address]').val('');
            })
            .fail(function() {
                $('.subscribe-feedback').html(
                    '<div class="alert alert-warning">There was a problem subscribing, please try again.</div>'
                );
            })
            .always(function() {
                $('.subscribe-submit').prop('disabled', false);
            });

        return false;
    });
</script>
</body>
</html>
  • You'll see that we have included the bootstrap css and js, as well as jQuery, using CDN links, so we don't have to host them.

  • The form is a simple form with just two text fields (first name and email address) and a submit button.

  • In the JavaScript we have written a submit function for the form, which does a number of things:

    • Disable the submit button. This is so the user can see that they have submitted the form whilst the AJAX request is sent, and to prevent them from submitting again

    • Send an AJAX request to /newsletter/subscribe with the first name and email address, expecting a JSON response.

    • On success of the request (but not necessarily a successful subscription) we display the message returned from the server and empty the input fields to prevent re-submission of the same data.

    • On failure of the request we display a default error message.

    • On both a successful or failed request, we re-enable the submit button so the form can be used again.

    • Return false. This is to prevent the forms default action from happening, i.e. stopping the form from submitting a normal submission.

Submitting the Form

Now we have a form which submits successfully to our newsletter subscriptions JSON endpoint, we just need to write our PHP code to handle the submission. Below is our updated Slim route from web/index.php

$app->post('/newsletter/subscribe', function () use ($app) {
    $first_name = $app->request->post('first_name');
    $email = $app->request->post('email_address');

    $mailchimp = new Mailchimp("[MAILCHIMP-API-KEY]");
    $mailchimp->lists->subscribe(
        "[MAILCHIMP-LIST-ID]",
        array('email' => $email),
        array('FNAME' => $first_name)
    );

    $app->response->setBody(json_encode(array(
        'message' => 'Thanks! You\'re now signed up.
    )));
});

So at the moment this is literally as simple as calling the Mailchimp::lists::subscribe() method with the first name and email address, then returning a nice success message to the user in a JSON object. Please remember to update the MailChimp API key and List ID to your own, instead of the placeholders above.

This is great, however it doesn't validate the form's input, nor does it handle any potential errors.

Validation and Error Handling

Adding some simple email validation and checking for exceptions thrown by MailChimp give us:

$app->post('/newsletter/subscribe', function () use ($app) {
    $first_name = $app->request->post('first_name');
    $email = $app->request->post('email_address');

    $message = 'Thanks! You\'re now signed up.';

    if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
        try {
            $mailchimp = new Mailchimp("[MAILCHIMP-API-KEY]");
            $mailchimp->lists->subscribe(
                "[MAILCHIMP-LIST-ID]",
                array('email' => $email),
                array('FNAME' => $first_name)
            );
        } catch (Exception $e) {
            $message = $e->getMessage();
        }
    } else {
        $message = 'Please enter a valid email address';
    }

    $app->response->setBody(json_encode(array(
        'message' => $message
    )));
});

Here you'll notice a couple of things:

  • We now validate the email address using PHP's filter_var function, displaying a useful message to the user if it is not valid.

  • We have put a try catch block around the MailChimp SDK code, which on an exception catch sets the message to tell the user to the error message returned by MailChimp.

  • Our frontend code was written in a way that it already handles these different message strings.

And that's it, we now have a nice and simple subscription form for our MailChimp mailing list. The code above is all available at https://github.com/gaw508/tutorials/tree/master/mailchimp-php-sdk-custom-signup-form-tutorial