Optimizing your WordPress site for speed is more critical than ever. With Google's Core Web Vitals placing a heavy emphasis on Largest Contentful Paint (LCP) and First Input Delay (FID), reducing render-blocking resources is a top priority for developers. One of the most common recommendations from speed testing tools like PageSpeed Insights is to enqueue jQuery in the footer.

By default, WordPress loads jQuery in the <head> section of your site. While this ensures maximum compatibility with plugins, it can delay the rendering of your page content. In this guide, you will learn multiple ways to move jQuery to the footer safely without breaking your site's functionality.

Why Does WordPress Load jQuery in the Head?

Before we dive into the code, it is important to understand why WordPress defaults to the header. Many themes and plugins use "inline" scripts—small snippets of JavaScript placed directly in the HTML—that rely on jQuery. If jQuery is moved to the footer, these inline scripts will fire before jQuery is loaded, resulting in the dreaded Uncaught ReferenceError: jQuery is not defined error.

However, if you are building a custom theme or using modern, well-coded plugins, moving jQuery to the footer can significantly improve your perceived load time.

Method 1: The Deregister and Reregister Approach

The most common way to move the core jQuery library is to tell WordPress to stop using its default registration and provide a new one with the footer parameter set to true.

You can add the following code to your theme's functions.php file:

function starter_scripts() {
    // Deregister the default WordPress jQuery
    wp_deregister_script( 'jquery' );

    // Register it again with the $in_footer parameter set to true
    wp_register_script( 'jquery', includes_url( '/js/jquery/jquery.js' ), false, NULL, true );

    // Enqueue the script
    wp_enqueue_script( 'jquery' );

    // Enqueue your other scripts that depend on jQuery
    wp_enqueue_style( 'starter-style', get_stylesheet_uri() );
    wp_enqueue_script( 'includes', get_template_directory_uri() . '/js/min/includes.min.js', array('jquery'), '', true );
}
add_action( 'wp_enqueue_scripts', 'starter_scripts' );

Pros and Cons of This Method

  • Pros: It is straightforward and gives you full control over the script source.
  • Cons: By manually pointing to the file path, you might accidentally lose the version string or break compatibility during major WordPress core updates.

Method 2: Using the add_data Logic (The Cleaner Way)

WordPress provides a more elegant way to modify script properties without completely unregistering them. By using the wp_scripts() object, you can change the "group" of a script. In WordPress internal logic, Group 1 represents the footer.

/**
 * Move jQuery to the footer without reregistering.
 */
function wp_move_jquery_to_footer() {
    // Check to ensure we are not in the admin dashboard
    if ( is_admin() ) {
        return;
    }

    wp_scripts()->add_data( 'jquery', 'group', 1 );
    wp_scripts()->add_data( 'jquery-core', 'group', 1 );
    wp_scripts()->add_data( 'jquery-migrate', 'group', 1 );
}
add_action( 'wp_enqueue_scripts', 'wp_move_jquery_to_footer' );

This method is generally preferred because it preserves the versioning and dependencies already established by WordPress core.

Method 3: Hooking into wp_default_scripts

If you want to ensure jQuery is moved to the footer as early as possible in the execution cycle, you can hook into wp_default_scripts. This modifies the script's registration at the source before other plugins have a chance to interfere.

add_action( 'wp_default_scripts', 'move_jquery_into_footer' );

function move_jquery_into_footer( $wp_scripts ) {
    if ( is_admin() ) {
        return;
    }

    $wp_scripts->add_data( 'jquery', 'group', 1 );
    $wp_scripts->add_data( 'jquery-core', 'group', 1 );
    $wp_scripts->add_data( 'jquery-migrate', 'group', 1 );
}

Note: Always wrap these functions in an is_admin() check. Moving jQuery to the footer in the WordPress dashboard will almost certainly break the Block Editor (Gutenberg) and other administrative features.

Handling the "Dependency Trap"

One common frustration developers face is that after adding the code above, jQuery still appears in the <head>. This happens because of the WordPress dependency system.

If any other script (from a plugin or your theme) is enqueued to load in the header and lists jquery as a dependency, WordPress will automatically move jQuery back to the header to ensure that script doesn't break.

To solve this, you must ensure that all scripts depending on jQuery are also set to load in the footer ($in_footer = true).

Using a CDN for jQuery

For even better performance, you might want to load jQuery from a Content Delivery Network (CDN) like Google or Cloudflare. This can be combined with the footer placement:

function use_jquery_from_cdn() {
    if ( is_admin() ) {
        return;
    }

    wp_deregister_script( 'jquery' );
    wp_deregister_script( 'jquery-core' );

    // Register from Google CDN in the footer
    wp_register_script( 'jquery-core', 'https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js', array(), null, true );
    wp_register_script( 'jquery', false, array( 'jquery-core' ), null, true );

    wp_enqueue_script( 'jquery' );
}
add_action( 'wp_enqueue_scripts', 'use_jquery_from_cdn' );

Frequently Asked Questions

This usually happens because a plugin is trying to execute a jQuery command (like $(document).ready()) inside the HTML body before the footer scripts have loaded. You must move that inline script to an external file and enqueue it with jquery as a dependency.

Yes, it can. This is why you should always use the if ( ! is_admin() ) check. The WordPress back-end relies heavily on jQuery being available in the header for various UI elements.

While possible by removing the wp_print_scripts action from wp_head, this is a radical approach that often breaks third-party plugins. It is better to manage scripts individually using the methods described above.

Wrapping Up

Moving jQuery to the footer is a powerful optimization technique, but it requires a careful approach to avoid breaking site functionality. For most users, Method 2 (using add_data) is the safest and cleanest way to achieve this, as it respects the core WordPress script registration system.

By ensuring your scripts load at the bottom of the page, you provide a faster, smoother experience for your users while satisfying the requirements for modern SEO and performance standards.