| @@ -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.1 | |
| 7 | +Stable tag: 1.3.6 | |
| 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**. The setup wizard shows a clearly labeled consent control for it (enabled by default, untick to opt out), and nothing is sent until you confirm your choices in the wizard. 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 your dashboard. 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. The setup wizard shows a clearly-labeled consent control for analytics (enabled by default, untick to opt out), and nothing is sent until you confirm your choices there. 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. |
| @@ -306,90 +306,107 @@ | ||
| 306 | 306 | * License: ISC |
| 307 | 307 | |
| 308 | 308 | == Changelog == |
| 309 | 309 | |
| 310 | -= [1.3.1] – 2026-09-14 = | |
| 310 | += [1.3.6] – 2026-09-28 = | |
| 311 | 311 | |
| 312 | -**Purge all now says what it actually cleared, on the button and in the toast, instead of claiming success when a store refused. Pro features are marked with one lock everywhere rather than amber squares and crowns, which also lifts the dimmed labels back to readable contrast. The Cloudflare panel is staged by connection state, so setup comes before the actions that depend on it — and the auto-purge switch is visible while disconnected instead of hidden.** | |
| 312 | +**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.** | |
| 313 | 313 | |
| 314 | -Dashboard & Admin UX: | |
| 315 | -- New: Purge all reports its outcome — Cleared, Already empty, Partly cleared or Purge failed — and the toast names the files and size cleared plus any other store, or the reason a store refused. | |
| 316 | -- Fixed: Pro features are marked with a single lock in the teal tint. Locked tabs are no longer dimmed to 70%, which had dropped their labels below readable contrast, and the amber squares, crowns and sparkles are gone from the tabs, badges and the sidebar tier slot. | |
| 317 | -- Fixed: Turning caching on no longer flashes "Another plugin owns the page cache on this site" while the toggle is in flight. A genuine foreign drop-in still shows the banner. | |
| 318 | -- Fixed: The Purge all button keeps its natural width at rest instead of reserving room for the outcome label. | |
| 314 | +Media: | |
| 315 | +- 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. | |
| 316 | +- 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. | |
| 319 | 317 | |
| 320 | -Cloudflare: | |
| 321 | -- New: The panel is staged by connection state — Connection, then Actions — so credentials and Verify come before the buttons that need them, and an action that cannot work is disabled with a hint rather than failing silently. | |
| 322 | -- Fixed: The auto-purge-on-purge switch is always visible, dimmed while disconnected, instead of being hidden until connected. Hiding it is how the edge-sync switch went unnoticed. | |
| 318 | +Optimization: | |
| 319 | +- 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. | |
| 320 | +- 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. | |
| 321 | +- 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. | |
| 322 | +- 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. | |
| 323 | +- 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. | |
| 324 | +- 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. | |
| 325 | +- 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. | |
| 326 | +- 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. | |
| 327 | +- 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. | |
| 323 | 328 | |
| 324 | -Documentation: | |
| 325 | -- Fixed: The full changelog moved to changelog.txt, shipped with the plugin and linked from the plugin page. wordpress.org truncates a changelog over 5,000 words on import, so the history past the cut had been dropped. | |
| 329 | +Resource Hints: | |
| 330 | +- 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. | |
| 326 | 331 | |
| 327 | -= [1.3.0] – 2026-09-13 = | |
| 332 | +Caching: | |
| 333 | +- 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. | |
| 334 | +- 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. | |
| 335 | +- 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. | |
| 328 | 336 | |
| 329 | -**A single page can now be purged straight from the admin bar, the post list or the editor, and known third-party scripts — analytics, chat widgets, tracking pixels — are delayed automatically without asking you to list them. A host or agency can pin any setting from wp-config.php with a constant: the dashboard shows the pin, names the constant, and lets an admin take the setting back. xSpeed can also take over an abandoned page-cache drop-in, with your consent, instead of being blocked by it forever.** | |
| 337 | +Database: | |
| 338 | +- 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. | |
| 330 | 339 | |
| 331 | -Caching: | |
| 332 | -- New: Purge a single page from the admin bar, the post list's row actions, or the editor — and the purge confirms what it actually removed instead of assuming. | |
| 333 | -- New: `wp xspeed purge` clears every cache in one call, and a purge is scoped to exactly what the caller asked for. | |
| 334 | -- New: Publishing or updating a post also purges the pages that list it, not just the post itself. | |
| 335 | -- New: An abandoned page-cache drop-in left by another plugin can be taken over with one consenting click, and a leftover husk of a drop-in no longer blocks caching forever. | |
| 336 | -- Fixed: A migration handover now completes instead of stopping halfway, from the dashboard and the CLI alike. | |
| 337 | -- Fixed: xSpeed no longer mistakes itself for a competing cache plugin. | |
| 340 | +Migration: | |
| 341 | +- Fixed: Importing LiteSpeed Cache settings no longer turns oEmbed off when the site had emoji removal on. That setting now maps to Disable Emojis. | |
| 342 | +- New: WP Rocket's emoji, embeds and CSS background lazy-load settings are imported. | |
| 338 | 343 | |
| 344 | +Dashboard & Admin UX: | |
| 345 | +- Fixed: The Cloudflare upsell no longer advertises an edge cache TTL the APO module does not set. | |
| 346 | + | |
| 347 | += [1.3.5] – 2026-09-22 = | |
| 348 | + | |
| 349 | +**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.** | |
| 350 | + | |
| 351 | +Media: | |
| 352 | +- 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. | |
| 353 | + | |
| 339 | 354 | Optimization: |
| 340 | -- New: Known third-party scripts are delayed until interaction automatically, including the inline install snippets vendors ask you to paste into the header. | |
| 341 | -- New: Font stylesheets are deferred out of the render path, and a Google Fonts request that blocks rendering is rewritten to swap. | |
| 342 | -- New: A manual preload list covers the images no detector can see. | |
| 343 | -- Fixed: The LCP preload no longer picks a brand logo over the page's real hero image. | |
| 344 | -- Fixed: Deferring no longer breaks inline scripts that depend on another handle, combining no longer swallows scripts that delaying protects, and handle exclusions are honoured in the delay pass. | |
| 345 | -- Fixed: Valid minified JavaScript is no longer rejected, asset URLs are matched across schemes, an uploads folder at the domain root is recognised, and `?ver` is kept on files plugins rewrite in place. | |
| 346 | -- Fixed: Lazy loading reads an image's size from whichever attribute holds its URL, and no longer mistakes a real image for a placeholder because of a word inside its filename. | |
| 355 | +- 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. | |
| 356 | +- 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. | |
| 357 | +- 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. | |
| 358 | +- Fixed: Complianz and NotificationX banners stay protected even when another plugin strips the id WordPress prints on their script. | |
| 359 | +- 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. | |
| 360 | +- 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. | |
| 347 | 361 | |
| 348 | -Settings: | |
| 349 | -- New: Any module setting can be pinned from wp-config.php with a constant. The dashboard shows a pinned field as read-only and names the constant that holds it. | |
| 350 | -- New: An admin can take a pinned setting back — the override displaces the host's constant and only that. | |
| 351 | -- Fixed: A panel containing a pinned field saves again, and editing a pinned setting is a single inline edit. | |
| 362 | +Health: | |
| 363 | +- 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. | |
| 352 | 364 | |
| 353 | -Object Cache: | |
| 354 | -- New: Redis credentials and Memcached servers are read from wp-config.php, and `WP_REDIS_PREFIX` is honoured as a key salt. | |
| 355 | -- Fixed: Cache keys are always namespaced per site, so two sites sharing a Redis or Memcached database can no longer read or purge each other's entries. | |
| 356 | -- Fixed: The dashboard panel gained every fix that had only reached the CLI, owns only what the plugin itself wrote, and no longer presents another plugin's object cache as xSpeed's. | |
| 365 | +Preloader: | |
| 366 | +- 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. | |
| 357 | 367 | |
| 358 | -Reliability: | |
| 359 | -- Fixed: Translations now load for both PHP and the dashboard, and the settings screens are translatable. | |
| 360 | -- Fixed: nginx sends one Cache-Control header per location instead of two, and the de-duplicated header no longer caches 404 responses. | |
| 361 | -- Fixed: An audit contributor that throws no longer takes the whole audit down with it, and add-ons can report findings of their own. | |
| 368 | += [1.3.4] – 2026-09-20 = | |
| 362 | 369 | |
| 363 | -AI tools: | |
| 364 | -- Improved: The optimize assistant honours its cooldown, never measures without consent, keeps the score through a run of failures, and reports the newest score with its age. | |
| 370 | +**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.** | |
| 365 | 371 | |
| 366 | -= [1.2.4] – 2026-09-06 = | |
| 372 | +Optimization: | |
| 373 | +- New: Below-fold sections are rendered lazily with content-visibility: auto, so the browser skips their layout and paint work until they scroll into view. | |
| 374 | +- New: Block-editor stylesheets are stripped from anonymous frontend pages that do not use any blocks. | |
| 375 | +- Fixed: Scripts that another plugin marks data-no-optimize or data-no-minify late — as consent managers such as Borlabs Cookie do — are restored to their original URL and left alone by minify, defer and delay, however late the marker is stamped. | |
| 367 | 376 | |
| 368 | -**The Overview now reports what is actually switched on, counted from the server rather than guessed from the payload, and a new xSpeed Scan grades the site from inside the plugin. Pages carrying a security token can use the fast static path again instead of silently falling back, and nginx users can now fetch their server config from the command line.** | |
| 377 | +AI / MCP: | |
| 378 | +- Improved: The AI & agents screen now leads with the MCP server and says what each of its tools does, with descriptions shown in full. | |
| 379 | +- Improved: An assistant already connected over OAuth may ask for approval once more after updating — nothing needs re-entering, and read-only connections stay read-only. | |
| 380 | +- Fixed: An AI assistant can now connect to xSpeed and to another MCP plugin on the same site. xSpeed's OAuth details moved to an address of their own under /xspeed/mcp, and the site-wide address is handed over as soon as another plugin asks for it — where nothing else wants it, xSpeed keeps answering there. | |
| 369 | 381 | |
| 370 | 382 | Dashboard & Admin UX: |
| 371 | -- New: The master cache switch now sits in the top bar, reachable from every screen. | |
| 372 | -- New: The sidebar collapses to a rail, and adapts on smaller screens. | |
| 373 | -- New: An (i) beside a module's pill explains why it is reported as on, where the rule is not obvious. | |
| 374 | -- Fixed: The Overview counts the features that are genuinely on. It previously counted entries in the payload, including ones that never rendered, so the number disagreed with the screen. | |
| 375 | -- Fixed: On/off state refreshes after a save, so counts update without reloading the page. | |
| 376 | -- Fixed: Collapsing the rail no longer shifts the content beside it, and rows keep their size. | |
| 377 | -- Fixed: The collapsed rail shows real tooltips rather than the browser's own, and the drawer is now reachable by keyboard. | |
| 383 | +- Fixed: Buttons can carry a border and always show keyboard focus, and the Cloudflare Dev-mode controls use proper button styling. | |
| 378 | 384 | |
| 385 | += [1.3.3] – 2026-09-16 = | |
| 386 | + | |
| 387 | +**Consent gets a dashboard home, the cache engine learns to leave non-HTML alone, and uncacheable pages now tell the CDN so.** | |
| 388 | + | |
| 389 | +Privacy & Analytics: | |
| 390 | +- New: A "Privacy & usage data" panel to view and withdraw usage-analytics consent any time, with a matching wp xspeed privacy command. | |
| 391 | +- Improved: The setup wizard's analytics consent now defaults to off and is only ever an explicit opt-in. | |
| 392 | + | |
| 379 | 393 | Caching: |
| 380 | -- Fixed: A page carrying a security token can use the fast static path again, expiring on the token's clock instead of being refused outright. | |
| 381 | -- Fixed: A refusal that silently disabled static serving is now surfaced rather than left to guess at. | |
| 382 | -- Improved: The cache signature records when it was generated. | |
| 394 | +- Fixed: WordPress's virtual robots.txt (and favicon) is no longer cached or minified, so every directive and newline reaches crawlers intact. | |
| 395 | +- Improved: /robots.txt joined the default cache exclusions, and the sitemap pattern now matches sitemaps.xml too — existing installs keep their working exclusion through the rename. | |
| 383 | 396 | |
| 384 | -Speed Test & Scan: | |
| 385 | -- New: An xSpeed Scan runs from inside the plugin and grades the site, with a score ring on the Overview. | |
| 386 | -- Improved: The Speed Test page reports both Lighthouse scores, organised into tabs. | |
| 387 | -- Fixed: A scan claims its slot atomically, so two runs cannot collide, and the card recovers when a poll fails. | |
| 397 | +Cloudflare & CDN: | |
| 398 | +- New: A page xSpeed refuses to cache now sends no-store edge headers, so a CDN never freezes a half-optimized or excluded page. | |
| 399 | +- Fixed: The deferred Cloudflare purge batch is bounded, cleared on deactivation, and says so when a purge is refused. | |
| 388 | 400 | |
| 389 | 401 | Optimization: |
| 390 | -- Fixed: A CSS background hero is now preloaded as an LCP candidate. | |
| 402 | +- Fixed: Scripts marked data-no-optimize or data-no-minify are left completely alone by minify, defer and delay — consent-manager configurations always ship current. | |
| 403 | +- Fixed: xSpeed's own scripts are never deferred or delayed by its own optimizer. | |
| 404 | +- Fixed: The Conservative preset now switches LCP preload and preconnect off, matching its "page cache + GZIP only" promise. | |
| 391 | 405 | |
| 392 | -nginx: | |
| 393 | -- New: `wp xspeed cache nginx-config` prints the server-block config, so an installer or provisioning script can fetch it without the dashboard. It assumes nginx on a site no request has reached yet, and `--server=` states the answer outright. | |
| 406 | +Dashboard & Admin UX: | |
| 407 | +- Improved: Preload now reports what actually happened — how many pages are warming, and the server's reason when a crawl cannot start. | |
| 408 | + | |
| 409 | +Reliability: | |
| 410 | +- Improved: Uninstall now removes all usage-tracking state, the scheduled send, and every leftover option row. | |
| 394 | 411 | |
| 395 | 412 | Older releases are listed in changelog.txt, included with the plugin, and at [xspeedcache.com/changelog](https://xspeedcache.com/changelog/). |