MailChimp ya ofrece todo lo necesario para utilizar los formularios de suscripción con Ajax. Pero viene con un problemilla: hay que cargar varios scripts externos. Para todos los que esta idea no nos gusta ni un pelo, MailChimp ofrece un API JSON excelente para comunicaciones Ajax. En este tutorial vamos a aprender a enviar un formulario de suscripción MailChimp con Ajax utilizando jQuery. Como es una solicitud cross-domain, utilizaremos el formato JSONP para el intercambio de datos.

1

El formulario

Para el formulario podemos utilizar el HTML generado desde la interfaz de MailChimp o puedes crear el tuyo propio. Por ejemplo, este es el que yo utilizo en el formulario de suscripción que puedes en esta misma página:

<form action="https://cybmeta.us8.list-manage.com/subscribe/post?u=e64350b5b9ffb665f6bcb3179&amp;id=ddf5e05cc8" method="post" id="subscription-form" role="form">
    <div class="form-group">
        <label for="mce-EMAIL" class="sr-only">Email address</label>
        <input type="email" placeholder="Introduce tu email" name="EMAIL" id="mce-EMAIL" class="form-control input-lg">
    </div>
    <div style="display:none;" class="alert notification-container small"></div>
    <div style="position: absolute; left: -5000px;"><input type="text" value="" tabindex="-1" name="b_e64350b5b9ffb665f6bcb3179_ddf5e05cc8"></div>
    <button id="mailchimp-submit" data-original-text="Suscribir" name="submit" class="btn btn-primary btn-lg btn-block" type="submit">Suscribir</button>
</form>

He tomado el formulario “Ultra Slim” directamente de MailChimp. Sólo he modificado el HTML para ajustarlo al marcado de mi CSS, lo importante del formulario se deja tal cual (los atributos action, method, name). Sólo he añadido el div de clase notification-container dónde pondré los mensajes recibidos en la respuesta Ajax. Si tomas el formulario estándar de MailChimp acuérdate de eliminar la carga de scripts externos.

2

API JSON de MailChimp

El API JSON de MailChimp está poco documentada y es bastante difícil de encontrar. Para acceder a ella toma la URL del action del formulario y cambia post por post-json. Por ejemplo:

https://cybmeta.us8.list-manage.com/subscribe/post?u=e64350b5b9ffb665f6bcb3179&id=ddf5e05cc8

por

https://cybmeta.us8.list-manage.com/subscribe/post-json?u=e64350b5b9ffb665f6bcb3179&id=ddf5e05cc8

A esta URL será a la que enviaremos la solicitud Ajax. Pero ojo, no pongas esta URL como action del formulario (como dicen en otros tutoriales) o no te funcionará para usuarios sin javascript. Esta URL la utilizaremos en el parámetro url de la función $.ajax de jQuery.

La respuesta JSON obtenida tiene esta estructura:

{
    "result":"error|success",
     "msg":"Mensaje de error o éxito"
}
3

Envío via Ajax

Ya tenemos el formulario, tenemos la URL a la que hacer la solicitud Ajax, y tenemos la estructura de la respuesta. Ya sólo nos queda el código jQuery que nos haga la magia.

//Al hacer click en el botón del formulario
$('#mailchimp-submit').on('click', function(e) {

     e.preventDefault();

     var submit_input = $('#mailchimp-submit');
     var notification_container = form.find('.notification-container');

     submit_input.html('Suscribiendo...');

      $.ajax({
          // Cambia por la URL de tu lista de correo
          url: "//cybmeta.us8.list-manage.com/subscribe/post-json?u=e64350b5b9ffb665f6bcb3179&id=ddf5e05cc8",
          // Serializamos los datos del formulario para pasarlos a pares query=value
          data: form.serialize(),
          dataType: 'jsonp',
          // Nombre de la función callback requerido por el API de MailChimp
          jsonp: 'c'
       }).done(function(data){
     
            if (data.result != "success") {
                    //Si el resultado no es "sucsess" mostramos el mensaje
                    //Y devolvemos el botón de envío a su estado original
                    notification_container.html(data.msg).show();
                    submit_input.html(submit_input.attr('data-original-text'));
            } else {
                    //Si el resultado es "sucsess" mostramos el mensaje
                    //Y escondemos el botón de envío
                    notification_container.html('¡Hecho! Comprueba tu bandeja de entrada para confirmar la suscripción.').show();
                    submit_input.hide();
            }

        }).fail(function(err){
                //Ha habido algún error en la comunicación
                notification_container.html("Lo sentimos. No se pudo conectar con el servidor de registro. Por favor, inténtalo de nuevo pasados unos minutos.").show();
                submit_input.html(submit_input.attr('data-original-text'));
            
        });
});

Puedes personalizar a tu gusto, como en los mejores restaurantes. Por ejemplo, yo he añadido algunos efectos y cambios de clase CSS según el resultado. Este es el código que estoy utilizando en el formulario de la newsletter de esta web (compatible con jQuery.noConflict()):

(function($){
 
  $('#mailchimp-submit').on('click', function(e) {
    e.preventDefault();
    send_form($('#subscription-form'));
  });
 
  function send_form(form) {
 
    var email_input = $('#mce-EMAIL');
    var submit_input = $('#mailchimp-submit');
    var notification_container = form.find('.notification-container');
 
    email_input.removeClass('has-error');
    submit_input.css('background-image', 'url("//cybmeta.com/wp-content/plugins/mailing/images/loading.gif")').css('background-repeat', 'no-repeat').html('Suscribiendo...');
 
    $.ajax({
      url: "//cybmeta.us8.list-manage.com/subscribe/post-json?u=e64350b5b9ffb665f6bcb3179&id=ddf5e05cc8",
      data: form.serialize(),
      dataType: 'jsonp',
      jsonp: 'c'
    })
    .done(function(data){
 
      if (data.result != "success") {
        submit_input.css('background-image', 'none').html(submit_input.attr('data-original-text'));
        email_input.addClass('has-error');
        notification_container.addClass('alert-danger').html(data.msg).show();
      } else {
        email_input.removeClass('has-error');
        notification_container.removeClass('alert-danger').addClass('alert-success').html('¡Hecho! Comprueba tu bandeja de entrada para confirmar la suscripción.').show();
        submit_input.hide();
      }
    })
    .fail(function(err){
      notification_container.addClass('alert-danger').html("Lo sentimos. No se pudo conectar con el servidor de registro. Por favor, inténtalo de nuevo pasados unos minutos.").show();
      submit_input.css('background-image', 'none').html(submit_input.attr('data-original-text'));
    });
 
    return form;
  } 
 
})(jQuery);

Ya está listo. Ya podemos utilizar el formulario de suscripción de MailChimp con Ajax. Más fácil imposible, aunque seguro que se puede hacer mejor. Si tienes sugerencias, no te las quedes.

  • Omar García

    Hola, en esta parte de código tengo 3 dudas:

    $.ajax({
    type: "GET",
    url: "http://cybmeta.us8.list-manage.com/subscribe/post-json?u=e64350b5b9ffb665f6bcb3179&id=ddf5e05cc8&c=?",
    data: form.serialize(),
    cache: false,
    dataType: 'jsonp',
    contentType: "application/json; charset=utf-8"

    1-¿Por qué Get y no Post?
    2-¿Por qué jsonp y no solo json?
    3-En la parte del data ¿cómo se envían realmente los datos? Sé que en json es llave-valor pero en este ejemplo los estaríamos enviando algo así como: data: email-input=correo@correo.com.

    De antemano gracias.

    • Hola Omar.

      Primero decirte que la solicitud Ajax, en este caso, se realiza entre dos dominios diferentes (cross-domain), entre un dominio cualquiera y MailChimp. Partidendo de ahí, te voy a responder tus preguntas en orden 2, 1 y 3.

      2.- JSONP es JSON con padding; no es más que el JSON “envuelto” como si fuera una función javascript. Las solicitudes Ajax entre diferentes dominios están prohibidas (same-origin policy), pero las solicitudes de scripts no. Si la respuesta Ajax desde el otro dominio es en formato JSONP podemos solicitarlo como un script normal, lo que no está prohibido entre diferentes dominios. En resumen, JSONP es una técnica, la más extendida hoy en día, para realizar solicitudes Ajax cross-domain, y es la que ofrece MailChimp, por eso JSONP y no JSON.

      1.- Las solicitudes JSONP, como te decía antes, se tratan como solicitudes de scripts y estas solicitudes no pueden ser por método POST, sólo GET (de todas formas, como estamos utilizando el API de un tercero, estamos limitados al método de solicitud que ese tercero admita).

      3.- Como la solicitud es GET, todos los parámetros se envian como query string en la URL, esto es, toda la parte del tipo ?param=valor&param2=valor2 de la URL.

      Y gracias por la pregunta, me ha hecho actualizar el post con una o dos frases más que creo que lo hacen un poco más claro. También he quitado parámetros de la solicitud ajax que jQuery establece por defecto al utilizar JSONP y que no eran necesarios. Por ejemplo, al utilizar JSONP, el método es automáticamente GET y no se puede cambiar.

    • Omar García

      Muchas gracias por responder de forma tan completa. He estado tratando de hacer pruebas, utilizando el segundo script que pones y siempre me sale el mensaje: “Blank email address”. ¿Alguna idea?

      Como detalle, me queda la duda, en el post mencionas: “deja tal cual (los atributos action, method, name)”, pero en tu html no hay name para el form, ¿no es necesario el name?

    • No hay atributo name en el elemento form pero sí en el elemento input dónde se introduce el email.

      Por otro lado, imposible de decirte por qué no funciona sin tener más información o ver exactamente el código que estás utilizando. Puede que se deba al atributo name del input del que hablaba antes.

    • Omar García

      Te comparto el código, ojalá tengas un minutos para revisarlo. ¡Gracias!


      <!DOCTYPE html>

      Nuevo

      Email address

      Suscribir

      (function($){

      $('#mailchimp-submit').on('click', function(e) {

      e.preventDefault();

      send_form($('#subscription-form'));

      });

      function send_form(form) {

      var email_input = form.find('.email-input');

      var submit_input = form.find('.submit-input');

      var notification_container = form.find('.notification-container');

      alert("Hola " + form.serialize());

      $.ajax({

      // Cambia por la URL de tu lista de correo

      url: "//ronineducacion.us10.list-manage.com/subscribe/post-json?u=cfbfcef28cdfdc1333e3d7072&id=154aff13b9",

      data: form.serialize(),

      dataType: 'jsonp',

      jsonp: 'c'

      }).done(function(data){

      if (data.result != "success") {

      submit_input.css('background-image', 'none').html(submit_input.attr('data-original-text'));

      notification_container.addClass('alert-danger').html(data.msg).show();

      } else {

      notification_container.removeClass('alert-danger').addClass('alert-success').html('¡Hecho! Comprueba tu bandeja de entrada para confirmar la suscripción.').show();

      submit_input.hide();

      }

      }).fail(function(err){

      notification_container.addClass('alert-danger').html("Lo sentimos. No se pudo conectar con el servidor de registro. Por favor, inténtalo de nuevo pasados unos minutos.").show();

      submit_input.css('background-image', 'none').html(submit_input.attr('data-original-text'));

      });

      return form;

      }

      })(jQuery);

    • Como decía, no puedes cambiar el atributo name:

      Esto:

      Debería ser:

      Puedes cambiar todos los demás atributos a tu gusto, pero no el atributo name ya que este el atributo utilizado para construir el query string que se envia a MailChimp y el email es necesario enviarlo como EMAIL=.

    • Omar García

      Muchas gracias por tu tiempo