Customize a Category Page With Genesis

Lately I’ve become a big fan of the Genesis framework for WordPress. It simplifies so many things for WordPress development. One thing that I recently needed was to apply specific categories a template page. Basically I had many categories that specific introduction content that I needed on the page. It was necessary to keep all other aspects for each category utilizing the same template. I found it was quite simple to implement once I learned some key features that Genesis has built in. This tutorial assumes that you are already using the Genesis Framework.

Getting Started

First, create a new page. After you have put your desired content on the page, select your template you wish to use. If you haven’t created one yet, simply create a blank PHP file and name it category.php (or a name of your choosing), then select that as your template.

Open the newly created category.php page. Add your template name in the header; this will be the name that will show up in your template selection drop-down. We will get into the setup of the compiled posts on that page a little later.

<?php
/**
 * Template Name: Category
 */

Pass Through Category Parameter

Genesis allows you to pass through parameters to your page from within the GUI to identify certain things about your page. You can pass through any number of parameters that you want by scrolling down the page within the Genesis Settings within the Custom Fields area as shown.

We want to pass through the category for that page, so we need to click “Enter new” (above the “Add Custom Field” button). Under the name field add “category” and under the value field you will need to put your category id. The category id can be found by going to your categories tab under posts. When you edit a category you can see the tag_ID in the address bar; that value [number] is the category ID. There is also a Reveal IDs plugin you may find useful that will show the category id directly within the categories table on the category page. Once that parameter is set click “Add Custom Field”; you are now ready to create the code in your template PHP page.

Coding the Custom Category Template

You will first need to remove the default loop and add your own custom loop:

remove_action( 'genesis_loop', 'genesis_do_loop' ); // Remove default loop
add_action( 'genesis_loop', 'category_page' ); // Set custom page content

Next you will push the content you wish to show in the main area of the page. This is where you will add the title, the content from the page GUI, and the call to compile all posts under the given category.
function category_page() {
    //add_action('genesis_loop', 'genesis_standard_loop');
    echo '<h1>';
    the_title(); // add title
    echo '</h1>';
    the_content(); // pulls content put within WordPress GUI page
    echo '<div class="entry-content">';
    child_grid_loop_helper(); // call to compile the posts
    echo '</div><!-- end .entry-content -->' ;
}

Within the child_grid_loop_helper is where all the magic begins to compile the posts. First, you need to pull the category that was previously passed through the custom field. The genesis_get_custom_field() will get the value of the desired “category” parameter needed for the grid_loop. Once that $category value is stored, you can use it in your loop to pull only that specific category.
function child_grid_loop_helper() {
    global $paged;
    $category = 1; // set default category
    if (function_exists('genesis_grid_loop')) {
        if (function_exists('genesis_get_custom_field')){ // only works with Genesis framework.
            $category = genesis_get_custom_field('category'); // set from custom field when building page
        }
        //set featured grid_args
        ///*
        $grid_args_featured = array(
            'features' => 1,
           // 'feature_image_size' => 'child_full',
            //'feature_image_class' => 'aligncenter post-image',
            'feature_content_limit' => 150,
            //'grid_image_size' => 'child_thumb',
            //'grid_image_class' => 'aligncenter post-image',
            'grid_content_limit' => 0,
            //'more' => '',
            'posts_per_page' => 1,
           'post_type' => 'post',
            'cat' => $category,
            'paged' => $paged
        );
        //*/
        //set non-featured grid_args
        $grid_args_rest = array(
            'features' => 0,
            //'feature_image_size' => 'child_full',
            //'feature_image_class' => 'aligncenter post-image',
            //'feature_content_limit' => 100,
            //'grid_image_size' => 'child_thumb',
            //'grid_image_class' => 'aligncenter post-image',
            'grid_content_limit' => 150,
            //'more' => '',
            'posts_per_page' => 5,
            'post_type' => 'post',
            'cat' => $category,
            'paged' => $paged
        );
      //assuming that features won't go beyond 1 page
      // genesis_grid_loop( $grid_args_rest );
     //  /*
        if ( ($grid_args_featured['paged'] > 1) || ($grid_args_past['paged'] > 1) )
            genesis_grid_loop( $grid_args_rest ); //do not show featured after page 1
        else {
            genesis_grid_loop( $grid_args_featured );
            genesis_grid_loop( $grid_args_rest );
        }
        //*/
    } else {
        genesis_standard_loop();
    }
}

You can adjust the grid_args to fit your needs. Now any page you setup as a category page that uses that template will pull in each of the specified category’s posts. Finally, don’t forget to call genesis(); at the end of your page so that it know to pull all other default content into your page (i.e. header, footer, sidebars, etc.).

Here is the complete code that your template page should have:

<?php
/**
 * Template Name: Category
 */
remove_action( 'genesis_loop', 'genesis_do_loop' ); // Remove default loop
//add_action('genesis_post_content','the_content');  // Adds your custom page code/content before loop
add_action( 'genesis_loop', 'category_page' ); // Do custom loop
function category_page() {
    //add_action('genesis_loop', 'genesis_standard_loop');
    echo '<h1>';
    the_title(); // add title
    echo '</h1>';
    the_content();
    echo '<div class="entry-content">';
    child_grid_loop_helper();
    echo '</div><!-- end .entry-content -->' ;
}
function child_grid_loop_helper() {
    global $paged;
    $category = 1; // set default category
    if (function_exists('genesis_grid_loop')) {
        if (function_exists('genesis_get_custom_field')){
            $category = genesis_get_custom_field('category'); // set from custom field when building page
        }
        //set featured grid_args
        ///*
        $grid_args_featured = array(
            'features' => 1,
           // 'feature_image_size' => 'child_full',
            //'feature_image_class' => 'aligncenter post-image',
            'feature_content_limit' => 150,
            //'grid_image_size' => 'child_thumb',
            //'grid_image_class' => 'aligncenter post-image',
            'grid_content_limit' => 0,
            //'more' => '',
            'posts_per_page' => 1,
           'post_type' => 'post',
            'cat' => $category,
            'paged' => $paged
        );
        //*/
        //set non-featured grid_args
        $grid_args_rest = array(
            'features' => 0,
            //'feature_image_size' => 'child_full',
            //'feature_image_class' => 'aligncenter post-image',
            //'feature_content_limit' => 100,
            //'grid_image_size' => 'child_thumb',
            //'grid_image_class' => 'aligncenter post-image',
            'grid_content_limit' => 150,
            //'more' => '',
            'posts_per_page' => 5,
            'post_type' => 'post',
            'cat' => $category,
            'paged' => $paged
        );
      //assuming that features won't go beyond 1 page
      // genesis_grid_loop( $grid_args_rest );
     //  /*
        if ( ($grid_args_featured['paged'] > 1) || ($grid_args_past['paged'] > 1) )
            genesis_grid_loop( $grid_args_rest ); //do not show featured after page 1
        else {
            genesis_grid_loop( $grid_args_featured );
            genesis_grid_loop( $grid_args_rest );
        }
        //*/
    } else {
        genesis_standard_loop();
    }
}
genesis();

  • Trisha Salas

    Thanks for posting this, just the right mix of Genesis and WordPress code!

    • http://graphnickdesign.com Nicholas Thane Haroldsen

      Thanks for stopping by.

  • colkav

    This was amazingly easy, many thanks! But there’s one problem I’m having – the default sidebar widget area is now appearing at the bottom of the Page, instead of the right / default. I’m using the Sample Child theme. Any idea how I could get it to the right again? Or does this all work best on a full width page?

    • http://graphnickdesign.com Nicholas Thane Haroldsen

      Thank you. Position of that sidebar can vary depending on what layout you specify. You can manipulate the positioning however you wish from within the CSS. I would have to look at your sample to see exactly what is going on.

      • colkav

        Thanks for your reply. Again, this is fantastic, but there’s a few things that I’d love to change. I’ve managed to get a slideshow and a paragraph of text in at the top, then we have the posts, this is where the problem is – the first is full width, i’d like to remove this one entirely, because the same post is then repeated in the grid and, just above the grid is an ‘older posts’ link, which i think would be more appropriate at the bottom. Is this something that could be easily rectified ? Here’s a link to what i mean: http://clienttest.macsupportedlondon.co.uk/every-day/

        • http://graphnickdesign.com Nicholas Thane Haroldsen

          It looks like you need to remove the genesis_do_loop:

          remove_action( ‘genesis_loop’, ‘genesis_do_loop’ );

          This will stop pulling the posts. Here is a link to other snippets by Greg Rickaby that you may find useful:

          http://gregrickaby.com/2011/02/genesis-code-snippets.html

          also check out:

          http://genesistutorials.com/snippets/

          To move the order of the placement of your content you will first need to remove it and then place it within the desired location by using the proper genesis methods. For example, if you want to move the genesis subnav to the footer, you would apply the following code to your functions.php or template.php page:

          remove_action( ‘genesis_after_header’, ‘genesis_do_subnav’ ); // remove subnav first
          add_action( ‘genesis_footer’, ‘genesis_do_subnav’ ); // place subnav where you want it

          Here is a guide I always refer to to reference what genesis elements need manipulated:

          http://genesistutorials.com/visual-hook-guide/

          I hope this helps. Good luck!

          • colkav

            Many thanks for the pointers, Nicholas I’ll get reading!

          • colkav

            I managed to sort out the problem / remove that first full width post, a bit of a fluke as I know next to nothing about php! The line of code that reads:

            $grid_args_featured = array(

            ‘features’ => 1,

            // ‘feature_image_size’ => ‘child_full’,

            //’feature_image_class’ => ‘aligncenter post-image’,

            ‘feature_content_limit’ => 150,

            //’grid_image_size’ => ‘child_thumb’,

            //’grid_image_class’ => ‘aligncenter post-image’,

            ‘grid_content_limit’ => 0,

            //’more’ => ”,

            ‘posts_per_page’ => 1,

            ‘post_type’ => ‘post’,

            ‘cat’ => $cat,

            ‘paged’ => $paged

            );

            I changed the ‘features’ => 1, from 1 to 10, and the full width post disappeared.

            I think I’d be better off learning how to code that this trial and error method!

            Many thanks again!

  • estan

    Good stuff. Just a note… you are missing a ‘>’ ending div of entry-content (echo ‘</div‘) This is why the sidebar was misplaced for colkav.

    • http://graphnickdesign.com Nicholas Thane Haroldsen

      Great catch, Estan. It has now been fixed in the post.

  • adelarogers

    Is it me, or do you call this page you’ve created by three different names during this tutorial?

    Under “Getting Started” first it’s category.php, then categories.php. And by the last code window, the template name is “cat”.

    I’m
    just a little confused. IN YOUR EXAMPLE, what is the name of the
    template? And what is the name of the page that uses the template?

    Thank you.

    • http://graphnickdesign.com Nicholas Thane Haroldsen

      Adela, You make some valid points. Thank you. I have updated the post to be more consistent. I have used the variable $category instead of “$cat” so as to not confuse it with the argument passed through to pull the correct “cat” value. The argument “cat” must remain as I have used it.

  • Tania Kopitar

    First Thank you for such a simple and straight forward tutorial! I’ve bookmarked it cuz i’m sure I will use it when I understand things more.
    I’m trying to figure out if this is the direction I should go in. I’ve tried it and it doesn’t work for what I’m trying to do so I’m guessing i’m confused on what it’s supposed to do.
    I’m trying to have pages such as “this_cities_restaurants” pull all posts created within a category called “this_cities_restaurants”. Each posts being each restaurant.
    I think I can create several templates and specify the categories within the code to pull the posts but that would mean I need to create a ton of templates for each city (then even broken down to restaurant, type, etc.) Which I will do but sounds like a bad idea to have that many files??
    So I’m trying to create a “custom_category_template” that pulls categories, THEN specify the category id within the custom field (name: this cities restaurants, value: cat=id#) on a page with that template.
    But that didn’t work.
    Am I going about this all wrong?
    Any advise? I truly appreciate any help :(

    • http://graphnickdesign.com Nicholas Thane Haroldsen

      Does it pull any posts or just error out? It is difficult to know what is going on without seeing your code. It sounds like you are close, but may be missing a step. What you could try is hard-coding the cat value within your grid loop with a specific category index. This way you can quickly see if your loop is working correctly. For example: ‘cat’ => 3,

      and if that works then you know your grid loop is working. Then, perhaps your $category variable isn’t getting passed through correctly:

      $category = genesis_get_custom_field(‘category’); // set from custom field when building page

      That example screenshot was given where the name equals ‘category’ and the value becomes the index of the category you wish it to have as explained in the post.

      Hope this helps.

      • Tania Kopitar

        Wow, thank you so much for getting back to me so quickly.
        It wasn’t pulling any posts but was pulling the title and text on that page (actually twice). I just changed it adding the cat=>id (37) to see if that worked and it still doesn’t work.
        I’m sure i’m doing something wrong or like you said i’m missing a step.
        Here is my code:

        <?php
        /**
        * Template Name: Custom Category
        */
        remove_action( 'genesis_loop', 'genesis_do_loop' ); // Remove default loop
        //add_action('genesis_post_content','the_content'); // Adds your custom page code/content before loop
        add_action( 'genesis_loop', 'category_page' ); // Do custom loop
        function category_page() {
        //add_action('genesis_loop', 'genesis_standard_loop');
        echo '’;
        the_title(); // add title
        echo ”;
        the_content();
        echo ”;
        child_grid_loop_helper();
        echo ‘‘ ;
        }
        function child_grid_loop_helper() {
        global $paged;
        $category = 1; // set default category
        if (function_exists(‘genesis_grid_loop’)) {
        if (function_exists(‘genesis_get_custom_field’)){
        $category = genesis_get_custom_field(‘category’); // set from custom field when building page
        }
        //set featured grid_args
        ///*
        $grid_args_featured = array(
        ‘features’ => 1,
        // ‘feature_image_size’ => ‘child_full’,
        //’feature_image_class’ => ‘aligncenter post-image’,
        ‘feature_content_limit’ => 150,
        //’grid_image_size’ => ‘child_thumb’,
        //’grid_image_class’ => ‘aligncenter post-image’,
        ‘grid_content_limit’ => 0,
        //’more’ => ”,
        ‘posts_per_page’ => 1,
        ‘post_type’ => ‘post’,
        ‘cat’ => 37,
        ‘paged’ => $paged
        );
        //*/
        //set non-featured grid_args
        $grid_args_rest = array(
        ‘features’ => 0,
        //’feature_image_size’ => ‘child_full’,
        //’feature_image_class’ => ‘aligncenter post-image’,
        //’feature_content_limit’ => 100,
        //’grid_image_size’ => ‘child_thumb’,
        //’grid_image_class’ => ‘aligncenter post-image’,
        ‘grid_content_limit’ => 150,
        //’more’ => ”,
        ‘posts_per_page’ => 5,
        ‘post_type’ => ‘post’,
        ‘cat’ => 37,
        ‘paged’ => $paged
        );
        //assuming that features won’t go beyond 1 page
        // genesis_grid_loop( $grid_args_rest );
        // /*
        if ( ($grid_args_featured['paged'] > 1) || ($grid_args_past['paged'] > 1) )
        genesis_grid_loop( $grid_args_rest ); //do not show featured after page 1
        else {
        genesis_grid_loop( $grid_args_featured );
        genesis_grid_loop( $grid_args_rest );
        }
        //*/
        } else {
        genesis_standard_loop();
        }
        }
        genesis();

        • http://graphnickdesign.com Nicholas Thane Haroldsen

          Tania,

          It appears that you did not remove the default genesis_do_loop and replace it with your own (unless you simply didn’t show that portion of your code). If you don’t remove it, then it will default to use the built in loop. Your grid_loop appears ok, you just need to put the first part in the genesis_loop as such:

          remove_action( 'genesis_loop', 'genesis_do_loop' ); // Remove default loop
          add_action( 'genesis_loop', 'category_page' ); // Do custom loop

          function category_page{
          the_title(); // add title
          the_content();
          echo '';
          child_grid_loop_helper();
          echo '' ;
          }

          Hope this helps.

          • Tania Kopitar

            I’m so sorry, it keeps cutting off my characters when I paste in. I think this is everything now. I basically copied your exact code so I referenced you remove_action and add_action.

            <?php
            /**
            * Template Name: Custom Category
            */
            remove_action( 'genesis_loop', 'genesis_do_loop' ); // Remove default loop
            //add_action('genesis_post_content','the_content'); // Adds your custom page code/content before loop
            add_action( 'genesis_loop', 'category_page' ); // Do custom loop
            function category_page() {
            //add_action('genesis_loop', 'genesis_standard_loop');
            echo '’;
            the_title(); // add title
            echo ”;
            the_content();
            echo ”;
            child_grid_loop_helper();
            echo ‘‘ ;
            }

            function child_grid_loop_helper() {
            global $paged;
            $category = 1; // set default category
            if (function_exists(‘genesis_grid_loop’)) {
            if (function_exists(‘genesis_get_custom_field’)){
            $category = genesis_get_custom_field(‘category’); // set from custom field when building page
            }
            //set featured grid_args
            ///*
            $grid_args_featured = array(
            ‘features’ => 1,
            // ‘feature_image_size’ => ‘child_full’,
            //’feature_image_class’ => ‘aligncenter post-image’,
            ‘feature_content_limit’ => 150,
            //’grid_image_size’ => ‘child_thumb’,
            //’grid_image_class’ => ‘aligncenter post-image’,
            ‘grid_content_limit’ => 0,
            //’more’ => ”,
            ‘posts_per_page’ => 1,
            ‘post_type’ => ‘post’,
            ‘cat’ => 37,
            ‘paged’ => $paged
            );
            //*/
            //set non-featured grid_args
            $grid_args_rest = array(
            ‘features’ => 0,
            //’feature_image_size’ => ‘child_full’,
            //’feature_image_class’ => ‘aligncenter post-image’,
            //’feature_content_limit’ => 100,
            //’grid_image_size’ => ‘child_thumb’,
            //’grid_image_class’ => ‘aligncenter post-image’,
            ‘grid_content_limit’ => 150,
            //’more’ => ”,
            ‘posts_per_page’ => 5,
            ‘post_type’ => ‘post’,
            ‘cat’ => 37,
            ‘paged’ => $paged
            );
            //assuming that features won’t go beyond 1 page
            // genesis_grid_loop( $grid_args_rest );
            // /*
            if ( ($grid_args_featured['paged'] > 1) || ($grid_args_past['paged'] > 1) )
            genesis_grid_loop( $grid_args_rest ); //do not show featured after page 1
            else {
            genesis_grid_loop( $grid_args_featured );
            genesis_grid_loop( $grid_args_rest );
            }
            //*/
            } else {
            genesis_standard_loop();
            }
            }
            genesis();

          • Tania Kopitar

            Did it again. keeps cutting off the top of my code after I hit post. Maybe it’s the start php tag. Here is just the top of the code before “function” starts:

            remove_action( ‘genesis_loop’, ‘genesis_do_loop’ ); // Remove default loop
            //add_action(‘genesis_post_content’,'the_content’); // Adds your custom page code/content before loop
            add_action( ‘genesis_loop’, ‘category_page’ ); // Do custom loop
            function category_page() {
            //add_action(‘genesis_loop’, ‘genesis_standard_loop’);
            echo ”;
            the_title(); // add title
            echo ”;
            the_content();
            echo ”;
            child_grid_loop_helper();
            echo ‘‘ ;
            }

          • http://graphnickdesign.com Nicholas Thane Haroldsen

            Yes. The php tag would kill it. Anyway, in looking at your code, it seems ok. How you implement it may be the problem. If you are getting the title and text twice it seems that you aren’t pulling that template as those first two methods should remove it. I suggest simplifying your code to make sure your template is getting used. Print out something on the page within the template to see that it is the correct template. At this point it is troubleshooting to pin point what is causing your issues. Perhaps remove the grid_loop to see if that is the issue itself, (but looking at it directly appears ok as long as 37 is the correct number). Sorry I can’t be much more help.

          • Tania Kopitar

            I know it’s been a while :( I still never got this to work and I followed your example. I wish I could see the problem :( just running in circles trying different things. Anything else you can think of that i’m missing?

            I’m creating a custom field within a page: Name: category – Value: 37 (the ID of the category I want to pull)

            I created a template and attached it to the page I want to pull this category.

            Is this line correct ‘cat’ => $category

            I’m sorry i’m just lost. Maybe it’s to do with my theme? I have no clue at this point.

          • http://graphnickdesign.com Nicholas Thane Haroldsen

            Sorry for your frustrations. Did you ever get it to work if you hard code the value of ‘cat’ to 37? If you set ‘cat’ to 0 it should pull all posts. If that is not working then there is some other syntax missing in your code. It could be some of your logic or something. Is it breaking altogether, or just not pulling the correct category posts?

          • Tania Kopitar

            Thank you so much for your help and insight! I will try again and keep you posted. I’m sure I’m missing something.

  • Chris Mower

    Two quick things:

    1) I’m unsure of why you’re using the custom field on a page when you could name your template file ‘category-id.php’ or ‘category-slug.php’ and WP would automatically detect the category archive page to use the new loop on. (See http://codex.wordpress.org/Category_Templates for more details).

    2) After implementing this, it doesn’t appear that my posts are actually displaying in a grid… they’re still just listed one on top of the other. Any ideas?

    • http://graphnickdesign.com Nicholas Thane Haroldsen

      Yes, creating multiple templates would be an option, but that doesnt make much sense if you only have one parameter different that could get passed through to pull a particular category. Plus, the url is simpler as no params are passed through to the page. My example does use categiry as an example, but has the potential to pass whatever is desired to a page.
      As far as your grid issue goes, I’m uncertain what is going on there. I would have to see your code. Could it be an issue in the loop itself, or in the styling?