WordPress AJAX uses admin-ajax.php as the endpoint. Always verify a nonce — never process requests without it.
Enqueue Script with AJAX Data
function my_plugin_enqueue_scripts() {
wp_enqueue_script(
'my-plugin-frontend',
plugin_dir_url(__FILE__) . 'assets/js/frontend.js',
['jquery'],
'1.0.0',
true // load in footer
);
// Pass AJAX URL and nonce to JavaScript
wp_localize_script('my-plugin-frontend', 'myPlugin', [
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('my_plugin_action'),
]);
}
add_action('wp_enqueue_scripts', 'my_plugin_enqueue_scripts');
Register AJAX Actions
// For logged-in users
add_action('wp_ajax_my_plugin_action', 'my_plugin_ajax_handler');
// For non-logged-in (public) users — add both for public forms
add_action('wp_ajax_nopriv_my_plugin_action', 'my_plugin_ajax_handler');
function my_plugin_ajax_handler() {
// 1. Verify nonce
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'my_plugin_action')) {
wp_send_json_error(['message' => 'Security check failed'], 403);
}
// 2. Sanitize input
$name = sanitize_text_field($_POST['name'] ?? '');
$email = sanitize_email($_POST['email'] ?? '');
$message = sanitize_textarea_field($_POST['message'] ?? '');
// 3. Validate
if (empty($name) || empty($email) || !is_email($email)) {
wp_send_json_error(['message' => 'Invalid input']);
}
// 4. Process (save to DB, send email, etc.)
// ...
// 5. Return success
wp_send_json_success(['message' => 'Submission received']);
}
JavaScript (jQuery) Request
jQuery(function($) {
$('#my-form').on('submit', function(e) {
e.preventDefault();
$.ajax({
url: myPlugin.ajaxUrl,
type: 'POST',
data: {
action: 'my_plugin_action',
nonce: myPlugin.nonce,
name: $('#name').val(),
email: $('#email').val(),
message: $('#message').val(),
},
success: function(response) {
if (response.success) {
alert(response.data.message);
} else {
alert('Error: ' + response.data.message);
}
},
error: function() {
alert('Request failed. Try again.');
}
});
});
});
Sanitization Quick Reference
| Input Type | Function |
|------------|---------|
| Plain text | sanitize_text_field() |
| Email | sanitize_email() |
| URL | esc_url_raw() |
| Integer | absint() or intval() |
| HTML content | wp_kses_post() |
| Multi-line text | sanitize_textarea_field() |
Always sanitize on input, escape on output (esc_html(), esc_attr(), esc_url()).