I've created a form in Wordpress that posts data to Mailchimp using the Mailchimp API. If I use just a regular form, with an action that goes to the appropriate page, it works fine; all the data imports as expected.
However, I want to do it via an AJAX POST command. I'm sending all the same information as when doing it using a traditional posted form, but it doesn't work. The AJAX success condition triggers to show that the page loaded successfully, so there must be something in that page that isn't working.
Here's my form:
<div class="card full">
<form id="mailchimp_actions" method="post" action="/ajax-curl-actions/">
<select name="action" id="action">
<option>Subscribe</option>
<option>Unsubscribe</option>
<option>Find</option>
</select>
<textarea name="import_data" id="import_data" placeholder="Email Address,First Name,Last Name"></textarea>
<input type="submit">
</form>
</div>
Here's the page it posts to:
<?php
// Template Name: AJAX - cURL actions.
$subscribers = bfm_data_format($_POST);
$final_report = array('successes'=>0,'failures'=>array());
foreach($subscribers as $subscriber) :
$post_data = array('email' => $subscriber[0], 'fname' => $subscriber[1], 'lname' => $subscriber[2]);
$action = $_POST['action'];
if(!bfm_subscriber_exists($subscriber[0]) && $action=='Subscribe') $action = 'Add New Subscriber';
$report = bfm_curl_actions(bfm_list_id(),bfm_api_key(),$post_data,$action);
if($report['success']) :
$final_report['successes']++;
else:
$final_report['failures'][] = $report['error'];
endif;
endforeach;
?>
<h1>Import Completed</h1>
<p><?=$final_report['successes']?> records were imported successfully.</p>
<h2>Failed imports</h2>
<table>
<tr>
<th>Email</th>
<th>Reason</th>
</tr>
<?php foreach($final_report['failures'] as $failure): ?>
<tr>
<td><?=$failure['email']?></td>
<td><?=$failure['message']?></td>
</tr>
<?php endforeach; ?>
</table>
Here are the various functions that make it work:
<?php
function bfm_fudge_timeout(){
$wpmetetxt = "
# WP Maximum Execution Time Exceeded
<IfModule mod_php5.c>
php_value max_execution_time 10000
</IfModule>";
$htaccess = ABSPATH .'/.htaccess';
$contents = @file_get_contents($htaccess);
if(!strpos($htaccess,$wpmetetxt))
file_put_contents($htaccess,$contents.$wpmetetxt);
}
add_action("after_switch_theme", "bfm_fudge_timeout");
// Format data
function bfm_data_format($data) {
$import_data = $data['import_data'];
$import_data_lines = explode("\n",$import_data);
$i=0;
foreach($import_data_lines as $import_data_line) :
$import_data_lines[$i] = explode(',',$import_data_line);
$i++;
endforeach;
return $import_data_lines;
}
// MailChimp data manipulation
function bfm_curl_actions($list_id,$api_key,$post_data,$action) {
$auth = base64_encode( 'user:'.$api_key );
$data = array(
'apikey' => $api_key,
'email_address' => $post_data['email'],
'merge_fields' => array(
'FNAME' => $post_data['fname'],
'LNAME' => $post_data['lname'],
)
);
if($action == 'Subscribe' || $action == 'Add New Subscriber') :
$data['status']='subscribed';
elseif($action == 'Unsubscribe'):
$data['status']='unsubscribed';
endif;
$member_id = md5($post_data['email']);
$json_data = json_encode($data);
$ch = curl_init();
$curlopt_url = "https://us7.api.mailchimp.com/3.0/lists/$list_id/members/";
if($action!='Add New Subscriber') $curlopt_url.=$member_id; // Member ID needs to be excluded if adding an entirely new person.
curl_setopt($ch, CURLOPT_URL, $curlopt_url);
if($action == 'Subscribe' || $action == 'Unsubscribe' || $action == 'Update') :
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH");
endif;
if($action == 'Find'):
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
endif;
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json',
'Authorization: Basic '.$auth));
curl_setopt($ch, CURLOPT_USERAGENT, 'PHP-MCAPI/3.0');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);
$result = curl_exec($ch);
$status = "undefined";
$msg = "";
$myArray = json_decode($result, true);
foreach($myArray as $key => $value)
{
if( $key == "status" )
{
$status=$value;
}
else if ($key == "title")
{
$msg=$value;
}
}
$email = $post_data['email'];
if($action == 'Subscribe' || $action == 'Add New Subscriber'):
if($status == "subscribed") :
$report = array ('success'=>true,'error'=>'');
else:
$report = array ('success'=>false,'error'=>array('email'=>$email,'message'=>$msg));
endif;
endif;
return $report;
}
function bfm_subscriber_exists($email) {
$api_key = bfm_api_key();
$list_id = bfm_list_id();
$auth = base64_encode( 'user:'.$api_key );
$data = array(
'apikey' => $api_key,
'email_address' => $email,
);
$member_id = md5($email);
$json_data = json_encode($data);
$ch = curl_init();
$curlopt_url = "https://us7.api.mailchimp.com/3.0/lists/$list_id/members/$member_id";
curl_setopt($ch, CURLOPT_URL, $curlopt_url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json',
'Authorization: Basic '.$auth));
curl_setopt($ch, CURLOPT_USERAGENT, 'PHP-MCAPI/3.0');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);
$result = json_decode(curl_exec($ch),true);
if ($result['status']=='404') return false;
return true;
die(' '); // Free up memory.
}
?>
All of the above works. Here's the jQuery I'm trying to use to do the same but via AJAX, and it fails.
// MailChimp Functions
$(document).on("submit","#mailchimp_actions",
function(event) {
event.preventDefault();
var import_data = $('#action').val();
var action = $('#import_data').val();
$.post("/ajax-curl-actions/",
{
import_data: import_data,
action: action
},
function () {
alert("All done!");
}
);
}
);