Drupal SEO audit: the issues built into Drupal — and how to fix them
A Drupal SEO audit checks your store across search, AI visibility, accessibility and security — with a fix for each issue we find.
A powerful enterprise CMS where SEO is module-driven — get the right modules configured and it's excellent; leave defaults and you ship numeric URLs with no meta or schema.
How does Drupal's architecture shape your SEO?
Drupal is a flexible, self-hosted enterprise CMS used for large, complex sites. Its defining SEO trait is that almost everything is module-driven: out of the box you get numeric node URLs (/node/123), no path aliases, no meta tag control, and no structured data. The right contributed modules — Pathauto, Metatag, Simple XML Sitemap, Schema.org Metatag — turn it into a strong SEO platform, but they must be installed and configured. Its powerful taxonomy and Views can also generate many listing/archive pages, and as a self-hosted system, caching, performance, and security patching are yours to own.
Reference: Drupal SEO guide →
What issues show up most on Drupal sites?
Why these happen on Drupal
Specific to how Drupal is built — not generic checklist advice.
Clean URLs require Pathauto
By default Drupal serves /node/123-style URLs. Without the Pathauto module configured with URL patterns, your content has non-descriptive, unstable URLs. Install Pathauto and define alias patterns for each content type.
Meta and structured data need modules
Drupal core emits no meta descriptions, canonical control, or JSON-LD. You need Metatag and Schema.org Metatag configured per content type, or your pages have no structured data and weak meta. Confirm the markup actually renders, not just that modules are enabled.
Taxonomy and Views listing duplication
Drupal's taxonomy terms and custom Views can produce many overlapping listing/archive pages. Decide which term and View pages should be indexed, and noindex the thin or duplicative ones.
Self-hosted performance and security
As a self-hosted platform, caching (internal + Varnish/CDN), valid SSL, security headers, and prompt security updates are all your responsibility. Drupal security advisories must be applied promptly — unpatched modules are a common exposure.
Fixes written for Drupal
We catalog 8 Drupal fixes — exact steps for Drupal's admin and theme, each with a link to the official docs.
Add a single, descriptive H1 tag to every page that currently lacks one, clearly stating the page's main topic.
- 1Drupal outputs the node Title as the H1 by default via the page-title.html.twig template. Ensure every node/product has a Title value.
- 2If the template overrides the tag, locate page-title.html.twig in your active theme and ensure it uses <h1{{ title_attributes }}>{{ title }}</h1>.
- 3For Drupal Commerce product pages, go to Commerce → Products → open the product and fill in the Title field.
- 4Clear the Drupal cache under Admin → Configuration → Performance → Clear all caches after template changes.
<h1>Women's Running Shoes</h1>Place exactly one of these per page, as the first heading in the main content area.
Add HowTo structured data (JSON-LD) to any page that walks customers through a multi-step process, so Google can display your instructions as rich results in search.
- 1Install the 'Schema.org Metatag' module or 'Metatag' module with the JSON-LD submodule from drupal.org.
- 2Configure schema mappings for the relevant content type (e.g. 'How-to Guide') under Configuration › Search and Metadata › Metatag.
- 3For HowTo, you may need a custom module or a preprocess hook in your theme's .theme file to build the JSON-LD array and attach it via #attached['html_head'] on the relevant node type.
- 4BreadcrumbList is handled by the 'Simple XML Sitemap' or Metatag modules, or via a custom hook_preprocess_page().
- 5Validate with Google's Rich Results Test.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>How to Complete Your Task | Your Store</title>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "HowTo",
"name": "How to Complete Your Task",
"description": "Follow these steps to complete your task easily.",
"totalTime": "PT10M",
"step": [
{
"@type": "HowToStep",
"position": 1,
"name": "Prepare your materials",
"text": "Gather everything you need before you start: list materials here."
},
{
"@type": "HowToStep",
"position": 2,
"name": "Complete the main action",
"text": "Describe exactly what the user should do in this core step."
},
{
"@type": "HowToStep",
"position": 3,
"name": "Verify the result",
"text": "Explain how the user confirms the task was completed successfully."
}
]
}
</script>
</head>
<body>
<!-- Your how-to page content -->
</body>
</html>Place this block inside the <head> element of any static HTML page that contains step-by-step instructions.
Give every button, link, and menuitem a clear, accessible name so screen readers can announce what it does.
- 1In Drupal admin, go to Appearance and identify your active theme.
- 2In your custom or sub-theme, locate the Twig template file responsible for the unlabelled element (e.g., button.html.twig, menu.html.twig).
- 3Add `aria-label="{{ 'Descriptive action'|t }}"` to the element tag (using Drupal's translation function for internationalisation). Add `aria-hidden="true"` to decorative SVGs.
- 4Rebuild the Twig cache (Configuration → Development → Performance → Clear all caches, or `drush cr`) and verify with axe DevTools.
<!-- OPTION 1: aria-label on an icon-only button -->
<button type="button" aria-label="Open cart">
<svg aria-hidden="true" focusable="false" width="24" height="24" viewBox="0 0 24 24">
<path d="M6 2L3 6v14a2 2 0 002 2h14a2 2 0 002-2V6l-3-4z"/>
<line x1="3" y1="6" x2="21" y2="6"/>
<path d="M16 10a4 4 0 01-8 0"/>
</svg>
</button>
<!-- OPTION 2: visually-hidden span inside the button -->
<button type="button">
<svg aria-hidden="true" focusable="false" width="24" height="24" viewBox="0 0 24 24">
<path d="M6 2L3 6v14a2 2 0 002 2h14a2 2 0 002-2V6l-3-4z"/>
</svg>
<span class="sr-only">Open cart</span>
</button>
<!-- OPTION 3: aria-labelledby pointing to existing visible text -->
<h2 id="cart-heading">Your Cart</h2>
<button type="button" aria-labelledby="cart-heading">View</button>
<!-- OPTION 4: icon-only link with aria-label -->
<a href="/cart" aria-label="View shopping cart">
<img src="cart-icon.svg" alt="" role="presentation" />
</a>Apply one of these patterns to any button, link, or menuitem that contains only an icon or image.
Fix all HTML lists so that only valid child elements appear directly inside `<ul>` and `<ol>` tags, and only `<ul>` or `<ol>` elements wrap `<li>` items.
- 1Broken list markup in Drupal usually originates in a Twig template. Find the relevant template in your theme's 'templates/' folder (e.g. 'menu.html.twig', 'item-list.html.twig').
- 2Open the template and verify that any <ul> or <ol> loop outputs <li> wrappers correctly: {% for item in items %}<li>{{ item.content }}</li>{% endfor %}.
- 3If the issue is in a contributed module's template, copy the template into your theme's templates directory (Drupal's template override system), then fix it there.
- 4Run 'drush cr' (cache rebuild) or go to Configuration → Performance → Clear all caches, then re-audit the page.
<!-- CORRECT: <ul> or <ol> with only <li> children -->
<ul>
<li>First item</li>
<li>Second item</li>
<li>Third item
<!-- CORRECT: nested list lives INSIDE an <li> -->
<ul>
<li>Nested item A</li>
<li>Nested item B</li>
</ul>
</li>
</ul>
<!-- WRONG: <div> as a direct child of <ul> -->
<!-- <ul>
<div>This breaks the list</div>
<li>Item</li>
</ul> -->
<!-- WRONG: <li> with no list parent -->
<!-- <li>Orphaned item</li> -->Correct list structure — all platforms. Use this as a reference for what valid markup looks like.
How AI reads Drupal sites · AEO
16% of Drupal sites publish structured data
JSON-LD is the schema.org markup AI answer engines read to understand — and cite — a page. But 0.9% of Drupal sites add it only after JavaScript runs, so non-JS AI crawlers never see it. SEOLZ checks whether your structured data is present, valid, and visible to AI.
Source: HTTP Archive — structured-data probes on static + rendered HTML across 140,812 Drupal sites.
The typical Drupal site · HTTP Archive
How Drupal sites measure up
Performance — median
Accessibility gaps — share of sites
Source: HTTP Archive lab performance + accessibility probes across 140,812 Drupal sites. SEOLZ measures your site against these.
Every scan checks all six pillars
You can't rank what AI can't read. SEO, AEO, and GEO tell you where you rank; WCAG, OWASP, and Lifecycle determine whether search and AI can read and trust you at all. SEOLZ scores all six as one system.
Your catalog pages may be invisible to Google right now and you'd have no way to know. Indexability gaps, canonical conflicts, and faceted navigation issues silently kill organic traffic — we surface every one and tell you which to fix first.
Learn how to fix SEO issues →When someone asks ChatGPT to recommend a product in your category, is your store in the answer? Often it isn't. We check the structured data, page structure, and brand signals that help search and AI understand your products and describe them accurately — and we measure whether they actually cite you, or a competitor.
Learn how to fix Answer Engine (AEO) issues →AI search is eating traditional organic traffic. We track your actual brand mentions across ChatGPT, Perplexity, and other AI engines — and tell you what's pushing you down in the results.
Learn how to fix AI Visibility (GEO) issues →Ecommerce stores are among the most frequent recipients of ADA accessibility demand letters. We run WCAG 2.1 AA checks across your catalog, surface the barriers that most often appear in demand letters, and track each one through to a verified fix.
Learn how to fix Accessibility (WCAG) issues →A missing security header exposes your customers, and a compromised or flagged site loses search visibility fast. We check the server configuration, HTTPS setup, and email authentication issues that erode trust — before they become an incident.
Learn how to fix Security (OWASP) issues →SSL expires. Plugin versions fall behind. GTM containers go unverified. These aren't hypothetical risks — they're the operational failures that cause outages, ranking drops, and security incidents. We catch them before they happen.
Learn how to fix Site Lifecycle issues →| Platform | |||||||
|---|---|---|---|---|---|---|---|
| Shopify | 8 | 85 | 61 | 94 | 72 | 53 | 75 |
| WordPress.org | 7 | 89 | 50 | 86 | 73 | 53 | 73 |
| BigCommerce | 5 | 79 | 20 | 89 | 66 | 50 | 64 |
Averages across audited sites · data as of October 2026. Updated as new audits complete. Platforms with fewer than 5 audits aren't shown.
Start free. Upgrade when ready.
- ✓Composite + pillar scores
- ✓Issue counts
- ✓Recurring five-pillar re-scan
- ✓Free forever
- ✓Every finding across all 6 pillars, with step-by-step fixes for your platform
- ✓Template fixes: fix it once, clear it on every page built from that template
- ✓Fix tracking: mark it fixed and the next audit confirms it
- ✓Email alerts for score drops, new security issues, and SSL / domain expiry
- ✓Report builder with PDF, HTML and Markdown export
- ✓GTM & tracking audit, plus Search Console topic gaps
Questions about Drupal audits
Is Drupal good for SEO?+−
It can be excellent — but only once the right modules (Pathauto, Metatag, Simple XML Sitemap, Schema.org Metatag) are installed and configured. Default Drupal is weak on SEO. We check whether yours is properly set up.
Does SEOLZ work with Drupal?+−
Yes — we crawl your live Drupal site and write fixes for module configuration, content-type settings, and server-level performance and security.
Why are my Drupal URLs showing /node/123?+−
Because Pathauto isn't configured. Install it and define URL alias patterns per content type, then your content gets clean, descriptive URLs. We flag every node still on a numeric path.
See what's holding back your Drupal site
Free scan, no credit card, results in minutes. We've got you.
Scan My Drupal Site Free