Title: MBR Performance
Author: robinmorgan2059
Published: <strong>June 5, 2026</strong>
Last modified: June 5, 2026

---

Search plugins

![](https://s.w.org/plugins/geopattern-icon/mbr-performance.svg)

# MBR Performance

 By [robinmorgan2059](https://profiles.wordpress.org/robinmorgan2059/)

[Download](https://downloads.wordpress.org/plugin/mbr-performance.1.15.0.zip)

 * [Details](https://wordpress.org/plugins/mbr-performance/#description)
 * [Reviews](https://wordpress.org/plugins/mbr-performance/#reviews)
 *  [Installation](https://wordpress.org/plugins/mbr-performance/#installation)
 * [Development](https://wordpress.org/plugins/mbr-performance/#developers)

 [Support](https://wordpress.org/support/plugin/mbr-performance/)

## Description

MBR Performance is a powerful, all-in-one performance optimization plugin that gives
you complete control over your WordPress site’s performance.

#### Features

**Core Features**
 * Disable unnecessary WordPress features (emojis, embeds, dashicons,
etc.) * Control REST API access * Manage heartbeat, revisions, and autosave * Remove
query strings for better caching * WooCommerce script optimization * XML-RPC and
RSS feed control * Disable the WordPress 7.0 AI Client, Abilities API and Connectors

**JavaScript Optimization**
 * Defer and async JavaScript loading * Move scripts
to footer * jQuery optimization and removal options * Minify and combine JavaScript
files * Delayed script execution for analytics * Remove script versions

**CSS Optimization**
 * Async CSS loading * Minify and combine CSS files * CSS scanner
for unused styles * Google Fonts optimization and combining * Conditional block 
styles loading * Remove global styles and CSS versions

**Font Optimization**
 * Preload critical fonts * Self-host Google Fonts with auto-
download * Manual font management * Font subsetting for reduced file sizes * Preconnect
to font domains * Font Awesome optimization * Font display strategies (swap, block,
fallback, optional) * Disable Google Fonts completely * Elementor Google Fonts control*
Clear font cache functionality

**Lazy Loading**
 * Native lazy loading for images * Lazy load iFrames and embedded
videos (YouTube, Vimeo, etc.) * Exclude specific images from lazy loading by: – 
CSS selectors – Class names and IDs – Data attributes – Keywords in src or class–
Parent element selectors * Smart exclusions to prevent breaking critical images

**Preloading & Speculative Loading**
 * Preload critical images (LCP, hero images)*
Cloudflare Early Hints support (HTTP 103) * Fetch Priority optimization – Automatic
high priority for first image – Custom selectors for critical images – Disable core
WordPress fetch priority * Speculative Loading for faster navigation – Prefetch 
mode (fetch next page resources) – Prerender mode (fully render next page in background)–
Configurable eagerness levels (conservative, moderate, eager) – Auto mode for optimal
performance

**Database Optimization**
 * Post revision cleanup with configurable limits * Auto-
delete old drafts and trash * Spam comment removal * Orphaned metadata cleanup (
posts, comments, terms, relationships) * Transient management and cleanup * Database
table optimization * Convert MyISAM tables to InnoDB * Table repair functionality*
Scheduled automatic cleanups

**WebP Image Conversion**
 * Convert JPG, JPEG, and PNG images to WebP format * 
Automatic conversion on upload * Bulk converter for existing Media Library images*
Configurable compression level (1–100) * HTML tag delivery with automatic fallback*
Apache/LiteSpeed .htaccess rewrite rules * Gutenberg and Elementor integration *
Server diagnostics panel * Conversion history with bulk management * Smart skip 
when WebP would be larger than original

**Image Sizing & Dimensions**
 * Automatically resize oversized uploads to a configurable
maximum dimension (default 2560px) to help fix the “Properly size images” PageSpeed
Insights warning * Preserves aspect ratio using the WordPress core scaling pipeline*
Adds missing width and height attributes to front-end images to help fix the “Ensure
images have explicit width and height” warning * Reduces Cumulative Layout Shift(
CLS) by giving browsers aspect ratios up front * Works on post content, Gutenberg
blocks, Elementor widgets, attachment images and post thumbnails * Dimension lookups
cached per URL for a week (in-memory + transient) to keep the filter cheap * Skips
external images, SVGs and data URIs — only local files are measured * Bulk resize
tool for existing Media Library images — scan first, then downscale in place with
progress bar and live log * Automatic sub-size regeneration and stale WebP cleanup
after each bulk resize

**Orphaned Media Cleanup**
 * Scans the Media Library for attachments no longer 
referenced anywhere on the site — covering images, videos, audio, documents, and
archives (configurable per scan) * Detection covers post parents, featured images,
post content (matching by attachment ID, shortcode reference and filename stem so
sized variants and URL-only references are caught), and a string-search across postmeta
values * Two-tier confidence classifier — high-confidence orphans are eligible for
bulk-delete, review-tier candidates require manual inspection * Configurable restore
window (7, 14, 30 or 60 days, or “keep forever”) with a daily cron purge of expired
records * Staging table records the full attachment post row, postmeta and file 
manifest before deletion — database records can be restored within the configured
window * Per-attachment exclusions list to permanently keep specific IDs off the
orphan list * For images: deletes the original file, all WordPress sub-size variants,
the “scaled” full-size variant and matching `.webp` siblings; for other media types,
removes the single attached file * Pre-deletion re-verification blocks the action
if an attachment has become referenced since the last scan * Live progress bar during
scans, batched in 50-attachment chunks to avoid timeouts on large libraries * Defaults
to images-only on upgrade from v1.10.0 — broader media types are opt-in via settings
checkboxes

**WooCommerce Optimisations**
 * Dedicated tab that only activates when WooCommerce
is installed * Cart fragments control — disable the admin-ajax request that fires
on every page load site-wide or only on non-shop pages * Expanded conditional asset
loading for WooCommerce scripts, styles, block assets, selectWoo and blockUI * Disable
the zxcvbn password strength meter on the frontend * Disable marketplace suggestions
and WooCommerce dashboard widgets * Prevent heavy wc-admin React bundles from loading
on non-WooCommerce admin pages * Configurable Action Scheduler retention period 
to stop `actionscheduler_actions` ballooning on busy stores * One-click cleanup 
for expired WooCommerce sessions and product/order/expired transients * Full backward
compatibility with the previous WooCommerce script and style toggles

**Multisite Network Support**
 * Network-wide activation and deactivation * Network
default settings managed from the Network Admin * Push settings to all sites (or
selected sites) in one click * Import settings from any existing site as network
defaults * Per-site override control — super admins can lock or unlock site-level
customisation * Automatic setup for newly-created sites using network defaults

### External services

This plugin can connect to the third-party services listed below. Each is optional
and is only contacted when you enable the relevant feature; with these features 
off, the plugin makes no external requests.

#### Google Fonts (Self-host Google Fonts feature)

When you enable “Self-host Google Fonts” and download a font from the Fonts tab,
your server contacts the Google Fonts API at fonts.googleapis.com to retrieve the
font’s stylesheet, and Google’s font CDN at fonts.gstatic.com to download the font
files. The files are then stored on your own server and served locally, so your 
visitors’ browsers do not contact Google. The request is made by your server only
at the moment you trigger a download in the admin area. It sends the requested font
family name(s) and the information present in any standard HTTP request (such as
your server’s IP address and user agent); no website-visitor data is sent.

This service is provided by Google. Google Terms of Service: https://policies.google.
com/terms — Google Privacy Policy: https://policies.google.com/privacy — Google 
Fonts privacy details: https://developers.google.com/fonts/faq/privacy

#### YouTube (Video facade feature)

When the video facade is enabled and a page contains an embedded YouTube video, 
the plugin shows a lightweight placeholder instead of the full embed. To display
a preview image, the visitor’s browser loads the video’s thumbnail from YouTube’s
image server at i.ytimg.com. The full YouTube player, and any YouTube cookies, are
loaded only if the visitor clicks to play. The thumbnail request is made by the 
visitor’s browser and includes the visitor’s IP address and the YouTube video ID.

This service is provided by Google/YouTube. YouTube Terms of Service: https://www.
youtube.com/t/terms — Google Privacy Policy: https://policies.google.com/privacy

#### Vimeo (Video facade feature)

When the video facade is enabled and a page contains an embedded Vimeo video, the
plugin shows a lightweight placeholder instead of the full embed. To display a preview
image, the visitor’s browser requests the video’s public metadata from Vimeo’s API
at vimeo.com/api/v2/video/{id}.json, which returns the thumbnail URL. The full Vimeo
player is loaded only if the visitor clicks to play. The request is made by the 
visitor’s browser and includes the visitor’s IP address and the Vimeo video ID.

This service is provided by Vimeo. Vimeo Terms of Service: https://vimeo.com/terms—
Vimeo Privacy Policy: https://vimeo.com/privacy

## Installation

 1. Upload the `mbr-performance` folder to the `/wp-content/plugins/` directory
 2. Activate the plugin through the ‘Plugins’ menu in WordPress
 3. Access settings via ‘MBR Performance’ in the WordPress admin toolbar
 4. Configure features one tab at a time

## FAQ

### Will this plugin break my site?

The plugin is designed to be safe, but we recommend:
 1. Taking a full backup before
using 2. Testing features on a staging site first 3. Enabling features one at a 
time 4. Testing thoroughly after each change

### Can I use this with a caching plugin?

Yes! This plugin works alongside caching plugins and provides complementary optimizations.

### Does this work with page builders?

Yes, the plugin is fully compatible with Elementor, Beaver Builder, Divi, Oxygen,
Bricks, and WPBakery. Optimizations are automatically disabled in editor/preview
modes.

### Does this work with WordPress Multisite?

Yes! From v1.5.0 onwards the plugin fully supports WordPress Multisite networks.
You can network-activate the plugin and manage default settings from the Network
Admin (Settings > MBR Performance). You can push those defaults to all sites at 
once, import settings from any existing site, and choose whether individual site
admins are allowed to override the network defaults.

### How do I access the settings?

Click ‘MBR Performance’ in the WordPress admin toolbar at the top of the screen.
You can also access individual tabs from the dropdown menu.

### What’s the difference between Lazy Loading and Preloading?

Lazy Loading delays loading of images/videos until they’re needed (saving bandwidth),
while Preloading loads critical resources early (improving perceived speed). They
work together for optimal performance.

### Does this disable WordPress 7.0’s built-in AI?

It can. WordPress 7.0 added a core AI Client, the Abilities API and a Settings -
> Connectors screen. They stay dormant until you connect an AI provider, so they
don’t slow a default site down — but if you’d rather the subsystem never loaded 
at all, tick “Disable AI Features (WordPress 7.0+)” on the Core tab. It uses WordPress’s
own wp_supports_ai kill switch and has no effect on WordPress 6.x.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“MBR Performance” is open source software. The following people have contributed
to this plugin.

Contributors

 *   [ robinmorgan2059 ](https://profiles.wordpress.org/robinmorgan2059/)

[Translate “MBR Performance” into your language.](https://translate.wordpress.org/projects/wp-plugins/mbr-performance)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/mbr-performance/), 
check out the [SVN repository](https://plugins.svn.wordpress.org/mbr-performance/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/mbr-performance/)
by [RSS](https://plugins.trac.wordpress.org/log/mbr-performance/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 1.15.0

 * Changed: every internal identifier now uses the unified `mbrpe` prefix (classes,
   constants, options, hooks, AJAX actions and script objects) to meet the WordPress.
   org four-character prefix requirement and avoid collisions.
 * Added: a one-time, automatic migration that moves existing settings, font caches
   and WebP/AVIF conversion registries to the new option names on upgrade — no reconfiguration
   needed.
 * Hardening: review-compliance pass — additional input sanitisation ($_SERVER and
   decoded AJAX payloads), late output escaping (wp_kses_post / esc_js), explicit
   prepared-SQL placeholders, and more robust URL-to-path resolution for subdirectory
   installs.

#### 1.14.1

 * Fixed: inline admin script strings are now escaped at the point of output (esc_js)
   for full WordPress.Security.EscapeOutput compliance. No functional change.
 * Internal: removed all heredoc/nowdoc syntax (disallowed by Plugin Check); inline
   scripts now build their content via local, immediately-closed output buffers.

#### 1.14.0

This release prepares the plugin for the WordPress.org plugin directory and includes
several feature removals — please read the Upgrade Notice before updating.
 * Renamed:
the plugin is now “MBR Performance” with the slug `mbr-performance` (previously “
MBR WP Performance” / `mbr-wp-performance`). Your saved settings are preserved —
the stored option keys are unchanged. * Removed: the Critical CSS field. Async CSS
loading continues to work on its own. * Removed: the Third-Party tab that self-hosted
Google Analytics, Google Tag Manager and Facebook Pixel. Filter-based removal of
enqueued Google Fonts is unaffected. * Removed: HTML minification. The saving is
marginal once gzip/brotli compression is in play, and it was a recurring source 
of edge-case layout breakage. * Removed: the “Disable Concatenation” toggle (admin-
only; it had no effect on front-end performance). * Changed: limiting post revisions
now uses the `wp_revisions_to_keep` filter rather than defining the global `WP_POST_REVISIONS`
constant at runtime. As a result the setting now takes effect reliably, which the
constant approach did not. * Changed: the autosave-interval setting now re-localises
the core autosave script instead of defining `AUTOSAVE_INTERVAL`, so the longer-
interval options take effect. * Internal: every inline `<script>`/`<style>` block
is now registered through `wp_enqueue_*` / `wp_add_inline_*`; removed `load_plugin_textdomain()`(
not required on WordPress 4.6+); added an “External services” section to this readme
documenting the Google Fonts, YouTube and Vimeo connections.

#### 1.13.9

 * Fix (UI): The “Compression” column header on the Conversion History table was
   set to 110px wide, which is just narrow enough that the word wraps onto a second
   line at the standard wp-list-table header font weight. Bumped to 140px so the
   label sits cleanly on one line.

#### 1.13.8

 * New: Bulk AVIF converter. The WebP tab now has an AVIF Bulk Converter section
   alongside the existing WebP one (Start AVIF Conversion, Clear AVIF History, Revert
   All AVIF Files), and only renders when the server has a real AVIF encoder available—
   so it can’t be enabled to no effect on hosts that lack libavif/libheif. Mirrors
   the WebP converter’s architecture: per-image AJAX with progress bar, history 
   option (`mbr_avif_converted_images`) parallel to the WebP one, and a registry-
   driven Revert All that deletes every .avif this plugin created without touching
   originals or WebP variants.
 * New: An “AVIF Size” column has been added to the Conversion History table, alongside
   the existing WebP Size column. The table now merges records from both `mbr_webp_converted_images`
   and `mbr_avif_converted_images` keyed by original path, so each image appears
   as a single row with whichever format data exists (a dash shown where a format
   hasn’t been generated for that image). The Compression column now reports the
   savings against whichever recorded format is smallest — AVIF when present, since
   it’s typically 20–30% smaller than WebP at equivalent perceived quality, otherwise
   WebP.
 * New: Auto-convert on upload now also writes to the AVIF history option, so newly-
   uploaded images appear in the table alongside bulk-converted ones. Previously
   the auto-upload AVIF path only populated the file registry; the size data wasn’t
   kept anywhere.

#### 1.13.7

 * Fix (AVIF false-positive detection): Server AVIF support was being detected via`
   function_exists('imageavif')`, which is unreliable. From PHP 8.1 onwards the `
   imageavif()` function is declared whether or not libgd was actually compiled 
   against libavif; on the very common shared-host configuration where it wasn’t,
   the function exists but calls fail silently at runtime, no `.avif` files are 
   produced, and visitors are served WebP (or the original) regardless of how aggressively
   the user has toggled AVIF on. Detection now uses `gd_info()['AVIF Support']`,
   which reflects what libgd was actually built with — the same reliable pattern
   the plugin’s WebP detection has always used via `gd_info()['WebP Support']`.
 * New: When AVIF is enabled in settings but the server can’t actually encode AVIF,
   the plugin now (a) does NOT register the upload-conversion filter (so it won’t
   trigger per-upload warnings), (b) shows an admin notice on its own admin pages
   explaining the mismatch, and (c) always renders the AVIF capability diagnostic
   on the WebP tab — both when supported (info notice with a quick confirmation)
   and when unsupported (warning notice with the GD/Imagick breakdown). Previously
   the diagnostic was only shown in the unsupported case, and the supported case
   showed nothing at all.
 * Note: existing `.avif` files on disk are still served. The fix only stops the
   plugin from quietly pretending conversion is happening when the server can’t 
   actually do it.

#### 1.13.6

 * Fix (UI contrast): Inline status messages rendered by AJAX handlers — visible
   on the Database panel and elsewhere — appeared with WordPress core’s near-black`.
   notice` text colour on the plugin’s dark-themed success/error/warning/info backgrounds,
   producing a low-contrast pill that was hard to read against the green tint. The
   plugin’s `.notice-success`, `.notice-warning`, `.notice-error` and `.notice-info`
   rules now set `color: var(--mbr-text-primary)` (the same light text colour already
   used by the equivalent `.mbr-performance-message.success/error` rules) and apply
   it to nested `<p>` elements too so it wins over any descendant rules WP core 
   may inject. Same fix applied to the network-settings inline notice variants.

#### 1.13.5

 * Fix (the actual root cause of the “CSS toggles revert” bug): Three font-related
   fields on the Fonts tab — Optimize Google Fonts, Font Display Strategy (duplicate),
   and Disable Elementor Google Fonts — had their form inputs scoped to `mbr_wp_performance_options[
   css][...]` instead of `[fonts][...]`. Submitting the Fonts tab therefore POSTed
   a partial `css` section, and the CSS sanitiser — doing exactly what a section
   sanitiser should do — replaced the entire stored `css` section with the partial
   input, setting every CSS boolean not present in the form to `false` and dropping
   the textareas. This is what users were observing as “the CSS settings all return
   to default (switched off) without warning” after some unknown period of time:
   the unknown period was the time between saving the CSS tab and saving the Fonts
   tab. The earlier v1.13.4 async-CSS safety interlock papered over the visual symptom(
   no FOUC even when toggles got wiped); this release fixes the cause.
 * Removed: The “Optimize Google Fonts” radio (default/combine) and the duplicate“
   Font Display Strategy” select on the Fonts tab. Both were dead UI — the radio
   had no runtime consumer and the select was a redundant duplicate of the legitimate,
   properly-scoped `[fonts][font_display]` select already present higher up the 
   same tab.
 * Moved: The Disable Elementor Google Fonts checkbox now writes to `[fonts][disable_elementor_fonts]`(
   was `[css][disable_elementor_fonts]`), and its runtime hook (`elementor/frontend/
   print_google_fonts` filter) moves from the CSS optimisations class to the font
   optimisations class where it belongs.
 * Migration: on upgrade, any existing `[css][disable_elementor_fonts]` value is
   moved to `[fonts][disable_elementor_fonts]` (only if `[fonts]` doesn’t already
   have a deliberate value, so a real user choice isn’t clobbered). Any stale `[
   css][font_display]` is similarly migrated. The orphan `[css][google_fonts_mode]`
   key is dropped. Migration is idempotent.
 * Cleanup: removed the corresponding entries from `sanitize_css_options` and added`
   disable_elementor_fonts` to `sanitize_font_options`.

#### 1.13.4

 * Removed: The “Auto-Generate Critical CSS” button on the CSS tab. The generator
   used regex-based extraction across hard-coded selectors (`body`, `header`, `h1`,`
   a` and similar), which is structurally too crude to produce safe critical CSS
   for a modern WordPress site. Failure modes included stripping `@media` wrappers
   off rules (extracting `body { padding: 0 }` from inside a viewport-conditional
   block and applying it at all viewports), matching unrelated selectors when one
   starts with a single-letter target (`a` matched `.article`, `p` matched `.product`
   etc.), blind inlining of every `@font-face` block on the site, and ignoring CSS
   variables defined on `:root`. Inlining the resulting output while async-loading
   the full stylesheets produced a broken or unstyled initial paint that several
   users misread as the plugin resetting their CSS settings — when in fact the toggle
   states were intact in the database and only the visual result of the optimisation
   chain was wrong. The Critical CSS Code textarea remains; users who want this 
   feature should paste in critical CSS produced by a proper viewport-aware tool
   such as Penthouse, Critical, Critters, or any of the online critical-CSS generators.
 * New: Async-CSS safety interlock. If “Load CSS Asynchronously” is enabled WITHOUT
   a critical-CSS bridge (Inline Critical CSS on + Critical CSS Code populated),
   the first two render-blocking-eligible stylesheets now stay render-blocking and
   the rest are still async’d. This guarantees the page paints with real CSS at 
   first paint regardless of how the rest of the chain is configured. With a critical-
   CSS bridge in place, every stylesheet is async’d as before.
 * Note on upgrade: if your site has Load CSS Asynchronously on but no critical 
   CSS provided, the first 2 stylesheets will become render-blocking again on upgrade.
   This is the correct behaviour — that configuration was previously causing a flash-
   of-unstyled-content window on first paint. To regain full async loading, paste
   critical CSS into the Critical CSS Code field and enable Inline Critical CSS.
 * Removed (internal): `ajax_generate_critical_css()`, `extract_css_for_selectors()`,
   and the private `minify_css()` helper from the admin class; the `wp_ajax_mbr_wp_performance_generate_critical_css`
   action registration; and the corresponding JS click handler and `generateCriticalCSS`
   function in admin-clean.js.

#### 1.13.3

 * Fix (Critical CSS): The “Auto-Generate Critical CSS” button stored its output
   under an internal key (`[css][critical_css_content]`) that was not in the CSS
   sanitiser’s whitelist, so the sanitiser stripped it on every save. Generated 
   CSS only survived at all because the admin JS also drops it into the editable
   textarea, which does persist. The generator now writes straight to the canonical`[
   css][critical_css]` field, so its output persists immediately and the frontend
   emits it without depending on that fallback. No action needed on upgrade; if 
   you previously generated critical CSS and saved, it is already in the right field.
 * Fix (Reset to Defaults): The “Reset to Defaults” button did nothing. It navigated
   to `?...&reset=1`, but no handler ever read that parameter. It now runs a proper
   nonce- and capability-checked POST request that resets every section to its defaults
   and reloads the page. (Implemented as POST rather than a GET link so it can’t
   be triggered by a crawler, prefetch, or a stray bookmark.)
 * Fix (Autoload Audit): The Diagnostics  Autoloaded Options audit claimed in code
   to exclude the plugin’s own options but the query didn’t, so MBR Performance’s
   own options could appear in the list and be offered for autoload-disabling. The
   query now excludes the `mbr_wp_performance_` namespace as documented.
 * Housekeeping: First-install defaults and the new reset routine now share a single`
   default_options()` definition rather than duplicating the structure.

#### 1.13.2

 * Fix: HTML minification could break the layout of pages that embed a complete 
   HTML document inside a page-builder HTML widget — for example an Elementor “HTML”
   widget holding a full `<!doctype html>...</html>` landing page. The rendered 
   response then contains a nested, doubly-declared document (two DOCTYPEs, two `
   <html>`, two `<head>`). Browsers tolerate this by leniently re-parsing, but collapsing
   the whitespace across the nested structure changed how the parser resolved it
   and stripped the page’s container boundaries, letting content run full-width 
   to the browser edges. The minifier now detects a nested/embedded document (a 
   second `<!doctype>`, `<html>`, or `<head>`) and skips minification on those pages
   entirely, leaving them byte-for-byte untouched. Natively-built pages with a single
   document continue to be minified as normal.
 * No settings change required. If you previously disabled Minify HTML because of
   this, it is now safe to re-enable — affected pages are skipped automatically 
   while the rest of your site is still minified.

#### 1.13.1

This release folds in three bug fixes that were made against the 1.12.x line (1.12.1,
1.12.2, 1.12.3) but had not yet been carried forward into the 1.13.0 codebase.

 * Fix (HTML minify): Minify HTML (Core tab) broke the front end of every site it
   was enabled on. The minifier extracts script / style / pre / textarea blocks 
   into placeholders before stripping comments, but the placeholder format was itself
   an HTML comment (`<!--MBR_PLACEHOLDER_0-->`). The comment-stripping step then
   deleted the placeholders, so the protected blocks were never restored — every
   inline script and stylesheet was silently dropped. Placeholders are now a collision-
   free per-request alphanumeric token. Whitespace handling is also now conservative(
   only newline-spanning runs are collapsed) so inline-element spacing and attribute
   values are preserved; inline `<svg>` is protected; AMP / REST / AJAX responses
   are skipped; and each regex pass falls back to the un-minified buffer if PCRE
   bails.
 * Fix (Elementor uploads): WebP / AVIF “Convert on Upload”, EXIF stripping, and
   resize-on-upload were silently bypassed when uploading through Elementor’s media
   picker (or any page-builder media interface that triggers editor-context detection).
   The plugin’s editor-context early-return was killing upload-pipeline optimisations
   as collateral damage. Upload-pipeline modules (WebP, AVIF, Image Dimensions, 
   Image Enhancements) now instantiate before the editor early-return; each self-
   gates its editor-sensitive front-end filters internally, so front-end optimisations
   remain suppressed inside editors exactly as before.
 * Fix (orphan media): The Orphaned Media scanner failed to detect orphan PDF, Word,
   video, audio and archive files because the post_content reference check stripped
   the file extension before matching. Stem-only matching is correct for images (
   so `image-300x200.jpg` matches `image.jpg`) but for non-image media it caused
   unrelated URLs to match — a PDF called `pricing.pdf` was wrongly classified as
   referenced whenever any post linked to `/pricing-page/` etc. Non-image media 
   now match against the full filename including extension; images keep the stem-
   based logic so sized-variant detection is unchanged. Also fixes the Type=Documents/
   Videos / Audio / Archives filter on the candidate list, which previously returned
   nothing because it queried `post_mime_type` against the staging table (whose 
   column is `mime_type`).
 * No data migration required for any of the three. Re-run an Orphaned Media scan
   after upgrading and any non-image attachments dropped under earlier 1.13.0 builds
   will surface correctly.

#### 1.13.0

 * Feature: New “Disable AI Features (WordPress 7.0+)” toggle on the Core tab, under
   WordPress Features. WordPress 7.0 ships a built-in AI Client, the Abilities API,
   and a Settings -> Connectors screen for wiring a site to AI providers. That infrastructure
   stays dormant until a provider connector is configured, so the front-end cost
   on a default install is minimal — but for site owners who want nothing to do 
   with it, this toggle switches the whole subsystem off rather than leaving it 
   idling. It hooks core’s own kill switch (`add_filter( 'wp_supports_ai', '__return_false')`)
   at PHP_INT_MAX priority so the AI Client and Abilities API never bootstrap, plus`
   wp_ai_client_prevent_prompt` as a second guard against any prompt execution that
   slips through.
 * Note: The toggle is off by default and existing behaviour is unchanged on upgrade.
   It has no effect on WordPress 6.x, where the `wp_supports_ai` filter does not
   exist, so it is safe to leave enabled across mixed-version sites. The Connectors
   admin screen is intentionally left in place — this is a performance and surface-
   area control, not a dashboard-hiding tool.
 * Tested up to WordPress 7.0.

#### 1.12.0

 * Fix: JavaScript optimisations module — previously a placeholder class with UI
   toggles but no backend logic — is now fully wired up. Defer, Move-to-Footer, 
   Defer jQuery, Remove jQuery (with test mode), Minify inline JS, Delay JS (with
   interaction-triggered runtime and configurable timeout), Disable Concatenation,
   and Remove Script Versions all work as advertised. Each defer/footer/delay path
   honours its own exclusion textarea.
 * Fix: CSS optimisations module — previously a placeholder class — is now fully
   wired up. Inline Critical CSS, Async CSS (via preload+onload with the standard
   loadCSS polyfill for older browsers), Minify inline CSS, Conditional Block Styles(
   should_load_separate_core_block_assets), Remove CSS Versions, Disable Elementor
   Google Fonts, and Disable WooCommerce CSS on non-shop pages all functional.
 * Fix: Database optimisations module — previously had only the WooCommerce cron
   listener — now drives full scheduled cleanup. The `mbr_wp_performance_database_cleanup`
   cron auto-reschedules to match the cleanup_schedule setting (daily/weekly/manual)
   and runs: auto-draft purge with configurable age, trash emptying with configurable
   retention, spam comment deletion with configurable age, unapproved comment deletion
   with configurable age, expired transient cleanup (handles site transients on 
   multisite), and revision trimming to the keep-N setting. A “Last Auto-Cleanup”
   log table is displayed on the Database tab plus a “Run Auto-Cleanup Now” button.
 * Feature: AVIF image conversion alongside WebP. New `<picture>` wrapper emits 
   AVIF first, then WebP, then the JPEG/PNG fallback — browsers automatically pick
   the first format they support. AVIF is typically 20-30% smaller than WebP at 
   equivalent perceived quality. Requires PHP 8.1+ with GD AVIF, or Imagick 7.0.25
   +. Falls back gracefully where unsupported; new tab section in WebP tab includes
   server capability diagnostics.
 * Feature: Self-hosted third-party scripts. New “Third-Party” tab with per-script
   toggles for Google Analytics (gtag.js), Google Tag Manager (gtm.js), legacy Google
   Analytics (analytics.js), and Facebook Pixel (fbevents.js). Scripts are downloaded
   daily to /wp-content/uploads/mbr-performance/third-party/ and outbound URLs are
   rewritten via output buffer. Removes the PSI “Reduce the impact of third-party
   code” warning and stops first-paint requests to googletagmanager.com / connect.
   facebook.net.
 * Feature: YouTube and Vimeo facade pattern. Replaces embedded video iframes with
   a static thumbnail and play button; the real iframe is only loaded on click. 
   Saves ~1.4MB of YouTube JS on initial page load and stops YouTube cookies being
   set until user interaction. Vimeo thumbnails are hydrated lazily via the public
   v2 API behind an IntersectionObserver. Keyboard accessible (Enter/Space). Toggle
   on Lazy Loading tab.
 * Feature: New “Server” tab. Browser-cache headers (Expires + Cache-Control, 1 
   year for images/fonts, 30 days for CSS/JS) and Brotli + Gzip text compression
   via .htaccess. Detects the web server and shows an equivalent Nginx snippet for
   Nginx hosts. Addresses two of the most common PSI warnings: “Serve static assets
   with an efficient cache policy” and “Enable text compression”. Marker blocks “
   MBR Browser Cache” and “MBR Compression” — fully removed on deactivation.
 * Feature: New “Diagnostics” tab containing three tools:
    - **Autoloaded Options Audit** — shows total autoloaded bytes and the top 30
      options by size, with a one-click “Disable autoload” button. Protected core
      options (siteurl, home, active_plugins, template, stylesheet, etc.) cannot
      be modified. Transients are flagged. This is the single most common WordPress
      DB perf killer and has not been addressable from inside the plugin until now.
    - **WP-Cron Viewer** — lists every scheduled event with next-run, recurrence,
      and a “Callback?” column showing whether any PHP callback is currently registered.
      Events with no callback (left over from deactivated plugins) are flagged “
      orphan” and can be unscheduled with one click. Includes instructions for replacing
      WP-Cron with a real system cron job for performance-sensitive sites.
    - **Caching Plugin Conflict Detector** — detects WP Rocket, W3 Total Cache, 
      LiteSpeed Cache, FlyingPress, WP Super Cache, Perfmatters, and Autoptimize,
      and lists which MBR options overlap with each — preventing the common pitfall
      of having defer/delay/minify enabled in two plugins at once.
 * Feature: HTML minification (Core tab). Output-buffered, strips HTML comments (
   preserves IE conditionals), collapses whitespace between tags. Carefully preserves
   the contents of `<pre>`, `<textarea>`, `<script>`, and `<style>` via placeholder
   swap. Typically saves 5-15% of HTML transfer size.
 * Feature: `decoding="async"` on images (WebP tab  Image Sizing & Dimensions). 
   Lets the browser decode images off the main thread, improving INP on image-heavy
   pages. Auto-skips any image already carrying `fetchpriority="high"` so the LCP
   candidate continues to decode synchronously.
 * Feature: EXIF metadata stripping on upload (WebP tab  Image Sizing & Dimensions).
   Removes EXIF, IPTC and XMP metadata (camera serial, GPS coordinates, embedded
   thumbnails) from newly uploaded JPEGs. ICC colour profiles are preserved so colours
   stay accurate. Uses Imagick where available (clean stripImage()) or falls back
   to GD. Privacy win plus typically 5-30% file size reduction with zero visible
   quality loss.
 * Feature: Hover prefetch (Preloading tab). On link hover (or first touchstart 
   on mobile), the destination page is prefetched so the next click feels instant.
   Uses the canonical instant.page v5.2.0 runtime (MIT). Server-side bail when the`
   Save-Data: on` header is present so users on metered connections aren’t penalised.
 * Improvement: `crossorigin="anonymous"` is now explicit on all preload and preconnect
   tags (font preloads and resource hints) — previously the bare `crossorigin` attribute
   was used, which is technically equivalent but flagged inconsistently by some 
   Lighthouse audits.
 * Three new option sections seeded on upgrade: `preloading`, `lazy_loading`, `third_party`,`
   server_headers`. Migration block handles the upgrade idempotently.
 * On deactivation: all v1.12.0 .htaccess marker blocks (MBR AVIF, MBR Browser Cache,
   MBR Compression) are cleanly removed; the third-party script refresh cron is 
   unscheduled; AVIF files in the registry are deleted.
 * Combine JS and Combine CSS toggles remain in the UI for forward compatibility
   but are no-ops in this release — a safe implementation handling dependency graphs
   and async order is a separate engineering project. Admin notice clarifies this
   when either toggle is enabled. Remove Unused CSS similarly remains a UI toggle
   pointing users at MBR Advanced Asset Manager for per-asset control.

#### 1.11.0

 * Feature: Orphaned Images tab renamed and expanded to “Orphaned Media” — scope
   now covers images, videos, audio, documents, and archives alongside the original
   image-only detection
 * Feature: Media-type checkbox group in tab settings — users opt in per type (Images/
   Videos / Audio / Documents / Archives); defaults to images-only on upgrade so
   v1.10.0 behaviour is preserved
 * Feature: New Type column in the candidate list with category icons (image, video,
   audio, document, archive) for quick visual scanning
 * Feature: Type filter dropdown alongside the existing Confidence and Sort filters—
   narrow the list to a specific media type
 * Feature: Per-type stat breakdown row above the candidates table showing count
   and reclaimable bytes for each enabled type
 * Tab slug changed from `orphaned-images` to `orphaned-media`; the legacy slug 
   continues to work for one release for any bookmarked URLs
 * Detection logic for non-image types relies on the existing filename-stem matching
   in `post_content` (which already catches URL-only references in `[video]`, `[
   audio]`, and `<a href>` tags) plus the postmeta string-search; explicit builder-
   aware detection lands in v1.12.0
 * Non-image deletions only remove the single attached file — no sub-sizes or `.
   webp` siblings to clean up for those types, so the deletion path is naturally
   simpler
 * Backward-compatible: existing v1.10.0 staging-table rows and exclusions list 
   carry over unchanged
 * Behaviour change: post_parent is no longer treated as definitive proof an attachment
   is in use. WordPress sets post_parent on upload via the post editor and never
   clears it, so attachments uploaded into a post and later removed from the content
   stayed hidden under v1.10.0. Parent-only matches now drop to Review tier so they
   can be inspected and deleted manually. Featured-image and post-content matches
   remain definitive.

#### 1.10.0

 * Feature: New “Orphaned Images” tab — scans the Media Library for image attachments
   that are no longer referenced anywhere, with a safe two-stage deletion workflow
   and a configurable restore window
 * Feature: Detection covers post_parent, featured images (_thumbnail\_id), post\
   _content (matching by attachment ID, attachment_ shortcode reference, and filename
   stem so sized variants are caught too), and a string-search across postmeta values
 * Feature: Two-tier confidence classifier — “High” candidates (zero references 
   found) are eligible for bulk-delete; “Review” candidates (matched only in postmeta)
   must be deleted individually after manual inspection
 * Feature: Staging table (`{prefix}mbr_orphan_log`) records the full attachment
   post row, postmeta, and file manifest before deletion — allows the database record
   to be restored within the configured window (7/14/30/60 days, or “keep forever”)
 * Feature: Per-attachment exclusions list to prevent specific IDs from ever being
   flagged as orphan
 * Feature: Daily WP-Cron job (`mbr_wp_performance_orphan_purge`) cleans up staging
   records past their restore window
 * Feature: File deletion handles the original file, all WordPress sub-size variants,
   the “scaled” full-size variant, and matching `.webp` siblings produced by the
   WebP converter — no orphan files left on disk
 * Feature: Pre-deletion re-verification — orphan status is re-checked at delete
   time, blocking the action if the attachment has become referenced since the scan
 * Feature: Live progress bar during scans, batched at 50 attachments per AJAX request
   to avoid timeouts on large libraries
 * Feature: Stat cards show high-confidence count, review-required count, and total
   reclaimable bytes
 * Note: Restore reinstates the database record only — image file bytes are physically
   deleted at the time of staging and must be re-uploaded if needed
 * Note: This release does not yet detect references stored in page builder data(
   Elementor `_elementor_data`, Bricks, Beaver Builder, etc.) beyond the postmeta
   string-search; review tier exists partly to cover this gap

#### 1.9.3

 * Feature: Allowlist of REST API namespaces on the Core tab. When “Disable REST
   API” is set to a non-default mode (Disable for Non-Admins or Disable When Logged
   Out), admins can now whitelist specific namespaces that should remain accessible—
   useful for plugins exposing public REST endpoints such as front-end chat widgets,
   contact forms, or store APIs.
 * Fix: Public REST endpoints registered with `permission_callback => '__return_true'`
   are no longer indiscriminately blocked by the REST hardening modes when their
   namespace is in the allowlist. Previously the only options were “all REST open”
   or “all REST blocked”, which broke any third-party plugin (or sister plugin like
   MBR Intelligent Site Assistant) that legitimately needed public REST access for
   non-admin or logged-out visitors.
 * Improvement: Helper text on the Core tab now explicitly lists common public namespaces(
   mbr-isa/v1, contact-form-7/v1, wc/store/v1) to make the configuration discoverable.

#### 1.9.2

 * Fix: “Remove Global Styles” no longer breaks the front end of Full Site Editing(
   block) themes — the optimisation is now auto-skipped when a block theme is active.
   FSE themes such as Twenty Twenty-Two through Twenty Twenty-Five rely on the inline`
   <style id="global-styles-inline-css">` output to render their colours, fonts,
   layout and spacing on the public front end. Stripping it left the Site Editor
   working but the front end with no design tokens.
 * Fix: Removed the duplicate (and previously non-functional) “Remove Global Styles”
   checkbox from the CSS tab. The working toggle on the Core tab is now the canonical
   home. Two checkboxes wrote to two different option keys but only one had a backend
   handler — now there’s just one.
 * Migration: any existing `[css][remove_global_styles]` truthy value is automatically
   copied to `[core][remove_global_styles]` on update, so users who toggled the 
   previously-orphaned CSS-tab checkbox don’t lose their setting. The migration 
   runs on `plugins_loaded` so it fires reliably on plugin update, not just manual
   activation.
 * Improvement: Updated the Core tab tooltip for “Remove Global Styles” to clearly
   warn that it’s incompatible with FSE themes, so the option remains available 
   to classic-theme users without footgunning anyone running a block theme.

#### 1.9.1

 * Feature: Weekly automated cleanup toggle in the WooCommerce tab — runs expired
   sessions, transients and Action Scheduler cleanup on the existing weekly cron
   hook
 * Feature: Geolocation and page cache advisory notice — warns when WooCommerce’s
   default customer location is set to “Geolocate” (breaks full-page caching entirely)
   or “Geolocate (with page cache support)” (appends `?v=<timestamp>` query string
   that some cache plugins mishandle)
 * Feature: Last-run log display showing when the scheduled cleanup last ran and
   what it removed
 * Feature: Direct link from the advisory notice to the WooCommerce General settings
   page for quick resolution
 * Fix: The `mbr_wp_performance_database_cleanup` weekly cron event now has an actual
   listener — previously the event was scheduled on activation but fired into the
   void with nothing attached
 * Improvement: Defensive re-scheduling of the weekly cron when the user enables
   automated cleanup, in case the event was cleared by another plugin or missed 
   during activation

#### 1.9.0

 * Feature: New dedicated WooCommerce tab consolidating all store-specific optimisations
 * Feature: Cart fragments control — disable the admin-ajax `get_refreshed_fragments`
   request site-wide or only on non-shop pages (major TTFB win on cached sites)
 * Feature: Expanded conditional asset loading — dequeues WC scripts, styles, block
   assets, selectWoo, blockUI and related libraries on non-shop pages
 * Feature: Disable the zxcvbn password strength meter on the frontend
 * Feature: Disable WooCommerce marketplace suggestions and dashboard status widgets
 * Feature: Prevent the heavy wc-admin React bundles from loading on non-WooCommerce
   admin screens
 * Feature: Configurable Action Scheduler retention period (default 30 days, options
   for 14/7/3) — stops `actionscheduler_actions` ballooning on busy stores
 * Feature: One-click cleanup buttons for expired WooCommerce sessions and product/
   order/expired transients
 * Feature: One-time admin notice on upgrade informing users that their existing
   WooCommerce settings have moved to the new tab (dismissible)
 * Improvement: Legacy `core.disable_woocommerce_scripts` and `css.disable_woocommerce_css`
   options remain fully backward-compatible — existing sites keep their behaviour
   without re-saving
 * Improvement: Tab gracefully shows an inactive state when WooCommerce is not installed,
   so the capability remains discoverable

#### 1.8.0

 * Feature: Bulk resize tool for existing Media Library images — scan for JPEGs 
   and PNGs exceeding the configured maximum dimension, then downscale them in place
 * Feature: Two-phase workflow (Scan  Start Resize) with progress bar, live log,
   and running savings total
 * Feature: Automatic sub-size regeneration after each resize using the WordPress
   core pipeline
 * Feature: Elementor CSS cache is cleared automatically after a bulk resize so 
   widgets re-render with the new dimensions
 * Improvement: Stale WebP files are deleted automatically before sub-sizes are 
   regenerated, and their entries are stripped from the WebP registry — prevents
   old WebP content being served after a resize
 * Improvement: Skips images that are already within the configured maximum, writes
   a clear “skipped” reason to the log
 * Improvement: Clear warning in the UI that bulk resize permanently overwrites 
   files on disk and cannot be undone automatically
 * Improvement: Paginated scan (batches of 200) to keep memory use reasonable on
   large libraries

#### 1.7.0

 * Feature: New “Image Sizing & Dimensions” section in the WebP tab
 * Feature: Automatic resize-on-upload with configurable maximum dimension (uses
   the WordPress `big_image_size_threshold` filter, default 2560px)
 * Feature: Automatic injection of missing width and height attributes on front-
   end images …

## Meta

 *  Version **1.15.0**
 *  Last updated **2 hours ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 5.9 or higher **
 *  Tested up to **7.0**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [cache](https://wordpress.org/plugins/tags/cache/)[database](https://wordpress.org/plugins/tags/database/)
   [optimization](https://wordpress.org/plugins/tags/optimization/)[performance](https://wordpress.org/plugins/tags/performance/)
   [speed](https://wordpress.org/plugins/tags/speed/)
 *  [Advanced View](https://wordpress.org/plugins/mbr-performance/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/mbr-performance/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/mbr-performance/reviews/)

## Contributors

 *   [ robinmorgan2059 ](https://profiles.wordpress.org/robinmorgan2059/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/mbr-performance/)