How To Add WordPress Breadcrumbs Without a Plugin

Breadcrumbs or breadcrumb trail is a navigation aid used in a Website. It gives users a way to keep track of their locations within the Website. Breadcrumbs typically appear horizontally at the top of a Web page. Breadcrumbs provide a trail for the user to follow back to the starting or entry point.

Breadcrumb trail is an important supplementary element of a Website´s navigation, especially for complex Websites. It improves usability, enhances user experience and it is better for SEO. Don´t take my word for it, Google recommends using Breadcrumbs in their SEO starter guide. Also Google is integrating breadcrumbs navigation within the Search Engine Results Pages.

Breadcrumbs are especially useful for complex Websites containing many pages and sub-pages, and organized into many categories. On the other hand, breadcrumbs for simple Websites are not really necessary.

The picture below shows examples of breadcrumb trails generated from this blog. This blog is using the breadcrumb code shown below, browse the various sections of this blog and see how it behaves.

Miscellaneous examples of breadcrumb trails for this blog.

Yes, there are plugins for WordPress breadcrumbs, such as BreadCrumb NavXT. But haven´t you read my previous post about the disadvantages of going crazy adding plugins to your theme? Also what would you do if you want to develop a theme with a built-in breadcrumb trail.

There is one disadvantage of using breadcrumbs, it increases the number of query requests to your database, and thus a slighter increase in load time. However, this could be neutralized with a caching mechanism implemented to your Website. Again, haven´t you read my previous post about the advantages of caching a dynamic Webiste? I believe that the benefits of breadcrumbs: better user experience, and making the Website friendlier for Search Engines, far outweighs its one disadvantage. Breadcrumb navigation is important for usability and for SEO, especially for complex Websites.

My Breadcrumbs Code: Supported Features

The code below display breadcrumb trail for:

  1. Single post listed in one category.
  2. Single post listed in multiple categories that are at the same level.
  3. Category and sub-category archives.
  4. Tag archive.
  5. Yearly archive.
  6. Monthly archive.
  7. Daily archive.
  8. Author archive.
  9. Search result page.
  10. Top-level pages (top-level menu).
  11. Multi-level sub-pages (multi-level sub-menus).
  12. 404 Not found Error page.

The code below also features:

  1. Complete or shortened post titles.
  2. Two custom delimiters. Same level categories use a different delimiter.

Also the code below works in both cases when:

  1. Your Website´s Front page displays your latest posts.
  2. Your Website´s Front page displays a static page and your posts are located somewhere else.

To better explain: the default WordPress settings is shown below. If you choose the other option: "Front page displays -> a static page (select below)", the breadcrumb code still works.

Default WordPress setting in the admin area.

My Breadcrumbs Code: NOT Supported Features

The code below does not support:

  1. Adding a page number at the end of the trail.
  2. Attachments.
  3. Custom post types.
  4. Custom taxonomies.
  5. A single post listed in a top category AND in a subcategory (or subcategories). An unlikely case, where you get a mix up of delimiters.

WordPress Breadcrumbs Function Code

This is my version of the WordPress breadcrumbs code. Open the functions.php file located in your theme´s folder and add (copy and paste) the following function. Sorry for the long code, but I commented it so you understand better what´s going on.

Note: To scroll within the code: You can also click on the code window and use your keyboard´s arrow keys.

<?php
/***********************************************************************
* @Author: Boutros AbiChedid 
* @Date:   February 14, 2011
* @Copyright: Boutros AbiChedid (http://bacsoftwareconsulting.com/)
* @Licence: Feel free to use it and modify it to your needs but keep the 
* Author's credit. This code is provided 'as is' without any warranties.
* @Function Name:  wp_bac_breadcrumb()
* @Version:  1.0 -- Tested up to WordPress version 3.1.2
* @Description: WordPress Breadcrumb navigation function. Adding a 
* breadcrumb trail to the theme without a plugin.
* This code does not support multi-page split numbering, attachments,
* custom post types and custom taxonomies.
***********************************************************************/

function wp_bac_breadcrumb() {   
	//Variable (symbol >> encoded) and can be styled separately.
	//Use >> for different level categories (parent >> child >> grandchild)
            $delimiter = '<span class="delimiter"> &raquo; </span>'; 
	//Use bullets for same level categories ( parent . parent )
	$delimiter1 = '<span class="delimiter1"> &bull; </span>';
    
	//text link for the 'Home' page
            $main = 'Home';  
	//Display only the first 30 characters of the post title.
            $maxLength= 30;
	
	//variable for archived year 
	$arc_year = get_the_time('Y'); 
	//variable for archived month 
	$arc_month = get_the_time('F');	
	//variables for archived day number + full
	$arc_day = get_the_time('d');
	$arc_day_full = get_the_time('l');	
	
	//variable for the URL for the Year
	$url_year = get_year_link($arc_year);
	//variable for the URL for the Month	
	$url_month = get_month_link($arc_year,$arc_month);

	/*is_front_page(): If the front of the site is displayed, whether it is posts or a Page. This is true 
	when the main blog page is being displayed and the 'Settings > Reading ->Front page displays' 
	is set to "Your latest posts", or when 'Settings > Reading ->Front page displays' is set to 
	"A static page" and the "Front Page" value is the current Page being displayed. In this case 
	no need to add breadcrumb navigation. is_home() is a subset of is_front_page() */
	
    //Check if NOT the front page (whether your latest posts or a static page) is displayed. Then add breadcrumb trail.
	if (!is_front_page()) { 		
		//If Breadcrump exists, wrap it up in a div container for styling. 
		//You need to define the breadcrumb class in CSS file.
		echo '<div class="breadcrumb">';
		
        //global WordPress variable $post. Needed to display multi-page navigations. 
		global $post, $cat; 		
		//A safe way of getting values for a named option from the options database table. 
 	    $homeLink = get_option('home'); //same as: $homeLink = get_bloginfo('url');
        //If you don't like "You are here:", just remove it.
 	    echo 'You are here: <a href="' . $homeLink . '">' . $main . '</a>' . $delimiter;	
		
		//Display breadcrumb for single post
		if (is_single()) { //check if any single post is being displayed.			
			//Returns an array of objects, one object for each category assigned to the post.
			//This code does not work well (wrong delimiters) if a single post is listed 
			//at the same time in a top category AND in a sub-category. But this is highly unlikely.
			$category = get_the_category();
			$num_cat = count($category); //counts the number of categories the post is listed in.
			
			//If you have a single post assigned to one category.
			//If you don't set a post to a category, WordPress will assign it a default category.
			if ($num_cat <=1)  //I put less or equal than 1 just in case the variable is not set (a catch all).
			{
				echo get_category_parents($category[0],  true,' ' . $delimiter . ' ');
				//Display the full post title.
				echo ' ' . get_the_title(); 
			}
			//then the post is listed in more than 1 category.	
			else { 
				//Put bullets between categories, since they are at the same level in the hierarchy.
				echo the_category( $delimiter1, multiple); 
					//Display partial post title, in order to save space.
					if (strlen(get_the_title()) >= $maxLength) { //If the title is long, then don't display it all.
						echo ' ' . $delimiter . trim(substr(get_the_title(), 0, $maxLength)) . ' ...';
					}                         
					else { //the title is short, display all post title.
						echo ' ' . $delimiter . get_the_title(); 
					} 
			}			
		} 
		//Display breadcrumb for category and sub-category archive
		elseif (is_category()) { //Check if Category archive page is being displayed.
			//returns the category title for the current page. 
			//If it is a subcategory, it will display the full path to the subcategory. 
			//Returns the parent categories of the current category with links separated by '»'
			echo 'Archive Category: "' . get_category_parents($cat, true,' ' . $delimiter . ' ') . '"' ;
		}		
		//Display breadcrumb for tag archive 		
		elseif ( is_tag() ) { //Check if a Tag archive page is being displayed.
      		//returns the current tag title for the current page. 
			echo 'Posts Tagged: "' . single_tag_title("", false) . '"';
    	}		 
		//Display breadcrumb for calendar (day, month, year) archive
		elseif ( is_day()) { //Check if the page is a date (day) based archive page.
     		echo '<a href="' . $url_year . '">' . $arc_year . '</a> ' . $delimiter . ' ';
     		echo '<a href="' . $url_month . '">' . $arc_month . '</a> ' . $delimiter . $arc_day . ' (' . $arc_day_full . ')';
    	} 
		elseif ( is_month() ) {  //Check if the page is a date (month) based archive page.
      		echo '<a href="' . $url_year . '">' . $arc_year . '</a> ' . $delimiter . $arc_month;
    	} 
		elseif ( is_year() ) {  //Check if the page is a date (year) based archive page.
     		echo $arc_year;
    	}		
		//Display breadcrumb for search result page
		elseif ( is_search() ) {  //Check if search result page archive is being displayed. 
      		echo 'Search Results for: "' . get_search_query() . '"';
 		}		
		//Display breadcrumb for top-level pages (top-level menu)
		elseif ( is_page() && !$post->post_parent ) { //Check if this is a top Level page being displayed.
      		echo get_the_title();
  	 	}			
		//Display breadcrumb trail for multi-level subpages (multi-level submenus)
	 	elseif ( is_page() && $post->post_parent ) {  //Check if this is a subpage (submenu) being displayed.
			//get the ancestor of the current page/post_id, with the numeric ID 
			//of the current post as the argument. 
			//get_post_ancestors() returns an indexed array containing the list of all the parent categories.				 
			$post_array = get_post_ancestors($post);
			
			//Sorts in descending order by key, since the array is from top category to bottom.
			krsort($post_array); 
			
			//Loop through every post id which we pass as an argument to the get_post() function. 
			//$post_ids contains a lot of info about the post, but we only need the title. 
			foreach($post_array as $key=>$postid){
				//returns the object $post_ids
				$post_ids = get_post($postid);
				//returns the name of the currently created objects 
				$title = $post_ids->post_title; 
				//Create the permalink of $post_ids
				echo '<a href="' . get_permalink($post_ids) . '">' . $title . '</a>' . $delimiter;
			}
			the_title(); //returns the title of the current page.			 	
		}			
		//Display breadcrumb for author archive   
		elseif ( is_author() ) {//Check if an Author archive page is being displayed.
       		global $author;
	  		//returns the user's data, where it can be retrieved using member variables. 
      		$user_info = get_userdata($author);
     		echo  'Archived Article(s) by Author: ' . $user_info->display_name ;
		}		
		//Display breadcrumb for 404 Error 
		elseif ( is_404() ) {//checks if 404 error is being displayed 
     	 	echo  'Error 404 - Not Found.';
		}		
		else {
			//All other cases that I missed. No Breadcrumb trail.
		}
       echo '</div>';	 	
 	}	
}
?>

After adding the above function in your functions.php file, copy and paste the code below in the header.php file located in your theme´s folder. Place the following code where you want the breadcrumb trail to appear.

CODE-2:

<?php 
	//function_exists() — Return TRUE if the given function has been defined.
	//code by BOUTROS ABICHEDID. Adding breadcrumb trail to the WordPress theme.
	if (function_exists('wp_bac_breadcrumb')) {wp_bac_breadcrumb();} 
?>

The easiest way is to place the above code (CODE-2) in your theme´s header.php file. If you decide otherwise, then you need to place it in multiple files like: single.php, archive.php, search.php, page.php (custom-page.php if you have one) and probably in other files depending on your theme. Did you get the point that adding it to the header.php is simpler?

Styling the Breadcrumbs

Finally we need to style the breadcrumb trail with CSS. The following code is what I used to style the breadcrumb navigation for this blog. The code should be added to your theme´s CSS file (usually called style.css). Of course go ahead and change it to fit your design.

/* Styling Breacrumb Navigation by BOUTROS ABICHEDID */
.breadcrumb{
	width:645px;
	float:left;
	padding:0 0 0 47px;
	margin:9px 0 0 0;
	font-size:90%;
	clear:both;
}
.delimiter{
	color:#000;
	background-color:inherit;
}
.delimiter1{
	color: #627FC3;
	background-color:inherit;
}

Conclusion

You now have the breadcrumbs code that can be used on any WordPress Website. If you have any questions, or if you have other ideas on how to improve and add more functionality to the code, be sure to leave a comment!

References

  1. Function Reference « WordPress Codex
  2. Conditional Tags « WordPress Codex

If you enjoyed this post, please consider: linking back to it, subscribing by email to future posts, or subscribing to the RSS feed to have new articles delivered to your feed reader. Thanks!

About the Author |
Boutros is a professional Drupal & WordPress developer, Web developer, Web designer, Software Engineer and Blogger. He strives for pixel perfect design, clean robust code, and user-friendly interface. If you have a project in mind and like his work, feel free to contact him. Connect with Boutros on Twitter, and LinkedIn.
Visit Boutros AbiChedid Website.

61 Responses to “How To Add WordPress Breadcrumbs Without a Plugin”

  1. Silver Moon says:

    Thanks, this is exactly what I was looking for.

  2. Sarah says:

    thanks for sharing!
    works great!

  3. abhi says:

    Works great. But how to change the back color of navigation. Please suggest me.

  4. 谢谢分享 says:

    Good for me. Tks

  5. Ryan says:

    Works great thanks, only problem is on the lowest depth category the delimiter is displayed on the end any suggestions? I thought about str_replace to remove the last character

  6. cindy says:

    This is working like a charm. Thanks author.

  7. Ali says:

    Hi Boutros;

    Thank you so much for your help! You have gone above and beyond what I asked.

    I modified your script by commenting out line 24 and then removing
    . $delimiter from line 58 and that seemed to do the trick.

    It all appears to be working fine.

    Thank you for your time, promise not to bug you anymore!

    Have a great day.:-)

  8. Ali says:

    Hello Boutros,

    Hope you are well.

    I followed your instructions to remove the home link from the breadcrumb but it did not work. The word Home is still there but it now just links to the current page.

    There must be one other change to make, any idea’s what it could be?

    Your help is much appreciated.

    Thanks

    • Hi Ali,
      Why don’t you share the link and I can take a look.
      If you are using a free WordPress theme share the link too.
      I am not sure if you missed something, or there is something else going on with the theme you are using.

      Boutros.

      • Ali says:

        Unfortunately, I am developing on my localhost otherwise I would have shared the link right away.

        I am using a child twenty eleven theme. I am also using WordPress as a network, not sure if that would make any difference.
        I realized I haven’t give you much info to go on which makes it difficult to debug. Thanks for your reply though.
        I’ll take another look and see if I can figure it out.
        Many thanks

        • Hi Ali,

          I installed the Twenty Eleven theme on my Blog and I tested the instructions I gave you, and the ‘Home’ is gone. check it for posts/pages/archives/dates, and you could compare it to other theme’s options choices on my blog.
          I will temporarily leave the Twenty Eleven theme for you for few hours until you have a chance to take a look at it yourself.
          On the right sidebar of my blog, head to the “Change Theme” section and choose Twenty Eleven. Twenty Eleven has no ‘home’ link in the Breadcrumb while other themes have the ‘Home’ as part of the Breadcrumb.
          Assuming that you did not miss anything from my instructions. If you are using twenty Eleven as a Child theme (http://codex.wordpress.org/Child_Themes), then I would look at a conflict in the parent theme.
          Hope this helps,
          Boutros.

  9. Mark says:

    Catchable fatal error: Object of class WP_Error could not be converted to string in C:\xampp\htdocs\wordpress\wp-content\themes\my-theme\functions.php on line 213 (which is line 72 in the code above)

    it showed that error when i installed wp orbit slider and tried to view a test slide… any solution?

    • If my code was working fine prior to installing the plugin. Then it’s a plugin conflict.
      Then you have to choose, either the plugin or the breadcrumb. Or you could try another plugin and see if it works.
      I can’t tell what’s the conflict with that specific plugin, I’m not familiar with it.

  10. jaffa says:

    I will happily contribute.
    Thank you.

  11. jaffa says:

    this is brilliant! Thank you for sharing.

    I would like it to not display the Home link, could you please tell me how I can do this?

    Many thanks

    -J

    • Thanks Jaffa.
      I am not sure why you don’t want to display the ‘home’ link. ‘Home’ is part of the tree.
      An example of a breadcrumb: “You are: Home » General • WordPress » Google Authorship: How To Show …”

      The ‘Home’ is a link that takes you back to the main page of the Blog. Not a good idea not to show it.
      Is it: 1. You don’t want to show it? or 2. You want it un-linked.?
      Let me know.
      Boutros.

      • jaffa says:

        Thanks for your reply.

        My client doesn’t want the word to be displayed at all. I have tried to explain why it should be there but never the less they would like it removed.

        So, I would just like to remove HOME completely from the breadcrumb. Crazy I know but what can I do?

        • Hi Jaffa,

          In this case comment line 56 of the main code (by placing // in front of the line),
          AND replace line 58 of the code with:

          echo 'You are at: ';

          Since you are using my code for a client, I would very much appreciate a donation of any amount you deem appropriate. The donation button is at the top.
          Also see Terms of Use.
          let me know if you have any questions.
          Boutros.

  12. Nique says:

    Very nice, works great! thanks so much.