W
WordPress SOPKnowledge Base
Search
← All topics

WordPress AJAX Handlers

runnable

Pattern for registering WordPress AJAX actions with nonce verification for both logged-in and public users.

developmentajaxpluginsecurity
Agent trigger phrases: wordpress ajax · wp_ajax · ajax handler wordpress · wordpress form submission ajax · wp_send_json

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()).