Mailchimp API 3.0 – PHP and AJAX subscription / unsubscription

Ready to use function which allows you to subscribe an email address to any of your mailchimp lists (with confirmation email or not) or unsubscribe it as well.

#admin-ajax.php, #mailchimp  /  November 16, 2015  /   57

Ok, if you are reading this post, you already know something about mailchimp and use default Mailchimp sign up forms maybe.

But what if you want your forms to be more customizable for your website purposes, such as:

  • original form design,
  • mailchimp subscription built-in another form (sign up checkbox in custom form — look at my comment form),
  • no confirmation emails,
  • subscribe or unsubscribe users via your website administration area etc.

First of all insert this function into your website code. If you use WordPress, it can be functions.php file.

function rudr_mailchimp_subscriber_status( $email, $status, $list_id, $api_key, $merge_fields = array('FNAME' => '','LNAME' => '') ){
	$data = array(
		'apikey'        => $api_key,
    		'email_address' => $email,
		'status'        => $status,
		'merge_fields'  => $merge_fields
	);
	$mch_api = curl_init(); // initialize cURL connection
 
	curl_setopt($mch_api, CURLOPT_URL, 'https://' . substr($api_key,strpos($api_key,'-')+1) . '.api.mailchimp.com/3.0/lists/' . $list_id . '/members/' . md5(strtolower($data['email_address'])));
	curl_setopt($mch_api, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: Basic '.base64_encode( 'user:'.$api_key )));
	curl_setopt($mch_api, CURLOPT_USERAGENT, 'PHP-MCAPI/2.0');
	curl_setopt($mch_api, CURLOPT_RETURNTRANSFER, true); // return the API response
	curl_setopt($mch_api, CURLOPT_CUSTOMREQUEST, 'PUT'); // method PUT
	curl_setopt($mch_api, CURLOPT_TIMEOUT, 10);
	curl_setopt($mch_api, CURLOPT_POST, true);
	curl_setopt($mch_api, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($mch_api, CURLOPT_POSTFIELDS, json_encode($data) ); // send data in json
 
	$result = curl_exec($mch_api);
	return $result;
}

Ok, now let me show what each parameter means.

$email
(string) I hope it is clear for you.
$status
(string) Subscriber status to set:

  • subscribed
  • unsubscribed
  • cleaned
  • pending (confirmation email will be sent)
$list_id
(string) Mailchimp list ID you want to add subscribers to. How to obtain it?

How to get Mailchimp list ID? #

Login to Mailchimp, go to Lists then click on the list title, then in list menu Settings > List name and defaults.

Go to Lists > Settings > List name and defaults to obtain a list ID. Do not use the list ID from the screenshot - it is fake.
$api_key
(string) API key is unique for every Mailchimp account. And this is how to get it:

How to get Mailchimp API keys? #

1. In main Mailchimp menu click on your picture and go to Account.

Mailchimp account settings is here.

2. Then choose Extras > API keys.

Click on «API keys» link from «Extras» dropdown menu then you will be redirected to page where you can create a Mailchimp API key.

3. That’s it. Click on Create A Key and your new API key will appear.

Click on Create A Key button to  create new mailchimp API key.
$merge_fields
(array) Subscriber fields, can be configured in a list settings. By default each mailchimp list has two merge fields (except email) — subscriber first name $merge_fields['FNAME'] and last name $merge_fields['LNAME'].

PHP Subscription example

Do not forget to copy the rudr_mailchimp_subscriber_status() function to your website code (you can find it at the beginning of the post).

$email = 'johndoe@rudrastyh.com';
$status = 'subscribed'; // "subscribed" or "unsubscribed" or "cleaned" or "pending"
$list_id = 'YOUR LIST ID HERE'; // where to get it read above
$api_key = 'YOUR MAILCHIMP API KEY HERE'; // where to get it read above
$merge_fields = array('FNAME' => 'Misha','LNAME' => 'Rudrastyh');
 
rudr_mailchimp_subscriber_status($email, $status, $list_id, $api_key, $merge_fields );

The very simple example. Do you think so?

AJAX Subscription example (WordPress-friendly)

Actually my blog is about WordPress, so the AJAX example will be adapted for WordPress.

Step 1. Sign Up form HTML

This form will work properly only if the JavaScript is enabled in user browser. You can also upgrade it to work both with JavaScript and without it.

<form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" id="mailchimp">
	<!-- for my website the site_url() function returns https://rudrastyh.com -->
	<input type="text" name="fname" placeholder="First name" />
	<input type="text" name="lname" placeholder="Last name" />
	<input type="email" name="email" placeholder="Email *" required />
 
	<input type="hidden" name="action" value="mailchimpsubscribe" />
	<!-- we need action parameter to receive ajax request in WordPress -->
 
	<button>Subscribe</button>
</form>

Step 2. jQuery code to send asynchronous request

Make sure that jQuery library is included to your website pages.

jQuery(function($){
	$('#mailchimp').submit(function(){
		var mailchimpform = $(this);
		$.ajax({
			url:mailchimpform.attr('action'),
			type:'POST',
			data:mailchimpform.serialize(),
			success:function(data){
				alert(data);
			}
		});
		return false;
	});
});

Step 3. PHP code for your functions.php file. Errors Handling

function rudr_mch_subscribe(){
	$list_id = 'YOUR LIST ID HERE';
	$api_key = 'YOUR MAILCHIMP API KEY HERE';
	$result = json_decode( rudr_mailchimp_subscriber_status($_POST['email'], 'subscribed', $list_id, $api_key, array('FNAME' => $_POST['fname'],'LNAME' => $_POST['lname']) ) );
	// print_r( $result ); 
	if( $resul->status == 400 ){
		foreach( $result->errors as $error ) {
			echo '<p>Error: ' . $error->message . '</p>';
		}
	} elseif( $result->status == 'subscribed' ){
		echo 'Thank you, ' . $result->merge_fields->FNAME . '. You have subscribed successfully';
	}
	// $result['id'] - Subscription ID
	// $result['ip_opt'] - Subscriber IP address
	die;
}
 
add_action('wp_ajax_mailchimpsubscribe','rudr_mch_subscribe');
add_action('wp_ajax_nopriv_mailchimpsubscribe','rudr_mch_subscribe');

Only the best of WordPress

once a week, no spam

Comments 57

  • Hii,

    I tried your code on my site but it’s not working for me.
    by the way should not this line be 3.0? curl_setopt($mch_api, CURLOPT_USERAGENT, ‘PHP-MCAPI/2.0’);

  • Hi, grate code :)
    Do you have an AJAX example not connected to WordPress?

  • Hi, Thanks !!
    Saved lot of time

  • Thanks, this was helpful when other tutorials were not.

  • Hi ,
    i need your help. I need the disable the double optin in mailchimp for my shopify. can you please what are all the steps i need to do for disable the double optin?

    • MishaAuthorJune 14, 2016 at 05:06

      Hi,
      Is MailChimp functionality integrated into your shopify theme? If yes, I recommend to perform a search through your theme files for a keyword pending. And when you find it, replace to subscribed.

      • Hi,
        Thanks for your reply.

        Actually i have a newsletter sign up form in my shopify site. So after i have created the signup form in my mailchimp account, i took the form action url alone and used in the shopify.Thats all.

        so i think mailchimp functionality is integrated with shopify like you are asking. but i have checked all the files. there is no keyword pending. I have a two shopify sites which one i am using “brooklyn” theme and another one is “Launch-pad star” theme. I am using the mailchimp sign up form integrated with the two sites of nesletter sign up form. But i can’t disable the double optin in those two sites.

        Can you please provide any other solution for this??? I really need your help.

        Thanks in Advance!!!

        • MishaAuthorJune 14, 2016 at 15:06

          I think it is because you are using HTML sign-up form — it doesn’t allow to disable double optin.

          If you want to subscribe users without confirmation, you have to use MailChimp API for these purposes. All the examples are above. Or you can try to look for an extension.

  • Can you give an example of this working? I am totally lost.

    • The example is above :) How can I help you?

      • Thank you for answering. I have so many questions – like:

        Where do I put the API?

        How do I make the API add new users based on a custom form?

        • I’m sorry, Sean, but answers to your questions are very clear in the post.

          So, I do not want just to duplicate the text and code from the post here, so I recommend you to read the post once again or ask me the other questions.

  • Hi Misha,
    first of all thank you for this!

    I used your WP example and adding users to a mailchimp list with the form works fine, but after user submission of the email a the browser popup dialog opens on the frontend and after closing this the user is redirected to

    http://mywebsite.com/admin-ajax.php?fname=Peter&lname=Piper&email=testmail%40testwebsite.com&action=mailchimpsubscribe

    My questions:
    How can i prevent the browser popup, and redirect to another link without displaying the user information in the browser adress bar? I am using the Foundation framework and would ideally like to open up a modal dialog (http://foundation.zurb.com/sites/docs/reveal.html) upon successful subscription.

    And is it possible to just have one field on the frontend for the user’s email adress instead of first & last name + email adress?

    Thank you for your time!

    • Hi Josh,

      of course user shouldn’t be redirected to admin-ajax.php. Oh, sorry, I forgot to add return false; in my jQuery code – plese try now.

      Yes, it is possible to have just email address field on the frontend.

  • Gautham SarangNovember 10, 2016 at 13:11

    Is it possible to retrive the number of subscribers displayed before the form? Like “Join the 456 others”

  • Thanks, this code is brilliant! I have it working without being connected to WordPress so thanks! I was just wondering if there is a way to add groupings to the submission through multiple checkboxes? Thanks in advance!

  • Hello, whenever I try to submit the form I get the error:

    POST http://newage.dev/wp-admin/admin-ajax.php 500 (Internal Server Error) jquery.min.js:4

    In the console.

    Do you know how to fix this?

  • Hey Misha! Thank you for this great tutorial. Stand alone, this is working perfect. However, i have some questions.

    1. How to check if the email is allready in the list? I can infinite subscribe and the returning message is the same “Succes!”
    2. I’m trying to make this as a widget for my theme but unfortunatelly, the admin-ajax.php is returning 0.

    This is what i’ve done:

    <?php
    // begin creating widget
    add_action('widgets_init', 'init_azd_newsletter');
     
    function init_azd_newsletter() {
        return register_widget('azd_newsletter');
    }
     
    class azd_newsletter extends WP_Widget {
     
        /** widget */
        function __construct() {
            $widget_ops = array(
                'classname' => 'widget_newsletter',
                'description' => __('Afișează in sidebar formularul de abonare newsletter prin MailChimp', 'newsletter_subscribe_widget'));
            parent::__construct('newsletter_subscribe_widget', __('Newsletter'), $widget_ops);
        }
     
        function widget($args, $instance) {
            extract($args);
     
            $title = apply_filters('widget_title', $instance['title']);
            $apikey = $instance['apikey'];
            $listid = $instance['listid'];
     
            echo $before_widget;
     
            echo $before_widget;
            if (!empty($title)) {
                echo $before_title . $title . $after_title;
            }
            ?>
            <?php
     
            function rudr_mch_subscribe() {
                $list_id = $instance['apikey'];
                $api_key = $instance['listid'];
                $result = json_decode(rudr_mailchimp_subscriber_status($_POST['email'], 'subscribed', $list_id, $api_key, array('FNAME' => $_POST['fname'], 'LNAME' => $_POST['lname'])));
                if ($resul->status == 400) {
                    foreach ($result->errors as $error) {
                        echo '<p>Error: ' . $error->message . '</p>';
                    }
                } elseif ($result->status == 'subscribed') {
                    echo 'You have successfully subscribed!';
                }
                die;
            }
     
            add_action('wp_ajax_mailchimpsubscribe', 'rudr_mch_subscribe');
            add_action('wp_ajax_nopriv_mailchimpsubscribe', 'rudr_mch_subscribe');
     
            function rudr_mailchimp_subscriber_status($email, $status, $list_id, $api_key) {
                $data = array(
                    'apikey' => $api_key,
                    'email_address' => $email,
                    'status' => $status
                );
                $mch_api = curl_init(); // initialize cURL connection
     
                curl_setopt($mch_api, CURLOPT_URL, 'https://' . substr($api_key, strpos($api_key, '-') + 1) . '.api.mailchimp.com/3.0/lists/' . $list_id . '/members/' . md5(strtolower($data['email_address'])));
                curl_setopt($mch_api, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: Basic ' . base64_encode('user:' . $api_key)));
                curl_setopt($mch_api, CURLOPT_USERAGENT, 'PHP-MCAPI/2.0');
                curl_setopt($mch_api, CURLOPT_RETURNTRANSFER, true); // return the API response
                curl_setopt($mch_api, CURLOPT_CUSTOMREQUEST, 'PUT'); // method PUT
                curl_setopt($mch_api, CURLOPT_TIMEOUT, 10);
                curl_setopt($mch_api, CURLOPT_POST, true);
                curl_setopt($mch_api, CURLOPT_SSL_VERIFYPEER, false);
                curl_setopt($mch_api, CURLOPT_POSTFIELDS, json_encode($data)); // send data in json
     
                $result = curl_exec($mch_api);
                return $result;
            }
            ?>
     
            <form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" id="mailchimp">
                <input type="email" name="email" placeholder="<?php _e('Adresa de email...', 'azd'); ?>" required />
                <input type="hidden" name="action" value="mailchimpsubscribe" />
                <button><?php _e('Abonare', 'azd'); ?></button>
                <p class="status"></p>
            </form>
     
            <p>List id: <?php echo $listid; ?></p>
            <p>Api Key: <?php echo $apikey; ?></p>
     
            <script>
                jQuery(function ($) {
                    $('#mailchimp').submit(function () {
                        var mailchimpform = $(this);
                        $.ajax({
                            url: mailchimpform.attr('action'),
                            type: 'POST',
                            data: mailchimpform.serialize(),
                            success: function (data) {
                                $('p.status').text(data);
                                document.getElementById("mailchimp").reset();
                            }
                        });
                        return false;
                    });
                });
            </script>
            <?php
            echo $after_widget;
        }
     
        function update($new_instance, $old_instance) {
            $instance = $old_instance;
            $instance['title'] = strip_tags($new_instance['title']);
            $instance['apikey'] = strip_tags($new_instance['apikey']);
            $instance['listid'] = strip_tags($new_instance['listid']);
            return $instance;
        }
     
        function form($instance) {
            $defaults = array(
                'title' => 'Newsletter',
                'apikey' => '',
                'listid' => '',
            );
     
            if ($instance) {
                $title = $instance['title'];
                $apikey = $instance['apikey'];
                $listid = $instance['listid'];
            } else {
                $title = '';
                $apikey = '';
                $listid = '';
            }
     
            $instance = wp_parse_args((array) $instance, $defaults);
            ?>
     
     
            <p style="text-align: center"> 
                <a href="https://mailchimp.com" target="_blank" title="MailChimp"><img src="https://static.mailchimp.com/web/brand-assets/logo-freddie-fullcolor.svg" alt="MailChimp" width="50" height="50"/></a><br/>
                <a href="https://mailchimp.com" target="_blank" title="MailChimp"><img src="https://static.mailchimp.com/web/brand-assets/history-script02.png" alt="MailChimp" width="100" height="26"/></a>
            <p>
                <label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Titlu:', 'azd'); ?></label>
                <input id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" class="widefat" />
            </p>
     
            <p>
                <label for="<?php echo $this->get_field_id('apikey'); ?>"><strong><?php _e('MailChimp Api Key:', 'azd'); ?></strong></label><br/>
                <small><?php _e('Adaugă mai jos API Key-ul de MailChimp. Click <a href="http://kb.mailchimp.com/integrations/api-integrations/about-api-keys" target="_blank">aici</a> pentru detalii.', 'azd'); ?></small><br/><br/>
                <input id="<?php echo $this->get_field_id('apikey'); ?>" name="<?php echo $this->get_field_name('apikey'); ?>" type="text" value="<?php echo $apikey; ?>" class="widefat" />
            </p>
     
            <p>
                <label for="<?php echo $this->get_field_id('listid'); ?>"><strong><?php echo ('MailChimp List ID:'); ?></strong></label><br/>
                <small><?php _e('Adaugă mai jos List ID-ul de MailChimp. Click <a href="http://kb.mailchimp.com/lists/managing-subscribers/find-your-list-id" target="_blank">aici</a> pentru detalii.', 'azd'); ?></small><br/><br/>
                <input id="<?php echo $this->get_field_id('listid'); ?>" name="<?php echo $this->get_field_name('listid'); ?>" type="text" value="<?php echo $listid; ?>" class="widefat" />
            </p>
     
     
     
            <?php
        }
     
    }

    Can you help me, please? :) Thank you!

    • Hi Valentin,

      1) You can use GET /lists/{list_id}/members/{subscriber_hash} method where subscriber_hash is md5( $email ).

      2) You should pull out the add_action() lines, and the rudr_ functions outside the WP_Widget class first of all :)

  • I’m looking for a way to trigger the subscribe action when a checkbox is check, as also call the unsubscribe function when the checkbox is uncheck.

    Does anyone have already achieved something like that?

    It’d be a really useful minimal UI enabling the user to easily to opt-in a newsletter subscription, perfect for scenarios such as user’s account settings.

    • Hello Adriano,

      just in the PHP code use the following:

      if( isset( $_POST['checkbox_name_attribute'] ) && $_POST['checkbox_name_attribute'] == 'on' ) {
      	// trigger subscribe function
      } else {
      	// trigger unsubscribe function
      }
  • Is there any way to add a a subscriber even if it is missing some ‘required’ merge fields?

  • Hi Misha!

    I cannot thank you enough for the tutorial and fantastic code.

    I only have one question: Is there a way to send the date added in the API? Right now when my subscribers are added, if the status is set to “subscribed”, then the date added is correct, but then the automated email does not send. If it is sent as “pending”, the email is sent but the date added is set to default 12/31/1969.

    I’d appreciate any help. Thank you. Here is my code:

    <!---In my functions file--->
                  <?php
    function rudr_mailchimp_subscriber_status( $email, $status, $list_id, $api_key, $merge_fields = array('FULLNAME' => '','DECNAME' => '','DATEHEB' =>'','DATEPREF' => '') ){
    	$data = array(
    		'apikey'        => $api_key,
        		'email_address' => $email,
    		'status'        => $status,
    		'merge_fields'  => $merge_fields
    	);
    	$mch_api = curl_init(); // initialize cURL connection
     
    	curl_setopt($mch_api, CURLOPT_URL, 'https://' . substr($api_key,strpos($api_key,'-')+1) . '.api.mailchimp.com/3.0/lists/' . $list_id . '/members/' . md5(strtolower($data['email_address'])));
    	curl_setopt($mch_api, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: Basic '.base64_encode( 'user:'.$api_key )));
    	curl_setopt($mch_api, CURLOPT_USERAGENT, 'PHP-MCAPI/2.0');
    	curl_setopt($mch_api, CURLOPT_RETURNTRANSFER, true); // return the API response
    	curl_setopt($mch_api, CURLOPT_CUSTOMREQUEST, 'PUT'); // method PUT
    	curl_setopt($mch_api, CURLOPT_TIMEOUT, 10);
    	curl_setopt($mch_api, CURLOPT_POST, true);
    	curl_setopt($mch_api, CURLOPT_SSL_VERIFYPEER, false);
    	curl_setopt($mch_api, CURLOPT_POSTFIELDS, json_encode($data) ); // send data in json
     
    	$result = curl_exec($mch_api);
    	return $result;
    }		
     
    ?>

    Then this in my form process:

         <?php
    $email = $_POST['cemail'];
    $cname=$_POST['cname'];
    $dname=$_POST['dname'];
    $dateeng=$_POST['dateenglish'];
    $datehebrew=$_POST['datehebrew'];
    $date_pref=$_POST['date_pref'];
    $status = 'pending'; // "subscribed" or "unsubscribed" or "cleaned" or "pending"
    $list_id = 'XXXXXXXXX'; // where to get it read above
    $api_key = 'CCCCCCCCCCCCC-us10'; // where to get it read above
    $merge_fields = array('FULLNAME' => $cname, 'DECNAME' => $dname, 'DECDATE' => $dateeng, 'DATEHEB' => $datehebrew, 'DATEPREF' => $date_pref);
     
    rudr_mailchimp_subscriber_status($email, $status, $list_id, $api_key, $merge_fields );				
     
    ?>

    Thank you for this awesome tool!

  • HI Misha

    This a great tutorials i want to add location of submitted user form how can i add in this

    • Hi,

      I recommend you to consider using HTML5 geolocation.

      • Can you show me in your current example you created as might help to other as well

        Hope :)

        • I have no ready code for this task :)

          • I try by this way added

            function rudr_mch_subscribe() {
                $list_id = '';
            	$api_key = '';
            	$ip = $_SERVER['REMOTE_ADDR'];
               $details = json_decode(file_get_contents("http://ipinfo.io/{$ip}/json"));
                $cnt=$details->country; 
                $result = json_decode(rudr_mailchimp_subscriber_status($_POST['email'], 'subscribed', $list_id, $api_key, array('FNAME' => $_POST['fname'], 'LNAME' => $_POST['lname']),array('country_code'=>'".$cnt."')));
            	 print_r($result);
                        if ($resul->status == 400) {
                            foreach ($result->errors as $error) {
                                echo '<p>Error: ' . $error->message . '</p>';
                            }
                        } elseif ($result->status == 'subscribed') {
                            echo 'You have successfully subscribed!';
                        }
                        die;
                    }
            add_action('wp_ajax_mailchimpsubscribe', 'rudr_mch_subscribe');
            add_action('wp_ajax_nopriv_mailchimpsubscribe', 'rudr_mch_subscribe');
            function rudr_mailchimp_subscriber_status( $email, $status, $list_id, $api_key, $merge_fields = array('FNAME' => '','LNAME' => ''),$location=array('country_code'=>'') ){
            	$data = array(
            		'apikey'        => $api_key,
                	'email_address' => $email,
            		'status'        => $status,
            		'merge_fields'  => $merge_fields,
            		'location'=>$location
            	);
            	$mch_api = curl_init(); // initialize cURL connection
             
            	curl_setopt($mch_api, CURLOPT_URL, 'https://' . substr($api_key,strpos($api_key,'-')+1) . '.api.mailchimp.com/3.0/lists/' . $list_id . '/members/' . md5(strtolower($data['email_address'])));
            	curl_setopt($mch_api, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: Basic '.base64_encode( 'user:'.$api_key )));
            	curl_setopt($mch_api, CURLOPT_USERAGENT, 'PHP-MCAPI/2.0');
            	curl_setopt($mch_api, CURLOPT_RETURNTRANSFER, true); // return the API response
            	curl_setopt($mch_api, CURLOPT_CUSTOMREQUEST, 'PUT'); // method PUT
            	curl_setopt($mch_api, CURLOPT_TIMEOUT, 10);
            	curl_setopt($mch_api, CURLOPT_POST, true);
            	curl_setopt($mch_api, CURLOPT_SSL_VERIFYPEER, false);
            	curl_setopt($mch_api, CURLOPT_POSTFIELDS, json_encode($data) ); // send data in json
             
            	$result = curl_exec($mch_api);
            	return $result;
            }
  • Hi

    i used the code but click on suscribe button it redirect to https://www.findmyprofession.com/wp-admin/admin-ajax.php?fname=&lname=&email=demo%40gmail.com&action=mailchimpsubscribe like this

  • Priya PatelApril 19, 2017 at 12:04

    Hi,

    I have tried your code.But it is not working for me.For AJAX which code should I use?Please tell me the steps.

    • MishaAuthorApril 19, 2017 at 19:04

      Hi,

      just read the post carefully – all the info is in it. I really have nothing to say, everything is in the post content, I do not want just to duplicate it here.

Leave your question or feedback

phpjsHTMLCSSSQLCode
Please, enter a comment
Please, enter a name
Incorrect email