Oct 08, 2020 in Drupal 8

Metatags can be hard when abandoning the body field in favor of paragraphs. This post gives you a generic solution for the problem.

We want to create a custom module that, after saving the content, scrapes the first <p>-tag and saves them to the node as the meta description. In this way, we make sure a description is set, and we no longer have to worry about the first paragraph not being a textfield. In custom_meta.module, add the following. The script will check if there is a summary, otherwise scrape the node for a <p>-tag and save it to the node.

<?php

/**
 * @param \Drupal\Core\Entity\EntityInterface $entity
 */
function custom_meta_node_presave(Drupal\node\NodeInterface $entity) {

 if(in_array($entity->bundle(), ['article','page'])) {
      $summary = $entity->get('body')->summary;
      if(strlen($summary) < 8) {
        $nid = $entity->id();
        $entity_type = 'node';
        $view_mode = 'full';
        $view_builder = \Drupal::entityTypeManager()->getViewBuilder($entity_type);
        $storage = \Drupal::entityTypeManager()->getStorage($entity_type);
        $node = $storage->load($nid);
        if($node)  {
          $build = $view_builder->view($node, $view_mode);
          $summary = custom_meta_get_paragraph_from_html($build);
        } else {
          $summary = '';
        }

      }

      if(strlen($summary) > 8) {
        $entity->set('field_meta_tags', serialize([
          'description' => $summary,
        ]));
      }
     if(strlen($summary) > 240) {
       $entity->set('field_meta_tags', serialize([
         'description' => substr($summary,0,250).'...'
       ]));
     }
  }

}

/**
 * Gets html, sends one sentence back.
 */
function custom_meta_get_paragraph_from_html($html) {
  $output = render($build);
  $first_paragraph = substr($output, strpos($output, "<p"), strpos($output, "</p>")+4);
  $first_paragraph = strip_tags($first_paragraph);
  $first_paragraph = preg_replace('/<!--(.|\s)*?-->/', '', $first_paragraph);
  $first_paragraph = htmlentities($first_paragraph, null, 'utf-8');
  $first_paragraph = str_replace("&nbsp;", "", $first_paragraph);
  $first_paragraph = html_entity_decode($first_paragraph);
  $summary = substr($first_paragraph,0,150).'...';
  return $summary;
}