# AJAX Loading 2.0: user guide

This guide explains every screen and every setting of AJAX Loading. It is written for site owners and administrators; no coding is needed.

Related documents:

* [Troubleshooting](troubleshooting.md): what to do when something does not work.
* [Upgrading from 1.x](migration.md): what changed and how to roll back.
* [Compatibility reference](compatibility.md): how themes, page builders, shops, forms and caching plugins are handled.
* [Developer guide](developer-guide.md): events, JavaScript API and PHP hooks for custom code.

## Contents

1. [How AJAX Loading works](#how-ajax-loading-works)
2. [Where to find the settings](#where-to-find-the-settings)
3. [Getting started safely](#getting-started-safely)
4. [Overview tab](#overview-tab)
5. [General tab](#general-tab)
6. [Loading Experience tab](#loading-experience-tab)
7. [Performance tab](#performance-tab)
8. [SEO & Integrations tab](#seo--integrations-tab)
9. [Exclusions tab](#exclusions-tab)
10. [Tools & Diagnostics tab](#tools--diagnostics-tab)
11. [About and Say Thanks tabs](#about-and-say-thanks-tabs)

## How AJAX Loading works

When a visitor clicks a link to another page of your site, AJAX Loading:

1. downloads the next page in the background, the same way a browser would;
2. checks that the page can be shown safely (it is a normal HTML page of your site, it is not excluded, and its layout matches the current page);
3. swaps in the parts that change, usually only the main content area, and updates the address bar, the page title and the tags in the page `<head>`;
4. runs the scripts of the new content, moves keyboard focus and tells screen readers about the new page.

If any check fails, or anything unexpected happens, the browser simply loads the page the normal way. Visitors never end up on a half-loaded page.

The script only runs on pages where AJAX navigation is active. It is loaded deferred in the footer and does not need jQuery.

## Where to find the settings

Go to **Settings → AJAX Loading** in your dashboard. The Plugins screen also has a **Settings** link under the plugin name. You need the "Manage options" capability (administrators have it).

The screen has nine tabs: Overview, General, Loading Experience, Performance, SEO & Integrations, Exclusions, Tools & Diagnostics, About and Say Thanks. The header always shows the current navigation status (Active, Administrators only, Paused or Off, plus "Safe mode" when it is on).

**Saving:** each tab has its own **Save Changes** button and only changes the settings of that tab. If a value is not valid (for example a number outside its range), the previous value is kept and a warning names the setting. If you try to leave a tab with unsaved changes, the page asks you first.

Some fields only appear when they matter. For example, **Bar height** is only shown when the progress bar is selected, and the prefetch options only when **Prefetch links** is on.

## Getting started safely

AJAX navigation is switched on for all visitors as soon as you activate the plugin. To try it without affecting visitors:

1. On the **Overview** tab, click **Test mode (administrators only)**. Only logged-in administrators now get AJAX navigation.
2. Open **Tools & Diagnostics** and click **Check content selectors**, then **Test navigation**.
3. Browse your site while logged in. Try menus, search, forms, sliders and any shop pages.
4. If something does not work, see [Troubleshooting](troubleshooting.md).
5. When you are happy, click **Enable for everyone** on the Overview tab.
6. If you use a page cache plugin or a CDN that caches pages, purge it. The same applies after every quick action and settings change that affects visitors (enable, disable, test mode, safe mode, pause, import, reset): cached pages keep the previous behaviour until they are purged. When a page cache is detected, the plugin's notices remind you.

## Overview tab

The Overview tab shows the state of AJAX navigation at a glance and has buttons for the most common actions. Buttons take effect immediately; there is nothing to save.

### Navigation status

| Status | Meaning |
|---|---|
| Active | AJAX navigation runs for every visitor. |
| Administrators only | Test mode: only logged-in administrators get AJAX navigation. Visitors get normal page loads. |
| Paused | Normal page loads for everyone until the time shown. |
| Off | The master switch is off. Every page loads normally. |

Next to the status:

* **Turn off** / **Turn on**: the master switch (same as **General → Enable AJAX navigation**).
* **Test mode (administrators only)** / **Enable for everyone**: switches who gets AJAX navigation (same as **General → Who gets AJAX navigation**). Only shown while the plugin is on.

### Quick actions

| Button | What it does |
|---|---|
| Preview transitions | Opens the live preview on the Loading Experience tab. |
| Clear navigation cache | Tells visitors' browsers to throw away pages they prefetched or cached earlier (see [Performance](#performance-tab)). Each browser does this the next time it loads a page from your server, or when the cache lifetime ends. Your server's page cache is not affected. |
| Run compatibility check | Opens the compatibility check on the Tools & Diagnostics tab. |
| Turn on safe mode / Turn off safe mode | Switches [safe mode](#safety). |
| Pause for 1 hour / Pause for 24 hours | Serves normal page loads until the time is up, without changing your settings. Handy while you edit your theme. Shown while the plugin is on and not paused. |
| Resume now | Ends a pause early. Shown while paused. |

### Summary cards

The cards show the values in effect for visitors. In safe mode, for example, **Prefetching** and **Page cache** show **Off (safe mode)**, and **Content area** says when **Whole page body** is stored but not in use.

| Card | Shows |
|---|---|
| Transition | The leave → enter animations, duration and easing. |
| Loading indicator | The indicator type, and either the mobile indicator or the delay before it appears. |
| Content area | Auto-detect, Custom selectors or Whole page body, and the number of configured selectors or whether the header stays in place. |
| Prefetching | On or off, and the triggers in use. |
| Page cache | On or off, and how many pages are kept for how long. This is the in-browser cache of the plugin, not your server's page cache. |
| Exclusions | How many rules apply: your URL patterns, selectors and post types plus the built-in rule sets (WordPress system URLs always; membership protection when switched on; WooCommerce protection when switched on and WooCommerce is active). |
| Last compatibility check | The result of the last check run on the Tools & Diagnostics tab, and when it ran. |

Below the cards:

* **Recent navigation errors**: the last 5 failed navigations, when **Record navigation errors** is on (Tools & Diagnostics tab).
* A note about reduced motion: whether visitors who ask their device to reduce motion see animations.
* When page view tracking is set to **Send GA4 page_view events**, a reminder about avoiding double-counted page views (see [Analytics](#analytics)).

### Notices

While AJAX navigation is paused, in safe mode or in test mode, a notice with a button to undo it appears at the top of the AJAX Loading screen and on the Plugins screen.

## General tab

### Activation

| Setting | Default | Options | What it does |
|---|---|---|---|
| Enable AJAX navigation | On | On / off | Master switch. When off, every page loads normally, and the plugin adds nothing to your pages. |
| Who gets AJAX navigation | Everyone | Everyone; Administrators only (test mode) | In test mode only logged-in users who can manage options (administrators) get AJAX navigation; everyone else gets normal page loads. |
| Desktop devices | On | On / off | Use AJAX navigation on screens wider than the mobile breakpoint. |
| Mobile devices | On | On / off | Use AJAX navigation on screens up to the mobile breakpoint. A browser that reports itself as a mobile device also counts as mobile. |
| Mobile breakpoint | 768 px | 320–2000 px | Screens this wide or narrower count as mobile. Also decides when the mobile loading indicator and mobile animation are used. |

### Content regions

These settings decide which part of the page is replaced when a visitor follows a link. Everything else stays in place.

| Setting | Default | Options | What it does |
|---|---|---|---|
| Content detection | Automatic | Automatic (recommended); Custom selectors; Whole page body | How the content area is found. See [Content detection](#content-detection) below. |
| Content selectors | empty | One CSS selector per line | In Custom mode: the regions to replace. In Automatic mode: tried first, before the built-in candidates. |
| Header selector | empty (auto-detect) | One CSS selector | Which element is your site header. Leave empty to detect it automatically. |
| Header | Keep it | Keep it (recommended); Replace it on every navigation | See [Header and footer](#header-and-footer). |
| Footer selector | empty (auto-detect) | One CSS selector | Which element is your site footer. Leave empty to detect it automatically. |
| Footer | Keep it | Keep it (recommended); Replace it on every navigation | See [Header and footer](#header-and-footer). |
| Load "not found" pages with AJAX | On | On / off | Shows your theme's 404 page without a full reload. When off, links to missing pages load normally. |

At the bottom of the tab a tip reminds you that you can mark your theme's content wrapper with the attribute `data-ajax-loading-container`.

#### Content detection

**Automatic (recommended).** The plugin looks for the main content area on both the current page and the next page. It first tries your own **Content selectors** and any element with the attribute `data-ajax-loading-container`, in that order; the first one that fits wins. Then it tries a list of common content containers used by themes and page builders:

`#content`, `.site-content`, `main#main`, `#site-content`, `#main`, `.site-main`, `.wp-site-blocks > main`, `main#wp--skip-link--target`, `main`, `#primary`, `.content-area`, `[role="main"]`, `#brx-content`, `#main-content`

Among these built-in candidates, the outermost one that fits is used. A candidate fits when:

* it matches exactly one element on both pages;
* it is not the whole `<body>`, does not contain the header, footer or admin bar, and is not inside the header or footer;
* the page structure around it is the same on both pages.

Sections next to the content area that differ between the two pages (for example a sidebar with page-specific widgets, or a page title banner that both pages have) are updated as well. Menus and widget areas that a theme prints directly inside the page body (for example Twenty Twenty's mobile menu) are kept, so their buttons keep working. If the structure around the content area differs, the next page loads normally. Examples: going from a full-width page to a page with a sidebar, or between a page with a hero or page title banner next to the content and a page without one. That is expected: the plugin never guesses, and it never leaves a section of the previous page on the new one. Elements that scripts add after the page has loaded (sticky header placeholders, mobile menus, cookie bars) and classes that scripts add or remove (for example the sticky or fixed header classes of Elementor, Divi and Bricks) do not count as differences.

**Custom selectors.** Exactly the regions listed in **Content selectors** are replaced. Each selector must match the same number of elements (at least one) on both pages; otherwise the next page loads normally. If a selector matches `body`, the whole body is replaced. If you choose Custom but leave the selector list empty, detection works as in Automatic mode.

**Whole page body.** Everything inside `<body>` is replaced, except the admin bar, the plugin's own loading indicator and the scripts and styles that sit directly in the body. This is the closest to how version 1.x worked. It is heavier, and header scripts (menus, sticky headers) may need to be re-initialised after each navigation. Safe mode switches this mode back to Automatic.

To see what is detected on your site, use **Tools & Diagnostics → Check content selectors**.

#### Header and footer

The header and footer are found automatically (common selectors such as `#masthead`, `.site-header`, `header.wp-block-template-part`, `#colophon`, `.site-footer`, `footer.wp-block-template-part`, and the header and footer areas of Elementor, Divi, Bricks and Beaver Builder), or with the **Header selector** and **Footer selector** you enter.

* **Keep it (recommended):** the header or footer stays as it is, so menus, search boxes and sticky headers keep working without being restarted. The plugin compares the header (or footer) of both pages. If the next page has a different header, for example a transparent header on the home page and a solid one elsewhere, the next page loads normally. Differences in "current menu item" classes and in classes that scripts change while the page is used (such as a sticky header turning fixed) are ignored. If only the per-page layout class names of WordPress blocks differ, the header or footer is replaced automatically so it keeps its styles.
* **Replace it on every navigation:** the header or footer is swapped together with the content. Use this when it shows page-specific content, such as a different hero image per page.

### Forms

Search and filter forms that use the GET method can be submitted without a full reload. POST forms (contact forms, comments, logins, checkout) are never handled.

| Setting | Default | What it does |
|---|---|---|
| AJAX search forms | On | Submits WordPress search forms without a full reload: the theme search form, the Search block, the Search widget and the WooCommerce product search. |
| Additional GET forms | empty | CSS selectors of other GET forms, such as product filters, one per line. |

A form is never handled when it uses POST, opens in another window (`target`), contains a file upload, sits inside an opted-out area (`data-no-ajax`, `.no-ajaxy`), or submits to an excluded URL.

### Advanced: scripts and compatibility

This section is collapsed. The defaults suit most sites; change these only when a theme or plugin needs it.

| Setting | Default | What it does |
|---|---|---|
| Run scripts inside new content | On | Runs the inline and external scripts that are part of the replaced content, as a normal page load would. Scripts marked with `data-ajax-loading-skip` or `data-no-ajax` are skipped. |
| Run new inline scripts | On | Runs inline scripts outside the content area that only exist on the next page. Analytics and tracking snippets (Google tag, Tag Manager, Meta Pixel, Hotjar, Clarity and similar) are never run again. |
| Refresh changed `-js-extra` data | On | Re-runs the WordPress script data blocks (the `…-js-extra` scripts plugins use for their settings) when they differ on the next page, so plugins read the new page's settings. |
| Fire page-load events again | Off | After each navigation, dispatches synthetic `DOMContentLoaded` and `load` events for old scripts that only start on page load. Some scripts may then start twice; enable only when needed. Ignored in safe mode. |
| Remove unused stylesheets | Off | Removes stylesheets the next page does not use. Keeps long visits lean, but a stylesheet needed again must be downloaded again. Ignored in safe mode. |
| Load jQuery for custom callbacks | Off on new sites, On after an upgrade from 1.x | Makes the plugin's script depend on jQuery, so jQuery is loaded on every page where AJAX navigation runs, and also on the pages the plugin excludes on the server (cart, login pages and the like). Version 1.x always loaded jQuery; keep this on if your own `wp_ajax_load_complete` code uses jQuery. |
| Disable WordPress emoji scripts | Off on new sites, On after an upgrade from 1.x | Removes WordPress's emoji detection script and styles from the front end, as version 1.x did, whenever AJAX navigation is enabled. Modern browsers show emoji natively. |

See [Upgrading from 1.x](migration.md) for when to switch the last two off.

## Loading Experience tab

The left side holds the settings; the right side holds the [live preview](#live-preview).

### Loading indicator

The indicator is shown while the next page loads. Fast navigations finish before it appears.

| Setting | Default | Options or range | What it does |
|---|---|---|---|
| Indicator | Progress bar | Progress bar, Spinner, Overlay, Text, Your logo, Skeleton placeholder, None | The type of indicator (described below). |
| Indicator on mobile | Same as desktop | Same as desktop, or any indicator type | A different indicator on screens up to the mobile breakpoint. |
| Indicator colour | `#2271b1` | Colour | Main colour of the progress bar, the spinner and the loading text. Shown for the bar, spinner, overlay, text and logo indicators. |
| Background colour | `#ffffff` | Colour | Used by the overlay, the skeleton placeholder and the plate behind the spinner, logo and text. Shown for the spinner, overlay, text, logo and skeleton indicators. |
| Loading text | empty ("Loading…") | Up to 100 characters | Text of the Text and Overlay indicators. Leave empty to use the translated default. |
| Logo image | none | Media library image | Image shown by the "Your logo" indicator. Square images of about 200 pixels work best. Without an image, a spinner is shown. |
| Indicator size | 40 px | 8–200 px | Size of the spinner or logo (Spinner, Overlay, Your logo). |
| Bar height | 3 px | 1–12 px | Thickness of the progress bar. |
| Bar position | Top of the screen | Top, Bottom | Where the progress bar runs. |
| Indicator position | Centre | Centre, Top left, Top right, Bottom left, Bottom right | Where the spinner, text or logo appears. |
| Overlay opacity | 0.7 | 0–1 (steps of 0.05) | 0 is fully transparent, 1 is solid. |
| Animation speed | 900 ms | 200–5000 ms | Length of one animation cycle. Lower is faster. |
| Stacking order (z-index) | 99999 | 1–2147483647 | Raise this if the indicator is hidden behind a sticky header or popup. |

The indicator types:

* **Progress bar:** a thin bar along the top or bottom edge of the screen that fills up while the page loads.
* **Spinner:** a rotating ring at the chosen position.
* **Overlay:** covers the page in the background colour at the chosen opacity, with a spinner and the loading text in the middle. The text sits on a solid plate in the background colour, so it stays readable whatever is underneath.
* **Text:** a small label with the loading text and animated dots.
* **Your logo:** your chosen image, animated, at the chosen position.
* **Skeleton placeholder:** grey placeholder lines drawn over the content area while it loads. A fixed or sticky header and the admin bar stay visible above it, also when the visitor scrolls while the page loads.
* **None:** no indicator.

The indicator is hidden from screen readers; they get their own announcement (see [After navigation](#after-navigation)).

### Indicator timing

| Setting | Default | Range | What it does |
|---|---|---|---|
| Show the indicator after | 150 ms | 0–2000 ms | Navigations that finish sooner never show an indicator, so fast pages do not flicker. |
| Minimum display time | 250 ms | 0–3000 ms | Once visible, the indicator stays at least this long so it does not blink. |

### Page transitions

Animations played when the old content leaves and the new content enters. Only opacity and position (transform) are animated, so they stay smooth on slow devices.

| Setting | Default | Options or range | What it does |
|---|---|---|---|
| Leave animation | Fade | Fade, Fade through, Slide left, Slide right, Slide up, Slide down, Scale, Smooth (fade and lift), None | Played on the old content while the next page loads. |
| Enter animation | Fade | same list | Played on the new content. |
| Animation duration | 250 ms | 0–2000 ms | Length of each animation. |
| Easing | Ease | Ease, Ease in and out, Ease out, Linear, Snappy | The speed curve of the animation. |
| Animate header and footer | Off | On / off | Also animate the header and footer when they are set to "Replace" on the General tab. |
| Animation on mobile | Same as desktop | Same as desktop, Fade only, None | A simpler animation, or none, on screens up to the mobile breakpoint. |
| Respect reduced motion | On | On / off | Skips animations for visitors whose device asks for reduced motion. Strongly recommended for accessibility. |

In **Whole page body** mode, slide and scale effects are shown as fades, so fixed headers, cookie bars and chat widgets do not move. Slide left and Slide right never make the page scroll sideways; when the content area sits directly inside the page body, they are shown as fades too.

### After navigation

| Setting | Default | Options | What it does |
|---|---|---|---|
| Scroll after navigation | Scroll to the top of the page | Top of the page; Top of the content area; Do not scroll | Where the page scrolls after a new page is shown. Links to a `#section` always scroll to that section, and back/forward restore the previous position when **Restore scroll position** is on (Performance tab). |
| Move keyboard focus to | The main heading (recommended) | The main heading; The content area; Leave focus where it is | Where keyboard and screen reader users continue on the new page. A `#section` target or an element with `autofocus` in the new content takes priority. Focus is not moved if the visitor already moved it during the load. |
| Announce page changes | On | On / off | Screen reader users hear "Navigated to" followed by the new page title. |

### Live preview

The preview plays a navigation between two sample pages using the values in the form, including unsaved changes, and the same indicator and transition code that runs on your site. It honours **Show the indicator after**, so a sample load faster than that delay shows no indicator, exactly as on your site.

* **Play** runs the preview.
* **Desktop / Mobile** previews the desktop or the mobile indicator and animation.
* **Simulated load time** (0.3 s, 1.2 s or 3 s) shows how the indicator delay and minimum display time behave on fast and slow pages.

If your own device asks for reduced motion, a note explains whether animations are skipped. The preview needs JavaScript; settings save without it.

## Performance tab

### Prefetching

Prefetching starts loading a page as soon as a visitor shows interest in a link, so it opens almost instantly when clicked. It uses a little extra bandwidth and some extra requests to your server.

| Setting | Default | Options or range | What it does |
|---|---|---|---|
| Prefetch links | Off | On / off | Turns prefetching on. |
| Prefetch when a link is | Hovered, Focused, Touched | Hovered with the mouse; Focused with the keyboard; Touched (before the tap completes); Visible on screen | Which signals start a prefetch. |
| Hover delay | 80 ms | 0–1000 ms | How long the pointer must rest on a link before it is prefetched (hover and keyboard focus). |
| Parallel prefetches | 2 | 1–6 | Maximum number of pages prefetched at the same time. |
| Visible links per page | 6 | 1–30 | Maximum number of on-screen links prefetched per page (only with "Visible on screen"). |
| Never prefetch | empty | URL patterns, one per line | Pages that must never be prefetched, for example pages that are expensive to generate. Same [pattern syntax](#pattern-syntax) as the Exclusions tab. |
| Respect data saver | On | On / off | Skips prefetching when the visitor has data saver on or a very slow (2G) connection. |

Prefetching is never used:

* for logged-in visitors;
* on personalised pages, or when the visitor has cart, comment-author or post-password cookies;
* for excluded links;
* on sites with pretty permalinks, for URLs that contain a query string (`?…`), as WordPress's own speculative loading does.

A prefetched page that is never clicked is simply discarded. When the in-browser cache is off, a prefetched page is kept for about 30 seconds and used once.

### In-browser page cache

Keeps recently visited pages in the visitor's browser memory, so going back to them is instant. Nothing is stored on your server, and the cache ends when the tab is closed or reloaded.

| Setting | Default | Range | What it does |
|---|---|---|---|
| Cache visited pages | Off | On / off | Turns the cache on. When off, every navigation, including back and forward, fetches the page again. |
| Pages to keep | 10 | 1–50 | Maximum number of cached pages. The least recently used page is dropped first. |
| Keep pages for | 300 seconds | 10–3600 seconds | How long a cached page may be reused. |
| Memory budget | 4096 KB | 256–20480 KB | Upper limit for the HTML kept in memory. |

Pages are never cached for logged-in visitors, on personalised pages, when the response was not a normal "200 OK" page, when the server says not to cache it (`no-store`, `private`, `no-cache`), after a redirect, for URLs with a nonce, for excluded URLs, or when the page alone is bigger than the memory budget.

**Clear cached pages:** the **Clear navigation cache** button at the bottom of this tab (also on Overview and Tools) tells visitors' browsers to discard pages they prefetched or cached. Use it after changing your theme, menus or widgets. Browsers discard their copies the next time they load a page from your server (a page served from their own cache does not tell them), or when the cache lifetime ends. Your server page cache, if you have one, must be cleared separately.

### Requests

| Setting | Default | Range | What it does |
|---|---|---|---|
| Request timeout | 10000 ms | 2000–60000 ms | If a page takes longer than this, the browser loads it normally instead. |
| Turn off WordPress speculative loading | On | On / off | WordPress 6.8 and later prefetch links on their own. Turning that off on pages where AJAX navigation runs avoids downloading pages twice. Pages that load normally keep WordPress's speculative loading. |

### Page state

| Setting | Default | What it does |
|---|---|---|
| Restore scroll position | On | Back and forward return the visitor to where they were on that page. |
| Restore search and filter inputs | Off | Back and forward restore what the visitor typed or selected in forms inside the content area. Passwords, hidden fields and file fields are never stored. Values are kept in the browser tab only. |
| Highlight the current menu item | On | Keeps your menus' "current page" highlighting and its screen reader equivalent (`aria-current`) in sync after each navigation. |

## SEO & Integrations tab

### Search engines and social sharing

The page title is always updated. These options keep the rest of the page `<head>` in sync, so copied links, share buttons, browser extensions and SEO tools see the right data. Search engines are not affected either way: they load every page normally.

| Setting | Default | What it updates |
|---|---|---|
| Update meta tags | On | Description, keywords, author, robots (including `googlebot` and `bingbot`), Open Graph (`og:`, `article:`, `product:`, `profile:`, `book:`, `fb:`), Twitter cards, oEmbed and REST API discovery links, and RSS feed links. |
| Update canonical and alternate links | On | Canonical URL, previous/next links, shortlink and language alternates (`hreflang`). |
| Update structured data | On | The JSON-LD (schema.org) blocks in the page head and those printed directly in the page body (for example WooCommerce product schema). They are swapped, never executed. |

The `<html lang>` and `dir` attributes and the body classes are always updated.

### Analytics

Make sure every AJAX navigation is counted as a page view exactly once. The first page of a visit is always counted by your normal tracking code; these settings only concern the pages loaded afterwards.

| Setting | Default | Options | What it does |
|---|---|---|---|
| Page view tracking | Automatic | Automatic: let Google Analytics or Tag Manager detect navigations; Send GA4 page_view events (gtag.js); Push a dataLayer event for Google Tag Manager | See below. |
| Send navigation timing | Off | On / off | Also sends how long each AJAX navigation took, in milliseconds. Only with the GA4 or dataLayer option. |
| dataLayer event name | `ajax_page_view` | Letters, numbers, dots, dashes and underscores; up to 64 characters | Event name pushed in dataLayer mode. |
| Require statistics consent | Off | On / off | Only track navigations when the WP Consent API reports consent for `statistics`. Has no effect if no consent plugin is installed. |
| Custom tracking function | empty | Name of a global JavaScript function, dotted paths allowed (for example `myTheme.trackPage`) | Called after every AJAX navigation with the navigation details. Leave empty for none. |

The three tracking options:

* **Automatic (recommended):** the plugin sends nothing. GA4 Enhanced Measurement with "Page changes based on browser history events" turned on, or a Tag Manager History Change trigger, counts each navigation because the plugin changes the address with the browser's history API.
* **Send GA4 page_view events:** after each AJAX navigation (including back and forward) the plugin calls `gtag('event', 'page_view', …)` with the page location, title and referrer. It needs the Google tag (gtag.js) on your site. In GA4, go to **Admin → Data streams → your web stream → Enhanced measurement → Page views → Show advanced settings** and turn off **Page changes based on browser history events**, otherwise every navigation is counted twice. The settings screen shows this reminder when the option is selected.
* **Push a dataLayer event:** the plugin pushes `{ event: 'ajax_page_view', page_location, page_path, page_title, page_referrer, navigation_type }` (with your event name). In Tag Manager, create a Custom Event trigger for that event name and do not also count History Change events.

With **Send navigation timing**, the GA4 option also sends an `ajax_navigation_timing` event, and the dataLayer option pushes an `ajax_loading_timing` event, both with `navigation_duration` in milliseconds.

The plugin never loads tracking scripts itself; it only calls tools that are already on your site. If an old ga.js `pageTracker` or a Reinvigorate tracker exists on the page, it is notified too, as in version 1.x.

### Integrations

A table lists every built-in integration, whether it was detected on your site ("Detected" or "Not detected"), and its behaviour:

* **Auto (built-in handling):** the plugin re-initialises the integration after each navigation. If it cannot do that safely on a particular page, that page loads normally.
* **Exclude (full page load):** whenever the next page's new content contains this integration, that page loads normally.
* **Off (no special handling):** the plugin ignores the integration.

| Integration | Default | What Auto does |
|---|---|---|
| WooCommerce | Auto | Re-initialises product galleries, variation forms, tabs and sorting after navigation and refreshes cart fragments. A page whose new content contains the cart or checkout loads normally; with **Protect WooCommerce pages** on (default), cart, checkout, account and order pages always do. |
| Elementor | Auto | Initialises Elementor widgets and Pro popups in the new content without re-running Elementor's global start-up. |
| Divi | Auto | Re-runs Divi 4 module initialisation and refreshes per-page Divi styles. Divi 5 pages always load normally. |
| Beaver Builder | Auto | Runs the page-specific Beaver Builder layout script of the new page. |
| Bricks | Auto | Refreshes Bricks page data and re-runs Bricks element scripts. |
| Contact Form 7 | Auto | Initialises Contact Form 7 forms that appear in new content. |
| Gravity Forms | Auto | Runs Gravity Forms initialisation scripts and post-render events for forms in new content. |
| WPForms | Auto | Refreshes WPForms settings and re-runs its initialisation for forms in new content. |
| Fluent Forms | Auto | Re-initialises Fluent Forms in new content. |
| Formidable Forms | Auto | Refreshes Formidable captchas; its form handlers keep working on new content. |
| Ninja Forms | Exclude | Ninja Forms cannot be started again after a page has loaded, so pages that contain a Ninja Form load normally. Only Exclude or Off. |
| ACF front-end forms | Exclude | ACF forms depend on page data printed in the footer, so pages that contain an ACF form load normally. Only Exclude or Off. |
| BuddyPress | Exclude | BuddyPress starts once per page, so BuddyPress pages and links inside BuddyPress content load normally. Only Exclude or Off. |
| Embeds | Auto | Loads X (Twitter), Instagram, Facebook and WordPress post embeds that appear in new content. |
| Lazy loading scripts | Auto | Makes lazysizes, vanilla-lazyload and the plugins that use them pick up images in new content. |
| Threaded comment replies | Auto | Keeps the "Reply" links of threaded comments working after navigation. |
| "post-load" event | Auto | Triggers the jQuery `post-load` event on the body after each navigation (the event used by infinite scroll; many plugins re-initialise on it). Needs jQuery on the page. |
| Multilingual (WPML, Polylang, TranslatePress …) | Auto | Language switches always use a full page load: language switcher links are never intercepted, and a page whose `<html lang>` differs from the current one loads normally. With **Exclude**, any page that has a language switcher or `hreflang` links loads normally, which on most multilingual sites means AJAX navigation is effectively off. With **Off**, language links are treated like any other link. |

Setting Ninja Forms, ACF front-end forms or BuddyPress to **Off** is not recommended; the environment report warns about it. Safe mode treats Elementor, Divi, Beaver Builder and Bricks as **Exclude** (unless set to Off).

### Developer reference

The bottom of the tab lists the JavaScript events and PHP hooks with copyable code snippets: running code after every navigation, the 1.x callback, the jQuery form, opting a link out, marking the content area, forcing a full reload when an asset changes, navigating from your own code, and two PHP examples. The [developer guide](developer-guide.md) explains them in detail.

## Exclusions tab

Links that match an exclusion load normally (full page load).

### Your exclusions

| Setting | Default | What it does |
|---|---|---|
| Excluded URLs | empty | URL patterns, one per line (up to 200 lines). See [Pattern syntax](#pattern-syntax). |
| Excluded links (CSS selectors) | empty | Links that match these selectors, or sit inside an element that matches them, load normally. One selector per line. Example: `.main-menu .external` or `#footer-links a`. |
| Excluded post types | none | A checkbox for each public post type. Single entries and archives of the ticked types always load normally. |

**Note on Posts and Pages:** custom post types usually share a URL prefix (such as `/products/`), so their links are recognised before anything is downloaded. Posts and Pages have no common prefix, so for them the plugin only notices the exclusion after it has fetched the page, and then loads it normally; such a link costs two requests. To exclude a few specific posts or pages, add their URLs to **Excluded URLs** instead.

### Protected areas

| Setting | Default | Options | What it does |
|---|---|---|---|
| Protect WooCommerce pages | On | On / off | Cart, checkout, My Account (with all its endpoints), order pages and cart actions always load normally: links with `add-to-cart=`, `remove_item=`, coupon, order-again, cancel-order, download and password-reset parameters, the `wc-api` and `wc-ajax` endpoints, add-to-cart and remove buttons, and the My Account logout link. Pages containing the cart or checkout block or shortcode also load normally. |
| Protect login and membership pages | On | On / off | Login, logout, registration and password reset pages (including `/login/`, `/logout/`, `/register/` and custom login URLs set by plugins), logout links, and the account, checkout, login and registration pages of Paid Memberships Pro, Ultimate Member, MemberPress and BuddyPress load normally. |
| Interactive blocks | Load these pages normally (recommended) | Load these pages normally; Replace them with AJAX | Blocks built with the WordPress Interactivity API (for example the navigation overlay, image lightbox, some Query Loop, Search and WooCommerce blocks) cannot be started again after an AJAX swap. With the recommended option, a page whose new content contains such blocks loads normally. Safe mode always uses the recommended option. |

While **Protect WooCommerce pages** is on, the plugin also recognises WooCommerce cart, checkout, account and order pages by their body class (in case their address is not a known one) and loads them normally; the same applies to Paid Memberships Pro checkout, billing and cancel pages while **Protect login and membership pages** is on. Switching a protection off really lets those pages load through AJAX, so do this only when you have tested them.

### Pattern syntax

Patterns are matched against the path and query string of a link (everything after the domain), ignoring upper and lower case and any `#fragment`. Non-ASCII addresses are matched both in their encoded (`%e0%a4%b9`) and their readable form.

| Pattern | Matches | Does not match |
|---|---|---|
| `/about` | `/about`, `/about/` (a trailing slash is optional) | `/about/team/` |
| `/members/` | `/members`, `/members/`, `/members/jane/` and everything else below it, because the pattern ends with a slash | `/members-area/` |
| `/shop/*` | everything under `/shop/`, such as `/shop/`, `/shop/shirts/`, `/shop/?orderby=price`. `*` matches any characters | `/shop` |
| `/?s=*` | search results such as `/?s=shoes`. A pattern that contains `?` is also matched against the query string | `/shop/?s=shoes` |
| `/` | the home page only | any other page |
| `download=` | any address containing `download=` anywhere in its path or query, such as `/files/?download=12`. Patterns without a leading slash match anywhere | |
| `*/print/` | any address containing `/print/` anywhere | |
| `https://example.com/landing/` | full addresses of your own site work too; the part after the domain is used like a `/…` pattern | addresses on other domains |

Lines are trimmed, empty lines and duplicates are dropped, and the characters `< > " { } \` and backticks are removed when you save.

You can also opt a single link, or a whole area, out in your templates or in the block editor's "Additional CSS class(es)" field:

* the attribute `data-no-ajax` (or `data-ajax-loading="false"`);
* the class `no-ajaxy` (kept from version 1.x) or `no-ajax`.

```html
<a href="/members/" data-no-ajax>Members</a>

<nav class="no-ajaxy">…</nav>
```

### Always excluded

The right-hand column lists the built-in rules. They keep sensitive or non-HTML pages on normal page loads and cannot be turned off:

* WordPress admin, login, registration and system files (`wp-admin`, `wp-login.php`, `wp-signup.php`, `wp-activate.php`, `wp-comments-post.php`, `xmlrpc.php`, `wp-cron.php`).
* REST API, feeds, sitemaps, post embeds, `robots.txt`, `favicon.ico` and `/.well-known/` URLs.
* Files in `wp-content`, `wp-includes` and the uploads folder, and links to non-HTML files (PDF, images, media, archives, documents).
* Previews, Customizer links and password-protected posts.
* Links with a nonce or an action parameter (`_wpnonce`, `?action=`), comment reply and moderation links, cron links.
* Links to other sites, links outside the WordPress home URL, same-page `#anchors`, links with `target`, `download` or `rel="external"`.
* Links inside `.no-ajax`, `.no-ajaxy`, `[data-no-ajax]` or `[data-ajax-loading="false"]`, and links in the admin bar.
* Lightbox links, Elementor popup and lightbox actions, and Interactivity API router links.
* Language switcher links (WPML, Polylang, TranslatePress, any link with `hreflang` or `lang`), unless the multilingual integration is Off.
* The WooCommerce and membership rules above, when those protections are on, the BuddyPress rule when that integration is set to Exclude, and your excluded post types.
* Pages containing interactive blocks or forms that cannot be re-initialised (per the integration settings), and any page that fails to load.

Ctrl-, Shift-, Alt- and Cmd-clicks and middle-clicks are also always left to the browser. On a multisite network, a page of another site of the network always loads normally too (the plugin recognises it by its marker after downloading it).

## Tools & Diagnostics tab

### Compatibility check

The compatibility check loads pages of your site the way the front end does, then runs the real link rules and content detection on them. It uses your **saved** settings, so save changes first. It needs JavaScript.

Fill in **From page** and **To page** (the fields suggest your home page, latest post, a page, a category and a search results page, but you can enter any address on your site), then:

**Test navigation** simulates a click from the first page to the second and reports, step by step:

| Check | What it tells you |
|---|---|
| Load (page) | HTTP status, size and time of each page, or why it could not be loaded (error status, not an HTML page, redirect, timeout). |
| Plugin marker on (page) | Whether AJAX Loading is active on that page, the page is excluded on the server, or the marker is missing (plugin off, paused, test mode for other users, or a page cache serving an old copy). Also warns when the page was rendered by another plugin version. |
| Link rules for the destination | Whether a link to the second page is handled with AJAX, or loads normally and why (reason code, see [Troubleshooting](troubleshooting.md#link-reason-codes)). |
| Prefetch for visitors | Whether visitors may prefetch that page. |
| Content to replace | The detected regions (content, header, footer or whole body), or why no matching content area was found. |
| Head tags that will be updated | The new title and the head tags that will be replaced. |
| Scripts and styles | How many scripts inside the new content and how many new external scripts and stylesheets will be loaded; warns about `document.write`. |
| Links on the start page | How many links on the first page load with AJAX, and the reasons for the others. |
| Things that force a normal page load | Interactive blocks, the Interactivity router, an integration set to **Exclude** whose content is on the destination page, a language change, protected page types (while the matching protection is on), tracked assets, personalised pages, test mode. |

The result ends with "This navigation will use AJAX" or "This navigation will fall back to a normal page load". Pages are fetched with your logged-in session, so visitors may see slightly different markup.

**Check content selectors** loads your home page, latest post, a page, a category archive and a search results page, and shows in a table which content area, header and footer are detected on each, whether the plugin marker is present, and whether a navigation from the first page would work.

Results are saved and summarised on the Overview tab under **Last compatibility check**.

### Environment report

A list of checks about your site, each marked OK, Info, Warning or Error, with a **Refresh** button:

Versions (WordPress and PHP), plugin status, pause, visibility (test mode), safe mode, front-end files, permalinks, home and site URL, HTTPS, `SCRIPT_DEBUG`, theme (block or classic, with a content selector hint), block theme layout classes, caching and optimisation plugins, other navigation plugins, other prefetch plugins, core speculative loading, detected integrations, Elementor Pro Page Transitions, Divi 5, plugins that always use full page loads, multilingual plugins, interactive blocks, the Interactivity router, the legacy jQuery dependency and the PHP DOM extension.

Read the Warnings and Errors first; each message says what to do. When asking for support, include this report.

### Recent navigation errors

A table of the last failed navigations: **Time**, **Error** (a readable label, the error code and a short message), **Page** (path only), **HTTP** status and **Type** (`link`, `popstate` for back/forward, `form` or `programmatic`). **Refresh** reloads the list; **Clear** deletes all entries. The list only fills while **Record navigation errors** (below) is on. The error codes are explained in [Troubleshooting](troubleshooting.md#error-codes).

### Safety

Whenever AJAX navigation cannot handle a page, the browser simply loads it normally. These options add extra protection.

| Setting | Default | Range | What it does |
|---|---|---|---|
| Safe mode | Off | On / off | Conservative behaviour for troubleshooting (see below). |
| Automatic fallback | On | On / off | If navigation fails repeatedly for a visitor, that visitor's browser tab switches to normal page loads for a while. |
| Failures before fallback | 3 | 2–20 | Number of failed navigations within 5 minutes that trigger the fallback. |
| Fallback duration | 30 minutes | 1–1440 minutes | How long the fallback lasts. |

Safe mode, while on:

* turns off prefetching and the in-browser cache;
* ignores **Additional GET forms** (search forms still work);
* keeps the header and footer in place, and uses Automatic detection instead of Whole page body;
* turns off **Fire page-load events again** and **Remove unused stylesheets**;
* loads pages with interactive blocks normally;
* loads pages built with Elementor, Divi, Beaver Builder or Bricks normally (unless that integration is set to Off).

Your saved settings are not changed; turning safe mode off restores them.

Only failures that point to a real problem count towards the automatic fallback: timeouts, server errors (HTTP 5xx), answers that cannot be read and unexpected script errors. Expected fallbacks, such as excluded pages, pages without the plugin marker, different layouts or a 404, never count, and neither does being offline. The fallback is stored in the visitor's browser tab (session storage), so a new tab starts fresh.

### Debugging

| Setting | Default | What it does |
|---|---|---|
| Debug logging | Off | Writes navigation details to the browser console (prefixed `[AJAX Loading]`). Turn it off on production sites. See [Troubleshooting](troubleshooting.md#debug-mode). |
| Record navigation errors | Off | Stores the last 50 failed navigations from your visitors and shows them under **Recent navigation errors**. Only the error code, page path (without query string), HTTP status, a short message and the navigation type are stored; no IP address, user agent or cookies. |

### Maintenance

| Tool | What it does |
|---|---|
| Pause AJAX navigation | **Pause for 1 hour** or **Pause for 24 hours** serves normal page loads for a while (for example during theme changes) without touching your settings. **Resume now** ends the pause. |
| Clear navigation cache | Tells visitors' browsers to discard pages they prefetched or cached earlier, the next time they load a page from your server or when the cache lifetime ends. |
| Export settings | **Download export file** saves all settings as a JSON file (`ajax-loading-settings-<your domain>-<date>.json`), for backups or to copy them to another site. |
| Import settings | Choose an AJAX Loading export file (`.json`, up to 100 KB) and click **Import settings**. You are asked to confirm. Settings in the file overwrite your current values; settings that are not in the file keep their current values. Files from other plugins or invalid files are rejected and nothing changes. Importing also clears visitors' navigation caches. |
| Restore defaults | Resets every setting to its default value after you tick **Yes, restore all default settings** and confirm. This switches AJAX navigation on for everyone, ends any pause, and turns **Load jQuery for custom callbacks** and **Disable WordPress emoji scripts** off. Consider exporting first. |

## About and Say Thanks tabs

**About** shows information about the plugin and its author, other plugins by the same author and some helpful links (including the support forum). It displays the author's Gravatar and plugin icons from wordpress.org, which your browser loads when you open this tab.

**Say Thanks** shows ways to support the author. The 1.x links to these tabs (`&con=about` and `&con=donate`) still work.
