Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Use AJAX in WordPress when a page must send or receive data without a full browser reload. The usual pattern is: enqueue a JavaScript file, pass it the site’s generated admin-ajax.php URL and a nonce, send an action value, handle the JSON response, and register matching PHP hooks. Protect the callback with nonce verification, input validation and a capability check; use the REST API instead when you are designing a reusable, resource-oriented endpoint.
Antihost offers managed WordPress hosting with free migration, one-click staging and a 14-day free trial.
What AJAX does in WordPress
AJAX is a browser request that retrieves information or submits data asynchronously, then updates part of the current page. The visitor can search, filter, save, vote or submit a form while the rest of the document remains in place. WordPress commonly returns JSON, so “AJAX” does not require an XML response.
As an Amazon Associate I earn from qualifying purchases.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWordPress has two practical interfaces for this work:
- Classic AJAX: requests go to the site-specific
wp-admin/admin-ajax.phpendpoint and identify a PHP callback with anactionvalue. - REST API: requests go to a registered route such as
/wp-json/...and model a resource or operation directly.
For a small interaction inside a theme or plugin, classic AJAX is often the fastest implementation. For an API that multiple pages, applications or integrations will reuse, a REST route normally gives you a clearer contract.
#1 Best Overall
The classic WordPress AJAX request lifecycle
A working request connects five pieces. If one name or hook does not match, the callback will not run.
- PHP enqueues the JavaScript through WordPress and supplies the generated AJAX URL.
- PHP creates a nonce for the operation and exposes it to the script.
- JavaScript sends the URL, an
action, the nonce and any form values. - WordPress dispatches the request to
wp_ajax_<action>for logged-in users orwp_ajax_nopriv_<action>for logged-out users. - The callback verifies the nonce, checks authorization, validates input and returns a predictable JSON success or error response.
The endpoint is not necessarily the same on every installation. Subdirectory sites, multisite setups and unusual configurations make hardcoded paths fragile, so generate it with admin_url( 'admin-ajax.php' ) and pass it to the browser.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Step 1: Enqueue the script and pass configuration
Load the file with WordPress rather than adding a raw <script> tag. On a front end, use wp_enqueue_scripts. On an administration screen, use admin_enqueue_scripts and restrict loading to the relevant screen.
<?php
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_script(
'my-plugin-ajax',
plugin_dir_url( __FILE__ ) . 'assets/ajax.js',
array( 'jquery' ),
'1.0.0',
true
);
wp_localize_script(
'my-plugin-ajax',
'myAjax',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'my_plugin_action' ),
)
);
} );
wp_localize_script() prints a JavaScript object before the enqueued file. In this example the browser receives myAjax.ajaxUrl and myAjax.nonce. The object name must be a valid, unique JavaScript identifier. Although the function was named for translated strings, it is also the established way to pass small PHP-generated configuration values to a script.
Do not expose secrets in this object. A nonce is intentionally visible to the browser; it helps prove that a request came from a page generated for your site, but it is not a password.
Rank #2
Since WordPress 6.5, script modules can be loaded with wp_enqueue_script_module(). Modules do not change the AJAX protocol: pass the generated endpoint and nonce to the module, then send the same action and security fields.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesStep 2: Send the request from JavaScript
Using jQuery
If the script depends on WordPress’s bundled jQuery, jQuery.post() is a concise option.
jQuery.post(
myAjax.ajaxUrl,
{
action: 'my_plugin_action',
_ajax_nonce: myAjax.nonce,
value: document.querySelector('#value').value
}
).done(function (response) {
if (response.success) {
document.querySelector('#result').textContent = response.data.message;
} else {
document.querySelector('#result').textContent = 'The request was rejected.';
}
}).fail(function () {
document.querySelector('#result').textContent = 'The server could not be reached.';
});
The string my_plugin_action must exactly match the suffix in the PHP hooks. The conventional nonce field is _ajax_nonce; that is what check_ajax_referer() checks by default. Handle both the JSON-level success: false result and a transport failure such as a network error or an invalid server response.
Using the Fetch API
Modern JavaScript can submit the same fields with fetch(). Because PHP examples usually read $_POST, encode the body as URL-encoded form data.
const form = new URLSearchParams({
action: 'my_plugin_action',
_ajax_nonce: myAjax.nonce,
value: document.querySelector('#value').value
});
fetch(myAjax.ajaxUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
body: form.toString()
})
.then((response) => response.json())
.then((response) => {
const result = document.querySelector('#result');
result.textContent = response.success
? response.data.message
: 'The request was rejected.';
})
.catch(() => {
document.querySelector('#result').textContent = 'The server could not be reached.';
});
The method can be GET for a read-only operation, but use the method your callback and caching policy expect. For changes to site data, POST is the safer normal choice.
Recommended Free Tools
Rank #3
Step 3: Register and secure the PHP callback
Register the logged-in hook for authenticated users. Add the logged-out hook only when the feature is intentionally available to visitors who are not signed in.
<?php
add_action( 'wp_ajax_my_plugin_action', 'my_plugin_action' );
add_action( 'wp_ajax_nopriv_my_plugin_action', 'my_plugin_action' );
function my_plugin_action() {
check_ajax_referer( 'my_plugin_action' );
if ( ! current_user_can( 'read' ) ) {
wp_send_json_error(
array( 'message' => 'Permission denied.' ),
403
);
}
$value = isset( $_POST['value'] )
? sanitize_text_field( wp_unslash( $_POST['value'] ) )
: '';
wp_send_json_success(
array( 'message' => 'Received: ' . $value )
);
}
wp_create_nonce( 'my_plugin_action' ) and check_ajax_referer( 'my_plugin_action' ) must use the same action name. The verification call rejects a missing, stale or mismatched nonce and stops the callback unless you explicitly choose a different failure behavior.
The capability test is separate and essential. Nonces are not authentication and do not authorize an operation. For an administrator-only change, check the capability that actually protects that setting, such as an appropriate management capability, rather than relying on a generic check. For a logged-in user feature, check the capability or ownership rule that applies to that user.
The sample registers wp_ajax_nopriv_ but then requires the read capability. That combination will deny normal logged-out visitors because they have no WordPress user capability. Keep the capability check for a signed-in operation and omit the public hook, or design a genuinely public callback with appropriate rate limits, validation and abuse controls. Never remove authorization merely to make a request work.
Validate, sanitize and return a stable response
Sanitizing input is not the same as deciding whether the input is allowed. Apply the function that matches the field, then validate its meaning and limits before using it.
Rank #4
- Use
wp_unslash()before processing values read from request arrays. - Use
sanitize_text_field()for a simple text value, but do not use it as a substitute for validating an email, integer, URL, identifier or selected option. - Check required fields, allowed values, numeric ranges and object ownership in PHP; browser-side checks can be bypassed.
- Escape data for its output context. In the example, assigning to
textContentavoids interpreting returned text as HTML. - Return
wp_send_json_success()orwp_send_json_error()instead of printing arbitrary markup or PHP warnings.
Successful responses conventionally contain {"success":true,"data":...}; errors contain success: false and can include a message or structured error data. A suitable HTTP status, such as 403 for a permission failure, helps clients distinguish authorization errors from a successful request whose business result happens to be negative.
How logged-in and logged-out requests differ
| Visitor state | Required PHP hook | Typical use | Security decision |
|---|---|---|---|
| Signed in | wp_ajax_<action> |
User-specific data, account actions or administration | Check the capability and, where relevant, ownership of the record |
| Signed out | wp_ajax_nopriv_<action> |
Deliberately public searches, previews or submissions | Do not assume a nonce makes it safe; validate aggressively and consider throttling and spam controls |
WordPress chooses the hook based on the visitor’s authentication state. If a public visitor sends the correct action but only wp_ajax_<action> is registered, no callback will handle the request. Conversely, adding the nopriv hook exposes an operation to the public, so make that an intentional product and security decision.
Classic AJAX or the REST API?
Both approaches can return JSON and both can be secured. Choose according to the shape and expected lifetime of the interface rather than by habit.
| Decision point | admin-ajax.php |
REST API route |
|---|---|---|
| Endpoint model | One site-specific endpoint; an action selects a PHP hook |
A named route represents a resource or operation |
| Best fit | A focused interaction in one theme or plugin screen | A durable interface reused by several pages, applications or integrations |
| Authentication and nonce | Usually a WordPress AJAX nonce in _ajax_nonce, verified with check_ajax_referer() |
For cookie-authenticated requests, create a wp_rest nonce and send it in X-WP-Nonce or _wpnonce |
| Dispatch | wp_ajax_<action> and optionally wp_ajax_nopriv_<action> |
Registered route, HTTP method, permission callback and route arguments |
| Reuse outside the current page | Possible, but callers must know the action-based contract | Designed for clients that consume a resource-oriented contract |
| Public versus user-specific work | Either is possible; you must register the appropriate hook and write the authorization logic | Either is possible; define a route permission callback and authentication method |
Use a REST route when the feature is naturally “list, read, create, update or delete this resource,” or when another client will consume it later. Use classic AJAX when a small page interaction already fits a single callback and there is no benefit in designing a broader API.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Calling a WordPress REST route securely
A REST implementation begins by registering a route with a permission callback and a callback that returns data. The exact route, schema and capability depend on the resource, so do not treat a REST URL as a replacement string for admin-ajax.php.
Best Value
For a browser request authenticated by WordPress cookies, create a nonce with the wp_rest action and send it in the X-WP-Nonce header. The nonce can also be supplied as the _wpnonce parameter. The route’s permission callback must still enforce the required capability; the nonce does not grant access.
fetch('/wp-json/my-plugin/v1/items', {
headers: {
'X-WP-Nonce': myRest.nonce
}
})
.then((response) => response.json())
.then((items) => {
// Render the resource returned by the route.
});
For authenticated external REST calls, WordPress Application Passwords are available beginning with WordPress 5.6. They are intended for API authentication, not for exposing a browser page’s secret. Choose the authentication method that matches the client and never embed a long-lived credential in front-end JavaScript.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Admin-screen and performance considerations
On an administration screen, attach the enqueue callback to admin_enqueue_scripts. Use the supplied screen identifier to load the AJAX file only where it is needed. Loading the script site-wide increases page weight and expands the number of places where an interface can be triggered without providing a benefit.
AJAX removes a full-page navigation; it does not make server work free. Keep database queries bounded, return only the fields the interface needs, and prevent duplicate submissions while a request is pending. For expensive jobs, an asynchronous request may need to start work and poll a status resource rather than hold the browser request open.
Troubleshooting: find the failing layer
The request never reaches the callback
- Open the browser’s Network panel and confirm the request URL is the localized
admin-ajax.phpvalue, not a guessed path. - Confirm the request method and inspect the submitted form data.
- Verify that
actionis present and is spelled exactly like the PHP hook suffix. - Determine whether the browser is logged in. A logged-in request needs
wp_ajax_<action>; a logged-out request needswp_ajax_nopriv_<action>.
The response says the nonce is invalid
- Check that PHP created the nonce with the same action string passed to
check_ajax_referer(). - Check that JavaScript sends the expected field, normally
_ajax_nonce. - Regenerate the value through the enqueue and localization path if the page was cached with an old nonce.
- Make sure the request is using the nonce intended for classic AJAX, not a REST
wp_restnonce or vice versa.
The callback runs but the browser cannot parse the response
Look for PHP notices, warnings, debugging output or accidental HTML printed before the JSON. Return responses through wp_send_json_success() and wp_send_json_error(), and inspect the raw Network response. The JavaScript should handle both the structured error branch and a non-JSON transport failure.
A public request is always denied
Review the authorization logic. A callback registered for wp_ajax_nopriv_ still cannot pass a capability check that requires a signed-in user. Decide whether the operation should be authenticated; then either require login and register only the authenticated hook, or build a genuinely public flow with controls appropriate to anonymous traffic.
Free tools Windows power users keep installed
One-click scans. No signup required.
The feature works on one site but not another
Check that the endpoint came from admin_url( 'admin-ajax.php' ) rather than a hardcoded root path. Also inspect caching, HTTPS mixed-content errors, script dependencies and whether the file was enqueued on the page where the UI appears.
A practical implementation checklist
- Load the script with
wp_enqueue_script(), or usewp_enqueue_script_module()for a module on WordPress 6.5 or later. - Use the correct enqueue hook:
wp_enqueue_scriptsfor the front end andadmin_enqueue_scriptsfor administration pages. - Pass the generated endpoint and operation nonce from PHP instead of hardcoding them.
- Send an
actionvalue that exactly matches the registered hook suffix. - Register the authenticated and anonymous hook deliberately; do not add
wp_ajax_nopriv_by reflex. - Verify the nonce, then perform a capability and ownership check.
- Unslash, sanitize and validate every request value on the server.
- Return predictable JSON and handle success, application errors and network failures in JavaScript.
- Prefer a REST route when the interface represents a reusable WordPress resource or needs external clients.
Bottom line
For a contained theme or plugin interaction, classic WordPress AJAX is straightforward: enqueue the script, localize admin-ajax.php and a nonce, send the matching action, register the correct hook and secure the callback. Treat the nonce as request integrity protection rather than permission, and enforce authorization in PHP. When the feature is a reusable resource API, use a REST route with a wp_rest nonce or an appropriate external authentication method.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




