← All articles
Technical SEO10 min read

Title Tags and Meta Descriptions: What Still Matters

Titles are still a ranking input, descriptions never were. Pixel widths, rewrite triggers, templating patterns that break, and how to audit both at scale.


Two tags sit next to each other in the <head>, look equally important, and behave nothing alike. The <title> is a genuine ranking input — one of the few pieces of on-page text search engines have told us they weigh. The meta description has not been a ranking factor since Google said so publicly in 2009, and it still isn't; it is a conversion surface. Treating them as one job ("fill in the SEO fields") is why so many sites have technically-complete metadata that neither ranks nor earns clicks. Here's what each one actually does, where the real constraints are, and how to check thousands of them without reading thousands of pages.

The title is a ranking input. The description is not.

Google's own documentation on title links says the title element is used to understand what the page is about and to generate the clickable headline in results. It is short, it is prominent, and it is one of the strongest topical signals a page emits. Change a title from "Products" to "Waterproof Hiking Boots for Wide Feet" and you have changed what the page is eligible to rank for.

Meta descriptions do not work that way. Google has repeatedly confirmed they are not used in ranking. What they do is influence whether a result gets clicked, and Google uses them as one candidate for the snippet — not the snippet itself. For head queries the description often survives intact. For long-tail queries, Google very frequently pulls a passage from the page body that contains the query terms, because that passage answers the specific question better than your generic summary does.

So the mental model is: write the title for the algorithm and the human; write the description only for the human, and expect it to be replaced maybe half the time.

Pixel width, not character count

Every "keep titles under 60 characters" rule is a proxy for the thing that actually matters: rendered width in the SERP layout. Google truncates on pixels.

The desktop title link renders in roughly 20px Arial inside a container of about 580–600 CSS pixels. The description block gets roughly 920–990 pixels across two lines at ~14px. These numbers have changed several times — Google bumped the title font size in 2020, mobile and desktop differ, and a favicon, breadcrumb, or sitelink can eat into the row — so treat them as a working range, not a specification.

The consequence is that character counts lie. Compare:

"Illinois Title Insurance Filing Timelines"   41 chars, ~355px
"WordPress Woodworking Workbench Warranty"    40 chars, ~410px

Same length; 55 pixels apart. A title full of narrow characters (i, l, t, f, j, .) fits far more than one full of W, M, G, @, and capitals. Uppercase-heavy titles run 15–20% wider than sentence case for the same string.

If you want a real number rather than a heuristic, measure it in a browser:

// Approximate Google's desktop title rendering
function titlePx(text) {
  const c = document.createElement("canvas").getContext("2d");
  c.font = "20px Arial, sans-serif";
  return Math.round(c.measureText(text).width);
}
titlePx("Waterproof Hiking Boots for Wide Feet | Northfell");  // -> ~470

Run that over a title export and you get a real truncation report instead of a character-count guess. Anything under ~560px is safe on desktop; 560–600px is a coin flip; past 600px you are writing text nobody will read.

The practical rule that follows: front-load the distinguishing information. Even if the tail gets cut, the part that tells a user this result is the one they want has already rendered. A title that reads "Northfell Outdoor Supply Co. — Boots — Waterproof Hiking Boots for Wide Feet" is a failure at any width, because the useful third is the part that disappears.

Why Google rewrites titles, and what triggers it

Google has said it uses the HTML <title> for the title link more than 80% of the time. Independent studies — the widely cited one from Zyppy looked at tens of thousands of results — found Google altering titles in the clear majority of cases. Both can be true: the discrepancy is about what counts as a rewrite. Trimming a trailing brand name, swapping a separator, or appending a site name is a change but not a replacement. Full replacements are much rarer than the scary headline number suggests.

What actually triggers a change, ordered by how often you'll see it in the wild:

  • Length. Titles well past the pixel limit get shortened, and Google shortens by dropping segments, not by adding an ellipsis at a sensible word boundary.
  • Boilerplate repetition. The same prefix or suffix on every page — Home | Acme , Blog | Acme, Blog | Category | Acme — signals low information. Google often strips the repeated part or substitutes text from an <h1>.
  • Keyword stuffing. Cheap Boots, Discount Boots, Boots Sale, Buy Boots Online gets rewritten with near-certainty.
  • Missing, empty, or near-empty titles. <title> | Acme</title> from a template where the variable resolved to an empty string is a guaranteed rewrite.
  • Query mismatch. If a heading or anchor text on the page matches the query better than your title does, Google may prefer it. This is the one case where a rewrite is often an improvement.
  • Site name handling. Google generates site names independently for homepage-level results and may add or remove your brand suffix regardless of what you wrote.

You cannot force Google to use your title, and there is no meta tag that opts out. What you can do is remove the reasons: a unique, appropriately sized, non-repetitive title that matches the page's dominant heading is rewritten far less often. If a specific page keeps getting rewritten, compare your <title> with the page's <h1> — when they disagree substantially, Google frequently sides with the H1, and consistent heading structure is part of the fix.

Good and bad HTML, concretely

<!-- Bad: brand-first, stuffed, over-width, duplicate description -->
<title>Northfell Outdoor Supply Co. | Boots, Hiking Boots, Waterproof Boots, Mens Boots, Womens Boots</title>
<meta name="description" content="Northfell Outdoor Supply Co. is your one-stop shop for outdoor gear. Shop now!">

<!-- Bad: template leakage -->
<title>undefined | Northfell</title>
<meta name="description" content="">

<!-- Good -->
<title>Waterproof Hiking Boots for Wide Feet | Northfell</title>
<meta name="description" content="Wide-fit waterproof hiking boots in EE and EEE widths, Gore-Tex lined, with a 40-day trail return policy. Sizing chart and break-in notes included.">

The good description works because it contains information a competitor's boilerplate does not: specific widths, a named membrane, a concrete return window. That is the difference between earning a click and baiting one. Clickbait ("You won't believe our boot prices") converts a click into a bounce, and the user goes back to the SERP — which helps nobody, including you.

Descriptions have a genuine sweet spot around 120–160 characters, but the reason is different from titles: shorter descriptions leave Google fewer reasons to substitute, and the two-line desktop cap is a soft one. Write one that is complete at 150 characters and let the tail be sacrificial.

Two directives are worth knowing:

<!-- Cap snippet length, or opt out of text snippets entirely -->
<meta name="robots" content="max-snippet:160">
<meta name="robots" content="nosnippet">
<!-- Exclude a specific element from snippet consideration -->
<p>Reliable summary text.</p>
<p data-nosnippet>Boilerplate legal text you don't want pulled into the SERP.</p>

data-nosnippet is the surgical tool: use it on cookie notices, shipping banners, and disclaimers that keep showing up as your snippet. The related directives interact with the rest of the robots family; robots.txt vs meta robots covers where those boundaries sit.

Templating at scale, and where templates break

For any site above a few hundred pages, titles are generated, not written. The template pattern that holds up is:

{primary distinguishing attribute} {noun} {qualifier} | {brand}

For a product: {product_name} - {key_spec} | {brand}. For a location page: {service} in {city} | {brand}. For an article: {headline} | {brand} and nothing else.

Where templates go wrong, from most to least damaging:

Null interpolation. Boots in | Northfell or literal undefined. Always guard, and make the guard produce a valid fallback rather than an empty slot:

export function pageTitle(parts: (string | null | undefined)[], brand: string) {
  const clean = parts.map(p => p?.trim()).filter(Boolean);
  if (clean.length === 0) return brand;
  return `${clean.join(" - ")} | ${brand}`;
}

Uncontrolled length. A template that is fine for "Boots" produces a 90-character title for "Insulated Waterproof Mid-Cut Hiking Boots for Wide Feet, Womens". Truncate on the variable field, not the whole string, so the brand suffix survives.

Near-duplicate output. Service × city pages generated from one template produce 400 titles that differ by one word. This is not automatically a problem — the city is the distinguishing attribute — but it becomes one when the template also stuffs the same three keywords into every variant. Vary the qualifier where the page content genuinely varies.

Pagination. Hiking Boots | Northfell on pages 1 through 12 is a real duplicate-title problem. Append - Page 3 and pair it with correct canonicals; canonical tag mistakes covers what happens when paginated canonicals point at page 1.

Framework-specific gaps. In App Router projects, a metadata export in a layout does not merge field-by-field with the page's the way people expect, and a client component cannot export metadata at all — which produces silently missing titles on exactly the interactive pages you care about. Next.js SEO problems goes through the specific failure modes.

Brand placement

Put the brand at the end, separated by a pipe or an en dash, for every page except the homepage. Reasons: the distinguishing text renders first, the brand is the safest thing to lose to truncation, and Google's site-name handling may append or replace it anyway.

Exceptions are real. If the brand is the query — a well-known publisher, a name people search for directly — leading with it costs nothing and may help recognition in a crowded SERP. And on the homepage, brand-first is correct: Northfell — Wide-Fit Hiking and Trail Boots.

Separator choice is cosmetic with one caveat: pipes and hyphens are narrower than em dashes, and at 20px Arial the difference across a large template is a few pixels of budget you may want back.

Duplicate and missing titles

Both are silent. Nothing errors; the page ships. The usual sources:

  • Faceted navigation generating thousands of URLs from one template
  • Client-side routing that sets document.title after paint, so the crawled HTML has the shell title
  • CMS drafts and archive pages inheriting a section title
  • Localised sites where the title was translated but the template was not
  • Print, AMP, or feed variants sharing a template

Duplicate titles are not a penalty. They are a self-inflicted disambiguation problem: you have told the search engine that twelve URLs are the same thing, so it will pick one and ignore the rest.

The Open Graph and Twitter card layer

og:title and og:description are separate from the SEO tags and serve a different audience — the social preview. They are not read by Google for search results. The mistake is to assume one falls back to the other, or that duplicating them is free.

<title>Waterproof Hiking Boots for Wide Feet | Northfell</title>
<meta name="description" content="Wide-fit waterproof hiking boots in EE and EEE widths, Gore-Tex lined, with a 40-day trail return policy.">

<meta property="og:title" content="Waterproof Hiking Boots for Wide Feet">
<meta property="og:description" content="EE and EEE widths, Gore-Tex lined, 40-day trail returns.">
<meta property="og:type" content="product">
<meta property="og:url" content="https://example.com/boots/waterproof-wide">
<meta property="og:image" content="https://example.com/og/boots-wide.png">
<meta name="twitter:card" content="summary_large_image">

Notes that matter in practice:

  • Drop the brand suffix from og:title. Social cards already show the domain, so the suffix is wasted width in a much narrower box.
  • Most consumers fall back to <title> and <meta name="description"> when the OG tags are absent, so partial coverage is worse than none — a page with og:image but no og:title gets an image plus whatever the scraper guessed.
  • twitter:card is still read by X; other properties largely fall back to OG. Setting summary_large_image without a suitably large image gets you a cropped mess.
  • og:image must be an absolute URL. Relative paths are the single most common OG bug, and they fail invisibly because your own site renders the image fine.
  • Scrapers do not run JavaScript. Client-injected OG tags do not exist as far as Slack, X, LinkedIn, or Discord are concerned.

Auditing both at scale

Start with the raw HTML, not the rendered DOM, because that is what most crawlers see first:

curl -sL https://example.com/boots/waterproof-wide \
  | grep -Eio '<title>[^<]*</title>|<meta[^>]+(name="description"|property="og:[^"]+")[^>]*>'

Then diff raw against rendered to catch JS-injected titles:

# raw
curl -sL "$URL" | grep -oP '(?<=<title>).*?(?=</title>)'
# rendered, if you have a headless browser available
node -e 'import("playwright").then(async ({chromium})=>{const b=await chromium.launch();const p=await b.newPage();await p.goto(process.argv[1],{waitUntil:"networkidle"});console.log(await p.title());await b.close();})' "$URL"

At list scale, the checks worth automating are boring and high-yield: missing title, empty title, title over ~600px, duplicate titles across URLs, title identical to H1's parent template, missing description, description under 50 characters, description duplicated across more than N URLs, og:image relative or absent. Every one of those is a string comparison — no crawler licence required.

SEO Fix Agent runs this set as part of its ~30-check single-page audit: title presence and rendered width, description presence and length, Open Graph and Twitter card completeness, all scored and exportable as CSV. Its Prompt Studio then compiles the failures into a severity-ordered prompt you paste into Claude Code or Cursor, which is useful precisely because metadata fixes are template edits — one change in a layout file resolves hundreds of URLs at once. It audits a page per run, so for large sites the workflow is: audit one representative URL per template, fix the template, re-audit.

The short version

Spend your effort on titles. They rank, they truncate on pixels rather than characters, and the fastest wins are usually removing boilerplate rather than adding keywords. Write descriptions for the human who is deciding between ten blue links, keep them specific enough that Google has no better candidate, and accept that it will often find one anyway. Keep the social layer complete rather than clever. Then automate the checks, because the failure mode for all of this is not a bad tag — it's a missing one nobody noticed for a year.

#title-tags#meta-descriptions#open-graph#serp-ctr#technical-seo

Audit your page, then ship the fix

SEO Fix Agent runs 30+ technical, content and AI-search checks on a page, then compiles every finding into a severity-ordered prompt your coding agent can execute. 75 free credits, no card.

Start free →

Keep reading