Learn to handle AJAX requests in WordPress securely. Master wp_ajax hooks, JSON responses, and frontend communication to power your plugin's interactivity.
Previously in this course, we explored unit testing foundations to ensure our code remains robust under pressure. Now that your plugin logic is verified, it's time to make it dynamic. In this lesson, we are moving beyond traditional page reloads by implementing AJAX (Asynchronous JavaScript and XML) to allow your Knowledge Base plugin to communicate with the server in the background.
In a standard WordPress request, the browser sends a request, the server processes it, and the entire page reloads. AJAX changes this by allowing the frontend to send and receive data without a full refresh.
In WordPress, this is handled via a centralized endpoint: wp-admin/admin-ajax.php. When you send an asynchronous request to this file, WordPress spins up the environment and triggers a specific hook based on the action parameter you provide.
To handle these requests in your plugin, you need three things:
wp_ajax_{your_action}.fetch API to hit the endpoint.Let’s add an "Upvote" feature to our Knowledge Base plugin. When a user clicks a button, we want to increment a count in the database without reloading the page.
In your AdminController or a dedicated AjaxController, register your handler:
PHPadd_action('wp_ajax_kb_upvote_article', [$this, 'handle_upvote']); add_action('wp_ajax_nopriv_kb_upvote_article', [$this, 'handle_upvote']); public function handle_upvote() { #6A9955">// 1. Verify the nonce for security check_ajax_referer('kb_upvote_nonce', 'security'); #6A9955">// 2. Sanitize and validate input $article_id = intval($_POST['id']); #6A9955">// 3. Perform the logic(e.g., updating post meta) $current = get_post_meta($article_id, '_kb_upvote_count', true); update_post_meta($article_id, '_kb_upvote_count', $current + 1); #6A9955">// 4. Send a JSON response and terminate wp_send_json_success(['new_count' => $current + 1]); }
You must pass the AJAX URL and the nonce to your JavaScript file using wp_localize_script, as we covered in enqueuing scripts and styles.
PHPwp_localize_script('kb-frontend-js', 'kb_ajax', [ 'url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('kb_upvote_nonce') ]);
Now, use fetch to send the request. If you are building modern interfaces, remember that handling form submissions or fetching data from an API follows similar asynchronous patterns.
JAVASCRIPTconst upvoteArticle = async (articleId) => { const formData = new FormData(); formData.append(CE9178">'action', CE9178">'kb_upvote_article'); formData.append(CE9178">'security', kb_ajax.nonce); formData.append(CE9178">'id', articleId); const response = await fetch(kb_ajax.url, { method: CE9178">'POST', body: formData }); const data = await response.json(); if (data.success) { console.log(CE9178">'New count:', data.data.new_count); } };
wp_ajax_ hook in your plugin core to handle the ID increment and return a JSON object with wp_send_json_success().fetch to send the request and update the button text with the new count returned from the server.wp_die() or wp_send_json(): If you don't terminate the script, WordPress appends a 0 (or the whole page HTML) to your JSON response, causing a parsing error. wp_send_json_success handles this for you.wp_ajax_nopriv_: If you want logged-out users to use your AJAX features, you must hook into both wp_ajax_{action} and wp_ajax_nopriv_{action}.admin-ajax.php. Always use admin_url('admin-ajax.php') to ensure compatibility with SSL and multisite environments.check_ajax_referer to verify that the request originated from your own site's form.We’ve learned that AJAX is the backbone of modern, interactive WordPress plugins. By using wp_ajax_ hooks, we can keep our PHP logic encapsulated while providing a fluid user experience. Always remember to sanitize your inputs, verify your nonces, and output valid JSON. These practices ensure your plugin remains secure and professional as it grows.
Up next: We will move from the legacy admin-ajax system to the modern, clean approach of REST API Integration.
Master WordPress security by implementing capability checks. Learn to use current_user_can to restrict admin features and enforce proper access control.
Handling AJAX Requests
Plugin Deployment Strategy
Advanced MVC: Dependency Injection
Handling Large Datasets
Error Handling and Logging