17 Dec.2022

Drupal 10: Remove the nodes marked as "noindex" from search API results

Search

Tired of irrelevant search results?

It can be frustrating when users come across search results that should be elsewhere. This is especially true for content you don't want to be indexed to avoid search engines. In Drupal 10, this can happen with nodes marked as "noindex" by the Metatag module.

But fear not! This article will show you a clever solution to this problem.

With a few lines of custom code, you can effectively exclude nodes marked as "noindex" from your Search API results. This will ensure that only the most relevant content shows up, providing a better experience for your users.

Here's a step-by-step guide to getting you started:

Identify the problem: Do you see irrelevant nodes in your search results, even though they are marked as "no index"?

Understand the solution: This article provides a custom code snippet that checks the "metatags" field for the "noindex" value and excludes those nodes from the search results.

Implement the code: Follow the step-by-step instructions in the article to add the code to your Drupal website.

Following these steps, you can say goodbye to irrelevant search results and keep your users happy!

File
\modules\custom\MY_CUSTOM_MODULE\src\Plugin\search_api\processor\NodeExclude.php
<?php
 
namespace Drupal\MY_CUSTOM_MODULE\Plugin\search_api\processor;
 
use Drupal\node\NodeInterface;
use Drupal\search_api\IndexInterface;
use Drupal\search_api\Processor\ProcessorPluginBase;
 
/**
 * Class NodeExclude.
 *
 * @package Drupal\MY_CUSTOM_MODULE\Plugin\search_api\processor
 *
 * @SearchApiProcessor(
 *   id = "MY_CUSTOM_MODULE_node_exclude",
 *   label = @Translation("Node exclude"),
 *   description = @Translation("Exclude specific nodes. For example remove the
 *   nodes marked as noindex by metatag."), stages = {
 *     "alter_items" = 0
 *   }
 * )
 */
class NodeExclude extends ProcessorPluginBase {
 
  /**
   * {@inheritdoc}
   */
  public static function supportsIndex(IndexInterface $index) {
    foreach ($index->getDatasources() as $datasource) {
      if ($datasource->getEntityTypeId() === 'node') {
        return TRUE;
      }
    }
 
    return FALSE;
  }
 
  /**
   * {@inheritdoc}
   */
  public function alterIndexedItems(array &$items) {
    /** @var \Drupal\search_api\Item\ItemInterface $item */
    foreach ($items as $item_id => $item) {
      $object = $item->getOriginalObject()->getValue();
      $exclude = FALSE;
      if ($object instanceof NodeInterface) {
        // Review it because oldest version of the Metatag module used field_meta_tags instead of field_metatag.
        if ($object->hasField('field_metatag')
          && !$object->get('field_metatag')->isEmpty()) {
          $metaTags = $object->get('field_metatag')->getString();
          $metaTags = unserialize($metaTags);
          if (isset($metaTags['robots'])) {
            $robots = explode(', ', $metaTags['robots']);
            if (in_array('noindex', $robots)) {
              $exclude = TRUE;
            }
          }
        }
      }
 
      if ($exclude) {
        unset($items[$item_id]);
      }
    }
  }
 
}

Ruslan Piskarov

Ukraine
PHP/WEB Developer / Drupal Expert. More than 11 years of experience delivering Drupal based General Purpose solutions for different sectors such as Job Boards, Product Portfolios, Geo Coding, Real Estate solutions, E-Commerce, Classifieds, Corporate and online Magazines/Newspapers.