WordPress and Admin AJAX

AJAX is a powerful tool that allows a website to extend its functionality and create a more seamless end-user experience. All AJAX calls in WordPress route through the same location, called Admin AJAX. Learn when not to use Admin AJAX and how to identify which AJAX actions are being made in excess.


About Admin AJAX

AJAX is a JavaScript technology that allows data to be requested and returned on a page without actually refreshing the page. For example, in Google Maps, to view new map sections you don’t need to load another page. As you move the map, it will load in new sections without having to fully reload the page.

By default, WordPress routes all AJAX requests through an admin file located at wp-admin/admin-ajax.php. This is why, when referring to AJAX in WordPress, we call it “Admin AJAX”.

A common example of Admin AJAX in WordPress would be a checkout page on an ecommerce website. When you enter your shipping information, the site can query the database and display an updated price without reloading the entire page.


High Admin AJAX Usage

When AJAX is called anywhere on a WordPress website, the Admin AJAX file is requested: wp-admin/admin-ajax.php. On WP Engine, the wp-admin/admin-ajax.php file is uncached meaning it is generated new for each request and is never served from cache storage. Uncached requests are significantly more resource-intensive than those served from cache.

NOTE

To review how WP Engine server caching works, we suggest checking out this guide.

While AJAX is a great tool, it can often run amok when set to make inefficient, unnecessary or a high number of calls. For this reason, it’s important to use AJAX calls sparingly and only when completely necessary.

For example, say that when a user visits a page it makes 5 Admin AJAX calls within a few seconds. Remember that AJAX calls are uncached, so all 5 must be processed by PHP anew. When 1 or 2 users are on the page, you may not see any impact with only 10 calls in a few seconds. However, when 5,000 visitors are on the page, you now have 25,000 uncached requests within just a few seconds. With enough visitors on the site pulling resources in this inefficient manner, the server will slow down (causing 504 errors) or even fail to complete requests completely (causing 502 errors).

If you’re seeing a large number of 504 or 502 errors on your site, it’s highly possible that excess Admin AJAX requests are the culprit.

NOTE

Need a refresher on these error codes? Learn more about the 502 error here. Learn more about the 504 error here.


Admin AJAX Log

As all AJAX requests go through the wp-admin/admin-ajax.php file, requests are easy enough to track back to a single culprit with some additional logging enabled. If you’re seeing a large amount of requests to wp-admin/admin-ajax.php within your access logs, your next step will be to enable Admin AJAX logging.

NOTE

Before continuing, be aware that the Admin AJAX log can grow exponentially fast, which can cause issues for your site. Disable Admin AJAX as soon as possible in your troubleshooting process. We typically find 5-10 minutes to be a sufficient amount of time enabled.

Admin AJAX logging can be enabled by adding the following line to the wp-config.php file using either SFTP or SSH Gateway. Be sure to add this just below the section that says # WP Engine Settings.

define( 'WPE_MONITOR_ADMIN_AJAX', true );

Once the line is added and the updated wp-config.php file has been uploaded back into the site, Admin AJAX logging will begin. We suggest timing 5 minutes before editing the file again to remove the line. During this time, perform any actions on your site where you’ve seen slowness or errors, to ensure the process in question is logged during the test period.

To disable Admin AJAX logging, open the wp-config.php file again and either remove the define above, or update the value to false.

To review the log, download it at wp-content/__wpe_admin_ajax.log

Finally, be aware that admin AJAX logging only record POST requests. GET requests to admin-ajax.php with arguments on the end are not logged. For example:
admin-ajax.php?action=do_something&that_something=should_be_cool


Troubleshoot Admin AJAX

We recommend troubleshooting high AJAX with SSH gateway, if possible, because we have provided some commands to easily parse the log from your terminal below. This is the same approach WP Engine Support will take to troubleshoot the issue, as it’s the most direct. All of the following commands will be run from the root of your website.

With AJAX logging enabled, view the AJAX actions live as the request is made on the website:

  • This is a good option if you are looking for the AJAX call causing slowness on a particular page. Enable AJAX logging, run the following command, then perform the action on the website.

tail -f wp-content/__wpe_admin_ajax.log | grep "action"

With AJAX logging disabled, search through the log to pull a list of actions made and the total times each action was requested during the logged period:

  • This is a good option if you’re seeing 502 or 504 errors with high AJAX usage.

grep "action" wp-content/__wpe_admin_ajax.log | sort | uniq -c | sort -rn | head

An example output looks like this:

  47608     [action] => adrotate_impression
    108     [action] => ga_stats_widget
     96     [action] => heartbeat
      2     [action] => wp-remove-post-lock
      2     [action] => adrotate_click
      1     [action] => do-plugin-upgrade

If you’re seeing issues with AJAX performance, the highest number is your most likely culprit. The next step is to determine the offender.

NOTE

The heartbeat action refers to a normal WordPress process that allows for functionality like auto-saving posts and pages. For more information, review the Heartbeat API Codex here. WP Engine disables heartbeat on all non-editing admin pages, so it is unlikely this action will cause any performance issues.

Use the following command to search your website’s files for a specific action name:

ack-grep --nosql action_name

For example, to search a site for the AJAX action adrotate_impression using the following:

ack-grep --nosql adrotate_impression

This example query was provided the following results:

wp-content/plugins/adrotate/adrotate-statistics.php
40:         return "<div class="adrotate_label">" + label + "<br /><span class="adrotate_clicks">Clicks:</span> " + env.opt.values['serie1'][index] + "<br /><span class="adrotate_impressions">Impressions:</span> " + env.opt.values['serie2'][index] + "</div>";
479: Name:      adrotate_impression_callback
483:function adrotate_impression_callback() {

wp-content/plugins/adrotate/library/dashboard.css
4:.adrotate_impressions { color: #F80; font-weight: normal }

wp-content/plugins/adrotate/library/jquery.adrotate.dyngroup.js
85: $.post(impression_object.ajax_url, {'action': 'adrotate_impression','track': tracker});

wp-content/plugins/adrotate/dashboard/settings/statistics.php
69: <input name="adrotate_impression_timer" type="text" class="search-input" size="5" value="<?php echo $adrotate_config['impression_timer']; ?>" autocomplete="off" /> <?php _e('Seconds.', 'adrotate'); ?><br />

wp-content/plugins/adrotate/adrotate-manage-publisher.php
724: $impression_timer = trim($_POST['adrotate_impression_timer']);

wp-content/plugins/adrotate/adrotate.php
68: add_action('wp_ajax_adrotate_impression', 'adrotate_impression_callback');
69: add_action('wp_ajax_nopriv_adrotate_impression', 'adrotate_impression_callback');

NOTE

We advise creating a backup of your site before making any changes to plugins or themes.

In this example, all the results for search query are located within the plugin directory wp-content/plugins/adrotate. The next step would be to check for any updates to the Adrotate plugin, and make sure it’s updated. (WP CLI can help with this.) Updating can often resolve issues where an asset’s AJAX usage spikes unexpectedly.

If updating doesn’t resolve the issue, then disabling the item would be the next step. Otherwise, reaching out to the plugin/theme support will ensure you’re able to get the most help, as fast as possible. We recommend providing the developer with your AJAX logs and findings covered above, as this can greatly improve the overall resolution time.


WooCommerce Cart Fragments

If you’re seeing a large amount of AJAX calls to wc-ajax=get_refreshed_fragments this refers to the “Cart Fragments” functionality in WooCommerce. In WooCommerce, the Cart Fragments request is made all the time, even when completely unnecessary, including pages without add-to-cart functionality, like an About Us page, Blog Posts, or on the Terms & Conditions page. This can pose performance issues, especially in times of high traffic.

There are two options to resolve high calls from Cart Fragments:

  1. Disable cart fragments and lose out on the dynamic cart functionality entirely
  2. Enable WP Engine’s eCommerce Solution Live Cart feature and maintain the real-time cart while simultaneously improving performance

NEXT STEP: Learn how to reduce “get_refreshed_fragments” Admin AJAX calls

Still need help? Contact support!

We offer support 24 hours a day, 7 days a week, 365 days a year. Log in to your account to get expert one-on-one help.

The best in WordPress hosting.

See why more customers prefer WP Engine over the competition.