Skip to content
ThemesIonic — home
Troubleshooting

Fixing Uncaught ReferenceError: jQuery Is Not Defined in WordPress

The script ran before jQuery existed on the page, or on a page where nothing asked WordPress to load jQuery at all. The fix is to declare the dependency, not to add another copy of the library.

5 min read intermediate

Your code ran before jQuery was on the page, or on a page where nothing told WordPress to load jQuery — declare the dependency and WordPress will load and order it for you. Uncaught ReferenceError: jQuery is not defined in the browser console is not a server error, and nothing on the server is broken. A script referenced the global jQuery at a moment when it did not exist.

How WordPress loads jQuery

WordPress registers jQuery under three handles in wp-includes/script-loader.php: jquery-core (the library, 3.7.1 in current versions), jquery-migrate (the compatibility layer) and jquery, which has no file of its own and simply depends on the other two. Two consequences cause most of these errors:

  1. On the front end, nothing loads jQuery by default. WordPress prints it only when an enqueued script lists jquery as a dependency, or someone enqueues it directly. A page whose plugins happen not to need it will not have it, so a hard-coded script that assumes jQuery works on one page and fails on the next.
  2. It loads in the head unless something moves it. The handles are registered without the footer flag, so inline code later in the page normally finds jQuery. Optimisation features that move, defer or delay scripts change that.

Cause 1: a script enqueued without the dependency

The script is loaded properly, but the registration never mentions jQuery:

// Wrong: no dependency, so the order is not guaranteed and jQuery may be absent.
wp_enqueue_script( 'my-slider', get_stylesheet_directory_uri() . '/js/slider.js' );

Declare it, and WordPress both loads jQuery and prints it first:

wp_enqueue_script(
	'my-slider',
	get_stylesheet_directory_uri() . '/js/slider.js',
	array( 'jquery' ),
	'1.2.0',
	array( 'in_footer' => true )
);

The array form of the last argument has been available since WordPress 6.3; true still works for the footer. More on the parameters in wp_enqueue_scripts, and the admin equivalent in admin_enqueue_scripts.

Cause 2: inline code that does not belong to a script

A <script> block pasted into a header/footer plugin, a Custom HTML block or a theme template runs where it sits, with no relation to WordPress's script queue. If jQuery is printed later on the page, or not at all, the block fails.

Attach the code to jQuery instead:

add_action( 'wp_enqueue_scripts', function () {
	wp_enqueue_script( 'jquery' );
	wp_add_inline_script(
		'jquery',
		'jQuery(function ($) { $(".faq-question").on("click", function () { $(this).next().slideToggle(); }); });'
	);
} );

wp_add_inline_script() prints the snippet immediately after the handle it is attached to, wherever that handle ends up. If jQuery is moved to the footer through WordPress's own queue, the snippet moves with it; a plugin that rewrites the finished HTML may still need the exclusions below. The same approach works for code you would otherwise put in a template, as covered in adding code to a WordPress page.

Cause 3: optimisation plugins

This is the cause when the error appears immediately after enabling a performance setting. Four features are involved:

Feature What it does to jQuery Why inline code breaks
Move scripts to footer Prints jQuery at the end of the body Inline code in the content runs earlier
Defer Adds defer, so jQuery executes after parsing Inline scripts without defer execute first
Delay JavaScript Loads nothing until the first interaction Everything that expects jQuery on load fails
Combine / minify Merges jQuery into a bundle A broken bundle or wrong order removes it

The safe configuration excludes jquery-core, jquery-migrate and the inline scripts that depend on them, usually by adding jquery to the plugin's exclusion field. Then purge every cache layer, as described in clearing WordPress cache, because a cached page keeps the broken order. If a script tag is being rewritten by a filter, script_loader_tag shows where the defer came from.

Cause 4: a replaced or blocked copy

Some themes and old snippets deregister the bundled jQuery and register one from a public CDN:

wp_deregister_script( 'jquery' );
wp_register_script( 'jquery', 'https://code.jquery.com/jquery-3.7.1.min.js' );

If the CDN is blocked by an ad blocker, a firewall or a content security policy, jquery is now an empty handle and every dependant fails. Deregistering jquery also removes the dependency on jquery-migrate, so plugins that still use removed methods break in a different way. Remove the snippet and let WordPress serve its own copy. Mixed content — a jQuery URL on http:// on an HTTPS page — is blocked by the browser and produces the same error; see mixed content warnings.

Common mistakes

  • Adding a second <script src="jquery.js"> to "make sure". Two copies mean plugins attach to one and your code to the other.
  • Writing $(...) in WordPress. The bundled file ends with jQuery.noConflict(), so $ is not defined globally; that is a different error, $ is not a function, with the same fix: use the wrapper jQuery(function ($) { ... }).
  • Fixing the error on the home page only. Test a page where no plugin needs jQuery.
  • Excluding a script from delay but not the inline code that calls it.

Verify

  • Open the browser console on the failing page with the cache bypassed; the error is gone.
  • In the page source, jquery-core-js appears before any script that uses jQuery.
  • jQuery.fn.jquery typed into the console returns the version WordPress bundles, not a CDN version.
  • Test a page that has none of the plugins that normally load jQuery.

Frequently asked

WordPress ships jQuery in no-conflict mode: its bundled file ends with jQuery.noConflict(), which releases the $ name. Use jQuery, or wrap your code in jQuery(function ($) { ... }) so $ is defined inside the wrapper.
No. Deregistering the bundled copy to load another one is a common cause of this error: the CDN file can fail or be blocked, its version may not match what plugins expect, and it lacks the no-conflict call WordPress adds.
Exclude jQuery, and any inline scripts that use it, from delaying or deferring, or turn the feature off for that page. Delaying postpones the library itself, so inline code that runs immediately finds nothing.

Related guides