WordPress Plugins
Free Tools
Pricing Blog Case Studies Switch to Royal Plugin Graveyard Support My Account Cart
Support / ForgeCache / JS/CSS Optimization Rollback

JS/CSS Optimization Broke My Site — Rollback + Surgical Fix

You enabled one or more of Defer JavaScript, Delay JavaScript until user interaction, Enable Critical CSS, or CSS Minification — and now something on your site is broken. Forms aren’t submitting, a slider isn’t initializing, the layout is missing styles, or accordions / tabs / popups simply don’t respond. This doc gives you the 60-second rollback, then walks through identifying the actual culprit and re-enabling optimization with a surgical exclusion instead of leaving the entire toggle off.

The Two Optimizations That Cause 90% of These Reports

Delay JavaScript until user interaction is the most common cause — it’s deliberately labeled Advanced in the settings UI because it pauses every script that isn’t on the hardcoded jQuery-core safe list until a scroll, click, or mouse move. Anything that needs to run before user interaction (analytics that should fire on page load, sliders that auto-rotate, modal triggers, custom font loaders) will look broken.
Enable Critical CSS is the second most common — if the Critical CSS you pasted in doesn’t cover everything above the fold, visitors get a flash of unstyled content (FOUC) for the first ~500ms while the async stylesheets load. Misconfigured Critical CSS can also wholesale break layout on pages where you haven’t generated CSS for that specific page type.

Step 1 — Roll Back in 60 Seconds

Before identifying the specific cause, get your site back to a working state. The rollback order below is the one ForgeCache support uses internally — from least-invasive optimization to most:

WP Admin → ForgeCache → Settings → Optimization

The Optimization tab has all the toggles that could have broken your site. Keep this tab open as you toggle.

Turn off “Delay JavaScript until user interaction” first

This is the #1 culprit. Uncheck Delay JavaScript until user interaction, click Save Changes, then reload the broken page (force-refresh with Ctrl/Cmd-Shift-R). If the site is back to normal, the issue is a script that’s incompatible with delay-until-interaction. Skip to Identifying the delayed script below.

If still broken, turn off “Enable Critical CSS”

Under CSS Optimization, uncheck Enable Critical CSS. (Leave the Critical CSS textarea itself populated — just turn off the toggle that makes it inline.) Save, reload. If fixed, your Critical CSS doesn’t cover what’s rendering above the fold. See Identifying the missing CSS.

If still broken, turn off “Defer JavaScript”

Under JavaScript Optimization, uncheck Defer JavaScript. Save, reload. If fixed, a specific script breaks when loaded with the defer attribute (it expects to execute synchronously during parsing). See Identifying the deferred script.

If still broken, turn off the master switches

Disable both Enable JavaScript optimization and Enable CSS optimization master switches. Save, reload. If the site is now back to normal, one of the minification options is the culprit (HTML / inline CSS / inline JS minification). Try toggling each minification sub-option to narrow it down.

If STILL broken — not ForgeCache

If every optimization toggle is off and your site is still broken, the issue isn’t ForgeCache optimization. Likely candidates: page caching is serving a stale broken copy (try ForgeCache → Clear All Cache), a different plugin / theme update happened around the same time, or an upstream CDN is serving cached HTML. Site got slower after activation covers the broader cache-stack diagnostic.

Force-refresh the page after every toggle

Ctrl-Shift-R (Cmd-Shift-R on Mac) bypasses your browser’s own HTTP cache. Without that, you may still be looking at a broken JS bundle your browser cached before you toggled the setting — making it look like the toggle didn’t fix anything when it actually did.

Identifying the Delayed Script That Broke

If turning off Delay JavaScript until user interaction fixed the site, the goal now is to find which specific script is breaking when delayed, exclude just that one, and re-enable the Delay toggle for everything else.

The diagnostic

Re-enable Delay JavaScript and reload the broken page

Yes — we’re going to break it again on purpose so we can read the error. Save Changes, reload the affected page, open DevTools (F12) before interacting.

Open the Console tab and look for the first error

The first JS error you see in red is almost always the one that needs an exclusion. Common patterns:

  • Uncaught ReferenceError: jQuery is not defined — some script is trying to use jQuery before jQuery has loaded. The script that errored is the candidate.
  • Cannot read properties of undefined (reading 'init') — a script depends on a global object that another script was supposed to create. Read the stack trace to find which script.
  • Uncaught TypeError: Slider is not a constructor / similar — the slider library hasn’t loaded yet but the init code ran.

Find the script URL in the Console error

The error message includes the file path. Look for the URL pattern /wp-content/plugins/<plugin-name>/…/script.js or /wp-content/themes/<theme>/…/script.js. That filename is the script you need to exclude from delay.

Use the Page Optimizer to exclude just that script

Go to ForgeCache → Page Optimizer — the per-page asset settings tool. Enter the URL of the broken page, click Scan, find the offending script in the asset table, and change its loading mode from Delay to Default (or Defer, which is usually safe). Save and reload. The script now loads normally on that page; everything else is still delayed. The Page Optimizer Guide has the full walkthrough.

Why ForgeCache uses Page Optimizer for exclusions instead of a global textarea

Other cache plugins ask you to paste a list of script patterns into a settings textarea, which then applies site-wide. The trade-off is that you exclude a script on every page even if it’s only used on one. ForgeCache’s Page Optimizer flips this — exclusions are per-page, so a slider script that needs to load eagerly on the home page can still be delayed on every other page where it’s not used. More work to configure, but better Core Web Vitals scores everywhere except where you actually need the exception.

Identifying the Deferred Script That Broke

Defer is generally safer than Delay — ForgeCache hardcodes a skip on jQuery core and any script tagged with no-defer. But some plugin scripts still need to run synchronously during page parsing, and adding defer to those breaks them.

The diagnostic

Same approach as the Delay diagnostic above: re-enable Defer JavaScript, reload the broken page with DevTools Console open, look for the first error, find the script filename in the error, and exclude that script via the Page Optimizer.

Common defer-incompatible patterns

Identifying the Missing CSS

If turning off Enable Critical CSS fixed the site, your Critical CSS doesn’t cover the elements that render above the fold. Critical CSS is paste-in — ForgeCache doesn’t generate it for you, you provide a snippet (from CoreWebVitals.io, BerqWP, etc.) and the plugin inlines that snippet in <head> while loading the rest of the stylesheets asynchronously.

Three ways to fix it

Option A: Generate Critical CSS for the right page type

The most common mistake: generating Critical CSS for your home page and using it site-wide. Your product page has different above-the-fold elements than the home page — the home-page CSS doesn’t cover them, so they flash unstyled. Either generate one Critical CSS per page type (homepage, product, blog post, etc.) and put a global CSS that covers all of them in the Critical CSS field, OR generate it for the most-trafficked page type and accept FOUC on the others.

Option B: Add problem stylesheets to CSS Async Exclusions

The CSS Async Exclusions field below the Critical CSS textarea lets you force specific stylesheets to load normally (not async). If a specific stylesheet is causing FOUC because it’s loading async when it shouldn’t, paste a handle name or URL fragment into the exclusions textarea, one per line. Example placeholders the field already shows:

elementor-icons
font-awesome

You can use any unique substring of the stylesheet URL or the WordPress handle name. Save Changes and reload to test.

Option C: Use the programmatic filter

For developers / mu-plugin authors, ForgeCache exposes forgecache_critical_css_excluded_handles — a WordPress filter that lets you add handles to the exclusion list from code:

<?php
add_filter( 'forgecache_critical_css_excluded_handles', function( $handles ) {
    $handles[] = 'my-theme-fonts';
    $handles[] = 'elementor-pro-styles';
    return $handles;
} );

Useful when the exclusion needs to vary by page type or by user role (logged-in, etc.).

Minification Caveats (Less Common)

ForgeCache’s minification is inline-only — it minifies inline <style> blocks, inline <script> blocks, and the HTML output itself. It does NOT minify external CSS / JS files (those should be minified at build time by your theme / plugin authors). So minification rarely causes the visible breakage that JS defer / CSS Critical can cause.

That said, two known minification edge cases worth knowing:

HTML minifier and framework SSR comment markers

ForgeCache’s HTML minifier preserves IE conditional comments and known SSR comment markers from Knockout (<!-- ko -->), Vue 2 (<!--v-if-->, the empty <!----> placeholder), and Vue 3 fragment boundaries (<!--[-->, <!--]-->). If you’re running a different SSR framework (Svelte hydration markers, Astro islands, etc.) and it gets stripped, the symptom is a client-side hydration mismatch — sections of the page won’t respond to interaction.

Workaround: disable HTML minification globally, or report the framework + the comment pattern via priority email support and we’ll add it to the preserve list.

Inline JS minifier and ES6 template literals

The inline-JS minifier is conservative on modern ES6 syntax. If you have an inline <script> that uses template literals (backtick strings), arrow functions in complex destructuring patterns, or async/await with optional chaining, and you’re seeing a syntax error in the Console after enabling JS minification — that’s the minifier mangling modern syntax. Disable Minify inline JavaScript only (leave the other minify toggles on).

Verify the Fix

After excluding the culprit script(s) via the Page Optimizer (or unchecking the toggle as a temporary measure):

Clear ForgeCache + the browser cache

ForgeCache → Settings → Tools → Clear All Cache, then in your browser hit Ctrl/Cmd-Shift-R to force-reload. Any cached HTML from the broken-state period needs to be purged before you can verify the fix.

Test the previously-broken interaction

The form submission, slider rotation, accordion expand, modal trigger — whatever you reported as broken. Confirm it works.

Run PageSpeed Insights to confirm performance didn’t regress

Per-script exclusions cost some performance but the Page Optimizer is per-page, so you’re only paying that cost on the pages where the script actually needs to run. PageSpeed Insights on the affected URL should still show good scores.

Still Stuck? Email Priority Support

If you can’t identify the culprit script from the Console, or every script you exclude reveals another that’s also broken:

Email support@royalplugins.com with the diagnostic info below. Priority email support is included with your ForgeCache Pro license — typical response time is within 24 hours.

Information to include in your email

  • Your ForgeCache version + WordPress version + PHP version (Tools → Site Health → Info).
  • Your theme + a list of active plugins (Plugins screen, or copy from Site Health Info).
  • Which optimization toggles are on. Defer / Delay / Critical CSS / Minify CSS / Minify JS / Minify HTML.
  • The exact Console error from DevTools when the breakage occurs (screenshot or copy/paste).
  • The URL of the affected page. Staging is fine, doesn’t need to be production.
  • Whether you already tried the Page Optimizer to exclude individual scripts — if so, which.
Related ForgeCache docs