Create a gist now

Instantly share code, notes, and snippets.

@jdennes /LICENSE
Last active Nov 17, 2017

What would you like to do?
Subscribing to a Campaign Monitor list using AJAX
<!-- 1. Take your Campaign Monitor subscribe form as generated through the app: -->
<form action="" method="post" id="subForm">
<label for="name">Name:</label><br /><input type="text" name="cm-name" id="name" /><br />
<label for="aljhk-aljhk">Email:</label><br /><input type="text" name="cm-aljhk-aljhk" id="aljhk-aljhk" /><br />
<input type="submit" value="Subscribe" />
<!-- 2. Add some JavaScript -->
<script type="text/javascript" src=""></script>
<script type="text/javascript">
$(function () {
$('#subForm').submit(function (e) {
this.action + "?callback=?",
function (data) {
if (data.Status === 400) {
alert("Error: " + data.Message);
} else { // 200
alert("Success: " + data.Message);
<!-- 3. AJAX subscription to your list! -->

jdennes commented Aug 18, 2011

This is enabled by JSONP callbacks. We allow the name of a callback function to be specified in the query string (which is only allowed to contain alphanumeric characters and underscores):

Which will return you a result as JSON, padding with a function named by your callback value. Something like:

  "Status": 400,
  "Message": "Sorry, but the email address you supplied was invalid and needs to be fixed before you can subscribe to this list.",
  "RedirectUrl": null

The resulting JavaScript object has three fields:

Status: A number representing the subscription status. 200 if subscription was successful, or 400 if subscription was unsuccessful.
Message: A string containing a message which describes the subscription status.
RedirecUrl: A string containing a redirect URL, only if subscription is successful and you have set up a redirect URL for the list in your account, otherwise null.

These are the possible values for the Message field (as of the time of writing, but subject to potentially changing):

When Status is 200 (Success Messages)

  • Your subscription has been confirmed. You've been added to our list and will hear from us soon.
  • You've just been sent an email to confirm your email address. Please click on the link in this email to confirm your subscription.

The difference between these two messages is determined by whether or not your list is a double opt-in, so you can display whatever message you prefer.

When Status is 400 (Failure Messages)

  • Invalid callback. Callback value may only contain alphanumeric characters and underscores.
  • This subscribe form requires that you fill in a CAPTCHA to be added to the list.
  • Sorry, but the email address you supplied was invalid and needs to be fixed before you can subscribe to this list.

The error conditions causing the first two failure messages should be discovered during form setup and testing, so once the form is setup and operating the only real reason for failure is an invalid email address.

Hrmm, this looks awesome, but seems to be erroring out a bit for me.
I get “Message: "Sorry, but the email address you supplied was invalid and needs to be fixed before you can subscribe to this list."” on every submission. :/


jdennes commented Sep 5, 2011

Does your form work successfully without the additional js (i.e. in a non-ajax way)? If you can point me to where the form is, I can take a look...


jdennes commented Sep 5, 2011

I emailed you the test I used to test this in your account (js only - no Coffeescript). Hope that helps.


How can i add the functionality so that it requires the name field to be filled?

Thanks in advance,


jdennes commented Sep 5, 2011

Hey Sam, we don't offer an option to enforce that server-side, but you can easily achieve it client-side. We have a blog post detailing how to do this using the jQuery validate plugin.

I'm not able to get additional mailing-list checkboxes to submit when using this AJAX script. I've tested the serialized string and that contains all the information and the name and email address are added to the default mailing list, but no records are adding to the additional mailing-lists. I was also having the same problem with custom fields initially so I chose the multiple list option instead.

It works fine without jquery, but with jquery I only seem to get the basic name/email data?

Any assistance would be greatly appreciated.

You can see the existing form here


jdennes commented Sep 7, 2011

Hey Luke, I've fixed an issue which was causing some issues with that, so you shouldn't have a problem with that now. Let us know if you do.

poudro commented Oct 8, 2011


The default code broke when using mootools, thought I might share what I came up with if anyone else is interested. The default behaviour of the Mootools JSONP class creates a callback function with a "." character in its name, as this is forbidden (cf first comment in this thread "which is only allowed to contain alphanumeric characters and underscores"), it is necessary to override this default behavior and use a custom function as the callback.

      window.mySubFormCallBack = function(data)
        if (data.Status === 400) {
            alert("Error: " + data.Message);
        } else { // 200
            alert("Succes: " + data.Message);

      $('subForm').addEvent('submit',function (e) {
          new Request.JSONP(
              callbackKey: "override"
          return false;


If an active subscriber of a double opt-in list subscribes again through the AJAX form, the success message is still displayed and tells him he will receive a confirmation email, which is never sent by the system. How to display a specific message (already a subscriber) in this case?


Works like a charm, thanks!

Hi franckmartin,

I'm afraid the form submission endpoint just doesn't provide that kind of information. If you're looking to distinguish between those cases, you'll need to incorporate the API and check the subscriber's state before attempting to add them to the list.

moniarde commented Mar 2, 2012


How can I incorporate the JSON call with the following jQuery from a SimpleModal window?

                    function () {
                        $('#contact-container .contact-loading').fadeIn(200, function () {
                                url: 'http://***',
                                data: $('#contact-container form').serialize() + '&action=send',
                                type: 'post',
                                cache: false,
                                dataType: 'html',
                                success: function (data) {
                                    $('#contact-container .contact-loading').fadeOut(200, function () {
                                        $('#contact-container .contact-title').html('Thank you!');
                                error: contact.error

nubz commented Sep 14, 2012

banging my head a bit - every submission comes back with invalid email error - including valid email addresses that are not on the list - using a double-opt-in if that makes any difference, but it's the same if I set it to single-opt-in

funkyboy commented May 7, 2013

Is this service still up and working as described?
I get a "Error: This subscribe form requires that you fill in a CAPTCHA to be added to the list."

Alternative, to use jQuery's built in support for JSONP, to avoid having to manually append the callback parameter to the URL:

Not tested, code might need syntax tweaks.

jordxn commented Nov 29, 2013

Seems like this doesn't work for the unsubscribe form? All I get back is html even with the same jsonp call as above :( It would be awesome if they did add support for it!

elmalto commented Jan 27, 2016

for angular, short snippet:

change YOUR_URL to the action url and EMAIL_FIELD_NAME to your email field name. Other fields accordingly

    $scope.addSubscription = function (email) {

          var url = 'YOUR_URL?callback=JSON_CALLBACK&EMAIL_FIELD_NAME=' + email;

            function (response) {
              if ( && === 400) {
                // process error
              else if (  && === 200) {
              // process success
            function (error) {
              // process failure
              console.error('Signup Error: %o', error);

llos commented Mar 18, 2016

I have SSL in my website and I can't use this code because of this error:

jquery.js?ver=1.11.3:5 Mixed Content: The page at 'https://www.../' was loaded over HTTPS, but requested an insecure script '…726137_1458306406869&cm-blleu-blleu=...'. This request has been blocked; the content must be served over HTTPS.

Any ideas of how can I use it over HTTPS?


petsto commented Mar 31, 2016

Works like a charm! Thank you!

Hi, I'm not getting any errors saying the email has already subscribed (already in the list) it just keeps giving me a success message. I think this would be a nice feature.

v1har commented Mar 15, 2017

Hey guys,

I just want to share my experience. If you can not use this code on your website, so the getJSON (submitting) is not working, try "https" instead of "http" in the form action! It helped me :)

I hope, it was a helpful information for you. ;)

mrmema commented May 12, 2017

need help pls, how to check if the email submitted is already on the campaign monitor list and get back a respond?
I am using the form to generate a coupon code ones the user provide the email BUT coupon must be generate ONLY if that email is unique on the campaign monitor list. Right now I am getting back all the time 200 even when the email is already on the list.

Can any one please tel how to check email is already their in list , Currently form allows me to add same email id n number of times, it should say "Email is already exist use differnt one"


gentle-media commented Jun 6, 2017

A lot of cries to add the response 'Email address already exist' to the 400 status. I also think this should be a default instead of resorting to the API for this.

jnsprngs commented Jun 16, 2017


In case someone wanted a vanilla javascript example....

<form id="subForm" action="" method="post">
	<label for="fieldEmail">Email</label><br />
	<input id="fieldEmail" name="cm-mkriuy-mkriuy" type="email" required />
	<button type="submit">Subscribe</button>
	<div id="messageDiv"></div>

var callbackFnName = function(res) {
	document.getElementById('messageDiv').innerHTML = res.Message;

var targetForm = document.getElementById('subForm');
targetForm.addEventListener('submit', function(e) {
	var emailField = document.getElementById('fieldEmail');
	var keyValues = [];
	keyValues.add = function(k,v) {
		return this;
	var query = function(arr) {
		return '?' + arr.join('&');
	keyValues.add('callback', 'callbackFnName').add(, emailField.value);
	var url = this.action + query(keyValues);
	var r = new XMLHttpRequest();, url, true);
	r.onreadystatechange = function() {
		if(r.readyState === 4) {
			var res = document.createElement('script');
			res.type = 'text/javascript', res.async = 1, res.innerHTML = r.responseText;
			var s = document.getElementsByTagName('script')[0];
	r.timeout = 3000;
	r.onerror = function() {console.log(this);}
}, false);

For anyone interested, you can't post data to the Campaign Monitor API using a custom sub domain with an SSL. For example, this would not work:
<form id="subForm" action="" method="post">
To make this work, use:
<form id="subForm" action="" method="post">
Or this:
<form id="subForm" action="*" method="post">
Hope this helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment