Drupal 8 - Search API expose Metatag keywords as searchable field

By kenneth, Sun, 11/03/2019 - 18:51

Authored on

Image
castle-germany

Adding keywords might be useful for search results perhaps if we include synonymous however there is not just yet a way to include Metatag keywords out of the box into Search API index then guess what, it turns out that I was asked to do that. So far it seems like I've been really busy with custom Search implementation lately.

I know, there are different ways to solve this particular requests, but I choose to create a search api processor plugin into my `keboca_search`. This pluging should live into `src/Plugin/search_api/processor` folder.

<?php

namespace Drupal\keboca_search\Plugin\search_api\processor;

use Drupal\node\Entity\Node;
use Drupal\search_api\Datasource\DatasourceInterface;
use Drupal\search_api\Item\ItemInterface;
use Drupal\search_api\Processor\ProcessorPluginBase;
use Drupal\search_api\Processor\ProcessorProperty;

/**
 * Adds the item's Metatag keywords to the indexed data.
 *
 * @SearchApiProcessor(
 *   id = "add_metatag_keywords",
 *   label = @Translation("Metatag keywords field"),
 *   description = @Translation("Adds the item's Metatag keywords to the
 *   indexed data."),
 *   stages = {
 *     "add_properties" = 0,
 *   },
 *   locked = true,
 *   hidden = true,
 * )
 */
class AddMetatagKeywords extends ProcessorPluginBase {

  /**
   * {@inheritdoc}
   */
  public function getPropertyDefinitions(DatasourceInterface $datasource = NULL) {
    $properties = [];

    if (!$datasource) {
      $definition = [
        'label' => $this->t('Metatag keywords'),
        'description' => $this->t('The Metatag keywords defined on content.'),
        'type' => 'string',
        'processor_id' => $this->getPluginId(),
      ];
      $properties['search_api_metatag_keywords'] = new ProcessorProperty($definition);
    }

    return $properties;
  }


  /**
   * {@inheritdoc}
   */
  public function addFieldValues(ItemInterface $item) {
    /** @var \Drupal\node\Entity\Node $node */
    $node = $item->getOriginalObject()->getValue();
    if ($node instanceof Node && $node->hasField('field_metadata')) {
      /** @var \Drupal\metatag\MetatagManager $metatag_manager */
      $metatag_manager = \Drupal::service('metatag.manager');
      $tags = $metatag_manager->tagsFromEntity($node);
      // Check description tags.
      if (!array_key_exists('keywords', $tags)) {
        return;
      }
      // Find fields based on property path.
      $fields = $this->getFieldsHelper()
        ->filterForPropertyPath($item->getFields(), NULL, 'search_api_metatag_keywords');
      // Walk-through fields to setup value.
      foreach ($fields as $field) {
        // Check data source id.
        if (!$field->getDatasourceId()) {
          // Add value.
          $field->addValue($tags['keywords']);
        }
      }
    }
  }
}

After I flushed all caches, then I can browse to fields inside search index in order to include a new `Metatag keywords field` inside general section:

metatag_keywords

That said, I hope it helps you at some point somehow!

Happy coding!

 

Comments1

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.

thetailwind (not verified)

07/04/2021 - 12:40:52

Thank your for posting this, I found it extremely useful and exactly what I was looking for. It appears that Drupal and Meta Tag have change a few things. For those following your guidance, they will need to update the addFieldValue function like that starts with:

if ($node instanceof Node && $node->hasField('field_metadata')) {

and update it to

if ($node instanceof \Drupal\node\NodeInterface && $node->hasField('metatag')) {

Then it worked for me.

Thanks again!