
Product Website Templates That Drive Sales
February 2, 2026
How to Fix the Facebook Link Thumbnail Not Working Error
February 7, 2026You open the browser console and there it is: Uncaught ReferenceError: jQuery is not defined. Something that should just work, doesn't.
This JavaScript error hits projects of every size, from WordPress blogs to full-scale web applications. jQuery still runs on roughly 77% of all websites, so this ReferenceError shows up constantly. And it has at least six different causes.
This guide breaks down how to fix the jQuery is not defined error by walking through each cause and its specific solution. Wrong script order, missing CDN files, async and defer conflicts, bundler scope issues, noConflict mode, and Content Security Policy headers blocking scripts.
You'll also get a step-by-step debugging workflow and platform-specific fixes for WordPress, Shopify, and modern frameworks like React and Vue.
What Is the "jQuery Is Not Defined" Error?

"jQuery is not defined" is a ReferenceError thrown by the browser's JavaScript engine. It fires when your code calls jQuery or $, but neither variable exists in the current scope.
The browser can't find the jQuery library. That's the whole story.
This error shows up in the browser console, whether you're working in Chrome DevTools, Firefox Developer Tools, or Safari's Web Inspector. It's not a server-side issue. It's strictly a client-side DOM and script loading problem.
W3Techs data from 2025 shows jQuery is still used by roughly 77.8% of the top 10 million websites. According to SimilarWeb, nearly 195 million websites run jQuery as of mid-2025. So yeah, this error isn't going away anytime soon.
The tricky part? Multiple things can cause it. A missing script tag, wrong file path, incorrect load order, a CDN that's down, scope isolation from a bundler like webpack. Even WordPress's built-in noConflict mode triggers a version of this error for developers who assume $ just works.
Plugins that depend on jQuery as a dependency (Bootstrap 4, Select2, DataTables, and others) will also throw this same ReferenceError if jQuery hasn't loaded before they run. You'll see something like Uncaught ReferenceError: jQuery is not defined pointing to the plugin file, not your code. That sends people on the wrong debugging trail.
The fix depends entirely on the cause. And there are at least six distinct causes worth checking.
I'm interrupting the article to tell you about BeTheme, the definitive multipurpose theme. If trying to satisfy multiple clients has become more stressful than rewarding, BeTheme is the solution for that.
BeTheme’s selection of hundreds of customizable, responsive pre-built websites is the highlight and a proven stress reducer.
The customizability of the theme makes it a dream come true for its users. There are 4 types of Page Builders that you can use with it: WPBakery, BeBuilder, and Elementor among them.
And now with the Live Builder, it’s even more impressive.
Check out BeTheme and see why our users love it!
The rest of the article is down below.
jQuery Loaded After Dependent Scripts
This is cause number one. Probably accounts for more "jQuery is not defined" errors than everything else combined.
Browsers parse HTML top to bottom. When they hit a script tag, they download and execute it before moving on. If your app script appears before the jQuery script tag in your HTML document, the browser runs your code first. jQuery doesn't exist yet. Error.
How Script Tag Placement Affects Load Order
External JavaScript files block parsing by default. The browser stops reading HTML, fetches the script, executes it, then continues. This is sequential and predictable.
Your jQuery script tag must appear before anything that references $ or jQuery. Always.
| Script Order | Result | Why |
|---|---|---|
| jQuery first, then app.js | Works | jQuery exists when app.js runs |
| app.js first, then jQuery | Error | $ is undefined when app.js runs |
| jQuery in , app.js before | Works | jQuery parses and executes first |
This also bites WordPress developers. The wp_enqueue_script() function has a dependency array that controls load order. If you register a script without declaring 'jquery' as a dependency, WordPress might load it before jQuery finishes.
Took me a while to figure that one out on a client project. The script worked fine locally because the files loaded fast enough. On a slower server? Broken.
The WordPress-Specific Fix
WordPress powers over 43% of all websites globally, according to W3Techs. That means a huge chunk of jQuery errors come from WP sites specifically.
The correct way to handle script dependencies in WordPress is through the enqueue system. Pass array('jquery') as the third parameter in wp_enqueue_script(), and WordPress guarantees jQuery loads first.
Never hardcode a script tag for jQuery directly in your theme header. WordPress bundles its own jQuery. Loading a second copy from a CDN creates conflicts, version mismatches, and exactly the kind of undefined variable errors you're trying to avoid.
jQuery File Not Loading at All
Sometimes jQuery isn't late. It's just... not there.
Open your browser's DevTools, click the Network tab, and filter by JS. Look for the jQuery file. If it returned a 404, your path is wrong. If it returned a 403, you have a permissions issue. If it's not listed at all, the script tag is missing from your HTML.
Common culprits:
- Typos in the file path (a misplaced forward slash or wrong directory name)
- Corporate firewalls or adblockers stripping out CDN requests
- HTTPS/HTTP mismatch on the CDN URL when your site enforces SSL
The local fallback pattern handles this gracefully. Load jQuery from a CDN, then immediately check if window.jQuery exists. If it's undefined, inject a script tag pointing to a local copy on your server.
CDN Links That Break Over Time
Cloudflare reported 2.8 hours of downtime in 2024 alone, and their November 2025 outage impacted roughly 28% of all HTTP traffic. CDNs go down. It happens.
Google Hosted Libraries, cdnjs, jsDelivr, and jQuery's own CDN are the main options. Each has different reliability profiles.
Version pinning matters. A URL like jquery/3.7.1/jquery.min.js is stable and cacheable. Pointing to "latest" means your site loads whatever version happens to be current, which can break plugins that expect a specific jQuery version.
Subresource Integrity (SRI) hashes add another layer. They verify the CDN file hasn't been tampered with. But if you update the jQuery version and forget to update the SRI hash, the browser blocks the file entirely. Silent failure. No jQuery. Error.
Using async or defer on the jQuery Script Tag
Performance optimization plugins love slapping async or defer on every script tag they find. Autoptimize, WP Rocket, LiteSpeed Cache. They do it indiscriminately. And it breaks jQuery.
Here's why.
async downloads the script in parallel with HTML parsing and executes it the moment it's ready. No guaranteed order. If your plugin script finishes downloading before jQuery does, it runs first and throws the error.
defer also downloads in parallel, but waits until the HTML is fully parsed before executing. Scripts with defer maintain their document order. This is safer, but only if both jQuery and your dependent scripts use defer.
| Attribute | Download | Execution Timing | Order Preserved? |
|---|---|---|---|
| None | Blocks parsing | Immediately | Yes |
| async | Parallel | As soon as ready | No |
| defer | Parallel | After HTML parsed | Yes |
The race condition with async is the dangerous one. Your page loads fine 9 out of 10 times because jQuery usually downloads faster (it's cached, it's on a fast CDN). Then on that one slow load, everything breaks. Intermittent bugs. The worst kind.
If you're using a caching or performance plugin in WordPress, check its JavaScript optimization settings. Look for options to exclude jQuery from async/defer treatment, or at minimum, make sure jQuery and its dependents share the same loading strategy.
jQuery Loaded Inside a Module or Isolated Scope
This one catches people who are moving from traditional script tags to modern JavaScript tooling.
ES modules (type="module") have their own scope. They don't pollute the global window object by default. So if jQuery is loaded as a module, $ and jQuery won't be available globally unless you explicitly assign them to window.
Same thing happens with bundlers. Webpack, Vite, Rollup. They isolate modules by design. jQuery gets bundled into your app, but it's scoped inside the bundle. Code outside that bundle (inline scripts, third-party plugins loaded via script tags) can't see it.
The Webpack Fix
webpack.ProvidePlugin is the standard solution. It tells webpack to automatically inject jQuery whenever it encounters $ or jQuery as a free variable in any module:
new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' })
According to webpack's official documentation, jQuery is literally the first example in the ProvidePlugin docs because this is such a common fix. Multiple GitHub issues on the webpack repository confirm developers consistently run into "jQuery is not defined" when migrating to bundled builds.
For Vite projects, the approach is different. You'll typically import jQuery at the top of your entry file and assign it to window.jQuery and window.$ manually.
Shadow DOM and Web Components
Shadow DOM creates an isolated subtree in your document. Scripts running inside a shadow root can't access jQuery attached to the main document's window unless you pass it through explicitly.
This is less common but increasingly relevant as web component adoption grows. If you're building with custom elements and still relying on jQuery plugins inside them, you'll need to pass the jQuery reference into the component scope.
jQuery noConflict Mode Removing the $ Variable
jQuery is loaded. It's there. You can verify it by typing window.jQuery in the console and getting back the function. But $ returns undefined.
That's noConflict mode.
jQuery.noConflict() releases the $ alias back to whatever library owned it before jQuery loaded. This prevents conflicts with other JavaScript libraries that also use $ as a shorthand (Prototype.js was the big one, historically).
WordPress runs jQuery in noConflict mode by default. This catches so many developers. You install WordPress, write $(document).ready(), and it blows up. The jQuery library is right there, but $ is gone.
Three fixes, pick the one that fits:
- Use the full name: Write
jQuery('selector')instead of$('selector') - IIFE wrapper:
(function($) { /* your code */ })(jQuery);passes jQuery as$inside the closure - DOM ready shorthand:
jQuery(function($) { /* $ works here */ });
The IIFE wrapper is the cleanest approach for WordPress theme and plugin development. It keeps your code portable. You write with $ like normal, but it works regardless of whether noConflict is active.
When WordPress 5.5 shipped without jQuery Migrate in 2020, Search Engine Journal reported it may have broken at least 50,000 sites. Older themes and plugins that relied on deprecated jQuery methods suddenly stopped working. The jQuery Migrate plugin was created specifically to bridge that gap, and WordPress eventually released the "Enable jQuery Migrate Helper" plugin to help site owners recover.
If you're building a website from scratch these days (whether it's a startup landing page or a full SaaS website), consider whether you actually need jQuery at all. Modern JavaScript covers most of what jQuery was built for. But if your stack depends on it, understanding noConflict mode saves hours of confusion.
Content Security Policy Blocking Inline jQuery or External CDN
This is the sneaky one. jQuery is in your HTML. The path is correct. The CDN is up. But the browser silently refuses to load it.
A strict Content-Security-Policy (CSP) header can block external script sources that aren't explicitly whitelisted. If your jQuery CDN domain isn't listed in the script-src directive, the browser kills the request before it even starts.
The error message looks different from a typical ReferenceError. Check the console for something like:
Refused to load the script because it violates the following Content Security Policy directive: "script-src 'self'"
That's the giveaway. The browser is telling you exactly what happened, but most developers skip past it looking for the "jQuery is not defined" message further down.
The 2024 Polyfill supply chain attack hit over 500,000 websites that trusted a single CDN domain, according to c/side research. CSP policies exist precisely to prevent that kind of breach. So tightening your CSP is good practice. But it does mean you need to explicitly whitelist every external JavaScript source.
The fix: Add the CDN domain to your CSP script-src directive. If jQuery is loaded from cdnjs.cloudflare.com, your header needs to include that domain.
Or skip the CDN entirely and host jQuery locally. With a self-hosted file, script-src 'self' covers it without additional configuration. Microsoft announced that SharePoint Online will enforce CSP starting March 2026, so this issue will only get more common as organizations tighten their security headers.
Diagnosing the Error Step by Step
You've read the causes. Now here's a fast, repeatable workflow for tracking down which one applies to your situation.
Check the Browser Console First
Open Chrome DevTools (F12 or Cmd+Option+I on Mac). Click the Console tab.
Look at the exact error message and the file/line number. If it says Uncaught ReferenceError: jQuery is not defined at line 1 of your plugin file, that plugin loaded before jQuery did.
If it says Refused to load the script, that's a CSP issue, not a load order problem.
Inspect the Network Tab
Filter by JS. Look for the jQuery file in the list of loaded resources.
| Status Code | What It Means | Likely Fix |
|---|---|---|
| 200 | jQuery loaded fine | Problem is load order or scope |
| 404 | File path is wrong | Fix the URL in your script tag |
| 403 | Access denied | Check permissions or CSP headers |
| Not listed | Script tag missing from HTML | Add the jQuery script tag |
Test window.jQuery in the Console
Type window.jQuery directly in the console and press Enter.
If it returns a function, jQuery is loaded globally. Your problem is scope isolation or noConflict mode. If it returns undefined, jQuery never loaded or it's trapped inside a bundled module.
View Page Source (Not Inspect Element)
Right-click the page and choose "View Page Source", not "Inspect." Inspect Element shows the live DOM after JavaScript runs. Page Source shows the raw HTML the server sent.
Find the jQuery script tag. Verify it appears before your app scripts. Check for async or defer attributes you didn't expect.
Platform-Specific Fixes
The "jQuery is not defined" error hits differently depending on your platform. WordPress, Shopify, and modern JavaScript frameworks each have their own quirks.
WordPress
WordPress powers over 43% of all websites globally (W3Techs, 2025). It bundles its own copy of jQuery. Don't load a second one.
Always use wp_enqueue_script() with array('jquery') as the dependency. This is the only correct way to load scripts that need jQuery in WordPress.
- Never hardcode script tags for jQuery in your theme header or footer
- WordPress runs jQuery in noConflict mode, so use
jQueryinstead of$ - Check for theme or plugin conflicts that deregister or replace the bundled jQuery
Performance plugins like WP Rocket and Autoptimize can add defer to the jQuery script, breaking plugins that expect it to be available immediately. Exclude jQuery from script optimization if you see intermittent errors.
Shopify
Shopify themes have moved away from jQuery in recent years. Many newer Shopify themes built on Online Store 2.0 don't include jQuery at all, relying on vanilla JavaScript instead.
Before writing any jQuery code for a Shopify store, check if the theme actually loads the library. Open the theme.liquid file and search for jquery.
If it's not there, you have two options. Either add jQuery yourself via a CDN link in theme.liquid, or (better) rewrite your code using native JavaScript. Shopify's fastest themes, like Turbo and Dawn, specifically avoid jQuery to cut page weight and improve performance scores.
React, Vue, and Angular Projects
These frameworks don't include jQuery. Period.
If a third-party plugin requires jQuery, install it explicitly with npm install jquery and import it at the top of your entry file. But here's the thing: direct DOM manipulation via jQuery conflicts with the virtual DOM approach that React, Vue.js, and Angular use.
Stack Overflow's 2024 survey of 65,000+ developers shows jQuery barely registers in discussions about modern web frameworks anymore. React, Vue, and Svelte dominate those conversations. If you're building a new project with one of these frameworks, look for a native component that replaces whatever the jQuery plugin does rather than shoehorning jQuery into a virtual DOM environment.
How to Prevent the Error From Coming Back
Fixing the error once is one thing. Keeping it fixed through deployments, updates, and team changes is the real challenge.
Lock Your jQuery Version
Pin a specific version. In your package.json, use an exact version number instead of a range. In your CDN URL, include the version number explicitly (like jquery/3.7.1/jquery.min.js).
Version drift is a real problem. A plugin that works with jQuery 3.6 might break on 3.7 because a deprecated method finally got removed. Docker's blog notes that a 2023 survey across 500 organizations found only 44% use maintained jQuery versions (3.6.0 or newer), while 59% still run older 1.x to 3.5.x releases.
Add a Smoke Test
After every deployment, a quick check that jQuery loaded properly can catch issues before users do.
You can do this with a simple script that runs after page load and checks window.jQuery. If it's undefined, log an error to your monitoring service. Tools like Sentry or LogRocket can catch these client-side JavaScript errors automatically.
Document Your jQuery Dependencies
If you're using a CMS, keep a list of which plugins and themes depend on jQuery. When you update WordPress, Shopify, or any CMS, you need to know what might break if jQuery gets removed, replaced, or updated to a new version.
This sounds basic. But the WordPress 5.5 jQuery Migrate incident proved that thousands of site owners had no idea their themes depended on deprecated jQuery methods until everything stopped working at once.
Consider Dropping jQuery Entirely
The permanent fix.
Modern JavaScript covers most of what jQuery was designed to do. querySelector replaces jQuery's selector engine. fetch() replaces $.ajax(). classList replaces .addClass() and .removeClass(). addEventListener replaces .on().
| jQuery Method | Native JavaScript Equivalent |
|---|---|
$('.class') |
document.querySelectorAll('.class') |
$.ajax() |
fetch() |
.addClass('x') |
el.classList.add('x') |
.on('click', fn) |
el.addEventListener('click', fn) |
W3Techs data shows jQuery is still present on roughly 77% of websites, but that number mostly reflects legacy installations. New projects are overwhelmingly choosing React, Vue.js, or vanilla JavaScript. Bootstrap 5 dropped its jQuery dependency entirely, which tells you where the industry is heading.
If your project is a product landing page or a simple website, you almost certainly don't need jQuery. If you're managing a technology website or a software website, your frontend team is probably already using something more current.
Dropping jQuery means you never have to fix "jQuery is not defined" again. And honestly, for most projects started after 2020? That's the right call.
FAQ on jQuery Is Not Defined
What does "jQuery is not defined" mean?
It's a ReferenceError thrown by the browser's JavaScript engine. It means your code called $ or jQuery, but the library hasn't loaded yet or isn't accessible in the current scope.
Why does jQuery work locally but not in production?
Usually a CDN issue. Your local files load instantly, but in production the CDN might be blocked by a firewall, Content Security Policy header, or regional restriction. Check the Network tab in DevTools for failed requests.
How do I check if jQuery is loaded on a page?
Open the browser console and type window.jQuery. If it returns a function, jQuery is loaded globally. If it returns undefined, the library either failed to load or is isolated inside a bundler scope.
Why does WordPress throw "$ is not defined" when jQuery is loaded?
WordPress runs jQuery in noConflict mode by default. The $ shorthand gets released. Use jQuery instead of $, or wrap your code in an IIFE that passes jQuery as the dollar sign.
Can async or defer attributes cause this error?
Yes. The async attribute removes guaranteed script execution order. If jQuery has async and your plugin script also has async, there's a race condition. Use defer on both or remove async from jQuery entirely.
How do I fix this error in a webpack project?
Use webpack.ProvidePlugin to inject jQuery globally across all modules. Set $: 'jquery' and jQuery: 'jquery' in the plugin configuration. This is the standard fix documented in webpack's official docs.
Does Shopify include jQuery by default?
Not always. Newer Shopify themes built on Online Store 2.0 often skip jQuery entirely for better performance. Check your theme.liquid file before writing any jQuery code. If it's missing, add it manually or use vanilla JavaScript.
What is the jQuery CDN fallback pattern?
Load jQuery from a CDN first. Then immediately check if window.jQuery exists. If it's undefined, dynamically inject a script tag pointing to a local copy on your server. This protects against CDN downtime.
Can Content Security Policy block jQuery from loading?
Yes. A strict CSP header with a narrow script-src directive will block external CDN scripts silently. The console shows a CSP violation message instead of the typical ReferenceError. Add your CDN domain to the directive or host jQuery locally.
Should I just stop using jQuery entirely?
For new projects, probably. Modern JavaScript methods like querySelector, fetch(), and classList cover most jQuery functionality natively. Bootstrap 5 dropped its jQuery dependency, and most modern frameworks don't use it at all.
Conclusion
Knowing how to fix the jQuery is not defined error comes down to identifying which of the six causes applies to your setup. Script tag placement, a missing library file, async/defer race conditions, bundler scope isolation, noConflict mode, or a restrictive CSP header.
The debugging workflow is always the same. Open Chrome DevTools, check the Console and Network tabs, test window.jQuery, and view the raw page source.
Platform matters too. WordPress has its own enqueue system and noConflict quirks. Shopify themes might not even include jQuery anymore. React and Vue.js projects need explicit imports and webpack configuration.
Pin your jQuery version. Document which plugins depend on it. And for any new project, seriously consider whether native JavaScript methods like querySelector and fetch() can replace the jQuery library altogether.
The best fix for an undefined variable error is removing the dependency entirely.





















