WordPress JavaScript Delay vs. Defer: What’s the Difference?

Two settings. Both promise a faster WordPress site. And a surprising number of site owners switch one on, watch their menu stop working, and decide the whole idea is broken.

Delay and defer sound like synonyms. They aren’t. Defer changes when a script runs during page load. Delay keeps a script out of the initial page load and releases it later, commonly after a visitor interacts with the page. Use the wrong one on the wrong script and you either leave speed on the table or break something your visitors can see.

So instead of dictionary definitions, let’s take one small online shop, a handful of scripts, and figure out which setting goes where.

Why JavaScript is the usual suspect

When a browser hits a plain <script> tag, it stops reading the HTML, downloads the file, runs it, and only then carries on. MDN calls this blocking the parser. One slow script near the top and everything after it waits.

Downloading is only half the cost. Every script also has to be parsed and executed on the main thread, the same thread that paints the page and answers taps. Too much JavaScript and the page looks ready but ignores you. That’s what shows up as Total Blocking Time in lab tests and as Interaction to Next Paint (INP) in real-world data, the Core Web Vital that replaced First Input Delay in March 2024.

WordPress makes this easy to overdo. Every plugin adds its own scripts, and plenty of them load on every page whether the page needs them or not. If PageSpeed Insights keeps nagging you about reducing unused JavaScript, this is where it comes from.

The shop we’re fixing runs a theme with a mobile menu and a product slider, WooCommerce, Google Tag Manager, a live chat bubble, a Meta pixel, and a cookie banner. Nothing exotic. Which is exactly why it’s a good example.

Defer: run it later, but still run it

Defer is a standard HTML attribute, and it’s the simplest fix on the list:

<script src=”/js/menu.js” defer></script>

The browser downloads the file in the background while it keeps reading the HTML. Once the page is fully parsed, the script runs, just before the DOMContentLoaded event. Deferred classic scripts run in document order, so a script that depends on another one still finds it waiting.

Three details trip people up. Defer only works on external files with a src, so inline scripts ignore it. Module scripts are deferred by default. And it’s not the same as async, which runs a script the moment it’s downloaded, in whatever order the downloads finish. Async suits independent scripts. Anything with dependencies should use defer.

Since WordPress 6.3, you don’t need hacks to get this. The Scripts API accepts a loading strategy, as the core dev note explains:

wp_enqueue_script(

    ‘shop-menu’,

    get_stylesheet_directory_uri() . ‘/js/menu.js’,

    array(),

    ‘1.0.0’,

    array(

        ‘in_footer’ => true,

        ‘strategy’  => ‘defer’,

    )

);

The appeal of defer is that nothing gets lost. Every script still runs on every visit, in a predictable order. The catch is in that last part: it still runs during page load. The browser is no longer blocked while reading the HTML, but the main thread still has to do the work right after parsing finishes. Stack up enough deferred scripts and that moment turns into one long task.

Delay: don’t run it until someone’s actually there

Delay isn’t an HTML attribute, and browsers have no built-in version of it. It’s a technique performance plugins use. They rewrite your script tags so the browser leaves them alone, then release them later, most often when a visitor first interacts with the page, for example by scrolling, tapping, clicking or pressing a key.

The potential payoff is bigger than with defer. While the page loads, the delayed scripts stay out of the way: no parsing and no execution, and usually no download either. The main thread is free to paint, and the page becomes usable sooner. Lab tests often see much less of the delayed JavaScript during the initial load, which is one reason scores can improve significantly.

But the scripts do have to run eventually, and that’s where Delay can bite:

  • On the first interaction, the whole backlog runs at once. A first tap can feel sluggish.
  • Anything that needs JavaScript to appear shows up late. Think sliders, animated headers, popups and menus built by scripts.
  • Depending on the setup, tools like analytics may miss visitors who leave without ever interacting.

So Delay is a trade. You push work out of the loading phase, and you accept that it lands somewhere else. For scripts nobody is waiting for, that’s a great deal. For scripts people can see or touch, it isn’t.

Delay vs. defer at a glance

Here’s the cheat sheet before we put it to work on the shop:

AspectDeferDelay
What it isA standard HTML attributeA plugin technique, no browser standard
When the script runsRight after the HTML is parsedLater, commonly after the visitor interacts
Runs on every visitYes, alwaysOnly once it’s released, commonly after interaction
Execution orderKeptDepends on the plugin
Effect on lab scoresGoodOften bigger
Main riskInline code that expects the script to be there alreadyMissing features until interaction, and a laggy first tap
Best forYour own scripts the page needs right awayThird-party and non-critical scripts

Which one goes where

Back to the shop. A simple rule gets you most of the way: if a visitor can see or touch it in the first second, defer it or leave it alone. If only a machine cares about it, delay it.

ScriptWho needs it, and whenBest treatment
Theme menu and mobile navigationThe visitor, on the first tapDefer
Product slider above the foldThe visitor, immediatelyDefer, or exclude from delay
Cookie bannerYour consent rules, on load: it needs to initialize early so consent applies before non-essential trackingDon’t delay
WooCommerce add-to-cartThe visitor, on clickDefer, and test before delaying
Google Tag Manager and analyticsYour reports, in the backgroundDelay if acceptable for your tracking setup, otherwise exclude from delay
Live chat bubbleThe visitor, but not for a few secondsDelay
Meta pixelYour ad reports, in the backgroundDelay

Notice the pattern. Your own theme and shop scripts are the ones people interact with, so they want to be ready, just not blocking. The third-party scripts are mostly there to watch or to wait, so they can wait a little longer. Tracking is the one place where it’s a trade-off, since a delayed tag can miss visitors who never interact.

One row deserves a second look: the cookie banner. Consent tools usually have to run early to do their job, which is why FastPixel’s Delay mode skips necessary scripts like GDPR ones.

How FastPixel handles JavaScript

FastPixel keeps all of this on one screen. The JavaScript tab in the plugin settings offers three modes, as described in the features docs:

  • Optimize JavaScript: scripts are optimized and run as on the original page, without being delayed. The most compatible, balanced choice.
  • Delay non-critical JavaScript: scripts are optimized and delayed, except necessary ones like GDPR scripts. The fastest option, and the one we recommend.
  • Do not optimize JavaScript: nothing is touched. Meant for cases where optimization causes problems.

Below the modes you’ll find exclusions: one for individual script files, one for RegExp matches on URLs, keywords or inline code, and a dedicated GDPR option for consent popups. Since version 1.9.0, you can also exclude a script from delay only, instead of dropping it from optimization completely. That’s the small detail that makes Delay much easier to live with.

Here’s how we’d set up the shop:

  1. Open the JavaScript tab and choose Delay non-critical JavaScript.
  2. Purge the full cache. Changes on this tab only apply after a full purge.
  3. Test the pages that matter on your phone: homepage, a product, the cart and checkout. Open the menu, flick the slider, add something to the cart, accept the cookie banner.
  4. If one thing misbehaves, add only that script to the delay exclusions.
  5. If the page still acts up, switch to Optimize JavaScript. Scripts still get optimized, but nothing waits for a click.

No FastPixel yet? You can run a test on test.fastpixel.io without installing anything. It optimizes a copy of your site so you can see the difference first.

The bottom line

For our shop, the final setup is short. Let the theme’s own scripts run as soon as the page is ready, delay the chat bubble and the Meta pixel, and keep the cookie banner out of it. Tag Manager and analytics are a judgment call: delay them if your tracking setup can handle it, exclude them if not. Most sites land somewhere similar: a few scripts that must be ready, and a long tail that can wait.

Using FastPixel? That translates to a couple of minutes in the JavaScript tab: choose Delay non-critical JavaScript, purge the cache, test your key pages, and exclude whatever misbehaves. FastPixel is free on sites under 1,000 page views a month, so there’s no cost to trying it.

FAQs

What’s the difference between delay and defer?

Defer runs a script right after the HTML is parsed, on every visit. Delay holds it back from the initial page load and releases it later, commonly after the visitor interacts with the page.

Can I use delay and defer together?

Yes, and most sites should. Defer suits your own scripts the page needs right away. Delay suits third-party scripts that can wait. A script that’s already delayed doesn’t need defer on top.

Does delaying JavaScript improve Core Web Vitals?

Often it helps loading metrics like Largest Contentful Paint and Total Blocking Time, because less work competes with the first paint. Keep an eye on INP, though. The first interaction triggers the delayed scripts, so check your real-user data and not only lab scores.

Which scripts should I never delay?

Anything visitors need to see or use right away: above-the-fold sliders, menus, and cookie or consent banners. FastPixel skips necessary scripts such as GDPR ones when Delay is on, but it’s still worth testing your own setup.

Enjoyed reading? Spread the word!
Bianca Rus
Bianca Rus
Articles: 35
en_USEnglish