The Node has attached a single Term.

Current breadcrumbs rendered


Want to render like this.


5 Answers 5


Yes @No Sssweat is right. I think you need to built a custom module for this.
Add Taxonomy Term to a Node's Breadcrumb in Drupal 8


Themers who don't want to use a custom module to implement a BreadcrumbBuilder can change the breadcrumbs in a preprocess hook.

Example how you can add a link before the last link:

function mytheme_preprocess_breadcrumb(&$variables) {
  $breadcrumb = &$variables['breadcrumb'];
  $lastlink = array_pop($breadcrumb);
  array_push($breadcrumb, [
    'text' => 'New Link',
    'url' => '/newlink',
  array_push($breadcrumb, $lastlink);

If you add a taxonomoy term from a node you would have to add both as cache tags and a cache context on the url to make this work.

  • I like your idea to achieve the same. :)
    Jan 25, 2017 at 11:36
  • I've tried to leverage the same, can you please review goo.gl/1nmkEU :) Jun 22, 2017 at 13:09
  • @RishiKulshreshtha, this looks good, you could add an answer with your code
    – 4uk4
    Jun 22, 2017 at 13:52

We can implement custom breadcrumb either via module or via HOOK_preprocess_breadcrumb.

Via HOOK_preprocess_breadcrumb:

Add this in your YOURTHEME.theme

 * Implements HOOK_preprocess_breadcrumb().
function YOURTHEME_preprocess_breadcrumb(&$variables) {
  if (($node = \Drupal::routeMatch()->getParameter('node')) && $variables['breadcrumb']) {
    $breadcrumb = &$variables['breadcrumb'];
    if (!empty($node->field_tags->entity)) {
      $term_url = $node->field_tags->entity->toLink();
      $node_url = array_pop($breadcrumb);
      array_push($breadcrumb, $term_url);
      array_push($breadcrumb, $node_url);
      // Implementing Cache.
      $variables['#cache']['contexts'][] = "url.path";
      $variables['#cache']['tags'][] = "node:{$node->nid->value}";

Via module:

In custom_breadcrumb.module file


namespace Drupal\custom_breadcrumb;

use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\node\NodeInterface;

 * Class Breadcrumbs.
 * @package Drupal\custom_breadcrumb
class Breadcrumbs implements BreadcrumbBuilderInterface {
  use StringTranslationTrait;

   * {@inheritDoc}
  public function applies(RouteMatchInterface $route_match) {
    return $route_match->getRouteName() == 'entity.node.canonical' && $route_match->getParameter('node') instanceof NodeInterface;

   * {@inheritDoc}
  public function build(RouteMatchInterface $route_match) {
    $node = $route_match->getParameter('node');
    $breadcrumb = new Breadcrumb();

    // By setting a "cache context" to the "url", each requested URL gets it's
    // own cache. This way a single breadcrumb isn't cached for all pages on the
    // site.

    // By adding "cache tags" for this specific node, the cache is invalidated
    // when the node is edited.

    // Add "Home" breadcrumb link.
    $breadcrumb->addLink(Link::createFromRoute($this->t('Home'), '<front>'));

    // Given we have a taxonomy term reference field named "field_tags" and that
    // field has data, add that term as a breadcrumb link.
    if (!empty($node->field_tags->entity)) {
    return $breadcrumb;


and then in custom_breadcrumb.services.yml

    class: Drupal\custom_breadcrumb\Breadcrumbs
      - { name: breadcrumb_builder, priority: 100 }

Both the ways are achievable, if your question is which one should be followed and which one should be referred as a best practice, refer https://drupal.stackexchange.com/a/238962/3808


A slightly more parametrized theme code example for non-node entities with taxonomy parents, made by combining Rishi Kulshreshtha's code with taxonomy parents addition by mfrosch

 * Implements hook_system_breadcrumb_alter().
function THEMENAME_preprocess_breadcrumb(array &$vars) {
  // proper taxonomy breadcrumbs for Commerce Products through field_category
  $entity_type = 'commerce_product'; // TODO: change or verify
  $taxonomy_field_name = 'field_category'; // TODO: change or verify

  if (($entity = \Drupal::routeMatch()->getParameter($entity_type)) && $vars['breadcrumb']) {
    $cache_tag = "{$entity_type}:{$entity->product_id->value}"; // TODO: change or verify

    $breadcrumb = &$vars['breadcrumb'];
    if (!empty($entity->$taxonomy_field_name->entity)) {
      $node_url = array_pop($breadcrumb);

      $term = $entity->$taxonomy_field_name->entity;
      $storage = \Drupal::service('entity_type.manager')
      $parents = $storage->loadParents($term->id());
      if (!empty($parents)) {
        foreach ($parents as $index => $parent) {
          array_push($breadcrumb, $parent->toLink());
      array_push($breadcrumb, $term->toLink());

      array_push($breadcrumb, $node_url);

      // Implementing Cache.
      $vars['#cache']['contexts'][] = "url.path";
      $vars['#cache']['tags'][] = $cache_tag;

Taking a quick peek in contrib modules, as of this writting, there doesn't seem anything that you can use for D8.

Here is a creative quick and easy solution/suggestion:

With Views and bit of Rewrite Results/Template file + CSS you could create your own breadcrumbs view block.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.