| @@ -3,9 +3,9 @@ | ||
| 3 | 3 | Tags: cache, performance, page speed, optimization, mcp |
| 4 | 4 | Requires at least: 6.0 |
| 5 | 5 | Tested up to: 7.1 |
| 6 | 6 | Requires PHP: 7.4 |
| 7 | -Stable tag: 1.3.4 | |
| 7 | +Stable tag: 1.3.7 | |
| 8 | 8 | License: GPLv2 or later |
| 9 | 9 | License URI: https://www.gnu.org/licenses/gpl-2.0.html |
| 10 | 10 | |
| 11 | 11 | A complete WordPress caching plugin: page cache, object cache, CDN, database cleanup and Core Web Vitals optimization, plus a built-in MCP server. |
| @@ -171,9 +171,9 @@ | ||
| 171 | 171 | = Private By Default = |
| 172 | 172 | |
| 173 | 173 | xSpeed Cache never collects personal data, stores IP addresses or uses tracking cookies. Every optimization runs locally on your server. By default it makes no calls to any third-party server. The only request is a quick check to your own site's home URL to confirm GZIP is active, rate-limited to once per hour. |
| 174 | 174 | |
| 175 | -xSpeed Cache also includes **optional usage analytics**. You are asked in two places, both off by default: a clearly labeled consent control in the setup wizard, and the switch in xSpeed Cache → Settings → Privacy & usage data. Nothing is sent unless you opt in from one of them. When enabled, xSpeed Cache shares anonymous, non-sensitive diagnostics: your WordPress and PHP version, active theme and plugins, server type, site language, and which xSpeed Cache features you have switched on, so we know what to keep fast and compatible. No personal data and no page content are ever sent, and you can turn it off again at any time from xSpeed Cache → Settings → Privacy & usage data. See the External services section below. | |
| 175 | +xSpeed Cache also includes **optional usage analytics**. You are asked in two places: a clearly labeled consent control in the setup wizard, and the switch in xSpeed Cache → Settings → Privacy & usage data. Nothing is sent until you confirm from one of them. When enabled, xSpeed Cache shares non-sensitive diagnostics: your WordPress and PHP version, active theme and plugins, server type, site language, and which xSpeed Cache features you have switched on, so we know what to keep fast and compatible. No page content is ever sent, and you can turn it off again at any time from xSpeed Cache → Settings → Privacy & usage data. See the External services section below. | |
| 176 | 176 | |
| 177 | 177 | = Backed By a Team You Trust = |
| 178 | 178 | |
| 179 | 179 | xSpeed Cache is developed by the trusted team at WPDeveloper, a leading WordPress marketplace used and loved by millions of users. |
| @@ -263,9 +263,9 @@ | ||
| 263 | 263 | 8. Migration — import settings from WP Rocket, W3 Total Cache, WP Super Cache, or LiteSpeed Cache. |
| 264 | 264 | |
| 265 | 265 | == External services == |
| 266 | 266 | |
| 267 | -xSpeed Cache contacts your own site (the gzip probe below); when usage analytics is enabled, an analytics service; only if you choose to submit the optional deactivation survey, that same service; and — only when you run a speed test yourself — one external performance-score provider. Analytics consent is asked in two places, both off by default — a clearly-labeled control in the setup wizard, and the switch in xSpeed Cache → Settings → Privacy & usage data — and nothing is sent unless you opt in from one of them; turning the switch off stops all collection and clears the scheduled send. The deactivation survey is separate and never sends anything unless you explicitly click Submit. External scores are off by default, turn on the first time you press Test, and never run on their own. | |
| 267 | +xSpeed Cache contacts your own site (the gzip probe below); when usage analytics is enabled, an analytics service; only if you choose to submit the optional deactivation survey, that same service; and — only when you run a speed test yourself — one external performance-score provider. Analytics consent is asked in two places — a clearly-labeled control in the setup wizard, and the switch in xSpeed Cache → Settings → Privacy & usage data — and nothing is sent until you confirm from one of them; turning the switch off stops all collection and clears the scheduled send. The deactivation survey is separate and never sends anything unless you explicitly click Submit. External scores are off by default, turn on the first time you press Test, and never run on their own. | |
| 268 | 268 | |
| 269 | 269 | = Self-hosted gzip probe = |
| 270 | 270 | |
| 271 | 271 | * **What it does:** Issues a single `GET` request to your site's home URL (`home_url('/')`) with an `Accept-Encoding: gzip` header to detect whether your web server is already serving gzipped responses. The response body is discarded; only the `Content-Encoding` header is read. |
| @@ -272,8 +272,15 @@ | ||
| 272 | 272 | * **When it runs:** On demand when the admin dashboard loads server status, throttled to once per hour via a transient (`xspeed_gzip_active`). |
| 273 | 273 | * **Where the request goes:** Your own site (`home_url()`). This request goes only to your own server. |
| 274 | 274 | * **What is sent:** No personal data, no site identifiers, no payload — just a standard HTTP `GET` from your server back to your server. |
| 275 | 275 | |
| 276 | += xSpeed Hub (app.xspeedcache.com) = | |
| 277 | + | |
| 278 | +* **What it does:** Lets you manage this site, with other sites, from one xSpeed Hub account and one AI connection. | |
| 279 | +* **When it runs:** Only after an administrator connects the site to xSpeed Hub from xSpeed Cache → AI & agents. A site that was never connected makes no Hub requests. | |
| 280 | +* **What is sent:** The site URL and this site's MCP token, which the Hub uses to call the site's own MCP endpoint. The token is sent when the site is connected, when the connection status is checked, when the token changes (Rotate, or Connect after Disconnect), when you disconnect, and with speed-test requests you start. | |
| 281 | +* **Where the request goes:** app.xspeedcache.com, operated by WPDeveloper. | |
| 282 | + | |
| 276 | 283 | == Third-party libraries == |
| 277 | 284 | |
| 278 | 285 | This plugin bundles the following GPL-compatible third-party libraries: |
| 279 | 286 | |
| @@ -306,8 +313,102 @@ | ||
| 306 | 313 | * License: ISC |
| 307 | 314 | |
| 308 | 315 | == Changelog == |
| 309 | 316 | |
| 317 | += [1.3.7] – 2026-10-01 = | |
| 318 | + | |
| 319 | +**Pages with a background-video hero now paint the hero text first, Load CSS Asynchronously no longer makes pages flash unstyled, sites in a multisite network stop sharing cached REST responses, and a site whose token changed can reconnect to xSpeed Hub.** | |
| 320 | + | |
| 321 | +Media: | |
| 322 | +- Fixed: A hero's background video (autoplay, muted, looping, no controls or poster) now starts on the visitor's first scroll, tap, key press or mouse move, so the hero text paints first instead of waiting for the video's first frame. | |
| 323 | +- Fixed: Only one image per page gets high fetch priority, instead of every image counted by Eager-load First N Images. | |
| 324 | + | |
| 325 | +Optimization: | |
| 326 | +- Fixed: Load CSS Asynchronously leaves stylesheets render-blocking unless the page has critical CSS, so pages no longer paint unstyled and then shift. Google Fonts, Bunny and Typekit stylesheets still load without blocking. | |
| 327 | +- Fixed: A page builder's row, column and section stylesheets stay render-blocking, so a builder hero no longer snaps into its grid after the first paint. | |
| 328 | +- Fixed: Under Delay JS, a script's inline data now waits with the script, so the script never runs without its data. | |
| 329 | +- Fixed: Combine CSS recognises another plugin's non-blocking stylesheet however its onload handler is written, instead of merging it into a print-only file. | |
| 330 | +- Fixed: Strip jQuery Migrate works when another plugin, such as Elementor Pro, loads the script registry before Bloat Control. | |
| 331 | + | |
| 332 | +Resource Hints: | |
| 333 | +- Fixed: When a background video opens the page, images below it are no longer preloaded as the LCP image. | |
| 334 | + | |
| 335 | +Caching: | |
| 336 | +- Improved: More click and campaign IDs are ignored in the cache key, on saved lists too. | |
| 337 | +- Fixed: Each site in a multisite network gets its own cached REST responses. Two sites requesting the same route could be served each other's data. | |
| 338 | +- Fixed: Installing a new plugin no longer empties the page cache as if live code had been replaced. | |
| 339 | +- Fixed: A request that measures a page's CSS is never answered from cache, whatever Ignored Query Parameters say. | |
| 340 | +- Fixed: xSpeed's own warming, benchmark and verifier requests, and bot hits, no longer count in the hit ratio or in site analytics. | |
| 341 | + | |
| 342 | +AI / MCP: | |
| 343 | +- New: Extensions can add hidden MCP tools, and oversized MCP request bodies are refused. | |
| 344 | +- Improved: The generate_critical_css tool builds Critical CSS for any page, not only the home page. | |
| 345 | +- Improved: get_cache_status reports the Site Icon. | |
| 346 | +- Fixed: A site whose MCP token changed can reconnect to xSpeed Hub. The Hub gets the new token, and a new credential clears its lockout. | |
| 347 | +- Fixed: The attach route no longer returns the admin's user ID. | |
| 348 | + | |
| 349 | +Dashboard & Admin UX: | |
| 350 | +- Improved: Settings labels and hints are rewritten in plain language and sentence case. | |
| 351 | +- Fixed: Leaving onboarding from the last step lands on the dashboard instead of a broken #[object Object] page. | |
| 352 | + | |
| 353 | += [1.3.6] – 2026-09-28 = | |
| 354 | + | |
| 355 | +**Smart Delay postpones the scripts other delay modes had to leave running, LCP background images and video posters are preloaded, LiteSpeed servers get the same static fast path nginx and Apache already had, lightbox videos open with their player instead of a blank window, and Turbo Render no longer clips designs that overlap their neighbours. Emojis can be switched off, post revisions capped, and inline background images held back until they scroll into view.** | |
| 356 | + | |
| 357 | +Media: | |
| 358 | +- New: Background images set in an element's inline style can be lazy-loaded. Each one loads just before its element scrolls into view, the first ones on the page load straight away (the Eager-load First N Images count), and with JavaScript off every background loads as before. Off by default. | |
| 359 | +- Fixed: A video embed inside a lightbox's hidden template (Essential Addons, Magnific Popup, Lity) is no longer swapped for the click-to-play facade — the popup opened blank because lightbox styling only sizes an iframe. The template's iframe stays lazy, so it still loads nothing until the popup opens, and the list of template classes can be extended with the xspeed_video_facade_popup_classes filter. | |
| 360 | + | |
| 361 | +Optimization: | |
| 362 | +- New: Bloat Control has a Disable Emojis toggle. It removes the WordPress emoji script and styles from pages, feeds, emails, embeds and wp-admin. Off by default. | |
| 363 | +- New: Turbo Render has an Excluded classes setting. A deferred section clips content that hangs over its boundary — a card overlapping the section below it, for example — so a section listed here always renders right away. | |
| 364 | +- Fixed: Turbo Render leaves any section holding an iframe alone. Deferring a map or video holder gained nothing and could paint it over content that overlaps it by design. | |
| 365 | +- New: Smart Delay. Delaying every script used to quietly skip any script that inline code depends on — on builder pages that was most of them. Smart Delay postpones those scripts anyway and parks their inline snippets with them, replaying everything in page order on the first interaction. Off by default; the exclusion list and consent-banner protection still win. | |
| 366 | +- Improved: Delayed scripts now replay the way a real page loads — in page order, with the document's readyState moving through its normal stages, and with each script's DOMContentLoaded and load handlers firing when its turn comes. | |
| 367 | +- Improved: A delayed inline loader now waits for the scripts it injects, a throwing inline module no longer stalls the replay behind it, and the replay works on pages with a hash-based Content-Security-Policy. | |
| 368 | +- Fixed: The replay no longer touches scripts and handlers the page ran normally — their writes, listeners and onreadystatechange calls behave exactly as before Delay JS was switched on. | |
| 369 | +- Fixed: A consent banner is only delayed by an entry that names it; a second protected token on the same tag now needs naming too. | |
| 370 | +- Fixed: A script whose author opted out of optimization late in the page no longer loses the defer attribute a stamper had already given it. | |
| 371 | + | |
| 372 | +Resource Hints: | |
| 373 | +- New: LCP background images declared in <style> rules and video poster images are now detected and preloaded, so hero sections painted from CSS backgrounds get the same head start as <img> heroes. | |
| 374 | + | |
| 375 | +Caching: | |
| 376 | +- New: LiteSpeed servers can opt into the static-rewrite fast path, serving cached pages before PHP starts — the same shortcut nginx and Apache sites already had. | |
| 377 | +- Fixed: Publishing a post on an nginx host no longer purges the server's entire cache — only the pages the post touches. Nginx Helper's own off switch is respected, and a content import ends with one server purge instead of one per post. | |
| 378 | +- Fixed: The admin-bar purge button answers immediately and runs the purge in the background, instead of holding the request open until some hosts cut it off. | |
| 379 | + | |
| 380 | +Database: | |
| 381 | +- New: Limit Post Revisions keeps only as many revisions per post as you choose, and 0 turns revisions off. A WP_POST_REVISIONS value in wp-config.php still wins, and the panel shows it. | |
| 382 | + | |
| 383 | +Migration: | |
| 384 | +- Fixed: Importing LiteSpeed Cache settings no longer turns oEmbed off when the site had emoji removal on. That setting now maps to Disable Emojis. | |
| 385 | +- New: WP Rocket's emoji, embeds and CSS background lazy-load settings are imported. | |
| 386 | + | |
| 387 | +Dashboard & Admin UX: | |
| 388 | +- Fixed: The Cloudflare upsell no longer advertises an edge cache TTL the APO module does not set. | |
| 389 | + | |
| 390 | += [1.3.5] – 2026-09-22 = | |
| 391 | + | |
| 392 | +**Consent banners now survive Delay JS on every site that ships one, Turbo Render works on any theme rather than only Elementor, JS-injected YouTube/Vimeo embeds load only on click, and nginx sites are no longer told to fix a configuration that was already correct.** | |
| 393 | + | |
| 394 | +Media: | |
| 395 | +- New: YouTube and Vimeo players that a theme or plugin injects with JavaScript after page load now get the same click-to-load facade as regular embeds, so no player code loads until a visitor presses play. | |
| 396 | + | |
| 397 | +Optimization: | |
| 398 | +- New: Turbo Render works on any theme or page builder. It recognises Divi, Bricks, Oxygen and Beaver Builder sections directly, and where no builder is recognised it falls back to the page's own structure, so the feature is no longer inert outside Elementor. | |
| 399 | +- Improved: Turbo Render is the new name for the feature previously called Render Skip — the same mechanism, named for what the visitor gets rather than what the browser postpones. | |
| 400 | +- Fixed: Consent banners from Cookie Notice, Moove, Termly, Usercentrics, Iubenda, OneTrust, Borlabs, Real Cookie Banner and SureCookie are never delayed, so a visitor is always offered the choice before leaving. | |
| 401 | +- Fixed: Complianz and NotificationX banners stay protected even when another plugin strips the id WordPress prints on their script. | |
| 402 | +- Fixed: An author's data-no-optimize, nowprocket or similar opt-out is now read as an attribute rather than matched anywhere in the tag, so a script is neither wrongly delayed nor wrongly skipped because the marker appeared in a URL, a class or a neighbouring inline block. | |
| 403 | +- Fixed: A script you name yourself in the Delay JS target list is now delayed even when it is a consent banner — the built-in banner protection yields to an explicit choice. | |
| 404 | + | |
| 405 | +Health: | |
| 406 | +- Fixed: nginx sites with a working configuration are no longer told to paste in a server snippet they already have. Site Health and the dashboard now reach the same verdict, and a check that cannot conclude says so instead of warning. | |
| 407 | + | |
| 408 | +Preloader: | |
| 409 | +- Fixed: Cache warming no longer identifies itself in a way that common firewall rule sets block, so newly published posts are warmed again on sites running 7G/8G-style protection. | |
| 410 | + | |
| 310 | 411 | = [1.3.4] – 2026-09-20 = |
| 311 | 412 | |
| 312 | 413 | **Consent-manager scripts marked late are now always left alone, below-fold sections skip rendering work until they are needed, and xSpeed's MCP server shares a site cleanly with other MCP plugins.** |
| 313 | 414 | |
| @@ -349,20 +450,6 @@ | ||
| 349 | 450 | - Improved: Preload now reports what actually happened — how many pages are warming, and the server's reason when a crawl cannot start. |
| 350 | 451 | |
| 351 | 452 | Reliability: |
| 352 | 453 | - Improved: Uninstall now removes all usage-tracking state, the scheduled send, and every leftover option row. |
| 353 | - | |
| 354 | -= [1.3.2] – 2026-09-15 = | |
| 355 | - | |
| 356 | -**Purging is now a contract other caches can join: clearing xSpeed's page cache also invalidates LiteSpeed Cache and the host's nginx FastCGI cache, and every purge is scoped to exactly the site and pages it was asked for — including on multisite.** | |
| 357 | - | |
| 358 | -Caching: | |
| 359 | -- New: A purge-event contract lets other caching layers invalidate together with xSpeed, so a purge clears every cache that matters in one action. | |
| 360 | -- New: Purge All is forwarded to LiteSpeed Cache and the host's nginx FastCGI cache when they are present. | |
| 361 | -- Fixed: One post change triggers exactly one invalidation, deleting a media file purges again, and a purge still finds its post when the hook hands over none. | |
| 362 | -- Fixed: Purges are scoped per site on multisite — a purge no longer sends another site's URLs to this site's server cache, a default port is not treated as a different site, and full purges stay on the current site. | |
| 363 | -- Fixed: A purge listener that throws no longer aborts the purge, a query string of "0" is still treated as a query, and a partial purge reports itself as partial instead of claiming success. | |
| 364 | - | |
| 365 | -Optimization: | |
| 366 | -- Fixed: Delaying JavaScript no longer breaks inline scripts bound to a delayed handle, and replayed external scripts keep their original load order. | |
| 367 | 454 | |
| 368 | 455 | Older releases are listed in changelog.txt, included with the plugin, and at [xspeedcache.com/changelog](https://xspeedcache.com/changelog/). |