Release Notes

GT Performance 1.2.0

Stable

Works out of the box: a guided setup, optimization for sites whose host already caches pages, and a plugin that cleans up after itself.

Setup and cache modes

  • A Setup tab walks a fresh install to a verified cached page: AUTH_KEY, OpenSSL, the cache directory, and who owns advanced-cache.php; active page-cache plugins and host caches (from the environment, or from the home page's headers fetched once as a visitor: LiteSpeed, Kinsta, Hostinger, SiteGround, WP Engine, Varnish, Nginx, and others); the cache mode; Cloudflare; store and language plugins; and a verification that requests the home page as a visitor, up to four times two seconds apart, until GT Performance answers HIT. Cloudflare's answer is shown beside the result rather than deciding it, because right after a full purge the edge can keep answering MISS for a minute while the origin already serves HITs. Nothing runs until a button is pressed, and activation does not redirect. The Dashboard points to Setup until verification passes.
  • Optimize-only mode runs the optimization pipeline on responses the eligibility rules would cache and hands them to the host's cache without storing them. The drop-in is not required, and the compiled configuration tells an installed one never to serve. Bypassed requests start no output buffer. Responses must pass the same checks a stored page must, and warming and stale refresh are skipped. Cache headers for eligible pages are left to the host. A response the eligibility rules would not cache is sent no-store, as in store mode: a shared cache that receives no Cache-Control applies its own default lifetime (two hours at Cloudflare), so staying silent would have shared pages this plugin refused to cache. The mode is chosen in Setup or on the Cache tab and shown on the Dashboard, in the health report, cache status, and the site-status ability.

Caching

  • "Cache each value separately" lists query parameters whose values each get their own stored copy, instead of bypassing the cache as unknown parameters. Values over 100 characters are not cached, and a page holds at most 100 variants; beyond that, new values are served uncached. Each variant is recorded in a per-page index, so purging the page removes every variant at the origin and passes their URLs to the edge purge.
  • The editor's GT Performance box adds "Don't cache this page" (never stored or optimized, sent no-store, reported by Explain as page-option) and "Use original CSS" (full stylesheets, no unused-CSS build queued).
  • Query parameters sent as arrays (name[]=) bypass the cache as query_array:<name> and are sent no-store, like never-cache parameters. parse_str() made them arrays and the request context kept only scalars, so ?preview[]=1 or ?s[]=x was judged and keyed as the page with no query, in WordPress and in the drop-in.
  • A preload that gets a redirect or a 4xx is recorded as skipped (redirect_301, http_404) instead of failing and retrying three times. On a large site, sitemap URLs of moved posts had made up most of the queue's failed jobs. Server errors and transport failures still fail and retry.
  • A settings save advances the cache generation, which purges the origin and sends purge-everything to Cloudflare, only when a setting that reaches cached pages changed. Credentials, connection status, background work, and admin-only settings are listed as output-neutral; anything else, including any new setting, still purges.
  • Unused CSS kept a block theme's fluid font sizes. The bundled parser (Sabberworm 9.4 and 9.5) silently drops any declaration with a bare parenthesised group inside a math function, such as clamp(1rem, 1rem + ((1vw - 0.2rem) * 0.196), 1.125rem), which is how WordPress writes every fluid font size; on Twenty Twenty-Five the page title fell from 43.8px to 16px. Such values are now hidden from the parser and restored byte for byte, and a stylesheet whose round trip loses any declaration is left untouched rather than pruned. Builds made before 1.2.0 are not reused after updating.
  • A price or stock change saved through the store's own tools purges the product, its shop page, and its categories immediately, at the origin and at the edge. Only that purge fires after the new price is written; it used to be queued, so a WooCommerce price change reached visitors only after the next queue run, and Cloudflare could re-store the old price in between. Listings found through recorded dependencies stay queued, since bulk stock syncs touch thousands of products.

Cloudflare

  • Deactivation deletes this site's managed Cache Rule, leaving every other rule, and purges this site's hostnames, best effort and without blocking deactivation. After reactivation the Cloudflare tab says the rule is gone until the next sync. wp gt-performance cloudflare disconnect [--forget] and a Disconnect button do the same and turn the integration off; --forget also deletes the credentials and Zone ID.
  • Sites that share a Cloudflare zone (example.com and shop.example.com on separate installs) no longer take over each other's cache rule. Every site used one fixed rule ref, and refs are unique per zone, so a second site's sync overwrote the first site's rule and its deactivation deleted it. New rules get a ref per hostname; a rule under the old shared ref still belongs to the site whose host its expression names and keeps that ref when updated, since Cloudflare refuses to change a ref. Conflict detection no longer mistakes a subdomain's rule for this host's.
  • A full edge purge (a cache-relevant settings save, disconnect, deactivation, cloudflare purge without --page-url) purges this site's hostnames instead of sending purge_everything, which also emptied Cloudflare's cache for every other site and subdomain in the zone. Purge by hostname is available on every plan.
  • Deactivation also empties the local page store. Nothing purges while the plugin is off, so a page edited in the meantime came back from the store as a HIT on reactivation.
  • Every sync, including the one Setup runs, purges this site's hostnames after writing the rule. A request that reached Cloudflare in the seconds before a just-deleted rule stopped applying could store the page WordPress sent without the plugin, and recreating the rule served that copy. Callers report a failed purge.
  • The ruleset backup written on every sync was never read, and restoring it would undo the site owner's later rule changes, so it is no longer written. Uninstall still removes the old option.
  • The connection check adds two stages that warn rather than fail: whether the site host's DNS records are proxied (falling back to the site's own CF-Ray header when the token cannot read DNS), and whether APO is on. The summary says when a stage needs attention.

Compatibility and diagnostics

  • WPML, Polylang, TranslatePress, Weglot, WooCommerce Multilingual & Multicurrency, CURCY, FOX (WOOCS), Aelia Currency Switcher, and Price Based on Country are detected. Integrations flags each active one with what to set, and the health report warns while any is active. Nothing is changed automatically.
  • The health report and cron checks are translatable, CronHealth leaves the server path out of exported reports through a flag instead of string replacement, and languages/gt-performance.pot ships with the plugin.