Conditionally Including scripts whether js or css in xhtml document head...has been a generally tricky affair, especially if you want to enqueue something, based on a shortcode or custom meta field or a widget.

If you know that you need your script for sure,you would just do what the Wordpress Codex suggest by using wp_enqueue_script with following hooks,

* init
* template_redirect
* admin_print_scripts

But sometimes you require a more nuance inclusion of a script or stylesheet. Script inclusions based on shortcodes for example. The issue with shortcodes is that you couldn't really tell if a shortcode has been used, unless you apply strpos() on the content. The reason for this is because, the 'init' + 'template_redirect' + 'admin_print_scripts' hooks fire before the WP_Query object is set, i believe. So it can get tricky for conditionally including scripts for shortcodes and other triggers.

To circumvent this, you can use strpos() with 'the_posts' hook, which gets fired before wp_head. But one of the drawbacks is that its an extra pass at the data.

Discussed at http://beerpla.net/2010/01/13/wordpress-plugin-development-how-to-include-css-and-javascript-conditionally-and-only-when-needed-by-the-posts/

Additionally, i havn't seen examples of this enqueue scripts with this hook being able inject js or css in the head of the document

Scribu suggest, using a flag variable, and sending it to the footer, http://scribu.net/wordpress/optimal-script-loading.html ...but that's not feasible for css style sheets that should be included in the head portion of the document

I've been pondering the best compromise,and wanted to know your thoughts. basically, my hook of choice is wp_head, because i have access to the WP_Query object, in case i need to search for the shortcode, or use a conditional tag, or even widget usage detection. If i know that i need to inject css or js, then i can just recall the wp_print_scripts() function, after figuring out if the page needs my js or css.

Here is a framework for script inclusion on WP 3.1...i've used it successfully for js inclusion. Havn't tried it for CSS yet, but i suspect it will work the same.

add_action("wp_head","add_conditional_scripts", 20);
function add_conditional_scripts() {
   global $posts, $wp_scripts;

    foreach ($posts as $post) { 
        if ( condition_gets_met == true ) : 
            wp_enqueue_script( "scripthandle" , get_home_url().'/js/scriptfilename.js, array('jcycle'), '1.0', true);   // This will add to the $wp_scripts variable

   wp_print_scripts(); // This uses the $wp_script object, will print, out the newly enqueue script

Note that the *condition_gets_met is a stand in for strpos check or a conditional tag, or custom_meta_field check.

Any feed back or criticisms of doing it this way would be great.

3 Answers 3


To circumvent this, you can use strpos() with the_posts hook, which gets fired before wp_head. But one of the drawbacks is that its an extra pass at the data.

You're essentially doing the same inside the callback you're hooking onto wp_head, i don't see the difference.. (please clarify if you think otherwise)..

Whether you hook onto the_posts or wp_head you're still iterating over the same array data, ie. $posts..

I personally don't see the issue with setting a flag inside the the_posts hook and if there's a concern that the hook may get called multiple times, simply check for the flag at the start of the callback and return if it's already set(ensuring only one iteration over that array).

I'm actually using this approach in a plugin i'm waiting to release, and i also realised the method Scribu posted about doesn't really work when you're using CSS, which can't go in the foot. Scribu mentioned possibly injecting CSS into the head with JS, but i personally find that somewhat hacky(my personal opinion).

I have a function hooked onto the_posts which goes like this..

public function on_the_posts( $posts ) {

    if( empty( $posts ) || $this->has_tabs )
        return $posts;

    // trimmed code not relevant to the example

    foreach( $posts as $post ) {
        if( !stripos( $post->post_content, '[end_tabset]' ) )
        $this->has_tabs = true;

    return $posts;

How would this be any different inside a callback on wp_head, i'm still going to need to iterate over $posts aren't i?

Is this a bad implementation of wp_enqueue_script for conditional usage?

No, i don't think so personally.

  • I belive your are right, it seems that I'm still looping over the $posts variable in my situation. I like scribu's method, but i prefer to output my scripts and css at the top of the doucment. Injecting css via js is a little to messy for me. So my method, seems to work for now, just wanted to see if there were potential pitfalls...
    – Wok
    Commented Apr 6, 2011 at 20:47

For such stuff there is wp_enqueue_scripts action that fires early (priority 1) inside wp_head . It is late enough for any conditions you might need to work, but earlier than scripts/styles queue output.

  • I tried out wp_enqueue_scripts instead of wp_head, and i couldn't get my it to output my scripts for some reason.
    – Wok
    Commented Apr 6, 2011 at 20:43
  • @Wok it should not be used for output, it should be used for queuing so that WP outputs your stuff slightly later by itself.
    – Rarst
    Commented Apr 6, 2011 at 20:48
  • I'm not manually outputing, i use wp_enqueue_scripts in my code sample above. I have cases where i only want to conditionally enqueue a script, after having figured out if a shortcode has been used. But it won't output to the html, if i use wp_enqueue_scripts, after the WP_Query object has been set. If you have a code sample of using the wp_enqueue_scripts i could try out that would be great.
    – Wok
    Commented Apr 6, 2011 at 21:32
  • @Wok I meant output as in you call wp_print_scripts() which you shouldn't usually do.
    – Rarst
    Commented Apr 7, 2011 at 9:08

Just to add to the other answers, if a user includes your shortcode in their theme files using the do_shortcode function then your scripts/css will not load

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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