I'd like to load some javascript files in my footer. I tried to accomplish it in functions.php like so:

function my_init() {
        // LOAD JQUERY
        wp_register_script('jquery', '//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js',$deps = array(),$in_footer = true);

        // LOAD STUTS
        wp_register_script('stuts',get_bloginfo('template_url') . '/js/spss-tutorials-custom-functions.js',$deps = array('jquery'),$in_footer = true);

        wp_register_script('mathjax','//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML',$deps = array(),$in_footer = true);
        $url = explode('?', 'http://'.$_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
        $ID = url_to_postid($url[0]);
        $mathjax = get_post_meta($ID,'mathjax',true);
            if($mathjax == 'y'){

add_action('init', 'my_init');

However, all scripts are still loading in my header.

I tried the solutions here, here and here but they didn't resolve the problem.

I do have

<?php wp_footer(); ?>

in my footer.php file. Any suggestions?

  • Possibly there is some jquery dependent plugin (or an admin component of WP itself) trying to load in the head. That will force jquery to load earlier than specified and the other scripts in the same action with it. – cjbj May 30 '16 at 10:53

Choose the right place in (rendering-)time

First off, you are hooking at init, while you want to add your callback on wp_enqueue_script.


add_action( 'wp_enqueue_script', function() {
    wp_deregister_script( 'jquery' );
    // Rest of logic
} );

Staying up to date with core

Also, you might want to use the correct version that core uses. I know, constantly looking at this is cumbersome and no one wants to monitor assets/ dependencies. Luckily you can use the information that is already present in core. The same goes for the needed dependencies for an asset has. Example:

add_action( 'wp_enqueue_script', function() {

    $version      = $GLOBALS['wp_scripts']->registered['jquery']->ver;
    $protocol     = 'sprintf( 'http%s://', is_ssl() ? 's' : '' );
    $dependencies = $GLOBALS['wp_scripts']->registered['jquery']->deps;

} );

Move registered scripts to the footer

There's also an easier way to move an already registered script to the footer: Edit it's information in the script registry directly. Consider the following (MU)plugin:

/* Plugin Name: Moves registered scripts to the footer */
add_action( 'wp_enqueue_scripts', function() {
    foreach ( apply_filters( 'wp_scripts.footer', [] as $script )
        $GLOBALS['wp_scripts']->add_data( $script, 'group', 1 );
}, PHP_INT_MAX -1 );

Now you can just attach an array to above filter and move scripts to the footer:

add_filter( 'wp_scripts.footer', function( Array $scripts ) {
    return [ 
        # Other scripts
} );

Additional notes, I could not stay back to write down…

There are also multiple very strange (but working) things to note about your code:

  • You are assigning variables when you do not need them. Especially in a function call, it's not necessary to use myFunction( $var = 'foo' ). Just add the value and that's it.
  • When you use //url.tld/script.js, then the client will be able to decide the route to go: HTTPS vs HTTP. This might be ok for distributed code (even then, it's better to fetch the protocol up front and use it), but if you know the way that you are serving your site, then please just use it. It is faster and if there's HTTPS available, then for gods sake: Use it!
  • Do not deregister WP core scripts. Use them. They are cached for logged in people already in their clients/ browsers. For all others, you will deliver a single, compatible version.
  • Relying on $_SERVER is only ok if your script will always only be executed via a client. On the command line, using data from this array is not reliable. In some cases it changes, in other's it's not set. WP has some fallbacks that you can use instead.
  • thanks a lot but this is too high level for me. I think I'll async my scripts instead of moving them, that should speed things up too. I hope. – RubenGeert May 30 '16 at 16:43
  • @RubenGeert np. When you read through the complete answer, you will find that it is not really anything over your head. In addition: The code is close to copypaste-ready. – kaiser May 30 '16 at 17:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.