WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I couldn't add defer tag in plugin javascripts. Google developer pagespeed test suggests me to add defer tag in contact form 7 javascripts.

This is how contact form 7 includes javascript in header.

add_action( 'wp_enqueue_scripts', 'wpcf7_enqueue_scripts' );

function wpcf7_enqueue_scripts() {
    // jquery.form.js originally bundled with WordPress is out of date and deprecated
    // so we need to deregister it and re-register the latest one
    wp_deregister_script( 'jquery-form' );
    wp_register_script( 'jquery-form', wpcf7_plugin_url( 'jquery.form.js' ),
        array( 'jquery' ), '2.52', true );

    $in_footer = true;
    if ( 'header' === WPCF7_LOAD_JS )
        $in_footer = false;

    wp_enqueue_script( 'contact-form-7', wpcf7_plugin_url( 'scripts.js' ),
        array( 'jquery', 'jquery-form' ), WPCF7_VERSION, $in_footer );

    do_action( 'wpcf7_enqueue_scripts' );

Now how to add defer="defer" tag in the above code?

share|improve this question
Relevant ticket: core.trac.wordpress.org/ticket/12009 – scribu Jan 9 '12 at 17:15
Nice Question @Viruthagiri. – Ramkumar Feb 2 '12 at 13:30
up vote 36 down vote accepted

As of WordPress 4.1 there is a filter: script_loader_tag. You can use it to find the correct script:

add_filter( 'script_loader_tag', function ( $tag, $handle ) {

    if ( 'contact-form-7' !== $handle )
        return $tag;

    return str_replace( ' src', ' defer="defer" src', $tag );
}, 10, 2 );

Old answer

There is no dedicated filter available … at least I cannot see one. But …

  • wp_print_scripts() calls WP_Scripts->do_items()
  • which calls WP_Scripts->do_item()
  • which uses esc_url()
  • which does offer a filter: 'clean_url'.

And here we go:

function add_defer_to_cf7( $url )
    if ( FALSE === strpos( $url, 'contact-form-7' )
      or FALSE === strpos( $url, '.js' )
    { // not our file
        return $url;
    // Must be a ', not "!
    return "$url' defer='defer";
add_filter( 'clean_url', 'add_defer_to_cf7', 11, 1 );

Caveat: not tested, just an idea. :)


I have written and tested a plugin with this code. See https://gist.github.com/1584783

share|improve this answer
This is perfect also to use with data-main in requirejs – Nicola Peluchetti Jun 6 '12 at 15:07
That's a nice hack, and so simple. I reckon it'd be good also for adding charset='utf-8' when necessary! – webaware Jan 16 '13 at 8:16
Great, but why: Must be a ', not "! ? – henrywright Feb 1 '14 at 2:09
@henrywright WordPress add ' on both side of the returned string, an " would result in invalid HTML. – toscho Feb 1 '14 at 10:54
Probably a good idea in case someone wants to turn this to work with other scripts will be to make sure to validate to use it only on the font-end maybe using if( ! is_admin() ){} popular plugins like ACF might give you a headache. – crissoca Apr 28 '15 at 2:09

protected by Community Nov 24 '13 at 2:33

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

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