Echo one category as title when post has multiple categories?

In order for this to work, you will need to know from where the single post was refered from and if the referrer is a valid one. Secondly, we need to adjust pagination between single posts in order for us to pass our referrer between single posts.

The problem with referrers is, they are set and controlled by user side. Referrers can be disabled or blocked (like users accessing a site behind a proxy). Just for interest sake, here is very interesting answer to the question In what cases will http referrer be empty taken from this post on SO

It will/may be empty when the enduser

  • entered the site URL in browser address bar itself.
  • visited the site by a browser-maintained bookmark.
  • visited the site as first page in the window/tab.
  • switched from a https URL to a http URL.
  • switched from a https URL to a different https URL.
  • has security software installed (antivirus/firewall/etc) which strips the referrer from all requests.
  • is behind a proxy which strips the referrer from all requests.
  • visited the site programmatically (like, curl) without setting the referrer header (searchbots!).

You would want to read the other answers there as well for extra insight

I sat with similar issue and was looking for a more reliable way to set and pass referrers, and this led to this question and a wonderful answer by @gmazzap

So your solution would be based on something similar. We will be adding a special parameter to our URL which will serve as referrer (I have made the assumption that your posts are from the build in post type post and taxonomy category)

  • Identify our category pages and add a referrer to the post links via the post_link filter. This referrer will hold the category id. You can use the category name, but this can become quite messy in your URL. The choice is all up you.

    add_filter('post_link', function( $permalink ) // Change to post_type_link for custom post type posts
    {
        if (      is_category() // Change to is_tax() for custom taxonomy pages
             && ( $cat = get_queried_object() ) 
        ) {
            $permalink = esc_url( add_query_arg( array( 'ref' => $cat->term_id ), $permalink ) );
        }
        return $permalink;
    });
    

    This will give you a URL like the following on your single post page if you click on a post link on the category page

    http://example.com/wordpress/post-name?ref=1
    
  • We must have a way to read and use that info from the URL in order to make it useful. For this, we must add a the query arg ref so WordPress can read it

    add_filter( 'query_vars', function ( $vars ) 
    {
        $vars[] = 'ref';
        return $vars;
    });
    
  • All you need to do now, is to check if the single post was a referred post, get the value from the URL and use that info to display the correct category name (NOTE: This piece of code goes into your single.php)

    $referrer = filter_input( INPUT_GET, 'ref', FILTER_VALIDATE_INT ); // This validate and checks if our referrer "ref" is set
    if ( $referrer ) {
        $category = get_category( $referrer );
        echo '<h2>' . $category->name . '</h2>';
    }
    

The above is just a rough draft of what you can do to accomplish this, it just gives you a foundation to work from. You can tweak and modify it as needed.

On your single pages, you will also need to get your referrer and pass that to your next and previous post links in order to maintain this feature between posts. I have written an answer for pagination based on this, it is quite bulky though and can use some clean up. There are some parts that I have handled here now, and there are also parts that you will most probably never need which you can just remove. You can work through it and modify and adjust it as needed.

I am busy rewritting the complete pagination function ( using better and cleaner php functionality ) with some extra features, the classes are done, it is just the final pieces putting everything into functional functions that is giving me a nightmare, and to be honest, I haven’t got back to working on the project for quite some time now as I really don’t have much time at night. When it will be completed is still a mystery. But the idea and code from what I have given in that specific answer should do the trick for you. You can check out my answer and referrer pagination function here

EDIT

I have quickly written a small plugin which covers the referrer and new pagination links to carry the referrer across multiple single posts. This pagination links will also page between single posts from the referrer

What this means is, if a single post was clicked from category B, and this post has three categories, category A, category B and category C, the next and previous adjacent post will be from category B. If you go to either post, the adjacent post from that clicked single post will also be from category B etc

I have commented the code so you should be able to follow it better and also adjust and modify it as needed. Just copy and paste this code in a plugin file and activate it. Alternatively, copy the code (without the plugin header of course) and paste it as is into your functions.php (NOTE: This only works for the build in taxonomy category and the build in post type post. You should modify it accordingly to your needs according to post type and custom taxonomy)

<?php
/*
 * Plugin Name: Category referred posts
 * URI: https://wordpress.stackexchange.com/a/192018/31545
 * Description: Add referrer links to single posts and pagination if single posts was referred from a category page
 * Version: 1.0
 * Author: Pieter Goosen
 */

/*
 * Add our custom query vars so WordPress can read it
 */
add_filter( 'query_vars', function ( $vars ) 
{
    $vars[] = 'ref';
    return $vars;
});

/* 
 * Add our referrer to single post links if we are on a category page
 */
add_filter('post_link', function( $permalink ) // Change to post_type_link for custom post type posts
{
    if (      is_category() // Change to is_tax() for custom taxonomy pages
         && ( $cat = get_queried_object() ) 
    ) {
        $permalink = esc_url( add_query_arg( ['ref' => $cat->term_id], $permalink ) );
    }
    return $permalink;
});

/*
 * Create our custom adjacent post link 
 */
function get_referred_adjacent_post( $args = [] ) 
{
    //First check if we are on a single post, else return false
    if ( !is_single() )
        return false;

    //Defaults arguments set for the function. 
    $defaults = [
        'previous'       => true,
        'anchor_text'    => '%anchor',
        'post_link_text' => '%text',
        'span_text_prev' => __( 'Older post: ' ),
        'span_text_next' => __( 'Newer post: ' ),
    ];  

    $combined_args = wp_parse_args( $args, $defaults );

    /**
     * Get the currently displayed single post. For this use 
     * get_queried_object() as this is more safe than the global $post
     *
     * The $post global is very easily changed by any poorly written custom query
     * or function, and is there for not reliable
     *
     * @see Post below on WPSE for explanation
     * @link https://wordpress.stackexchange.com/q/167706/31545
    */ 
    $current_post       = get_queried_object();
    $current_post_date  = $current_post->post_date;
    $current_post_type  = $current_post->post_type;

    //Set the important parameters to either get the next post or previous post
    $previous = $combined_args['previous'];
    $order    = ( $previous ) ? 'DESC' : 'ASC';
    $op       = ( $previous ) ? 'before' : 'after';

    // Check if we have a referrer, if so, we need to set this to get the next post in this specific referrer category
    $cat_id = filter_input( INPUT_GET, 'ref', FILTER_VALIDATE_INT );

    if ( $cat_id )
        $custom_args = ['cat' => $cat_id];

    /**
     * Set the default arguments to merge with the referrer arguments
     *
     * Uses date_query (introduced WordPress 3.7) to calculate the appropriate adjacent post
     * @see http://codex.wordpress.org/Class_Reference/WP_Query#Date_Parameters
    */ 
    $query_args = [
        'post_type'         => $current_post_type,
        'posts_per_page'    => 1,
        'order'             => $order,
        'no_found_rows'     => true,
        'suppress_filters'  => true,
        'date_query'        => [
            [
                $op         => $current_post_date,
                'inclusive' => false
            ]
        ]
    ];

    $query_args = ( isset( $custom_args ) ) ? wp_parse_args( $custom_args, $query_args ) : $query_args;

    $q = new WP_Query( $query_args );

    //If there are no post found, bail early
    if( !$q->have_posts() === 0 )
        return false;

    //If there are posts, continue
    $adjacent_post = $q->posts[0];

    //Build the permalinks for the adjacent post
    $permalink = get_permalink( $adjacent_post->ID );

    // Return the correct permalink, we should add our referrer to the link now if this post was referred
    $link = ( $cat_id ) ? add_query_arg( ['ref' => $cat_id], $permalink ) : $permalink;

    // Set up out link text to display
    $span_text = ( $combined_args['previous'] ) ? $combined_args['span_text_prev'] : $combined_args['span_text_next'];
    $span = '<span class="meta-nav">' . $span_text . '</span>';

    // Create our anchor and post title text. By default. The post title is used
    $anchor_text = ( $combined_args['anchor_text'] == '%anchor' )  ? $adjacent_post->post_title : $combined_args['anchor_text'];
    $post_title  = ( $combined_args['post_link_text'] == '%text' ) ? $adjacent_post->post_title : $combined_args['post_link_text'];

    //Create the link with title name and anchor text
    $adjacent_post_link = $span . '<a href="' . $link . '" title="' . $anchor_text . '">' . $post_title . '</a>';

    return $adjacent_post_link;
}

// Create the next post link - Return the post link
function get_next_adjacent_post_link( $anchor_text="%anchor", $post_link_text="%text", $span_text_next="Newer post: " )
{
    $args = [
        'previous'       => false,
        'anchor_text'    => $anchor_text,
        'post_link_text' => $post_link_text,
        'span_text_next' => $span_text_next,
    ];
    return get_referred_adjacent_post( $args );
}

// Create the previous post link - Return the post link
function get_previos_adjacent_post_link( $anchor_text="%anchor", $post_link_text="%text", $span_text_prev = 'Older post: ' )
{
    $args = [
        'previous'       => true,
        'anchor_text'    => $anchor_text,
        'post_link_text' => $post_link_text,
        'span_text_prev' => $span_text_prev,
    ];
    return get_referred_adjacent_post( $args );
}

// Create the next post link - Echo post link
function next_adjacent_post_link( $anchor_text="%anchor", $post_link_text="%text", $span_text_next="Newer post: " )
{
    echo get_next_adjacent_post_link( $anchor_text, $post_link_text, $span_text_next );
}

// Create the previous post link - Echo post link
function previos_adjacent_post_link( $anchor_text="%anchor", $post_link_text="%text", $span_text_prev = 'Older post: ' )
{
    echo get_previos_adjacent_post_link( $anchor_text, $post_link_text, $span_text_prev );
}

You should now add the following in your single.php:

  • To display your custom text

    $referrer = filter_input( INPUT_GET, 'ref', FILTER_VALIDATE_INT ); // This validate and checks if our referrer "ref" is set
    if ( $referrer ) {
        $category = get_category( $referrer );
        echo '<h2>' . $category->name . '</h2>';
    }
    
  • To display your post links

    if ( function_exists( 'next_adjacent_post_link' ) )
        next_adjacent_post_link();
    if ( function_exists( 'previos_adjacent_post_link' ) )
        previos_adjacent_post_link();
    

    Just add your relevant mark up to your links. Also check the accepted arguments to customize the text the links display.

This should lay the foundation to set you on your way. You should be able to customize this to suit your exact needs

Leave a Comment