Conditional Loop Actions

Some time ago I wrote an article on making content conditional. In this I explained the basic of adding code via actions, either manually or through the Genesis Simple Hooks plugin, that will only appear in specific parts of the site. If you are looking for the basics on getting something to only show on your home page, category archives, single post pages …. then go check out that article.

There is a lot to conditional code that could be covered, but one question I see on a regular basis is “how to I get something to show up after X posts in the loop?”

This seems rather monumental, but with Genesis it is actually pretty simple. Genesis has a built in global variable that tells you how many posts the loop has processed. If you look in the genesis/lib/structure/loops.php file you will see this

	global $loop_counter;

	$loop_counter = 0;

	if ( have_posts() ) : while ( have_posts() ) : the_post();

//bunch of code 

	do_action( 'genesis_after_post' );
	$loop_counter++;

	endwhile; /** end of one post **/

Basically, this means the $loop_counter variable gets set to 0 before the loop starts, then after it runs all the stuff for a single post in the loop, it adds 1 to that value.

I am explaining this because it is important to understand at which point the post is counted. It is after everything has been done. So if you want to run something on a specific post in the loop, you need to subtract 1.

So here are a few examples.

Example 1: Add Adsense Code on First Two Posts only

This one is huge. Adsense will only work three times on a given page, so if you have an adsense ad in your sidebar and want to put an add on genesis_after_post_content, you need to limit the number of times ads are shown in the loop. This code would go in your functions.php file

add_action( 'genesis_after_post_content', 'child_adsense_after_post_content' );
/** Put adsense code into the loop but only on the first two posts */
function child_adsense_after_post_content() {
    global $loop_counter; //important, this makes the variable available within this function.

    if( 1 >= $loop_counter ) { ?>

    put your adesense code here, this is in html mode so no need for the echo function.

    <?php }

}

Notice, I am using 1 >= $loop_counter. After the second post is processed, the $loop_counter variable will be “2″ so that will be greater than and not equal to “1″ and the server will ignore the code inside the conditional statement.

Example 2: Adding An Image After the Third Post

In the previous example it used the greater than symbol so all posts before the count was too large received the code. Also, I demonstrated how to make the code work with a manual hook. In this example I’m going to show how to work with a specific post (the third) and how to use the Genesis Simple Hooks plugin. This code would go in the genesis_after_post field of the Genesis Simple Hooks plugin.

<?php //important, you have to invoke php with <?php before it will work in the hook fields

global $loop_counter; //important, this makes the variable available within this hook.

if( 2 == $loop_counter ) { ?>

    <img src="http://example.com/path/to/image.png" alt="this is a divider image shown after the third post" />

<?php } ?>

Don’t forget, you must subtract 1 from the post number, since I want this to show after the third post I check to make sure only 2 posts were processed in the loop so far. Also, don’t forget to enable PHP on the hook.

I hope that these two examples will help you work with the $loop_counter variable. You can build some pretty advanced tests to see where you are in the loop using basic math and PHP functions. Have fun with it.

Comments

  1. Another approach is to use WordPress’ built-in loop counter.

    Inside your child_adsense_after_post_content() function, change global $loop_counter to global $wp_query, and change the if statement to use $wp_query->current_post.

    The benefit to this method is it works with any loops – the main loop, and any custom loops you do.

  2. Hermann says:

    Hi,
    sorry for that silly question, I’m not a programmer but what you describe is exactly what I’m looking for. I like to have banner ads after the x-post on the homepage (same as you can see at TechCrunch)

    What I tried is:

    /** Register ad-widget after third post on home page */
    genesis_register_sidebar( array(
    ‘id’ => ‘after-third-post-ad’,
    ‘name’ => __( ‘After Third Post Ad’, ‘eleven40′ ),
    ‘description’ => __( ‘This is a widget area that can be placed after the third post on the Homepage’, ‘eleven40′ ),
    ) );

    add_action( ‘genesis_after_post_content’, ‘child_ad_after_third_post_content’ );
    function child_ad_after_third_post_content() {
    global $loop_counter; //important, this makes the variable available within this function.

    if( 2 == $loop_counter )
    return;
    genesis_widget_area( ‘after-third-post-ad’
    );

    }

    But of course things go wrong after ” genesis_widget_area( ‘after-third-post-ad’
    ); ” Can you tell me whats missing to output the widget content after the third post on the homepage? Thanks very much for your help.
    Best, Hermann

    • Hermann says:

      Stupid me – I should have read more about it. So I’m sorry Nick either you can delete the post or leave it for someone stumble upon the same problem.

      Here’s the solution, hopefully everything is o.k. For me it works fine now.

      /** Register ad-widget after third post on home page */
      genesis_register_sidebar( array(
      ‘id’ => ‘after-third-post-ad’,
      ‘name’ => __( ‘After Third Post Ad’, ‘eleven40′ ),
      ‘description’ => __( ‘This is a widget area that can be placed after the third post on the Homepage’, ‘eleven40′ ),
      ) );

      add_action( ‘genesis_after_post’, ‘child_ad_after_third_post_content’ );
      function child_ad_after_third_post_content() {
      global $loop_counter; //important, this makes the variable available within this function.

      if( 2 == $loop_counter ) {
      echo ”;
      dynamic_sidebar( ‘after-third-post-ad’ );
      echo ”;
      }

      }

  3. Hello Nick very nice work my friend

  4. Nick,

    Any advice on how to handle this on a non-Genesis site? I’m working with a stand alone theme and would like to achieve the same effect…

  5. vajrasar says:

    Hi Nick,

    Great article. I tried to implement the same to print birthday msgs between posts by inserting following code in function.php ->

    genesis_register_sidebar( array(
    ‘id’ => ‘birthday-between-post’,
    ‘name’ => __( ‘Birthday Between Posts’, ‘news’ ),
    ‘description’ => __( ‘To display Birthday Custom Posts Type Posts between all Posts List.’, ‘news’ ),
    ) );

    add_action (‘genesis_after_post_content’, ‘my_custom_loop_func’);

    function my_custom_loop_func() {
    global $loop_counter;
    if( 2 == $loop_counter ) {
    dynamic_sidebar( ‘birthday-between-post’ );
    echo ‘hi from function file’;
    }
    }

    Now the problem is , I checked that the msg “hi from function file’ gets printed after the 3rd post but when I try to put anything (text widget) in the ‘BirthDay between post’ sidebar, it echoes nothing.

    Actually I made a custom post type for bday msgs and plan to execute 3-posts-loop via enabling the php in widget and placing the code in text widget, but for initial testing I did the above thing.

    • If you are just using a text widget why not just put your code into the function instead of requiring a widget area and loading a text widget?

  6. Vajrasar Goswami says:

    Nick, I sorted out the problem. It was because of the wrong ‘type’ of single quotes used in dynamic_sidebar.

    Thanks for this writeup, once again! :)