How to move WordPress core JavaScript to the footer

How to make your SearchEngine happy
]1 How to make your SearchEngine happy

Every time I register a script and add jquery as dependency, it gets added to the <head> in the finally rendered HTML page. As this blocks page rendering time – the included script might modify the DOM – I want to add it to the end of the page to prevent this behavior. This will make Google happy and positively influence my page rank as page loading time should decrease.

class RegisterScripts
    public function __construct()
        add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) );
    public function scripts()
            array( 'jquery' ),
            filemtime( plugin_dir_path( __FILE__ ).'assets/scripts/vendor/requirejs/require.js' ),

So what does core do then? Actually it’s quite easy. The WP_Scripts class is an extension for the class WP_Dependencies. And when you make a call to wp_enqueue/register_script(), it just uses the add_data() method from there.

$wp_scripts->add( $handle, $src, $deps, $ver );
if ( $in_footer )
    $wp_scripts->add_data( $handle, 'group', 1 );

As you can see, it adds “data” with the script name as a first argument and sets some group to 1. This just tells the class where to put the the script data in the global array. Then, when looping through the array, WP just checks the current hook and prints either the default part or, in case of the end of the page, the wp_footer hook, all scripts that have a group equal and/or higher than 1. That’s it.

Now to the part where we quickly fix that:

// Move jQuery to the footer
global $wp_scripts;
$wp_scripts->add_data( 'jquery', 'group', 1 );

Of course you can do that with every other script as well. A (maybe incomplete) list of default scripts can be found in Codex. If you want to have the real list, you’ll have to dump $GLOBALS['wp_scripts'] and look through the array. In case you want to wrap all this up in a standalone plugin, you of course can do. I recommend using a mu-plugin.

/* Plugin Name: jQuery to the footer! */
add_action( 'wp_enqueue_scripts', 'wcmScriptToFooter', 9999 );
function wcmScriptToFooter()
    global $wp_scripts;
    $wp_scripts->add_data( 'jquery', 'group', 1 );

Keep in mind that there might be plugin or theme scripts doing things wrong(!) and this solution might break. Normally this would happen if the custom scripts are loaded into the header or if the whole WP Dependency API is bypassed and the script hard coded. Conclusion: Test before you add that mini plugin to an already live page. If it doesn’t work, inspect where and how the script loading works. Then fix that and try to load those blocking scripts to the footer as well. Google will love you.

If you want to go further, here’s a related recommendation. If you want to create JavaScript classes, take a look at JavaScript++.


  1. Ohhh, yes “solution” will break for sure :) Think of a slider which does things correctly and only load stuff including jQuery snippet when in use, probably via short code. This can very well be mid-page and then boom. Was the big trick of WP 3.3 or something, see Scribu site… But with some determination it is possible. Can then force jQuery in head for this or that conditional or may be fiddle with what ever it is that require jQuery to be present at all times. For everyone? nope. So for this and other reasons I will bet someone will soon comment and warn against your methods and way of using brain, heh. WP world is generally not tuned in to basic and known web performance tricks. Is weak spot. You see it all over. Is it good and safe for masses? yes or no? That is what counts. So all can back up their opinions. You know what you are doing so not part of a big crowd.

    Good devs. in control of site and maintenance can do this – if they do not they suck :) As a general tip it cant work. Just today I was checking local WP forum and some guy could not understand why his “Woo shop” did not work in IE. Notice no speak of which version of IE, already a hint of level. Well 3-4 people replied that it was fine (more hints!). No it is not because the person have applied this plugin from .org site Is made by a non-dev who have found a way to pump up plugin production. Just load crap and talk it up. .org love that type of stuff. So almost premium… I would ban his ass. Only causing wasteful issues for other devs. but nm. It only does one thing. Deregister jQuery and loads jQuery 2.0.3 from his plugin folder (sigh), which means IE8 and lower cant use jQuery. Is jQuery ABC since April this year when jQuery 2.0 was released. This is bad but shows level of WP vs. script loading :)

    Side note to this is I read .org site now review plugins. I do not know that much about theme review team but will bet 2 premium sliders with premium effects that their review process blow super hard. May be like TF where “back catalogue” is to be protected or what ever. Even I could review stuff like idiotic updater plugin, take 5 seconds. Potentially save other devs hours. Wasting peoples time is worst offence.

    So your idea of core manipulation is extravagant but also top notch under right conditions. Except I would use jQuery 2.0.x – is 10kb smaller ;) Also test for jquery migration script need. Core loads that of course. If all is fine without, you can make it fine by not using old crap, get rid of that thing. Is of course bundled with wonder CSS/JS tool but still. 10kb is a whole 4kb or what ever when Gzipped but 4kb is 4kb. Optimizing does not leave out small gains. All adds up. Again how to “recommend” not using migration script? WHY waste resources loading a file never used IF you use updated jQuery code??? No one can because all is chaos on most sites, heh. Sad but true. This must be manually checked and set up.

    Somewhat relevant, check MinQueue 100% manual tool for making JS/CSS bundles yet super friendly. Has pop up window showing handles and placement of load (head/footer) – color coded of course… Superb as you can only use it if you somewhat know what you are doing = less W3TC or other “auto” incidents. Also encourage conditional thinking which is just what performance people suggest. Big fat 250kb file with bundled stuff is not the best. Not for mobile units at least.

    Btw. webaware suggestion in other comment of “Use Google Libraries” plugin is good but it kinda sucks for jQuery UI stuff. Google does not have all the sub modules for individual download so what happens is the whole monster file is called when just 1 of them is required. For that it blows but of course not fair to blame dev. for that. Is nasty thought to load such a big file for potentially so little need. Plugin is one of the few safe to recommend in this area. Also Google CDN is not always the fastest. For me here in Denmark Cloudfront CDN from London is faster than Google but of course this differ. May be also over time, must redo tests over and over. Real optimizer maniac would… Some have tested this. Google is slowish in some areas, faster in others. If majority of visitors to X site come from Y country, what is optimal for Y is what goes.

    1. Thanks for your comment.
      Yes, this might break. That’s why I added the final note about cases where it won’t work. Or where you will have to walk in and fix things. At least it’s a recommendation for developers. And as a developer your job anyway goes beyond “click together some plugins”.

      1. Well it is more like it will typically break. I see inline scripts a lot. Because I always put jQuery at footer I guess. There are also variants like something is put in “wp_footer”. Ok, so that is before/after jQuery? Is order of code kept? Whats that localize stuff now? Did Minqueue handle that properly. No? Try to update it! Oh, now it works :) Can go round and round and then people run out of fuel fast. Not always straightforward if you take on ALL scripts on messy site.

        Obviously most plugin devs. do not expect people to fiddle – also why you rarely see this mentioned in documentation. That is real issue, lack of focus. Decisions not options and all that. Which can be excuse for being lazy! You are on your own that is for sure. Also why many WP productions do not care for updating jQuery scripts. Is all connected, may be conspiracy :)

        Fresh example: jigoshops latest update Then this Can you get in your head how what must be professional devs. can ignore updates for so long that their entire plugin suffer? Then call embarrassing fix a “tweak”. Lots of improvements though. They have upgraded entire handling of jQuery/CSS but it was newbie bad before, like for years. Not how to slap Woo. Is just typical and hard to manipulate.

        But if site dev say “well then just let it be, let all incoming scripts and CSS files sort them self out, do not know half of them anyway” then site is not optimized. Also not if stuff is bundled via W3TC or what ever. Plugins and may be custom code should also be evaluated on scripts. Are not all the same. Different in size, in cpu usage, in being 2 years old or brand new. Not to mention being maintained for not. Fxxx that I have my W3TC and buttons! Yeah good luck, heh.

      2. Btw. is the site with only jQuery 2.0.3 issue. Look at source code. There you have it all, almost seems like ALL, lol. Putting jQuery in footer is only beginning of long long journey :) This is typical WP site with shop etc. and why you see so much talk of jQuery issues on for example .org site. Is chaotic and delicate.

  2. I like it, very nice trick. Unfortunately it’s only of use on sites where you have control of the theme and plugins and can be sure that none of them use inline JavaScript with jQuery. In practice, that means most free and commercial themes and many plugins will break.

    My preference is to try to leverage off the heavily used Google CDN copy of jQuery, which gives sites a fair chance to have already loaded and cached jQuery. Sure, it won’t please Google’s pagespeed tools, but better real page speed is more important. I highly recommend leaving the task to a solid plugin, Use Google Libraries, which will match the version in WordPress with the one it loads from the CDN.

    Inline script can be a performance booster itself. Some script tasks are very small, and the trade off between loading from an external script vs inlining weighs in favour of inlining because it saves an extra resource request. With gzip compression on the page, small scripts don’t impact much on the page download but an addition resource request is another round trip to the server, best avoided if possible.

    So nice trick, but probably not useful for real world websites.

    1. Thanks for your comment.

      About inline scripts: That’s (sadly) not entirely true. Every browser pauses rendering until a script is loaded. The reason is simple: Scripts might change the DOM.

      Surely small scripts don’t add much to the loading time and you can outsource them using CDN versions, but concatenating them and loading them at the end of the page is what really boosts performance.

Comments are closed.