Metatag module: a primer and best practices

Reviewed 230615

The metatag module is probably the most commonly used tool for setting up the metadata used for SEO and other metadata-based data interchange like enabling Facebook previews and Twitter cards.

Installation

Like most other modules, the best way to install the metadata module is via composer:

composer install drupal/metatag

Unlike most other modules, the metatag dependency comes with a bevy of installable submodules

a plentitude

Enable the modules relevant to the content on the site. For our purposes here, We’ll enable the base metatag module, Metatag: Open Graph, and Metatag: Twitter Cards. We’ll explain how and why to set those up, and then talk briefly about Metatag: Favicons, Metatag: Dublin Core, Metatag: Verification, and Metatag: Views. Finally, we’ll briefly talk about the Schema.org Metatag module.

Enable the modules

drush en metatag metatag_open_graph metatag_twitter_cards

The metatag module introduces the “Administer meta tags” permission which should only be given to administrators in most cases.

Understand the Interface

Below is a screenshot of the first of two main configuration panes for the metatag module. From here you can control what types of Drupal content get what kinds of metatags. I’d like to highlight a few things here:

  1. The Type column lets you see all the different types of content that have metatags configured.

  2. Different types can override earlier settings. You can see that Front Page inherits from Global, so the Front Page canonical_url settings override the Global ones.

  3. There are edit buttons for each type to get to a detailed pane where the values for each metatag can be set. If the type is one of the default types, there is a revert button available behind the triangle button next to the Edit button. If this is not a default type, there is a Delete button.

  4. You can add new types to allow more detailed control of metatags

  5. There is also a settings tab where you can make overall changes to how the module operates.

You can add some other types for metatag configuration with the + Add default meta tags button.

As you can see, you can add metatags for Specific content types, Url Aliases, tags, and users besides the default types covered. If two types inherit from the same type, only the first one to overwrite it will be recognized, so If I have a title tag set for Global, Content, Content (article), and URL Alias. Then add an Article with a URL Alias. The system will first evaluate the Global tags, then hit Content (ignoring URL Alias which also inherits form Global), and finally evaluate Content (article) which inherits from Content.

Settings

The settings pane allows you to turn off the tagsets you don’t need per type, and set some character limits per tag. If it is installed, the MaxLength module can be used to enforce the limits. You can also select whether the trimming should happen before the word that hits the limit, after the word that hits the limit, or right on the limit. When selecting tagsets per type, if you leave all items unselected they will all show up.

Global

  • Basic > Page title: [current-page:title] | [site:name]

  • Advanced > Canonical URL: [current-page:URL]

  • Open Graph > Title: [current-page: title]

  • Open Graph > Site name: [site:name]

  • Open Graph > Content type: website

  • Open Graph > Page URL: [current-page:URL]

  • Open Graph > Title: [current-page:title]

  • Open Graph Image > Image, Image width, Image height, Image ‘alt’ – If you have a good default image that should be used whenever there isn’t a more specific image to represent the content, this is where to add it.

  • Twitter Cards > Twitter card type: Summary Card with large Image or Summary Card, depending on Image availability

  • Twitter Cards > Site’s Twitter account: Your site’s twitter handle including @

  • Twitter Cards > Do Not Track: ‘on’

Front Page

defaults are fine unless you have something you want to specifically use, especially for social media shares of the top page

Content

  • Basic > Title: [node:title] | [site:name]

  • Basic > Description: [node:summary] or something specifically for SEO if available

  • Advanced > Canonical URL: [node:URL]

  • Open Graph > Description: Same as Basic Description or something more specifically tailored to social media

  • Open Graph > Image tags if they weren’t available on the Global context

  • Twitter Cards> Twitter card type: switch type if there is an image now, but there wasn’t before

  • Twitter Cards > Creator's Twitter account: author’s Twitter handle including @ if it is likely to be different than the Site’s Twitter account, and we have a field on the user profile to collect the handle.

Content: {{content-type}}

  • Open Graph > Content type: article or something else more specific that website if applicable

  • Open Graph > Image tags if they weren’t available before but are on this type.

  • Twitter Cards> Twitter card type: switch type if there is an image now, but there wasn’t before

  • Twitter Cards > Creator's Twitter account: author’s Twitter handle including @ if it is likely to be different than the Site’s Twitter account, and we have a field on the user profile to collect the handle and this wasn’t available on content in general.

Basic Setup

Because of its use of tokens, it isn’t possible for Metatag to validate the values you provide for its tags. Please carefully inspect the output in your page source to insure that what you expect to be output is being output, and that tags you configure are not being output on pages where you wouldn’t expect them to be.

The base Metatag module provides two tagsets Basic, and Advanced. The basic tags are as follows: Page title, Description, Abstract, and Keywords.

Metatag sets up some reasonable defaults for a few metatags: Canonical URL, Page title, Short Link, Description, and in the case of a 403 page, a robots directive to stop search indexes from indexing 403s. It is commonly considered better practice not to use keyword tags, and the abstract tag is no longer supported by major search engines, the default values are ok. It could be a good idea to use a dedicated description field dedicated to a SEO, if the content team is willing to take that on. This is often the excerpt text that appears below the title on search engine results pages.

Advanced Tags

Beyond the default settings already included, there aren’t a lot of tags in the Advanced section that would be worth changing. If there is a section of the site that should be treated differently by search engines, the Search engine control settings could be useful. If content is sequential, the Next page URL, and Previous Page URL tags could be useful. The refresh tag is an easy way to trigger a periodic refresh, though that likely prevents accessibility issues. The cache related tags Cache Control, Expires, and Pragma could be useful when you need to demand that a specific set of pages not be cached.

Here is the full set of tags as of this writing and an example of what each outputs:

  • ICBM Address (latitude, longitude) <meta name="icbm" content="50.167958, -97.133185" />

  • Geographical region (US-NH) <meta name="geo.region" content="US-NH" />

  • Geographical place name <meta name="geo.placename" content="James Lake" />

  • Geographical position (same as ICBM?) <meta name="geo.position" content="50.167958, -97.133185" />

  • Shortlink URL <link rel="shortlink" href="https://kala9-trial.ddev.site/" />

  • Canonical URL <link rel="canonical" href="https://kala9-trial.ddev.site/" />

  • Content Language <meta http-equiv="content-language" content="en-US" />

  • Search engine control settings <meta name="robots" content="index, follow, noarchive, nosnippet, noimageindex, notranslate, max-snippet:450, max-video-preview:60, max-image-preview:standard, unavailable_after:2023-06-30" />

    • Robots - control search engine behavior

    • Max Snippet - longest snippet a search engine can generate

    • Max Video Preview - longest video preview to generate

    • Max Image Preview

    • Unavailable after date

  • Next page URL <link rel="next" href="/node/58" />

  • News Keywords <meta name="news_keywords" content="news, keywords" />

  • Previous page URL <link rel="prev" href="/node/56" />

  • Standout - for Google News. Google page about it is broken, probably not worth using <meta name="standout" content="oh yeah" />

  • Image <link rel="image_src" href="https://media.newyorker.com/photos/590971152179605b11ad79aa/master/w_2560%2Cc_limit/151019_r27147.jpg" />

  • Generator (does not replace the Generator meta tag that Drupal inserts by default <meta name="generator" content="Drupal 48" />

  • Author <meta name="author" content="James Satake" />

  • Original source <meta name="original-source" content="https://en.wikipedia.org/wiki/Dublin_Core" />

  • Google <meta name="google" content="nositelinkssearchbox, notranslate" />

  • Referrer Policy <meta name="referrer" content="no-referrer-when-downgrade" />

  • Set cookie <meta http-equiv="set-cookie" content="JAMES=SATAKE" />

  • Refresh <meta http-equiv="refresh" content="180" />

  • Rating <meta name="rating" content="14 years" />

  • Rights <meta name="rights" content="Creative Commons Share-Alike" />

  • Revisit After <meta name="revisit-after" content="3 days" />

  • Cache control <meta name="cache-control" content="no-Cache" />

  • Expires <meta name="expires" content="Thu, 01 Sep 2016 00:12:56 GMT" />

  • Pragma <meta name="pragma" content="NO-CACHE" />

Open Graph

The Open Graph meta tags are used to control how Facebook, Pinterest, LinkedIn and other social networking sites interpret the site's content.

Every page on your site should have the Title, Content Type, Image, and Page URL tags well configured. The Title is likely to be similar to the basic tags title value, though you likely want to remove the site name. Page URL will most likely be the same as the Canonical URL tag. The type should be an appropriate value from the list of Open Graph types, likely website by default, and article for some of your article types of content. Image has a number of sub tags for providing width, height, and alt text. Be sure to choose a suitable image style for your images to make sure they are appropriate for Open Graph tags. (The recommended size is at least 1200x630 px.) Choose a representative image for each page's content if such a token exists.

You may also want to consider adding values for the Description (you can use the same value as the description tag in the basic section), Locale (en-US, ja-JP, etc), Site Name ([site:name]), and the Video tags if you have a section that features video.

Getting these basic tags set up should cover you for getting nice-looking cards created when your site is shared on Facebook, LinkedIn, Pinterest, and Twitter. The section below will provide you with Twitter-specific settings, but Twitter falls back to Open Graph tags when Twitter ones don’t exist.

Global
  • Site name: [site:name]

  • Content type: website

  • Page URL: [current-page:URL]

  • Title: [current-page:title]

  • Image, Image width, Image height, Image ‘alt’ – If you have a good default image that should be used whenever there isn’t a more specific image to represent the content, this is where to add it.

Content
  • Title: [node:title]

  • Image tags: If all the content on your site shares an image field usable for this you can add tokens for this here. If all your content types have different image fields suitable for this, but they each have one and only one of the tokens listed, you can add all the tokens here, and metatag will fill in the one that has content, and fill in nothing for the blank ones.

Content: Article (and other types)

Content type: article (or appropriate type)

Image tags: as appropriate if this isn’t covered in the Content config above. e.g. Image: [node:field_image:wide:URL], Image width: [node:field_image:wide:width], Image height: [node:field_image:wide:height], Image ‘alt’: [node:field_image:alt]

Video tags: as appropriate if relevant.

 

Here is a list of all the Open Graph tags with an example of their output:

 

Determiner (leave blank unless you have a good reason)

<meta property="og:determiner" content="Determiner" />

Site name

<meta property="og:site_name" content="Site name" />

Content type

<meta property="og:type" content="Content type" />

Page URL

<meta property="og:url" content="https://Page.URL" />

Title

<meta property="og:title" content="Title" />

Description

<meta property="og:description" content="Description" />

Video URL

<meta property="og:video" content="https://Video.URL" />

Image

<meta property="og:image" content="https://kala9-trial.ddev.siteImage.jpeg" />

Image URL

<meta property="og:image:url" content="https://Image.URL/Image.jpeg" />

Video Secure URL

<meta property="og:video:secure_url" content="https://Video.Secure/URL.mp4" />

Image Secure URL

<meta property="og:image:secure_url" content="https://Image.Secure/URL.jpeg" />

Video type

<meta property="og:video:type" content="Video.type" />

Image type

<meta property="og:image:type" content="Image type" />

Video width

<meta property="og:video:width" content="Video width" />

Image width

<meta property="og:image:width" content="Image width" />

Image height

<meta property="og:image:height" content="Image height" />

Video height

<meta property="og:video:height" content="Video height" />

Content modification date & time

<meta property="og:updated_time" content="Content modification date &amp; time" />

Image 'alt'

<meta property="og:image:alt" content="Image &#039;alt&#039;" />

Video duration (seconds)

<meta property="og:video:duration" content="Video duration (seconds)" />

See also

<meta property="og:see_also" content="See also" />

Longitude

<meta property="place:location:longitude" content="Longitude" />

Latitude

<meta property="place:location:latitude" content="Latitude" />

Street address

<meta property="og:street_address" content="Street address" />

Locality

<meta property="og:locality" content="Locality" />

Region

<meta property="og:region" content="Region" />

Postal/ZIP code

<meta property="og:postal_code" content="Postal/ZIP code" />

Country name

<meta property="og:country_name" content="Country name" />

Email address

<meta property="og:email" content="Email address" />

Phone number

<meta property="og:phone_number" content="Phone number" />

Fax number

<meta property="og:fax_number" content="Fax number" />

Locale

<meta property="og:locale" content="Locale" />

Alternative locales

<meta property="og:locale:alternate" content="Alternative locales" />

Article author

<meta property="article:author" content="Article author" />

Article publisher

<meta property="article:publisher" content="Article publisher" />

Article section

<meta property="article:section" content="Article section" />

Article tag(s)

<meta property="article:tag" content="Article tag(s)" />

Article publication date & time

<meta property="article:published_time" content="Article publication date &amp; time" />

Article modification date & time

<meta property="article:modified_time" content="Article modification date &amp; time" />

Article expiration date & time

<meta property="article:expiration_time" content="Article expiration date &amp; time" />

Book author

<meta property="book:author" content="Book author" />

ISBN

<meta property="book:isbn" content="ISBN" />

Release Date

<meta property="book:release_date" content="Release Date" />

Book tag(s)

<meta property="book:tag" content="Book tag(s)" />

Audio URL

<meta property="og:audio" content="Audio URL" />

Audio secure URL

<meta property="og:audio:secure_url" content="Audio secure URL" />

Audio type

<meta property="og:audio:type" content="Audio type" />

First name

<meta property="profile:first_name" content="First name" />

Last name

<meta property="profile:last_name" content="Last name" />

Gender

<meta property="profile:gender" content="Gender" />

Username

<meta property="profile:username" content="Username" />

Actor(s)

<meta property="video:actor" content="Actor(s)" />

Actor's role

<meta property="video:actor:role" content="Actor&#039;s role" />

Director(s)

<meta property="video:director" content="Director(s)" />

Series

<meta property="video:series" content="Series" />

Release date

<meta property="video:release_date" content="Release date" />

Tag words

<meta property="video:tag" content="Tag words" />

Scriptwriter(s)

<meta property="video:writer" content="Scriptwriter(s)" />

Twitter Cards

The Twitter Cards tags allow you to configure how site links shared on Twitter will appear in the Twitter timeline or embedded on a web page. Many of the fields can safely be inherited from the Open Graph tags configured in the previous section unless you have a reason that you want to differentiate them on Twitter. For that reason, I’ll only cover the tags that seem that it may be necessary to make your content look as good as possible on Twitter:

  • Twitter card type: This will determine how your content is displayed. Unsurprisingly, the Twitter documentation for this is in a bad state as of this writing. You are most likely to want a Summary, Summary with large image, Photo, or Gallery card unless you are promoting an app, a product, or a page with a feature video. In those cases be sure to review the other fields because there are some relevant to those card types that I’m not mentioning here. By default probably choose Summary Card if you are likely not to have an image available (in this case no other Twitter card fields need to be filled), and Summary Card with large image otherwise. Read the Notes below the Twitter card type field, it lets you know which types use which fields

  • Site’s Twitter account: The @username for the website, which will be displayed in the Card's footer; must include the @ symbol.

  • Creator’s Twitter account: If you have multiple authors on the site, and have a profile field with their twitter handles in them, include it here. Make sure it starts with @

  • Do Not Track: set to ‘on’ to prevent Twitter from tracking users when an embed is used.

  • 1st-4th gallery image: If you have multiple images for a content type and want a gallery card, this is where you provide the URLs for those images. Make sure to choose an appropriate image style.

Twitter card type

<meta name="twitter:card" content="summary_large_image" />

Title

<meta name="twitter:title" content="Title" />

Description

<meta name="twitter:description" content="Description" />

Site’s Twitter account

<meta name="twitter:site" content="Site&#039;s Twitter account" />

Site’s Twitter account ID

<meta name="twitter:site:id" content="Site&#039;s Twitter account ID" />

Creator’s Twitter account ID

<meta name="twitter:creator:id" content="Creator&#039;s Twitter account ID" />

Creator’s Twitter account

<meta name="twitter:creator" content="Creator&#039;s Twitter account" />

Do Not Track

<meta name="twitter:dnt" content="Do Not Track" />

Page URL

<meta name="twitter:url" content="Page URL" />

Image URL

<meta name="twitter:image" content="https://kala9-trial.ddev.siteImage URL" />

Image width

<meta name="twitter:image:width" content="Image width" />

Image height

<meta name="twitter:image:height" content="Image height" />

Image alternative text

<meta name="twitter:image:alt" content="Image alternative text" />

1st gallery image

<meta name="twitter:gallery:image0" content="https://kala9-trial.ddev.site1st gallery image" />

2nd gallery image

<meta name="twitter:gallery:image1" content="https://kala9-trial.ddev.site2nd gallery image" />

3rd gallery image

<meta name="twitter:gallery:image2" content="https://kala9-trial.ddev.site3rd gallery image" />

4th gallery image

<meta name="twitter:gallery:image3" content="https://kala9-trial.ddev.site4th gallery image" />

App store country

<meta name="twitter:app:country" content="App store country" />

iPhone app name

<meta name="twitter:app:name:iphone" content="iPhone app name" />

iPhone app’s custom URL scheme

<meta name="twitter:app:url:iphone" content="iPhone app&#039;s custom URL scheme" />

iPhone app ID

<meta name="twitter:app:id:iphone" content="iPhone app ID" />

iPad app name

<meta name="twitter:app:name:ipad" content="iPad app name" />

iPad app ID

<meta name="twitter:app:id:ipad" content="iPad app ID" />

iPad app’s custom URL scheme

<meta name="twitter:app:url:ipad" content="iPad app&#039;s custom URL scheme" />

Google Play app name

<meta name="twitter:app:name:googleplay" content="Google Play app name" />

Google Play app ID

<meta name="twitter:app:id:googleplay" content="Google Play app ID" />

Google Play app’s custom URL scheme

<meta name="twitter:app:url:googleplay" content="Google Play app&#039;s custom URL scheme" />

Media player URL

<meta name="twitter:player" content="https://kala9-trial.ddev.siteMedia player URL" />

Media player width

<meta name="twitter:player:width" content="Media player width" />

Media player height

<meta name="twitter:player:height" content="Media player height" />

MP4 media stream URL

<meta name="twitter:player:stream" content="MP4 media stream URL" />

MP4 media stream MIME-type

<meta name="twitter:player:stream:content_type" content="MP4 media stream MIME-type" />

Label 1

<meta name="twitter:label1" content="Label 1" />

Data 1

<meta name="twitter:data1" content="Data 1" />

Label 2

<meta name="twitter:label2" content="Label 2" />

Data 2

<meta name="twitter:data2" content="Data 2" />

Metatag: Favicons

This submodule allows you to configure several Favicons and touch icons. If you want to make sure your site has icons for every occasion a combination of this submodule and image styles should help you to accomplish it. Most of the fields want images to be PNGs, and one asks for an SVG

Metatag: Dublin Core

Dublin Core and Dublin Core Advanced, provide configurable Dublin Core standard tags. These are generally used to provide metadata about online content and are expanded upon to create several standards for annotating metadata for academic materials online.

Metatag: Verification

Many search engines provide you an option of verifying that you are the owner of a site you are asking them to index, by adding verification metatags into your HTML markup. This submodule enables you to easily include these verification tags.

Metatag: Views

Metatag Views provides a metatag configuration pane within the Views UI interface, allowing you to configure metatags per view. This can be useful, but you should be aware that like other metatag configuration, this is considered config, not content. With metatag configuration for content, for example, you can readily use tokens to allow content entered by editors to populate the metatags. With views, there may be no obvious place for editors to add that content.

Schema.org Metatag module

This module enables you to add schema.org defined microdata to your site which can be used by search engines and other crawlers looking for this kind of specialized data. The module has more submodules than the metatag module itself, and installing just the base module doesn’t give you any additional functionality. You’ll need to enable at least one submodule. For your purposes here we’ll configure tags for an Event content type, so we’ll enable the base module and the Schema.org Event submodule.

drush en schema_metatag schema_event

After installing we get a new configuration pane allowing us to set up our tags

The interface gives a fair amount of guidance or links to guidance on expected values for these fields. Sometimes the data that is required may not match, or may be in a different format than you are capturing it in on your site, so if you are designing a new content type with the intention of adding schema.org tags to it later, it can be useful to review the requirements before you decide on your fields, or even use the Schema.org Blueprints module to help generate your content type. I’m not sure without more research how to change the value of the dropdown fields dynamically. You can utilize token alters to transform token values into the formats you need. There is also an example submodule included, in case you need to implement your own submodule.

After filling in a few of the fields in the Event schema, here is some sample output:

<script type="application/ld+json">{ "@context": "https://schema.org", "@graph": [ { "@type": "Hackathon", "url": "url", "name": "name", "description": "description", "eventStatus": "eventStatus", "eventAttendanceMode": "eventAttendanceMode", "image": { "@type": "ImageObject", "representativeOfPage": "True", "url": "url", "width": "width", "height": "height" }, "doorTime": "doorTime", "startDate": "startDate", "isAccessibleForFree": "False", "location": [], "offers": [] } ] }</script>

Review History

Who

When

Status

Who

When

Status

 

 

 

Bob

20230615

Add info on schema.org Blueprints

Bob

20230607

Initial Draft Completed

Bob

20230531

This deserves an update after other pages are reviewed.