Skip to main content

I had a request this morning on how to create a short code in WordPress that would list out all of the post titles and dates separated by month.  Similar to the blog layout, but only titles and again separated by month placeholders.

Here is a snippet of code to do just that.

Navigate to your functions.php in your theme folder /wp-content/themese/themeName and add this to the bottom:

function get_monthly_posts_custom() {
$time_start = microtime(true);

/** Set up a date interval object for 6 monts ago (you can change as required) */
$interval = new DateInterval('P6M');
$interval->invert = 1;

/** Grab the date as it was 6 months ago */
$date = new DateTime(date('Y-m-d'));

/** Query the database for all posts newer than the the given date interval */
$args = array(
    'nopaging'          => true,
    'posts_per_page'    => -1,
    'post_type'         => 'post',
    'post_status'       => 'publish',
    'order_by'          => 'date',
    'date_query'        => array(
        'after' => $date->format('Y-m-d')
$month_query = new WP_Query($args);

/** Check to ensure that there are articles for this month... */
if($month_query->have_posts()) :

    $month_titles = array();
    $close_ul = false;

    //echo '<ul style="padding-left: 250px;" id="monthly-posts">';

    /** Set the attributes for displaying the title as an attribute */
    $title_attribute_args = array(
        'before'    => 'Visit article \'',
        'after'     => '\' ',
        'echo'      => false

    /** Loop through each post for this month... */
    while($month_query->have_posts()) : $month_query->the_post();

        /** Check the month/year of the current post */
        $month_title = date('F Y', strtotime(get_the_date('Y-m-d H:i:s')));

        /** Maybe output a human friendly date, if it's not already been output */
        if(!in_array($month_title, $month_titles)) :

            if($close_ul) echo '</ul>';                                                             // Check if the unordered list of posts should be closed (it shouldn't for the first '$monthe_title')
            echo '<h1 style="padding-left: 250px;" id="monthly-title">' . $month_title . '</h1>';   // Output the '$month_title'
            echo '<ul style="padding-left: 250px;" id="monthly-posts">';                            // Open an unordered lists for the posts that are to come
            $month_titles[] = $month_title;                                                         // Add this `$month_title' to the array of `$month_titles` so that it is not repeated
            $close_ul = true;                                                                       // Indicate that the unordered list should be closed at the next oppurtunity


        /** Output each article for this month */
            '<li id="monthly-post-%1$s">%2$s <a href="%3$s" title="%4$s">%3$s</a></li>',
            get_the_ID(),                               /** %1$s - The ID of the post */
            get_the_title(),                            /** %2$s - The article title */
            get_permalink(get_the_ID()),                /** %3$s - The article link */
            the_title_attribute($title_attribute_args)  /** %4$s - The title for use as an attribute */


    if($close_ul) echo '</ul>'; // Close the last unordered list of posts (if there are any shown)


Save and upload.  Then in any posts or pages just use this short code to output:


Leave a Reply