Skip to Content

Title or meta description missing from the HTML

What Is This Issue

This issue checks whether your page’s title tag and meta description are present in the initial server-rendered HTML response, not just added later by JavaScript.

Modern websites often use JavaScript to dynamically inject metadata like titles and descriptions after the page loads. However, search engine crawlers may not execute JavaScript or may not wait for it to finish. For this check to pass:

  • The title tag must be present in the raw HTML returned by the server
  • The meta description tag must be present in the raw HTML returned by the server
  • Both must be inside the <head> section of the HTML
  • The title and description should not be empty

Example: When a crawler fetches your page, it should immediately see <title>My Page Title</title> and <meta name="description" content="My page description"> in the HTML source code, not have them added later by JavaScript.

Why Is This Important

Having metadata in server-rendered HTML is critical for:

  • Indexability: Search engines need to see metadata in the initial HTML to understand and index your page properly
  • Rankings: Title tags are a primary ranking factor, and meta descriptions influence click-through rates
  • Crawlability: Crawlers with limited JavaScript execution will miss metadata that’s only added by JavaScript
  • AI Search / AEO: AI systems need to access metadata in the initial HTML response to understand page content

When title and meta description are only added by JavaScript:

  • Search engines may see missing or incorrect metadata
  • Your pages may appear in search results with generic or incorrect titles/descriptions
  • Crawlers may generate their own snippets from page content, which may be less effective
  • Some search engines or crawlers may not see the metadata at all

Resolving this issue improves your SEO health score by ensuring search engines can reliably access your page metadata.

How XeoPix Detects This

XeoPix identifies JavaScript-rendering metadata issues through these steps:

  1. Fetches the raw HTML: XeoPix sends an HTTP request and captures the raw HTML response from the server (after following redirects).

  2. Does NOT execute JavaScript: The system only analyzes the raw HTML—it doesn’t run JavaScript or render the page in a browser.

  3. Extracts metadata: XeoPix parses the raw HTML to find:

    • The <title> tag in the <head> section
    • The <meta name="description"> tag in the <head> section
  4. Checks for issues: The system evaluates:

    • Is the title tag present in the raw HTML?
    • Is the meta description present in the raw HTML?
    • Are they inside the <head> section?
    • Are they empty or just whitespace?
    • Are there duplicate meta description tags?
  5. Flags JavaScript-dependent metadata: XeoPix triggers issues when metadata is missing from the raw HTML, indicating it might only be added by JavaScript.

The detection specifically checks the server response before any JavaScript execution—this is what search engine crawlers typically see first.

How To Fix

  1. Check your pages: Use “View Source” (not Inspect Element) to see if your title and meta description are in the initial HTML response.

  2. Move metadata to server-side: Ensure your server-side templates or SSR (Server-Side Rendering) framework generates the title and meta description in the initial HTML.

  3. Avoid client-side only injection: Don’t rely solely on JavaScript frameworks (like React, Vue, or Angular) to inject metadata after page load.

  4. Use SSR frameworks properly: If using Next.js, Nuxt, or similar frameworks, use their built-in metadata/head management features that render to server HTML.

  5. Test with crawlers: Use tools like Google’s Rich Results Test or fetch as Google to verify metadata is visible to crawlers.

  6. Validate placement: Ensure metadata is inside the <head> section, not in the <body>.

  7. Check for duplicates: Make sure you have only one title tag and one meta description tag per page.

  8. Test your changes: Recrawl your pages to confirm metadata is now present in the server-rendered HTML.

What We Store

Storage Level

Page Level


Database Table / Prisma Model

PageSeoBasicsData


Stored Fields

FieldTypeDescription
titleString?The page title
metaDescriptionString?The meta description

Detection Dependencies

  • HTML Document
  • JavaScript Rendering (if applicable)

Examples

Example 1: Server-rendered metadata

Scenario: A page with metadata in the initial HTML response.

Passes because:

  • Title tag is present in the raw HTML
  • Meta description is present in the raw HTML
  • Both are inside the <head> section
<head> <title>My Page Title</title> <meta name="description" content="This is my page description" /> </head>

Example 2: JavaScript-injected metadata

Scenario: A page that relies on JavaScript to add metadata.

Fails because:

  • Metadata is not in the initial HTML response
  • Crawlers that don’t execute JavaScript won’t see the metadata
  • Search engines may see missing or incorrect metadata
<!-- Initial HTML response --> <head> <!-- No title or meta description --> </head> <body> <script> // JavaScript adds metadata after page load document.title = "My Page Title"; const meta = document.createElement("meta"); meta.name = "description"; meta.content = "This is my page description"; document.head.appendChild(meta); </script> </body>

Corrected version: Move metadata to server-side rendering.

Example 3: Empty metadata

Scenario: A page with empty title or meta description.

Fails because:

  • Title or meta description is present but empty
  • Search engines have no meaningful metadata to use
<head> <title></title> <meta name="description" content="" /> </head>

Corrected version:

<head> <title>My Page Title</title> <meta name="description" content="This is my page description" /> </head>

Unit Test

Test File

__tests__/seo-audit-checks/pageSeoBasics/issue-212-meta-description-length.test.js __tests__/seo-audit-checks/pageSeoBasics/issue-212-uses-rel-next.test.js

Purpose

Validates that the SEO audit correctly detects meta description length issues (too short or too long) and the use of rel="next" pagination links.

Tested Function

runPageSeoBasics() from toggleGroups/pageSeoBasics.js

Issue Information

  • Issue Number: 212
  • Issue Code (Meta Description Length): TITLE_META_DESCRIPTION (title_meta_description)
  • Issue Code (Uses rel=“next”): USES_REL_NEXT (uses_rel_next)
  • Toggle Group: pageSeoBasics

Test Scenarios

Meta Description Length

Positive Test Cases
  1. Optimal meta description length — Meta description is 155 characters (within the 150–160 range). No issue should be reported.
  2. Meta description at minimum boundary — Meta description is exactly 150 characters. No issue should be reported.
  3. Meta description at maximum boundary — Meta description is exactly 160 characters. No issue should be reported.
Negative Test Cases
  1. Meta description too short — Meta description is shorter than 150 characters (e.g., “Too short”). The issue should be reported with issueType: 'meta-too-short'.
  2. Meta description too long — Meta description is longer than 160 characters (e.g., 200 characters). The issue should be reported with issueType: 'meta-too-long'.
  3. Empty meta description — Meta description has an empty content attribute. The issue should be reported.
Boundary Cases
  1. Minimum boundary (150 characters) — Exactly 150 characters should pass.
  2. Maximum boundary (160 characters) — Exactly 160 characters should pass.
Edge Cases
  1. Empty meta description — Empty content attribute triggers the detection.

Uses rel=“next” Pagination

Positive Test Cases
  1. No pagination links — Page has no <link rel="next"> or <link rel="prev"> tags. No issue should be reported.
  2. Only rel=“prev” present — Page has <link rel="prev"> but no <link rel="next">. No issue should be reported.
Negative Test Cases
  1. Has rel=“next” link — Page has a <link rel="next"> tag. The issue should be reported with details.paginationNext containing the next page URL.
  2. Both rel=“next” and rel=“prev” — Page has both <link rel="next"> and <link rel="prev">. The issue should be reported.
  3. Multiple rel=“next” links — Page has two <link rel="next"> tags. The issue should be reported.
Edge Cases
  1. Both rel=“next” and rel=“prev” — Verifies detection works when both pagination links are present.
  2. Multiple rel=“next” links — Handles multiple next links gracefully.
  3. Empty HTML — The function handles empty HTML input without crashing.

Expected Outcome

Meta Description Length

Pass

The issue is not reported when the meta description length is between 150 and 160 characters (inclusive).

Fail

The issue is reported when the meta description is shorter than 150 characters, longer than 160 characters, or empty.

Uses rel=“next” Pagination

Pass

The issue is not reported when the page has no <link rel="next"> tag.

Fail

The issue is reported when the page has one or more <link rel="next"> tags.

Validation

  • Verifies correct issue detection for meta description length (too short, too long, empty)
  • Verifies no issue is reported for optimal/boundary meta description lengths
  • Verifies issueType in payload is correct ('meta-too-short', 'meta-too-long')
  • Verifies correct issue detection for rel="next" pagination links
  • Verifies no issue is reported for pages without rel="next"
  • Verifies rel="prev" alone does not trigger the issue
  • Verifies details.paginationNext contains the correct URL
  • Verifies empty HTML does not cause crashes
  • toggleGroups/pageSeoBasics.js
  • issueCodes.js
  • utils/issues.js

Coverage Summary

  • Covers optimal meta description length (pass)
  • Covers meta description at 150-character minimum boundary (pass)
  • Covers meta description at 160-character maximum boundary (pass)
  • Covers meta description too short (fail)
  • Covers meta description too long (fail)
  • Covers empty meta description (fail)
  • Covers no pagination links (pass)
  • Covers only rel=“prev” (pass)
  • Covers rel=“next” present (fail)
  • Covers both rel=“next” and rel=“prev” (fail)
  • Covers multiple rel=“next” links (fail)
  • Covers empty HTML error handling (no crash)

References

Last updated on