Search code examples
phpdrupalcharacter-encodingfacebook-opengraphdrupal-8

Drupal escaping url in dynamically created meta tags


I am trying to add open graph meta tags dynamically to drupal 8 using the the page_attachments hook.

The meta tags are generated correctly however image and the website urls are being encoded by drupal and the result is broken links.

function module_page_attachments(array &$page)
{
  $tags = [
    ["name" => "twitter:card", "content" => "summary"],
    ["name" => "og:url", "content" => "https://example.net/index.php?param1=1&param2=2&param3=3"],
    ["name" => "og:title", "content" => "My title"],
    ["name" => "og:description", "content" => "My description"],
    ["name" => "og:image", "content" => "https://example.net/images?id=1&size=400"],
  ];

  foreach ($tags as $tag) {

    $headerTag = array(
      '#tag' => 'meta',
      '#attributes' => array(
        'property' => $tag['name'],
        'content' => $tag['content'],
      ),
    );
    $page['#attached']['html_head'][] = [$headerTag, $tag['name'] . "Id"];
  }
}

The result is the following

<html>
<head>
    <meta charset="utf-8" />
    <meta property="twitter:card" content="summary" />
    <meta property="og:url"
        content="https://example.com/index.php?param1=1&amp;param2=2&amp;param3=3" />
    <meta property="og:title" content="My title" />
    <meta property="og:description"
        content="My description" />
    <meta property="og:image"
        content="https://example.net/images?id=1&amp;size=400" />

</head>
<body>
</body>
</html>

All the & characters have been encoded and transformed into &amp;. How can I prevent Drupal from encoding the characters?


Solution

  • There is an open ticket for issue with the status needs work on drupal's website.

    The issue can be found here:

    www.drupal.org/project/drupal/issues/2968558

    A work around to solve the issue is to intercept the page and alter its template in the module file like the example here below shows:

    file name: example.module

    /**
     * Drupal bug caused the application to escape links. Therefore the og:image and og:url
     * were not working. Drupal kept converting `&` to `&amp;`
     * The solution here below converts the tags into inline templates
     */
    function spa_seo_page_attachments_alter(array &$attachments)
    {
      if (isset($attachments['#attached']['html_head'])) {
        foreach ($attachments['#attached']['html_head'] as $key => $item) {
    
          $property = !empty($item[0]['#attributes']['property']) ? $item[0]['#attributes']['property'] : '';
    
          if ($property == "og:url" || $property == "og:image") {
            $content = $item[0]['#attributes']['content'];
            $property = $item[0]['#attributes']['property'];
            $attachments['#attached']['html_head'][$key][0] = [
              '#type' => 'inline_template',
              '#template' => "{{ meta|raw }}",
              '#context' => [
                'meta' => '<meta property="' . $property . '" content="' . $content . '" />',
              ]
            ];
          }
        }
      }
    }
    

    Note

    Please note that DrupalCoreRenderMarkupdoes not solve the issue as this is a bug.