Stop loneliness
A story about meta tags in Drupal.
In a way the work of a web developer is not unlike that of a midwife, when our work is done the subject (the child or the website) is just at the beginning of its life. And, like a midwife, we also hope that our brand new site will grow up to be successful, with a lot of sensible, useful content and of course lots of friends or, in our case, visitors. And of course the content is what really makes a website and although we have little or no influence on the content, we can do a lot to make sure that the content is found by the right persons. One way to do this is by supplying search engines and social media platforms with the correct data about our site by means of meta tags. Here’s how you do this properly in Drupal.
In this blog I will discuss a number of things. First I will give you a number of reasons why you should implement meta tags. Then I will give a short overview of the most important kinds of meta tags and I will give a short overview of the use of meta tags in Drupal.
A large part will be dedicated to how to set up meta tags Drupal and I will end with how to test the meta tags for your website.
Why use meta tags
So why would you spent time setting up meta tags. Of course it will help your site to be found, but there are also some other advantages.
Control social media images
For one, setting up the meta tags will give you full control over the images used on social media and in search results. If the image used in the article is shown it will be a lot more attractive to users to follow the link compared to showing just some random image from your site. This is for example how Facebook and Twitter show some recipes I shared:
Because in Drupal it is possible to select a specific image style to be used in the different meta tags, you also can control how the image will be cropped. I will go into this in more detail when discussing how to set up meta tags in Drupal.
Hierarchy of objects
Schema.org, implemented by Google, Microsoft Bing, Yahoo and Yandex has an extra advantage: because of its roots in semantic web initiatives, it has a hierarchy of objects with specific properties that can be used by search engines to do more with the search result. A good example of this is the “how to”-type. If I search for ‘drupal 8 upgrade to 9’ in Google it will not only show websites with content about Drupal 8 and 9, it will also show some of the steps necessary to perform the upgrade.
Another good example is the “Recipe”-type (which is a subclass of the “How to”-type). If I search in Google for “risotto Jamie Oliver” the first result will not only point me to a website with this recipe, it will also show the ingredients necessary for this recipe.
Although it is hard to predict when Google will show the recipe and when not, in cases it does it certainly will attract extra traffic to your site.
The list of available types can be viewed at
https://developers.google.com/search/docs/data-types/article
Types of meta tags
The internet is a still evolving environment and although al lot is done to set standards for every part of the web, in some cases, like in the case of meta tags, this resulted in a (large) number of standards. I will discuss not all of them, but take a selection bases on the question of making your website less lonely, and yes, that means social media are involved.
HTML
The oldest type are the basic tags in HTML. In HTML there are a number of default meta tags that are added by Drupal:
<meta name="title" content="Page Title | Website name" />
<meta name="Generator" content="Drupal 8 (https://www.drupal.org)" />
<meta name="MobileOptimized" content="width" />
<meta name="HandheldFriendly" content="true" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Learn more about meta tags." />
The effectivity of the proprietary tags ‘MobileOptimized’ and ‘HandheldFriendly’ is a point of discussion, see the links at the end of this article.
These tags were declared dead more than once, but since we get them for free from Drupal and because the description tag can be used by search engines as primary description for your website it still is a good idea to use them.
Open Graph
The Open Graph meta tags are used by, among others, Facebook, Pinterest and LinkedIn. According to the (apparently out of date) https://opg.me-website
The Open Graph protocol enables any web page to become a rich object in a social graph. For instance, this is used on Facebook to allow any web page to have the same functionality as any other object on Facebook.
In the page source you can recognise the Open Graph tags by the ‘og-’ prefix of the property, for example:
<meta property="og:site_name" content="Lekkertoegankelijk" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://lekkertoegankelijk.nl/blog/stop-loneliness" />
<meta property="og:title" content="Stop Loneliness" />
The meta tags-module also has a ‘Facebook’-submodule. This is a a set of meta tags specially for controlling advanced functionality with Facebook and is not a replacement for the Open Graph tags. Unless you have specific requirements you can leave the fields in the ‘Facebook’-section empty, but for a correct display of your site when the URL is shared on Facebook setting up the Open Graph meta tags is essential.
Twitter cards
The documentation from Twitter states:
With Twitter Cards, you can attach rich photos, videos and media experiences to Tweets, helping to drive traffic to your website.
So exactly what we are looking for! In the page source you can recognise the Twitter card tags by the ‘twitter’-prefix of the name, for example:
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Stop Loneliness" />
<meta name="twitter:description" content="Learn more about meta tags." />
<meta name="twitter:url" content="https://lekkertoegankelijk.nl/blog/stop-loneliness" />
Schema.org
As stated above, the schema.org tags are not part of the meta tags module. To use them you have to get the module
composer require drupal/schema_metatag
and then at minimum enable the modules
- Schema.org Metatag
- Schema.org Article
Schema.org does not use the default tags but uses the ld+json-format, for example:
<script type="application/ld+json">{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Article",
"headline": "Stop Loneliness",
"name": "Stop Loneliness",
"description": "Learn more about meta tags.",
"isAccessibleForFree": "True",
"author": {
"@type": "Organization",
"@id": "https://lekkertoegankelijk.nl",
"name": "Lekkertoegankelijk",
"url": "https://lekkertoegankelijk.ddev.site/"
},
"publisher": {
"@type": "Organization",
"name": "Lekkertoegankelijk @ Limoengroen",
"url": "https://lekkertoegankelijk.ddev.site/"
},
"mainEntityOfPage": "https://lekkertoegankelijk.ddev.site/blog/stop-loneliness"
}
]
}</script>
The list of possible objects in schema.org is huge, see https://schema.org/docs.
For an overview of the objects implemented in the Drupal module see the Drupal project page at https://www.drupal.org/project/schema_metatag.
Meta tags in Drupal
De Drupal meta tags module (https://www.drupal.org/project/metatag) is used by over 400,000 sites (statistics of august 2020) and comes with a (still growing) set of sub-modules which make it easy to supply meta tags for a large number of social media platforms and support for, for example, the views-module. The module supports among others:
- Dublin core
- Twittercards
- Google Plus
If you include the separate Schema meta tag module you will have covered the most important meta tags.
Metatags UI
The default use case of the meta tags module is one in which all meta tags are set (via tokens) in the admin UI on ‘/admin/config/search/metatag’, which we will discuss later on.
There is however also the possibility to allow content editors to fill in the meta tags. This is done by adding a field of the type ‘Metatags’ to the content type and add it to the form display. This will work, but by default it will show all possible settings, which can be quite dazzling for a less-experienced editor because, depending on the enabled sub modules, this can be dozens of fields.
One solution for this would be to add a custom module with a hook_form_node_form_alter
and to hide all the fields which we do not want to show to the editor.
However, in most cases we only want to make a small number of fields, like ‘Description’ or ‘Summary’, available to be overridden by the editor and use the defaults for the rest. In this case a cleaner solution would be to add extra fields to the content type which will only be available in the edit form. In the default settings for meta tags (‘/admin/config/search/metatag’) this field can then be filled in with the correct token.
Custom meta tags
You can also define your own meta tags, for example if you want custom data for a specific analytics tool.
Defining a meta tag in a custom module is rather simple because of the Drupal 8 plugin and annotation systems. In your custom module add a class in
custom_module/src/Plugin/metatag/Tag/CustomMetaTag.php
With as content
namespace Drupal\custom_module\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The custom meta tag.
*
* @MetatagTag(
* id = "custom_tag_id",
* label = @Translation("Custom"),
* description = @Translation("The custom tag."),
* name = "custom:thema",
* group = "custom",
* weight = 8,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
/**
* CustomMetaTag.
*/
class CustomMetaTag extends MetaNameBase {
/**
* {@inheritdoc}
*/
public function output() {
(...)
}
}
If you do not define a custom output method, the data from the token of text will be rendered.
Of course the real magic is in the implementation of the ‘output’-function if you want anything else than plain tokens (see for an example the code in the module code in ‘src/Plugin/metatag/Tag/Keywords.php’), but since there are enough examples in the meta tag module I will not go into this in detail.
If you do not define a custom output method, the data from the token or text will be rendered.
This will give you a new type of meta tag that you can edit on the administration pages just like any other meta tag. You can use the same tokens as in other meta tags and of course can also implement your own tokens if you have need for some specialised data.
Meta tags settings
The settings page for meta tags (/admin/config/search/metatag
) is divided in a number of sections. Almost all sections inherit the settings from 'Global', but there are a number of exceptions which are discussed below.
Global
The settings in ‘Global’ are inherited by most other sections so it would seem to be the (only) place to set the meta tags. But if you check which tokens are available here, you will notice that the tokens for ‘node’ are not present. So yes, this is a important section to set up correct, but most of the ‘real’ work will be done in the ‘Content’-section.
Front page
The front page is somewhat special. Even if you have a custom node type for the front page, you should set the meta tags here because the settings for that type will not be used when the front page is rendered.
As an alternative you can use the hook_metatag_route_entity
to set the node whose meta tags will be rendered on the front page:
/**
* Implements hook_metatag_route_entity().
*/
function mymodule_metatag_route_entity(RouteMatchInterface $route_match) {
// For which route
if ($route_match->getRouteName() === 'mymodule.front') {
//Custom service to get our front node.
if ($node = \Drupal::service('mymodule.helper')->getFrontpageNode()) {
return $node;
}
}
}
In the above code we assume there is a custom route ‘mymodule.front’ and a service ‘mymodule.helper’ with a function ‘getFrontpageNode’ which returns the node we use as front page.
But in hook_metatag_route_entity
you can use any method to get the correct node, even a hard coded node id (although personally I regard setting hard coded node id's in code as something evil).
The meta tag module also defines a hook that can be used to alter the meta tags for any given route:
/**
* Implements hook_metatags_alter().
*/
function mymodule_metatags_alter(array &$metatags, array &$context) {
// Exclude meta tags on frontpage.
if (\Drupal::service('path.matcher')->isFrontPage()) {
$metatags = NULL;
}
}
403 Access denied & 404 Page not found
Default these two items inherit the canonical_url
and the shortlink
from the settings in 'Global'. Is it important that the 'Page not found' can be found? The defaults settings will be sufficient in this case.
Content
As stated above the content section is the section where we will do most of the work. Most of the meta tags should be set here, but if a certain content type (for example a ‘Blog’) has specific settings, you can add these by with the button ‘Add default meta tags’ on ‘/admin/config/search/metatag’.
of course with this button you will not be adding default meta tags, but add settings for default meta tags for a specific content type. In the use case where editors have the ability to set the meta tags for each content item however, these settings are the defaults they will see in the node add/edit form, hence the description in the button.
In the content section you will have access to all the node tokens and so this will be the place to talk about a number of specific details.
Description
For the description fields you may be tempted to use the node:summary
-token but please be aware that this token is somewhat special. In the Drupal core code it says:
if ($name == 'summary') {
// Generate an optionally trimmed summary of the body field.
// Get the 'trim_length' size used for the 'teaser' mode, if
// present, or use the default trim_length size.
In other words, if you want to set the number of characters shown, you must alter the number of characters shown in the summary of the body field for the ‘Teaser’ view mode for all (or a specific) content type.
Furthermore the text will be truncated so the editors will have no influence on the text shown. In most cases it will be better to give the editors access to a field to enter the description, and not reuse the summary for this.
Dates
All dates for Schema.org must be formatted in the ISO 8601 format. A clean solution for this is by adding a date time format for this Format string ‘c’. If the machine name for this is ‘iso_8601’ you kan use it with a token in the following way:
[node:changed:iso8601]
Even if you have an existing date time format adding one specific for ISO 8601 wil prevent errors when the date format is changed because for usage on other places.
Images
If an image is added, for example for the OpenGraph ‘Image’-tag, make sure you use a correct image style to limit the size of the image.
If for example, if the field that references a media item with an image is called ‘field_image’, the media item uses the field ‘field_media_image’ to store the image and the image crop we want tos use has the (machine) name ‘metatag_image’ then the value in the OpenGrap image field would be
[node:field_image:entity:field_media_image:metatag_image]
And for the dimensions of the image we would use
[node:field_image:entity:field_media_image:metatag_image:height] [node:field_image:entity:field_media_image:metatag_image:width]
So this can become more complex than just adding a token to a field.
OpenGraph types
The ‘Content type’-field suggests, by being a text field, that any text can be entered here. There is however a strict list of allowed type you can use here, see https://ogp.me/#types.
Twitter card-type
For ‘normal’, mainly text content ‘Summary Card with large image’ is the preferred type. If you have content that consists mainly of photo’s or streaming media, or an IOS or Android app, you can add overrides for that type via the ‘Add default meta tags’-button. Do not the explanation beneath the ‘Image URL’ field which states:
The URL to a unique image representing the content of the page. Do not use a generic image such as your website logo, author photo, or other image that spans multiple pages. Images larger than 120x120px will be resized and cropped square based on longest dimension. Images smaller than 60x60px will not be shown. If the ‘type’ is set to Photo then the image must be at least 280x150px. This will be able to extract the URL from an image field. This will be able to extract the URL from an image field.
Schema.org Author & Publisher
At first sight it may seem a good idea to use @type ‘Person’ and the [node:author]
token here, but keep in mind that in most cases this wil show data about persons whose data is not publicly available, for example the webmaster or site editors.
As a rule of thumb only show the author for content like blogs which has a strong connection to the person who wrote it. For most content it is a better choice to use the @type ‘Organization’ and use the site URL as @id and the site name as name. And again make sure to use a valid image style for the logo and to set representative Of Page to ‘False’.
Taxonomy term
Make sure to set these if you have taxonomy pages that are publicly available. Like with content, the tokens for taxonomy terms are only available here, and not in the global section. And just as witch ‘Content’, you can use the ‘Add default meta tags’-button if you have special requirements for a taxonomy.
Beware that taxonomy terms have different names, e.g. [node:title] vs. [term:name] and that you should alway use term instead of node as the base of the tokens.
User
As always make sure you are not sharing too much information about your users in the meta tags, like the account name or the user id.
Fields that are not shown on the user pages will still be available in the tokens, so make sure you check which fields are public and which are not. And these meta tags only make sense if the user pages are publicly available.
Testing meta tags
The first, basic test is to check the source if the different pages and make sure that you see the meta tags and the content you expect. In some cases the meta tag will not be shown because the token used did not render any content, maybe because the field the token referred to is not a required field and the default set in the ‘Global’ section is not set.
Other common pitfalls are content types that use different fields for the same functionality, like a hero image that is only available on blogs. If this is the case you can override the meta tags by adding default settings for that specific content type.
But always make sure you examine the source for at least one item of each content type to make sure the correct tags are rendered and do not assume it will work.
Local testing
To use the testing tools for Twitter cards and OpenGRAPH (used by Facebook) your site must be publicly available before you can use the test tool. If we do not take into account tunnelling services like ‘ngrok’ or elaborate router configurations, this means that you cannot test these meta tags before deployment.
So make sure to set all the correct values before deployment and, because perfection does not exists, make some room in your planning to test and re-deploy the meta tags once the site is live.
Testing Twitter cards
To test your Twitter cards meta tags you can use the testing tool at https://cards-dev.twitter.com/validator. For this page you must login and so a Twitter account is required. This tools only validates site that are publicly available so you can only use if after the site has gone into production.
But it seems that this tool currently has some problems and only gives the message ‘Unable to render Card preview’, even for sites that render perfectly fine when mentioned in a tweet. Which, by the way, is another method to test your site because the preview will be rendered before you actually place the tweet.
Testing OpenGraph
The testing tool from Facebook https://developers.facebook.com/tools/debug/sharing/ is available with a Facebook account and gives a detailed overview of the issues present in your webpage.
By default the tool uses a scraped version of the site, which makes it a bit harder to iteratively perfect your meta tags. Make sure to update the scraped version with the ‘Scrape again’-button under the ‘When and how we last scraped the URL’-button if you updated the meta tags.
Testing Schema.org
Google had a rather fine working testing tool at https://search.google.com/structured-data/testing-tool?hl=en, but decided to deprecate it in favour of https://search.google.com/test/rich-results, which however does not has the ability to test off line sites anymore (because even if you use the code option all resources need to be be accessible) and seems to have problems with generated images in some cases, without specifying exactly what the error is.
Of course there are other tools, but most of them not free and mainly targeted at check the validity of the generated JSON-LD (which is not a major problem in Drupal because the module generates it).
But I expected…
You did not expect I would tell you what value to use for each of the settings, did you? First, this largely depends on the entities you defined in Drupal. of course I can tell you that you should use a field with name ‘field_description’ for the meta tag description, but chance is you read this blog long after all entities were defined.
So no, I will not tell you what to put where, but I hope you understand more about what to put why.
Documentation and links
- Meta tags module: https://www.drupal.org/docs/8/modules/metatag
- Twitter cards: https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/abouts-cards
- OpenGraph: https://ogp.me
- Schema.org: https://json-ld.org/
- Facebook (only with Facebook account): https://developers.facebook.com/tools/debug/sharing/
- Twittercards validation: https://cards-dev.twitter.com/validator
- About Twittercards: https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/abouts-cards
- Google: https://search.google.com/test/rich-results
- About the viewport meta tag: https://www.davidbcalhoun.com/2010/the-viewport-metatag-mobile-web-part-1/
- About the handheld friendly meta tag:https://www.metatags.nl/2015/06/metatags-mobiel/mobiele-metatags-voor-de-smartphone/
- About the description meta tag: https://www.metatags.org/all-meta-tags-overview/the-important-meta-tags/meta-name-description/