MailChimp form using API v3.0 and jQuery ajax

As per notification at the top of this page, all prior versions of the API will not be supported after 2016.

I created a simple HTML page for a dynamic MailChimp sign-up form using jQuery ajax. This means that your users can signup for your MailChimp list without leaving your page. Better than that, they will signup without a page refresh, as the jQuery and `ajax()` will dynamically update the page with the response from the MailChimp API server. This means that you can use jQuery animations to fade out the form, display an animated spinner while the user waits, and then fade in the message. With jQuery, and a little imagination, the possibilities are endless.

The PHP files are “hidden” in the background where the user never sees them yet the jQuery ajax can still access them invisibly. Even when your website is static HTML, without any PHP, this solution will work so that nobody will ever know PHP is being used in the background.

1) Download a PHP wrapper that supports API v3.0. As of this writing, there is nothing official listed in the latest MailChimp docs that supports v3.0, but several are listed on GitHub, so I selected this one.

2) Create the following PHP file, `store-address.php`, using your own API key and list ID, and then place it in the same directory as the wrapper from step one. Remember to follow the documentation for your wrapper, but they all seem fairly similar to this.

<?php // for MailChimp API v3.0

include('MailChimp.php');  // path to API wrapper downloaded from GitHub

use \DrewM\MailChimp\MailChimp;

function storeAddress() {

    $key        = "xxxxxxxxxxxxxxx-us1";
    $list_id    = "xxxxxx";

    $merge_vars = array(
        'FNAME'     => $_POST['fname'],
        'LNAME'     => $_POST['lname']

    $mc = new MailChimp($key);

    // add the email to your list
    $result = $mc->post('/lists/'.$list_id.'/members', array(
            'email_address' => $_POST['email'],
            'merge_fields'  => $merge_vars,
            'status'        => 'pending'     // double opt-in
            // 'status'     => 'subscribed'  // single opt-in

    return json_encode($result);


// If being called via ajax, run the function, else fail

if ($_POST['ajax']) { 
    echo storeAddress(); // send the response back through Ajax
} else {
    echo 'Method not allowed - please ensure JavaScript is enabled in this browser';

3) Create your HTML/CSS/JavaScript(jQuery) form (It is not required to be on a PHP page, and the visitor will never see that PHP is being used in the background.)

The response is in JSON so you’ll have to handle it correctly.

Here is what my `index.html` file looks like:

<form id="signup" action="index.html" method="get">
    First Name: <input type="text" name="fname" id="fname" />
    Last Name: <input type="text" name="lname" id="lname" />
    email Address (required): <input type="email" name="email" id="email" />
    <input type="submit" id="SendButton" name="submit" value="Submit" />
<div id="message"></div>

<script src="jquery.min.js"></script>
$(document).ready(function() {
    $('#signup').submit(function() {
        $("#message").html("Adding your email address...");
            url: 'inc/store-address.php', // proper url to your "store-address.php" file
            type: 'POST', // <- IMPORTANT
            data: $('#signup').serialize() + '&ajax=true',
            success: function(msg) {
                var message = $.parseJSON(msg),
                    result = '';
                if (message.status === 'pending') { // success
                    result = 'Success!  Please click the confirmation link that will be emailed to you shortly.';
                } else { // error
                    result = 'Error: ' + message.detail;
                $('#message').html(result); // display the message
        return false;

CodeIgniter pagination configuration file seems pointless

In the CodeIgniter documentation:

Simply create a new file called `pagination.php`, add the `$config` array in that file. Then save the file in `application/config/pagination.php` and it will be used automatically. You will NOT need to use `$this->pagination->initialize()` if you save your preferences in a config file.

However, one of the pagination configurations is the `base_url`, which presumably is going to be unique in every instance of pagination. For instance, if you use pagination for a controller function named `yesterday` your `base_url` might be something like `/news/yesterday/pages/`. Then for a controller function named `today`, your `base_url` might be `/news/today/pages/`. Given this scenario, you’ll need settings common for both instances stored in your `pagination.php` file and unique settings declared at the time you create the pagination links.

Consider this code:

$config['base_url'] = '/news/yesterday/pages/';   // <- unique to this instance
$config['uri_segment'] = 4;   // <- depends on above setting

$data['pagination'] = $this->pagination->create_links();

In older versions of CodeIgniter, this code worked in conjunction with a `pagination.php` config file. However, after upgrading my project to version 3.1.0, I discovered the styling of my pagination links were totally broken. The settings contained within `pagination.php` were suddenly being ignored. Apparently the `initialize()` function is resetting pagination to its defaults, disregarding the `pagination.php` file entirely, and only using the `$config` settings array passed into it.

I no longer see the use of having a `pagination.php` file for common settings. If one of the core principals of CodeIgniter is DRY (Do not Repeat Yourself), then `pagination.php` has been rendered useless in this regard. You’re going to have both common configuration settings for all pagination instances in your project along with settings that are unique to each instance. If having unique settings for multiple instances precludes being able to use `pagination.php`, then its own purpose is already defeated. In order to use `pagination.php`, every instance of pagination would need an identical URL structure, which makes it impossible to use on more than one Controller function.

Consider two scenarios that illustrate the issue:

1. Do not use `pagination.php` file – Declare all settings for each instance of pagination by constructing the `$config` array in every Controller function. Settings common to all instances of pagination will need to be repeated for each instance of pagination throughout your Controller functions. Does not adhere to DRY principles. Not ideal.

2. Use `pagination.php` file – All pagination settings are contained in a central location adhering to DRY principles. However, since `base_url` is also a pagination setting, you’ll be forced to use the same Base URL for all instances of pagination. Impossible.


1. Copy your common pagination settings into your custom configuration file contained within `application/config/` directory. If you don’t already have a custom configuration file, create and auto-load it. Assign the array to a single configuration item named `pagination`:

// pagination
$config['pagination']	= [
    'attributes'            => array('class' => 'page'),
    'full_tag_open'         => '<p class="pagination">',
    'full_tag_close'        => '</p>',
    'cur_tag_open'          => '&nbsp;<span class="page page-current">',
    'cur_tag_close'         => '</span>',
    'first_link'            => '&laquo;',
    'last_link'             => '&raquo;',
    'next_link'             => '&rsaquo;',
    'prev_link'             => '&lsaquo;',
    'num_links'             => 6,
    'use_page_numbers'      => TRUE,
    'per_page'              => 16,	// number of items per page

2. Access these common settings within your Controller by calling your new custom configuration item. Use a `foreach` to loop through the `pagination` settings array:

foreach ($this->config->item('pagination') as $key => $value)
    $config[$key] = $value;
$config['base_url'] = '/news/yesterday/pages/';   // <- unique to this instance
$config['uri_segment'] = 4;   // <- depends on above setting

$data['pagination'] = $this->pagination->create_links();

One advantage of this method is that you can individually over-ride any specific setting by simply assigning it to the `$config` array anytime after your `foreach` loop.

foreach ($this->config->item('pagination') as $key => $value)
    $config[$key] = $value;
$config['first_link'] = '&larr;'; // <- overrides your custom setting
$config['base_url'] = '/news/yesterday/pages/';   // <- unique to this instance
$config['uri_segment'] = 4;   // <- depends on above setting

3. Delete the seemingly useless `pagination.php` file!