# AJAX Loading 2.0: troubleshooting

AJAX Loading is built to fail safe: whenever it cannot show a page correctly, the browser loads that page the normal way. So most problems show up in one of two ways:

* **pages reload normally** instead of loading with AJAX, or
* **something on the new page does not work**, usually a script that only starts on a full page load.

This guide helps you find out which one you have and what to do. Settings are explained in the [user guide](user-guide.md), plugin and theme specifics in the [compatibility reference](compatibility.md), and custom code in the [developer guide](developer-guide.md).

## Contents

1. [First steps](#first-steps)
2. [Debug mode](#debug-mode)
3. [Content does not change, or the wrong part changes](#content-does-not-change-or-the-wrong-part-changes)
4. [Pages reload instead of loading with AJAX](#pages-reload-instead-of-loading-with-ajax)
5. [Scripts, sliders, forms or widgets stop working](#scripts-sliders-forms-or-widgets-stop-working)
6. [Styles flash, are missing or look wrong](#styles-flash-are-missing-or-look-wrong)
7. [Analytics count too many or too few page views](#analytics-count-too-many-or-too-few-page-views)
8. [Caching and optimisation plugins](#caching-and-optimisation-plugins)
9. [Other problems](#other-problems)
10. [Automatic fallback](#automatic-fallback)
11. [The error log](#the-error-log)
12. [Safe mode and pausing](#safe-mode-and-pausing)
13. [Turning AJAX Loading off completely](#turning-ajax-loading-off-completely)
14. [Asking for help](#asking-for-help)

## First steps

1. **Check the status.** Open **Settings → AJAX Loading**. The status at the top must be **Active** (or **Administrators only** if you are testing while logged in as an administrator).
2. **Check that the page is handled.** Open a page of your site, view its source (Ctrl+U or Cmd+Option+U) and search for `name="ajax-loading"`:
   * `content="enabled"`: AJAX navigation runs on this page.
   * `content="bypass"`: this page is excluded on the server (for example the cart, a login page or an excluded post type). It and links to it load normally.
   * Not found: the plugin is not active for this page view. It is off or paused, you are a visitor while test mode is on, the page is a cached copy from before the plugin was activated, or it is a context where the plugin never runs (Customizer preview, page builder editor, AMP page).
3. **Run the compatibility check.** Go to **Tools & Diagnostics**, click **Check content selectors**, then fill in a start page and a destination page and click **Test navigation**. The result tells you whether that navigation will use AJAX and, if not, why.
4. **Turn on debug mode** (next section) and watch the browser console while you click around.
5. **Try safe mode.** If the problem disappears in safe mode, it is caused by one of the features safe mode turns off (see [Safe mode and pausing](#safe-mode-and-pausing)).

## Debug mode

Turn on **Tools & Diagnostics → Debugging → Debug logging** and save. Then, on your site:

1. Open the browser's developer tools (F12, or Cmd+Option+I on a Mac) and select the **Console** tab.
2. Make sure the console shows all levels. In Chrome and Edge, open the levels menu and tick **Verbose**; most messages of the plugin are debug messages.
3. Click a link. Every message starts with `[AJAX Loading]`.

Turn debug logging off again when you are done; it is meant for testing.

Warnings and errors (for example "AJAX navigation disabled for 30 minutes after 3 failures" or "document.write() was ignored") are printed even when debug logging is off.

| Message | Meaning |
|---|---|
| `Ready` | The engine started on this page. |
| `Not starting: …` | The engine did not start on this page; every link loads normally. See the table below. |
| `Native navigation (reason)` | A clicked link was left to the browser. See [Link reason codes](#link-reason-codes). |
| `Full navigation (reason): URL` | A back/forward or scripted navigation was turned into a normal page load. Same reason codes. |
| `Content regions: …` | What was replaced, for example `content #content`. |
| `Content detection failed: code message` | No matching content area; the page loads normally. |
| `Full navigation required by integration "name" (code).` | An integration decided the page must load normally. |
| `Navigation fell back to a full page load (code): message` | The page was fetched but could not be shown with AJAX. See [Error codes](#error-codes). |
| `Page view tracked: /path` | An analytics call was made (only in the GA4 or dataLayer modes, or with a custom tracking function). |

### "Not starting" reasons

| Reason | What to do |
|---|---|
| `configuration missing` | The plugin's inline configuration (`window.ajaxLoadingConfig`) did not load before the script. Usually an optimisation plugin moved, delayed or combined it; see [Caching and optimisation plugins](#caching-and-optimisation-plugins). |
| `browser not supported` | The browser lacks a feature the engine needs. Pages load normally, which is fine. |
| `customizer preview` | Expected: the plugin stays off in the Customizer. |
| `marker missing` | The page has no `<meta name="ajax-loading">` tag, usually a cached copy from before activation. Purge your page cache. |
| `page bypassed by the server` | The current page is excluded (cart, checkout, login, excluded post type …). Expected. |
| `Interactivity API router present` | The page uses WordPress's own client-side router (for example a Query Loop block with "Force page reload" turned off). The two would conflict, so AJAX Loading stays off on that page. |
| `auto-disabled after repeated failures` | The [automatic fallback](#automatic-fallback) is active in this browser tab. |
| `disabled on this device type` | **Desktop devices** or **Mobile devices** is off on the General tab, and this screen counts as that device type (see **Mobile breakpoint**). |
| `a required module failed to initialise` | An unexpected error; the error is printed with it. Please report it. |

### Link reason codes

These codes appear in `Native navigation (…)` messages and in the compatibility check.

| Code | Meaning |
|---|---|
| `modified-click` | Ctrl, Shift, Alt or Cmd was held (open in new tab or window). |
| `not-primary-button` | Not a left-click. |
| `default-prevented` | Another script already handled the click (for example a menu toggle or lightbox). |
| `no-href` | The link has no address. |
| `target` | The link opens in another window or tab (`target="_blank"` and similar). |
| `download` | The link has a `download` attribute. |
| `rel-external` | The link has `rel="external"`. |
| `opt-out` | The link is inside `data-no-ajax`, `.no-ajaxy`, `.no-ajax`, `[data-ajax-loading="false"]` or the admin bar. |
| `excluded-selector` | The link matches an excluded CSS selector (yours, an integration's or a built-in one such as lightbox and add-to-cart links). |
| `protocol` | Not an `http`/`https` link (`mailto:`, `tel:`, `javascript:` …), or the address is invalid. |
| `cross-origin` | A link to another site, another subdomain, or `http` vs `https`. |
| `outside-home` | Outside the WordPress home address (for sites installed in a subdirectory). |
| `hash-only` | A `#section` link on the same page; the browser scrolls to it. |
| `file` | A link to a file (PDF, image, media, archive, document, feed …) or to a `.php` file other than `index.php`, or into `wp-content`/`wp-includes`. |
| `excluded-url` | The address matches an exclusion pattern (yours or a built-in one), or has a query parameter whose name contains "nonce". |
| `admin` | A link into `wp-admin`. |
| `login` | A login, signup or activation link. |
| `same-document` | (Prefetch only) the link points to the current page. |
| `prefetch-excluded` | (Prefetch only) matches **Never prefetch**, or has a query string on a site with pretty permalinks. |
| `logged-in` | (Prefetch only) logged-in visitors are never prefetched for. |
| `personalized` | (Prefetch only) the visitor has cart, comment or post-password cookies, or the current page is personalised. |
| `form-method` | (Forms) the form does not use GET. |
| `form-files` | (Forms) the form has a file upload field. |
| `form-not-allowed` | (Forms) not a search form and not listed under **Additional GET forms**. |

### Error codes

These codes appear in `Navigation fell back to a full page load (…)` messages, in the `wp_ajax_load_error` event and in the [error log](#the-error-log). In every case the visitor ends up on the right page through a normal page load.

| Code | Label in the error log | Meaning | What to do |
|---|---|---|---|
| `network` | Network error | The browser is offline, or the server's answer could not be read completely. | Usually temporary. Repeated network errors point to a server, proxy or firewall problem. |
| `timeout` | Request timed out | The page took longer than **Performance → Request timeout**. | Speed up the page (page cache) or raise the timeout. |
| `http_status` | Server returned an error status | The server answered with an error, for example 403, 500 or 503, or 404 while **Load "not found" pages with AJAX** is off. | Check that the page works when opened directly. Server errors (5xx) count towards the automatic fallback. |
| `invalid_content_type` | Response was not an HTML page | The link led to a file, feed, JSON or a download. | Expected. If it is a page that should be HTML, check what the server sends. |
| `parse_error` | Page could not be parsed | The response was empty or could not be read as HTML. | Open the page directly and check for PHP errors or an empty response. |
| `unsupported_charset` | Unsupported character set | The page uses a character encoding the browser cannot decode. | Use UTF-8 (WordPress's default). |
| `marker_missing` | Destination page is not served by AJAX Loading | The fetched page has no `<meta name="ajax-loading">` tag: a cached copy from before activation, or AJAX navigation is not active on that page (for example turned off with a filter). It never counts towards the automatic fallback. | Purge your page cache. To avoid the wasted request, exclude such pages with a URL pattern. |
| `bypass` | Destination page is excluded | The destination is excluded on the server (cart, checkout, My Account, order pages, login or membership pages, excluded post types, previews, password-protected posts), or its body class marks it as a WooCommerce cart/checkout/account/order page or a Paid Memberships Pro checkout/billing/cancel page (while the matching protection switch is on), or it is a BuddyPress page while BuddyPress is set to Exclude, or it belongs to another site of the same multisite network. | Expected. |
| `container_mismatch` | Content area not found on both pages | Automatic mode: no content container exists exactly once on both pages. Custom mode: a selector matches no element, or a different number of elements on the two pages. | Run **Check content selectors**. Add `data-ajax-loading-container` to your content wrapper or fix your custom selectors. |
| `layout_mismatch` | Pages use different layouts | The structure around the content area differs (for example full width vs sidebar, or a hero or page title banner next to the content that only one of the two pages has), or the kept header or footer differs between the pages, or exists on only one of them. | Expected between different templates. If it happens between pages that look alike, set **Header** or **Footer** to **Replace**, or mark a wrapper that contains the banner and the content with `data-ajax-loading-container` (or list it under custom selectors). |
| `cross_origin_redirect` | Redirected to another site | The link redirected to another domain (affiliate links, short links). The browser reports a request that failed for another reason while it was online (connection dropped, server unreachable, blocked by a firewall) the same way, so this code covers those too. | Expected for redirecting links; exclude them to save one request. If it appears for normal pages, open them directly and check the server. |
| `excluded_redirect` | Redirected to an excluded URL | The link redirected to an address that must load normally (login, admin, an excluded page). | Expected. |
| `integration_excluded` | Page uses an integration set to reload | An integration set to **Exclude** appears in the new content, or an integration in **Auto** cannot start safely on this page (for example Elementor, Divi or Bricks content when their scripts are not loaded on the current page, Divi 5, a WooCommerce block cart or checkout, a form whose plugin is not ready). | Expected. |
| `interactive_content` | Page contains interactive blocks | The new content contains Interactivity API blocks and **Interactive blocks** is set to load these pages normally. | Expected (recommended setting). |
| `language_changed` | Page is in another language | The destination's `<html lang>` differs from the current page. | Expected on multilingual sites. |
| `asset_changed` | Tracked assets changed | Elements marked `data-ajax-loading-track="reload"` differ, or the destination was rendered by a different version of AJAX Loading (a page cache from before an update). | Purge your page cache after updating the plugin. |
| `prevented` | Cancelled by a site script | A script cancelled the navigation through the `wp_ajax_load_before_replace` event. | Check your custom code or other plugins. |
| `exception` | Unexpected script error | Something went wrong in the engine or during the swap. | Look at the console for the error, try safe mode, and report it. |
| `circuit_open` | Automatic fallback active for this visitor | Recorded once when the [automatic fallback](#automatic-fallback) switches a visitor's tab to normal page loads. | Look at the errors recorded just before it. |
| `device_disabled` | Disabled for this device type | Reserved code. The current version does not record it; a disabled device type shows `Not starting: disabled on this device type` instead. | |
| `personalized` | Personalised page | Reserved code. The current version uses `personalized` only as a prefetch reason. | |

Only `timeout`, server errors (`http_status` 5xx), `parse_error`, `unsupported_charset`, `exception` and `network` errors where the answer could not be read count towards the automatic fallback. Being offline, failed requests reported as `cross_origin_redirect`, and every expected fallback never count.

## Content does not change, or the wrong part changes

| Symptom | Likely cause | Fix |
|---|---|---|
| Every click is a normal full page load, with no loading indicator or transition. | The engine is not running on this page. | Follow [First steps](#first-steps): check the status, the `ajax-loading` meta tag and the `Not starting` message. |
| Only part of the content changes; for example the page title area, breadcrumbs or a sidebar still show the previous page. | The detected content area is smaller than the part of the page that changes. | Run **Check content selectors** to see what is detected. Add the attribute `data-ajax-loading-container` to the wrapper that contains all page-specific parts, or choose **Custom selectors** and list each region (one per line). |
| The header shows the previous page's hero image or title. | The header is kept. | Set **General → Header** to **Replace it on every navigation**. |
| Content is replaced, but in the wrong place, or the header appears twice. | A custom selector matches the wrong element or an element that contains the header. | Check your **Content selectors**; they must match the content area itself, not a wrapper around the header. |
| Some page types always reload (for example archives, but not posts, or pages with a hero banner, but not pages without one). | `layout_mismatch`: those templates are built differently. | Expected. If the pages look alike, set the header or footer to **Replace**, or use custom selectors (or `data-ajax-loading-container`) for a wrapper that exists on all templates and contains every page-specific part. |
| With **Custom selectors**, every page reloads. | `container_mismatch`: a selector is missing on some pages or matches a different number of elements. | Use selectors that exist exactly as often on every page. **Check content selectors** shows the match count per page. |

## Pages reload instead of loading with AJAX

Find the reason first: the debug console (`Native navigation (…)` or `Navigation fell back … (…)`), the **Test navigation** result, or the [error log](#the-error-log).

| Cause | How you recognise it | Fix |
|---|---|---|
| The link is excluded. | `excluded-url`, `excluded-selector` or `opt-out`. | Check **Exclusions** and your templates for `data-no-ajax` / `no-ajaxy`. The built-in rules on the Exclusions tab cannot be changed. |
| The link is a file, another site, opens in a new tab, etc. | `file`, `cross-origin`, `target`, `download` … | Expected browser behaviour. |
| The destination is excluded on the server. | `bypass`. | Expected for cart, checkout, account, login, membership pages and excluded post types. |
| A page cache serves old copies. | `marker_missing` or `asset_changed` right after activating or updating the plugin. | Purge the page cache (plugin, host and CDN). |
| The two pages have different layouts. | `layout_mismatch` or `container_mismatch`. | See the [previous section](#content-does-not-change-or-the-wrong-part-changes). |
| An integration or interactive blocks require it. | `integration_excluded`, `interactive_content`. | Expected. You can change integration behaviour on **SEO & Integrations**, but pages may then not work after navigation. |
| The server returns an error or is slow. | `http_status`, `timeout`, `network`. | Check the page directly; raise **Request timeout** if pages are just slow. |
| Navigation used to work, then stopped for a while in your browser. | `Not starting: auto-disabled after repeated failures`. | See [Automatic fallback](#automatic-fallback). |
| Only some visitors or devices get AJAX navigation. | Test mode is on, the plugin is paused, or a device type is switched off. | Check the Overview status and **General → Activation**. |
| The first click after a page load is a normal load, later clicks use AJAX. | An optimisation plugin delays JavaScript until the visitor interacts with the page. | Exclude the plugin's script from delaying (see [Caching and optimisation plugins](#caching-and-optimisation-plugins)). |
| Navigation is erratic, pages load twice or history entries are duplicated. | Another AJAX navigation or page transition feature is active (the environment report lists "Other navigation plugins" and "Elementor Pro Page Transitions"). | Use only one of them. |

## Scripts, sliders, forms or widgets stop working

After an AJAX navigation, scripts inside the new content run, and scripts the new page needs are loaded. But scripts that were already loaded on the first page do not start again by themselves. A slider, gallery or form whose script only sets things up "when the page is ready" therefore needs help.

| Symptom | Likely cause | Fix |
|---|---|---|
| A slider, carousel, gallery, map or tabs block appears empty or static after navigation. | Its script only initialises on a full page load. | 1. If it belongs to a listed integration, set it to **Auto**. 2. Re-initialise it after each navigation with the `wp_ajax_load_complete` event ([developer guide](developer-guide.md)). 3. Or exclude the pages that use it. 4. As a last resort, turn on **General → Advanced → Fire page-load events again**. |
| A form (validation, AJAX submit, captcha) does not work after navigation. | The form plugin was not re-initialised. | Contact Form 7, Gravity Forms, WPForms, Fluent Forms and Formidable Forms: set the integration to **Auto**. Ninja Forms and ACF front-end forms: keep **Exclude** (their pages load normally). Other form plugins: exclude the pages with forms, or re-initialise them with the `wp_ajax_load_complete` event. |
| Content with "animate on scroll" effects stays invisible. | The animation library was not restarted. | Restart it in a `wp_ajax_load_complete` listener, or exclude those pages. |
| Navigation menu overlays, image lightboxes, accordions or WooCommerce blocks do not respond. | **Interactive blocks** is set to **Replace them with AJAX**; WordPress cannot start those blocks again. | Set **Exclusions → Interactive blocks** back to **Load these pages normally**. |
| Something runs twice after navigation (duplicate items, double submits, two popups). | **Fire page-load events again** is on, or custom code re-initialises parts of the page that were kept (header, footer). | Turn that option off. In custom code, only initialise elements inside `event.detail.container` (the [developer guide](developer-guide.md) shows how). |
| Header widgets (mobile menu, search toggle, sticky header) stop working. | The header is set to **Replace**, so its elements are new but their scripts did not start again. | Keep the header (**General → Header → Keep it**), or re-initialise those scripts after each navigation. |
| An ad or embed that uses `document.write` is missing; the console says "document.write() was ignored". | `document.write` would wipe the whole page after it has loaded, so the plugin blocks it. | Exclude the pages that contain it. |
| Custom code fails with "jQuery is not defined". | jQuery is no longer loaded by the plugin. | Turn on **General → Advanced → Load jQuery for custom callbacks**, or enqueue jQuery for your script. |
| A theme or plugin script on the new page does not run at all. | **Run scripts inside new content** or **Run new inline scripts** is off, the script tag is marked `data-ajax-loading-skip`, or an optimisation plugin changed its `type` (only normal JavaScript tags are run). | Turn those options back on; see [Caching and optimisation plugins](#caching-and-optimisation-plugins). |
| A script runs on a normal page load but not after AJAX navigation, and your site sends a `Content-Security-Policy` with nonces (security plugin, host or CDN). | The plugin runs only the scripts of a loaded page that this page's own policy allows, as the browser would on a normal load: a script without the page's nonce is skipped when it is inline or the policy uses `'strict-dynamic'`. Hash sources (`'sha256-…'`) are not checked, so a script the policy allows only through its hash does not run after an AJAX navigation. With [debug mode](#debug-mode) on, each skipped script logs "Skipping a script the page's Content Security Policy does not allow." | Give the script the page's nonce (scripts WordPress prints can get it through the `wp_script_attributes` and `wp_inline_script_attributes` filters), or exclude the pages that need it. |

For custom code, the [developer guide recipes](developer-guide.md#8-recipes) show how to re-initialise sliders and lightboxes, run code once per page, and migrate a 1.x `wp_ajax_load_complete` function. How each integration is handled is described in the [compatibility reference](compatibility.md).

## Styles flash, are missing or look wrong

The plugin loads the stylesheets the new page needs before it shows the new content, waiting up to 3 seconds for them.

| Symptom | Likely cause | Fix |
|---|---|---|
| The new content is unstyled for a moment. | A new stylesheet took longer than 3 seconds, or the page adds its CSS with JavaScript after loading. | Speed up or combine the CSS, or exclude those pages. |
| Some elements look unstyled only after AJAX navigation, not on a normal load. | An optimisation feature creates page-specific CSS (for example "remove unused CSS" or critical CSS) or loads CSS in a way the plugin cannot follow. | Turn that feature off to test. If it is the cause, keep it off or exclude the affected pages. |
| Styles of the previous page affect the new page. | Old stylesheets stay in place (needed for the kept header and footer). Inline `<style>` blocks without an id that the previous page printed outside the content area (for example block layout CSS on older WordPress versions) are removed automatically when the new page does not print them. | Turn on **General → Advanced → Remove unused stylesheets** (a stylesheet needed again is then downloaded again). To keep a style in place on every page, give it the attribute `data-ajax-loading-persist`. |
| The footer or header loses its layout on a block theme. | Before WordPress 6.8, block layout class names can change from page to page (the environment report warns about this). | Set **General → Footer** (or Header) to **Replace**, or update WordPress. |
| The whole screen flashes or goes blank between pages. | An **Overlay** indicator with a high opacity, or strong leave/enter animations. | Lower **Overlay opacity**, choose another indicator, or use **Fade** or **None** as transitions. |
| The loading indicator is hidden behind a sticky header or popup. | Its stacking order is too low. | Raise **Loading Experience → Stacking order (z-index)**. |

## Analytics count too many or too few page views

Pick **one** way of counting AJAX navigations. The first page of every visit is always counted by your normal tracking code.

| Symptom | Likely cause | Fix |
|---|---|---|
| GA4 counts every AJAX navigation twice. | **Send GA4 page_view events** is selected and GA4 Enhanced Measurement also counts history changes. | In GA4: **Admin → Data streams → your web stream → Enhanced measurement → Page views → Show advanced settings**, turn off **Page changes based on browser history events**. Or switch the plugin back to **Automatic**. |
| Tag Manager counts every navigation twice. | **Push a dataLayer event** is selected and a History Change trigger also fires your page view tag. | Use either the plugin's custom event or the History Change trigger, not both. |
| AJAX navigations are not counted at all. | **Automatic** is selected but GA4's history-based page views are off (or no History Change trigger exists in Tag Manager). | Turn the GA4 option on (or add the trigger), or switch the plugin to **Send GA4 page_view events** / **Push a dataLayer event**. |
| Nothing is sent in GA4 mode. | `gtag()` is not on the page (debug console: "Analytics mode is gtag but gtag() is not available"). | Install the Google tag, or use the dataLayer mode with Tag Manager. |
| Nothing is sent for some visitors. | **Require statistics consent** is on and those visitors did not consent. | Expected. |
| A conversion or tracking snippet inside a page's content fires again on every AJAX visit to that page. | Scripts inside the new content run, as on a normal page load. | Expected. To skip one, add `data-ajax-loading-skip` to its `<script>` tag. |

## Caching and optimisation plugins

Page caches work with AJAX Loading: the plugin requests pages exactly as a browser does, without special headers. The environment report on **Tools & Diagnostics** lists the caching and optimisation plugins it detects.

* **Purge the page cache** after activating, updating or reconfiguring the plugin, and after the quick actions on the Overview tab. Cached copies from before cause `marker_missing` or `asset_changed` fallbacks, or keep the previous settings. When the plugin detects a page cache (`WP_CACHE` or a known page caching plugin), its notices remind you after each change.
* **JavaScript combining, minifying, deferring or "delay until interaction":** if navigation stops working or only works after the first click, exclude these from those features:
  * the script `wp-content/plugins/ajax-loading/assets/dist/frontend.min.js` (script handle `ajax-loading-WPajaxLoad`; the file `frontend.js` when `SCRIPT_DEBUG` is on);
  * its inline configuration (the script `ajax-loading-WPajaxLoad-js-before`, which contains `window.ajaxLoadingConfig`);
  * the inline script `ajax-loading-reload-helper-js` in the page head (contains `reload_helper`).

  Many plugins accept keywords; `frontend.min.js`, `ajaxLoadingConfig` and `reload_helper` identify all three.
* **Features that rewrite `<script>` tags** (for example changing their `type` to delay them) can stop scripts in new content from running after AJAX navigation, because the plugin only runs normal JavaScript tags. Exclude the affected scripts from that feature.
* **Prefetching:** if another plugin already prefetches links (the environment report mentions it), keep AJAX Loading's **Prefetch links** off.

## Other problems

| Symptom | Likely cause | Fix |
|---|---|---|
| Back or forward shows the right address but the page jumps to the top. | **Restore scroll position** is off. | Turn it on (**Performance → Page state**). |
| The menu highlights the previous page. | **Highlight the current menu item** is off, or the menu marks the current page in an unusual way. | Turn it on (**Performance → Page state**). |
| Switching language behaves oddly. | The multilingual integration is **Off**. | Set it to **Auto** (language switches then always reload). |
| WooCommerce cart contents or the mini cart look out of date. | Cart fragments were not refreshed. | Keep the WooCommerce integration on **Auto**, and keep **Exclusions → Protect WooCommerce pages** on so cart, checkout and account pages always load normally. |
| Logged-in administrators see AJAX navigation, visitors do not. | Test mode. | Click **Enable for everyone** on the Overview tab. |

## Automatic fallback

When **Automatic fallback** is on (default), a visitor whose navigations fail repeatedly (by default 3 times within 5 minutes) gets normal page loads for a while (by default 30 minutes). This protects visitors from a site that is temporarily broken. The settings are on **Tools & Diagnostics → Safety**.

Good to know:

* Only real problems count (see [Error codes](#error-codes)); excluded pages, different layouts, 404 pages and other expected fallbacks never do.
* A successful navigation resets the count.
* The fallback lives in the visitor's browser tab (session storage). Closing the tab, or opening a new one, starts fresh.
* To reset it in your own tab while testing, close the tab, or run `sessionStorage.removeItem('ajxl:breaker')` in the browser console and reload.
* When **Record navigation errors** is on, the moment the fallback starts is logged as `circuit_open`, after the errors that caused it.

## The error log

Turn on **Tools & Diagnostics → Debugging → Record navigation errors** and save. From then on, visitors' browsers report failed navigations to your site.

* **Where:** **Tools & Diagnostics → Recent navigation errors** (all entries, with **Refresh** and **Clear**) and the Overview tab (last 5).
* **Columns:** time, error (readable label, code and a short message), page path, HTTP status, and type: `link` (click), `popstate` (back/forward), `form` or `programmatic` (started by a script).
* **What is stored:** only the error code, page path (without query string or `#fragment`), HTTP status, a short message and the navigation type. No IP address, user agent or cookie.
* **Limits:** the last 50 entries are kept; each visitor's page sends at most 10 reports, and the site accepts at most 30 reports per 10 minutes.
* The log is deleted when you uninstall the plugin.

Look for patterns: the same code on many pages usually means a site-wide cause (page cache, optimisation plugin, layout); one page with repeated errors usually means a problem on that page. Use the [error code table](#error-codes) for the meaning of each code.

## Safe mode and pausing

**Safe mode** (Overview quick action, or **Tools & Diagnostics → Safety**) keeps AJAX navigation running with conservative behaviour: no prefetching or cache, no additional GET forms, header and footer kept, automatic detection instead of whole body, no synthetic page-load events, no removal of stylesheets, interactive-block pages and page-builder pages (Elementor, Divi, Beaver Builder, Bricks) load normally. Your settings are not changed. If a problem disappears in safe mode, turn safe mode off and change those settings one by one to find the culprit.

**Pause** (Overview or **Tools & Diagnostics → Maintenance**) serves normal page loads to everyone for 1 or 24 hours, for example while you change your theme. **Resume now** ends it early.

**Test mode** (**Test mode (administrators only)** on the Overview tab) keeps AJAX navigation for logged-in administrators only, so you can keep testing while visitors get normal page loads.

## Turning AJAX Loading off completely

* **Switch it off:** Overview → **Turn off** (or untick **General → Enable AJAX navigation**). Every page loads normally and the plugin adds nothing to your pages. Your settings are kept.
* **Deactivate the plugin:** **Plugins → Installed Plugins → Deactivate**. With WP-CLI: `wp plugin deactivate ajax-loading`.
* **Switch it off with WP-CLI without deactivating:** `wp option patch update _wp_ajax_loading enable_plugin off`.
* **If you cannot reach the dashboard:** AJAX navigation never runs inside wp-admin, so the dashboard should still work. If not, rename the folder `wp-content/plugins/ajax-loading` (for example via FTP or your host's file manager); WordPress then deactivates it.
* **For one browser tab only** (useful when comparing behaviour): run `AjaxLoading.disable()` in the browser console. `AjaxLoading.enable()` turns it back on; reloading the page also restores it.
* **Remove everything:** deactivate, then **Delete** the plugin on the Plugins screen. This removes all of its settings, the error log and its other stored data (see [Upgrading from 1.x](migration.md#what-uninstalling-removes)).

## Asking for help

Ask in the [support forum](https://wordpress.org/support/plugin/ajax-loading/) and include:

* the environment report from **Tools & Diagnostics** (copy the Warnings and Errors);
* the result of **Test navigation** between two pages where the problem happens;
* the error codes from the error log or the debug console;
* your theme, page builder and caching or optimisation plugins;
* the steps to reproduce the problem.
