Drupal core builds no meta description and serves no XML sitemap — every search-visible tag on a Drupal site above the page title is put there by a contributed module, and by a configuration object you can open and read. That is the part most Drupal SEO advice skips, and it is the part that decides what Google actually receives.
Everything below was read from source on disk: Drupal 11.4.6 core (core/lib/Drupal.php line 79 declares VERSION = '11.4.6') and the module copies in the codebase behind this site. Where a number came from the live site instead, it says so.
What core leaves out, measured rather than assumed
Two scans of core, each with a control so a zero could be trusted:
- No sitemap route. 146
*.routing.ymlfiles in core declare no path containing the word sitemap. The control — searching the same 146 files for the node route/node/{node}— found it, so the search was working. - No description tag. Across 6,191 PHP, module, Twig and include files in core, none builds a
<meta name="description">. The control for that pass looked for the string'canonical'in the same files and returned 57 hits.
The modules that fill the gap, and what each declares
| Module | Version on disk | Declared core support | What it puts on the page |
|---|---|---|---|
| Metatag | 2.2.0 | ^10.3 || ^11 | Title, description, canonical, robots and 27 other tags from the base module |
| Metatag Open Graph | submodule of the above | as parent | 59 og: tag plugins |
| Schema.org Metatag | 3.0.4 | ^9 || ^10 || ^11 | The JSON-LD block, built on top of Metatag |
| Simple XML Sitemap | 4.2.3 | ^10.3 || ^11 | The document served at /sitemap.xml |
| Pathauto | 8.x-1.15 | ^10.2 || ^11 | The URL alias itself, generated from a token pattern |
One thing in that table matters more than the feature columns: not one of those five copies declares ^12. Anyone planning a Drupal 12 move should treat the SEO layer as an upgrade item with a date on it, not as something that comes along for free. That is a fact about the copies on this disk on the day it was written, and newer releases may already have moved — check the .info.yml of the version you are about to install rather than trusting this paragraph. The same method, applied across a whole site, is what a module and theme inventory is for.
Metatag: two config objects decide almost everything
Metatag is not configured per page in practice. It is configured once in a defaults entity, and then inherited. The two that matter ship in metatag/config/install/:
metatag.metatag_defaults.global.yml- Sets
canonical_urlto[current-page:url]and the title to[current-page:title] | [site:name]. Everything on the site inherits this unless something more specific overrides it. metatag.metatag_defaults.node.yml- Sets the title to
[node:title] | [site:name], the canonical to[node:url], and — the consequential one — the description to[node:summary].
Your teaser is your search snippet
Because the shipped node default is [node:summary], the description Google sees on a content page is the teaser an editor typed into the summary field. Not the first paragraph of the article, not the title, and not anything an SEO tab was asked for. On this article's own page today, the served description is 151 characters and ends in an ellipsis because the teaser it was built from ran longer than the field would show.
Metatag's own Description plugin documents the target in its annotation: a maximum of 160 characters (src/Plugin/metatag/Tag/Description.php). So the practical rule on any Drupal site using the shipped default is to write summaries as one complete sentence under roughly 158 characters — because that field, not a separate SEO field, is the snippet.
Trimming is available and switched off
Metatag can truncate tags for you, but metatag.settings.yml ships tag_trim_maxlength as an empty map, with tag_trim_method: beforeValue waiting for a number that has not been set. Out of the box nothing is trimmed. If your descriptions are being cut, something else did it, and the honest next step is to view the page source rather than guess.
If this is the point where a site starts sounding like more configuration than anyone wants to own, that is a reasonable conclusion — it is the sort of thing a Drupal development engagement settles once and then leaves documented.
Simple XML Sitemap: what is really at that URL
Read from simple_sitemap.settings.yml: sitemaps are generated on cron, duplicates are removed, an XSL stylesheet is attached, and the entity types enabled by default are nodes, taxonomy terms and menu links. A single sitemap file holds up to max_links: 2000 URLs before the module splits it and builds a chunk index.
Measured on this site today: /sitemap.xml returns 200, is about 103 KB, and contains 340 <url> entries — comfortably one file, no index. Entries carry lastmod, changefreq and priority, the home page at 1.0 and articles at 0.7, and image entries are included inline where a node has one.
One detail surprises people: the sitemap response itself is sent with X-Robots-Tag: noindex, follow, hardcoded in the module's controller (src/Controller/SimpleSitemapController.php line 61). A tool reporting that your sitemap URL is not indexed is reporting a deliberate header, not a fault.
Pathauto: the alias is cleaned before it is stored
Core stores aliases; Pathauto is what generates one from a token pattern. Its shipped settings (pathauto.settings.yml) do more to your URL than most people expect: text is transliterated, forced to lower case, punctuation is replaced by the - separator, each component is capped at 100 characters and the whole alias at 150, and a list of stop words including a, an, the, of, for and with is stripped out of the generated path.
That is why a title of The Ultimate Guide to Boosting Your Organic Visibility becomes ultimate-guide-boosting-your-organic-visibility. Nothing is broken; the cleaner did its job. The practical consequence is that keywords you care about should sit early in a title, because the 150-character cap truncates from the end.
The order to do this in
- Install Pathauto with Token and define the alias pattern before publishing, so you are not renaming URLs later.
- Install Metatag, then set the node defaults once. Per-node overrides are the exception, not the routine.
- Write summaries as real one-sentence descriptions, because that is the field that becomes the snippet.
- Install Simple XML Sitemap, enable only the entity types and bundles that should be indexed, and confirm the generated file rather than assuming cron ran.
- Only then look at structured data, which Schema.org Metatag layers on top of the Metatag configuration you already set.
Common questions
- Does Drupal need an SEO module at all?
- For a description tag and a sitemap, yes — core produces neither, and that was measured against core on disk rather than recalled.
- Where does the search snippet come from on a Drupal site?
- With Metatag's shipped node default, from the node summary token. Change the summary and the snippet changes.
- Why is my new page missing from the sitemap?
- Generation runs on cron by default, and only for entity types and bundles that are enabled. Check both before suspecting the module.
- Is a sitemap enough to get pages indexed?
- No. It is a discovery aid. An orphan page that nothing links to and that nobody searches for stays unindexed however neat the XML is.
- Do these modules make a slow site faster?
- No, and the two problems are unrelated. Page weight and caching are a separate diagnosis, covered in why a Drupal site is slow.
Where this leaves you
Two companion pages take this further in directions this one deliberately does not: what third-party authority scores can and cannot tell you, and what free SEO tools can see through a Drupal front end.
This page was written by Alaa Haddad, who has worked in web development since 2005 and is the author of Drupal modules and themes — the code is public and readable on the drupal.org profile. If you want the configuration above checked on your own site rather than described in general, that is a short piece of work: get in touch with the site URL and what you think is wrong.