Integrate your MailChimp Newsletter Subscription

MailChimp is a great mailing list provider with a great control panel and many useful features like: campaign management, statistics, responders and complete set of list management tools. They offer also an small code snippet to place a subscription form on your website. This form powered by jQuery is good enough for most common cases, but what if you like to combine your mailing list subscription with a standard function like contact or registration form?

The secret to make your list bigger is to integrate the opt-in function with often used functions like a registration or contact form.

In our tutorial we showcase how-to create a contact form application which will send a message and subscribes the user to a mailing list hosted by MailChimp.

Smarter Web Hosting
Hosting for developers - Free Trial!

Preparations

  • If you don’t have a MailChimp account, register one at MailChimp. They offer a free account for the first 500 mailing list members and for 3.000 messages a month. Sign-up now for free and get a $30 bonus if you upgrade your account after a while.
  • Setup a mailing list via the MailChimp control panel and obtain the Unique list ID (via the list settings page, lower left corner).
  • Now we need an MailChimp API Key, create one from the control panel (Account -> API Keys & Info)
  • As an option create a custom field (List settings -> List Fields and *|MERGE|* Tags) and name it subscription_via. Don’t change the other variables. We use this field to store the information that a subscription is done via the contact form we create.

The contact form (html code)

We need to have a simple contact form, with a field for name and e-mail address, a text-area for the message and a check-box for the subscription. The following example is very basic for a better understanding. In real you might to use an Ajax contact form (check the jQuery form plugin listed below).

<form action="process.php" method="post">
	<div>
		<label for="name">Name</label>
		<input type="text" value="" name="name" />
	</div>
	<div>
		<label for="email">E-mail</label>
		<input type="text" value="" name="email" />
	</div>
	<div>
		<label for="message">Message</label>
		<textarea name="message" cols="30" rows="4"></textarea>
	</div>
	<div>
		<input type="checkbox" value="yes" name="newsletter" />
		<label for="newsletter">Subscribe to newsletter</label>
	</div>
	<div>
		<input type="submit" value="Register" name="subscribe" />
	</div>
</form>

Using the MailChimp API with cURL

The MailChimp API has several modes on how-to communicate with the system. In this tutorial we use the simple HTTP GET/POST URL method. We request the data using cURL functions and we like to have a response which is a JSON array.

$apikey = 'Your API Key';
$listID = 'Your List';
$url = sprintf('http://api.mailchimp.com/1.2/?method=listSubscribe&apikey=%s&id=%s&email_address=%s&merge_vars[OPTINIP]=%s&merge_vars[MERGE1]=webdev_tutorials&output=json', $apikey, $listID, $email, $_SERVER['REMOTE_ADDR']);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
curl_close($ch); ID';

Update on 1st march 2012!
There is a new API version: 1.4 and it seem that newer Mailchimp accounts need to use the API on the right server location (my account is an older one where the change doesn’t exists). If you API key ends with “us2″ you need to use that string as sub domain too, like http://us2.api.mailchimp.com/1.3/. Check also the MailChimp API documentation here.

You can see that we created a string using the PHP function sprintf to add our variables. You need to use at least one merge variable, in this example we submit the users IP and a value for the custom field we created before. After the cURL request is done we get a response called $data, the JSON array.

This so far about the communication. Before we submit any data we need to check if the submitted email address is valid. I the email address is valid we send the message.

	if (preg_match("(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,})", $_POST['email'])) {
		$email = $_POST['email'];
		//
		// process here the contact form data like name and message
		mail('your@mail.com', 'Subject: contact form', $_POST['message']); // example
		//

Note this is just an e-mail example, nothing special because how-to create a safe contact or mail form is not part of this tutorial. Check out the PHPMailer tutorial if you like to use a full featured PHP email class.

Putting all stuff together

After the e-mail address is validated and the message is send we check if the checkbox was checked to send the data to the MailChimp API. Here is the complete script for the file process.php.

<?php
$apikey = 'Your API Key';
$listID = 'Your List';
 
if (isset($_POST['subscribe'])) {
	if (preg_match("(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,})", $_POST['email'])) {
		$email = $_POST['email'];
		//
		// process here the contact form data like name and message
		mail('your@mail.com', 'Subject: contact form', $_POST['message']); // example
		//
		if (!empty($_POST['newsletter'])) {
			$url = sprintf('http://api.mailchimp.com/1.2/?method=listSubscribe&apikey=%s&id=%s&email_address=%s&merge_vars[OPTINIP]=%s&merge_vars[MERGE1]=webdev_tutorials&output=json', $apikey, $listID, $email, $_SERVER['REMOTE_ADDR']);
			$ch = curl_init($url);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			$data = curl_exec($ch);
			curl_close($ch);
			$arr = json_decode($data, true);
			if ($arr == 1) {
				echo 'Check now your e-mail and confirm your subsciption.';
			} else {
				switch ($arr['code']) {
					case 214:
					echo 'You are already subscribed.';
					break;
					// check the MailChimp API for more options
					default:
					echo 'Unkown error...';
					break;			
				}
			}
		}
	}
}
?>

We’re using the PHP function json_decode to convert the JSON array into a PHP array and echo different messages upon the result. We used the most common results:

  • 1 (not an array) = conformation mail is send
  • code 214 = the submitted email address already exists
  • By default we use a standard message

Using the API this way it’s possible to have your own (translated) messages. If you like to use more different messages for different response codes, just add them into the switch statement.

Comments

  1. Thanks for providing this tutorial. Using your example, I created a form where people take part of some promotion.
    They enter their email address and just need to check the box if they like to join our mailing list.

    I created two functions:

    First I added the record to my database and send an email message about the promotion. Next I send the subscription to MailChimp.

    Works great, the frequency for new subscriptions went up for 600%

  2. Hello I can’t seem to get to work. I get an Unknown Error…
    My site is denver-photographers.net The site isn’t done by a long shot but I need I put this up so maybe someone can take a look at it and help me.

    I didn’t understand how to do this final step…
    “As an option create a custom field (List settings -> List Fields and *|MERGE|* Tags) and name it subscription_via. ”

    You say “as an option” so I was hoping it would be okay without it. If I need it can you give me a little more detail as to how this step works. Thanks.

  3. Hello Jermaine,

    I tried your form, but I can’t see the subscription option.

    About your question, yes it’s optional to custom merge fields. I use them for filters (f.e. “send via domain.com”) or if I need extra fields for later mailings.

    Using this fields in custom forms or scripts is sometimes a little tricky because the documentation on the mailchimp is not 100% clear in my opinion.

    If you have trouble with your code please post the relevant part here.

  4. You are the best! I’ve been working on this forever and you gave me the direction I needed.

    I have a slightly different form which has many other validations, so I used it like this:

    Then on to my MySQL database and happily ever after!

    THANK YOU!

  5. I had some code in there that I used and I figured I would share – yours modified – but it disappeared upon submission. Maybe the system thought it was a PHP injection. Anyway, thanks again.

  6. Hi JD,

    great that it works for you! If you put code into the “code” tags it should be visible after submission.

    If you like I can post the code for you, send me the code by e-mail (finalwebsites at gmail dot com).

  7. Hi Olaf,

    Great post, thank’s so much for keeping it active!

    I’ve copied your form and PHP script but am getting an error when I try and run it. Specifically: “Parse error: syntax error, unexpected T_IF in (URL) on line 5″

    Code is below.. Help!

    Thank you so much!
    Daniel

  8. code tags didn’t work for that.. anyway, suffice it to say the only thing I added in is my mailchimp information and email address. maybe i’m heading the file incorrectly? I’m very inexperienced with PHP!

    Here’s the link to the file via dropbox:
    http://dl.dropbox.com/u/2019793/process.php

  9. Hi Daniel,

    do you created a merge tag named “MMERGE1″ in Mailchimp?

    (I guess the T_IF error is gone?)

    PS. remove the personal information from your example file ;)

  10. Hi Olaf! Thanks for the response.. under the gun and I don’t know how to swim.

    The Merge Tags are confusing me… there already is one default in mailchimp. here’s a screenshot (via cloud app.. i recommend it).

    http://cl.ly/3M2j3V2Z3Y32400q3J28

    Also, what’s the appropriate document heading for a PHP file? is it just heading, title body?

  11. thanks for the hint, but I like to use google docs and dropbox.

    While using your form, do you receive the data except for the custom tag?

    what is this about?

    Also, what’s the appropriate document heading for a PHP file? is it just heading, title body?

    A PHP file doesn’t has a header, it’s a script

  12. Also great choices.. of which I use both.

    ignore my document heading question. looked it up. just needed the head and body tags to be semantically correct.

    When I use the form, I dont receive any information in my mailbox. The browser directions the PHP file’s URL and it gives me that parse error message.

    Really not sure where i’m going wrong.

  13. I mean if you fill in the form, is the address subscribed to the mailing list in mailchimp?

  14. No, it is not subscribed.

  15. okay, than start with a non-ajax version first: use the form and post the values to the target form (process.php). Let’s see if there are some errors ;)

  16. Oh dear. Forgive me Olaf, but I dont know how to make a non-ajax version of the form: my PHP knowledge is somewhere less than zero.

    I’m sorry to be spending your time so selfishly.

  17. Actually posting a form is not really PHP related ;)

    Just change the form to a “normal” with a regular submit button and use the process.php file as form action

  18. Oh, I see. Attempted without the subscribe section, still the same error. Sigh! Might have to walk away defeated on this one.

  19. i got an error like “unknown error” pls suggest any solution

  20. Hi,

    put this row above the one with the error message to get the error code:
    echo $arr['code'];

    Check the error code within the Mailchimp documentation.

  21. Thanks Olaf for sharing amazing article,

    I have got an error code of 104 which says invalid data center, i have checked the api key and it ends with us2. is there any changes in the mailchimp url for the specific data center.

    Thanks

  22. Hi Reyaz, do you tried contact MC about this problem?

  23. thanks olaf,

    I have managed to fix the issue by adding datacenter prefix to the url

    i have used us2.api.mailchimp.com/1.2/ instead of api.mailchimp.com/1.2/

  24. Hi Reyaz,

    thanks for sharing this information.

  25. [...] (which fires off a bunch of scripts) In the final confirmation I execute a php script (from here) to send data to mailchimp: PHP Code: <?php $apikey = 'MY API KEY'; [...]

  26. Maybe that the author at DT is reading this blog too ;)

    The code he posted seems to have problems, how does he get the variables like “$step_one["email"], $step_one["firstname"], $step_one["surname"]” ?

  27. How can I pass some value to MailChimp, for example users Name or Location?

  28. hello Mike, just follow the tutorial. :)

  29. Olaf, I have, but custom value is only mentioned for example “message” in:

    mail(‘your@mail.com’, ‘Subject: contact form’, $_POST['message']);

    But doesn’t this just sends email?

    Would it be OK if I change $_SERVER['REMOTE_ADDR'] with user’s value (for example location which i have in $location variable)? If not, how can I then pass this value to MC along with email?

  30. Mike,
    I don’t understand what you’re trying. Do try to send your “normal” email messages via mailchimp?

  31. No, I am trying to call the API and pass on the email (and location) to add to MC. But there’s code for sending message mail in example:

    // process here the contact form data like name and message
    mail(‘your@mail.com’, ‘Subject: contact form’, $_POST['message']); // example

  32. so you try to store the value of $_POST['message'] in Mailchimp?
    Add within MC an custom field and use it for that form field (like I did)

  33. I should probably include it in this like, right?

    $url = sprintf('http://api.mailchimp.com/1.2/?method=listSubscribe&amp;apikey=%s&amp;id=%s&amp;email_address=%s&amp;merge_vars[OPTINIP]=%s&amp;merge_vars[MMERGE1]=webdev_tutorials&amp;output=json', $apikey, $listID, $email, $_SERVER['REMOTE_ADDR']);

    So should I just add $location at the end, so that I have:

    $url = sprintf('http://api.mailchimp.com/1.2/?method=listSubscribe&amp;apikey=%s&amp;id=%s&amp;email_address=%s&amp;merge_vars[OPTINIP]=%s&amp;merge_vars[MMERGE1]=webdev_tutorials&amp;output=json', $apikey, $listID, $email, $_SERVER['REMOTE_ADDR'], $location);

    BTW, what is [MMERGE1]=webdev_tutorials, can this be removed or…?

  34. yes something like that, you need to add variable name and value in the order. Most important are the tests with your Mailchimp account.

  35. Hello Mike,

    the problem is the the location from the list:

    /cms1/admin/jscripts/tiny_mce/lists/images.php

    This URL does not exist.

  36. Hi Olaf, great tutorial but I’m having problems modifying it for my needs. Basically I want something much simpler.

    1) text input field (where user inputs email address)
    2) “Subscribe” button

    When the user clicks Subscribe, he is sent the Mailchimp confirmation email and sees some kind of “success” message beneath the button. There is no page reload. Can I achieve this using your tutorial?

  37. Hello Mark,
    the tutorial doesn’t use any Ajax request. I remember me there is a ready made function on the mailchimp website do you tried this one?
    (In MC: select your list, choose “for your website”, select “standard form”)

  38. Yes I have tried that one but it opens a new browser window when the user clicks “subscribe”, which isn’t ideal for user experience.

  39. Hi Mark, you need to use the “standard” form not the “slim” form. The standard form is using jQuery, if it doesn’t work there might be something wrong in the code.

  40. Hi Olaf, I don’t see a “standard” form. Do you mean the “classic” form?

  41. Yes! It’s the classic one! :)

  42. hehe, rigtht classic will not mean standard, but sometimes a classic is also the standard :)

  43. Hello, Thanks for posting!

    How do I include more custom fields? For instance I am creating a custom form that sends a question or contact via the mail function. But, i’d like to include a subscribe checkbox that while checked I could add more custom fields to mailchimp like:

    first name
    last name
    email
    question

    I declared all of the variables and the mail function is working but instead of adding to mailchimp I get the unknown error in the switch statement.

    any ideas appreciated

  44. Hi Ed,
    first include the fields in Mailchimp (test them first with one of the standard forms)
    next create the form elements on your submission page and last add the name/value pairs here:

    $url = sprintf('http://api.mailchimp.com/1.2/?method=listSubscribe&apikey=%s&id=%s&email_address=%s&merge_vars[OPTINIP]=%s&merge_vars[MMERGE1]=webdev_tutorials&output=json', $apikey, $listID, $email, $_SERVER['REMOTE_ADDR']);
  45. Thanks for your quick reply! Just to clarify. If my MMERGE1 field was Firstname would my version be[MMERGE1]=Firstname?I figured if that is the way it works would I separate them with ampersands? like so?

    $url = sprintf('http://api.mailchimp.com/1.2/?method=listSubscribe&amp;apikey=%s&amp;id=%s&amp;email_address=%s&amp;merge_vars[OPTINIP]=%smerge_vars[MMERGE1]=Firstname&amp;[MMERGE2]=Lastname&amp;[MMERGE3]=Subject&amp;output=json', $apikey, $listID, $email, $_SERVER['REMOTE_ADDR']);
  46. Ed, looks to me that the ampersand symbols are missing. Search also google for “query string” to get more information how the variable/value pairs in a URL have to look like.

  47. I have a custom php script which has a checkbox and a textbox(email address) within it for subscribing to the newsletter. Will the above code work for my needs?

  48. Hi, it should work if you change your HTML a little bit (use the same names for the fields email and the subscribe checkbox).

  49. Hi I’m using this:

    $url = sprintf('http://us2.api.mailchimp.com/1.3/?method=listSubscribe&amp;apikey=%s&amp;id=%s&amp;email_address=%s&amp;merge_vars[OPTINIP]=%s&amp;merge_vars[MMERGE1]=firstname&amp;output=json', $api, $list_id, $emailaddress, $merge_vars, $ffname, $_SERVER['REMOTE_ADDR']);

    but the name posted in the firstname field is just firstname…any help?

  50. Hi David,

    replace
    merge_vars[MMERGE1]=firstname
    with
    merge_vars[MMERGE1]=%s

    and it will work :)

  51. thank you for your reply.

    I now get no information in the firstname feild.

  52. David, you need to check the (form) variable name/value for $ffname.
    If you want me to check your code please post it @pastebin.com (posting code using the comment form doesn’t work)

  53. pastbin.com seems to be dead. the Field name and value of my form is “firstname”. I use .$_POST["firstname"]. When sending through the form entries to my email.

    I’ve also tried defining this $firstname then merge_vars[MMERGE1]=$firstname but mailchimp shows the first name as “$firstname” rather than the entry. I’ve also tried echoing this variable with the same result.

  54. Sorry it’s “pastebin.com”, what happens if you output the post array to your screen (print_r($_POST);)

  55. Thank you for posting this. I am having an issue (I’m sure it’s something that I’m screwing up)
    when I replace

    merge_vars[MMERGE1]=firstname
    with
    merge_vars[MMERGE1]=%s

    I get an error of:
    Warning: sprintf() [function.sprintf]: Too few arguments on line 43
    Unkown error…

    This is the $url I’m using:

    $url = sprintf('http://us4.api.mailchimp.com/1.3/?method=listSubscribe&amp;apikey=%s&amp;id=%s&amp;email_address=%s&amp;merge_vars[OPTINIP]=%s&amp;merge_vars[MERGE1]=%s&amp;output=json', $apikey, $listID, $email, $_SERVER['REMOTE_ADDR']);

    Any ideas?

  56. Hi Ben,

    there is an error in your sprintf function:

    The value for MERGE1 is missing at the end (after $_SERVER['REMOTE_ADDR'])

    Don’t forget to define MERGE1 as field in your Mailchimp backend.

  57. It works now. Thank you Olaf. That was helpful.

  58. Olaf, I think this tutorial is what I want/need, but it reads as greek to me :) I already have a contact form on my website that sends me an email when someone fills it out. Right now there is a checkbox to subscribe to my email newsletter. Right now if they leave that box checked, I have to manually enter them into my database. What part of this code can I use to create a checkbox (that is checked by default) that integrates with Mailchimp so that not only do I get a copy of their contact form, but Mailchimp is notified too and adds them to my mailing list? Thanks! You can view my website to see how it is set up now if you wish.

  59. Hello Lori,
    Your site looks really good, but has technically a very bad concept (reading your code looks like Greek too, hehe).
    It’s not a big problem to use that code together with a contact form on a “regular” website, but I’m afraid it will break your current site (or someone has to investigate all client site scripts first).
    Maybe you like to switch to WordPress, there are a lot of photography websites created with that CMS. Using WordPress it’s much easier too solve these problems and your site is able to get much more traffic from Google.

Because of all the spam attemps I've decided to close the comment form at this time. If you have have any questions or comments please post them by using Google+ or Twitter (the links to my profiles are located at the top of this page).