ScreenshotNeo

BlogHow-to

Using Custom HTML and CSS for Metadata Previews

Learn which HTML metadata controls search and social previews, why CSS cannot replace it, and how to validate reliable preview output.

By the ScreenshotNeo team29 September 20268 min read

Using Custom HTML and CSS for Metadata Previews

Short answer: custom HTML controls the values that preview systems read, while CSS controls the appearance of content rendered on the page. Put a descriptive <title>, <meta name="description">, canonical link, and (when needed) Open Graph tags in the document head. Do not expect CSS, including generated text from ::before, ::after, or the content property, to set a search or social preview. Google says CSS-generated content is not part of the DOM and is ignored by Google Search.

A preview is produced by a consuming system. Google Search may choose your meta description, visible page text, or another relevant passage. A social platform may read Open Graph fields and render them according to its own rules. Your HTML supplies inputs; it does not guarantee the exact text, truncation, layout, or image that every client displays.

1. Put preview metadata in valid HTML

Use the document head for metadata. Google documents title, meta, link, script, and style as valid head elements. Invalid markup can change how later metadata is parsed, so close tags correctly and keep metadata inside <head>.

HTML metadata feeds different consumers, each of which applies its own preview rules.
HTML metadata feeds different consumers, each of which applies its own preview rules.
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>Using Custom HTML and CSS for Metadata Previews | Example</title>
  <meta name="description" content="Learn how HTML metadata controls search and social previews, and why CSS cannot replace it.">
  <link rel="canonical" href="https://example.com/metadata-previews">

  <meta property="og:type" content="article">
  <meta property="og:url" content="https://example.com/metadata-previews">
  <meta property="og:title" content="Using Custom HTML and CSS for Metadata Previews">
  <meta property="og:description" content="A practical guide to HTML metadata, Open Graph fields, and CSS limitations.">
  <meta property="og:image" content="https://example.com/images/metadata-previews.jpg">
  <meta property="og:locale" content="en_US">
</head>
<body>
  <main>
    <h1>Using Custom HTML and CSS for Metadata Previews</h1>
    <p>This visible text supports users and gives crawlers useful page content.</p>
  </main>
</body>
</html>

The title is the document title and a common input to search title links. The description is an input, not a fixed snippet. Google may use it when it is more accurate than the page text, and snippets are selected for the particular query. Write a useful visible introduction as well; do not put the only meaningful summary in a meta tag.

CMS-managed sites

If you cannot edit templates, use the CMS SEO or page-settings fields that emit these tags. Inspect the generated HTML afterward. A field saved in an admin panel is not useful if the theme omits it, places it in the body, escapes it incorrectly, or renders different values for the canonical and public URLs.

2. Understand what CSS can and cannot change

CSS can change the visible page: typography, spacing, colors, responsive layout, and the design of a page that a browser or screenshot service captures. It does not change the value of meta elements or Open Graph fields. CSS-generated text is especially unsafe for metadata. For example:

.summary::before {
  content: "Important release notes";
}

The string may appear visually in a browser, but it is not normal DOM text. Google’s developer guidance says content added through CSS content is not part of the DOM and Google Search ignores it at the moment. Put important words in real HTML:

<p class="summary">Important release notes</p>

There is no CSS selector that rewrites og:description, changes a canonical URL, or forces a search snippet. If a preview needs a different message, generate a different HTML metadata value for that URL or state.

3. Search previews and social previews use different inputs

Consumer Typical inputs What you control What remains variable
Google Search title, meta description, visible text, robots directives Accurate metadata, useful page content, crawl access Query-specific snippet selection, rewriting, truncation, title-link changes
Open Graph consumers og:url, og:title, og:description, og:image Fields and referenced image URL Platform caching, rendering, image crops, unsupported fields

Open Graph is a separate vocabulary for describing web page objects. Add the fields relevant to your page and use absolute, publicly reachable URLs. A platform may cache an earlier response, so changing tags does not always update an already fetched preview immediately.

4. Control snippet eligibility carefully

Google supports robots metadata such as nosnippet, max-snippet, and data-nosnippet for limiting preview text. Use these only when you have a clear reason. They require Google to crawl the page; a blocked page cannot be updated through a directive it cannot read.

<meta name="robots" content="max-snippet:160">

<p data-nosnippet>This internal pricing note should not appear in snippets.</p>

data-nosnippet marks a specific visible region. It is not a replacement for writing a good description. Avoid accidentally wrapping your entire article in the attribute.

5. A complete implementation workflow

  1. Define the page promise. Write one sentence describing what a visitor will find. Use it as the starting point for the title, description, and opening paragraph.
  2. Emit valid head markup. Ensure one meaningful title, one description, a canonical URL, and the Open Graph fields your sharing targets use.
  3. Make visible content match. Put the core topic in an h1 and introductory paragraph. Do not hide the only summary behind CSS or JavaScript.
  4. Check crawl access. Confirm the URL is not blocked by robots.txt, authentication, or a firewall that rejects crawlers.
  5. Inspect the delivered source. View the server response and rendered DOM. Confirm production values, not development placeholders, are present in <head>.
  6. Validate each URL variant. Test trailing slashes, query parameters, locale paths, redirects, and canonical targets. Metadata should describe the final canonical page.
  7. Refresh external caches. When a social client retains an old card, use that platform’s documented debugger or wait for its crawler to fetch the URL again.

6. Capturing and reviewing the rendered result

Metadata itself is text, but reviewing the rendered page catches mismatches that source inspection misses: a consent banner covering the heading, a JavaScript error leaving an empty page, or a responsive layout that collapses at the target viewport. A browser automation script can load the URL, wait for the main selector, and save a screenshot for review.

import { chromium } from 'playwright';

const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await page.goto('https://example.com/metadata-previews', { waitUntil: 'networkidle' });
await page.screenshot({ path: 'metadata-review.png', fullPage: true });
await browser.close();

Use this visual check alongside source and DOM checks. A screenshot cannot prove which metadata a crawler read, and metadata inspection cannot prove that the page is legible to users.

7. Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. It accepts cookie banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result.

A clean capture removes obstructing overlays before saving the rendered page.
A clean capture removes obstructing overlays before saving the rendered page.

Read the full parameter reference in the ScreenshotNeo documentation. The simplest call is:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

For metadata review, useful options include a CSS selector for one element, full-page capture with lazy images loaded, a device preset or custom viewport, retina scale, dark mode, custom CSS or JavaScript, selector waits, delay, network-idle waits, request blocking, custom headers and cookies, timezone and geolocation, resizing, a chosen cache TTL, and PDF paper size, margins, orientation, or page ranges. Async jobs, signed webhooks, bulk capture for up to 100 URLs, usage reporting, and signed links support larger pipelines. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

There are 1,000 free shots per month with no card. Paid plans start at $5 for 3,000 shots; yearly billing gives two months free, and every feature is included on every plan. Create a free ScreenshotNeo account to capture a page and inspect its rendered state.

8. Troubleshooting common failures

Symptom Likely cause Fix
Search shows unrelated text Google selected visible text for the query Improve the page’s opening content and make the description accurate; selection is not guaranteed.
Social card has old copy Crawler cache Re-fetch with the platform’s official debugger and verify the public response.
Tags are missing CMS template, malformed head, or client-only rendering Inspect delivered HTML, repair the template, and keep essential metadata server-rendered.
CSS text never appears in a snippet content is generated presentation, not DOM text Move the text into an HTML element or metadata field.
Title is replaced or truncated Length, mismatch, language, or query context Use a concise accurate title that matches the page’s language and main content.
Screenshot is blank Timeout, bot check, blocked resource, or app error Wait for a selector or network idle, supply required headers, inspect logs, and test the URL without authentication.
Consent dialog covers content Capture occurred before interaction Use a consent-aware capture flow or ScreenshotNeo’s banner and popup removal.

9. Performance, reliability, and cost considerations

  • Keep head metadata small. A short title and description reduce parsing mistakes and make source inspection easy.
  • Prefer server-rendered values. Client-side updates can arrive after a crawler captures the initial response.
  • Wait for the right event. Fixed delays are simple but can waste time; a selector or network-idle condition is usually more deterministic for screenshots.
  • Control expensive pages. Block ads, trackers, video, or other resource types when they are irrelevant to the review. Cache stable URLs with a TTL when repeated captures do not need fresh pixels.
  • Retry selectively. Retry transient network failures, but record bot checks, authentication failures, and invalid URLs separately so a retry loop does not hide a configuration error.
  • Measure billing from headers. ScreenshotNeo returns X-Page-Verdict and X-Billed, allowing a pipeline to distinguish a clean billed shot from a failed or cache-hit request.

10. FAQ

Can CSS set a Google meta description?

No. CSS styles rendered content. Put the description in a meta element.

Will Google always show my meta description?

No. Google may select page text that better matches the query.

Open Graph is a separate vocabulary. Use Google-supported metadata for Search and Open Graph fields for consumers that read them.

Should every page use the same description?

No. Give each indexable page a specific summary that matches its visible content.

Can I use a screenshot to verify metadata?

A screenshot verifies the rendered page, not the metadata values a crawler reads. Pair it with source and DOM inspection.

What should I do when a page requires login?

Provide an authorized test environment or the required headers and cookies to your capture process, while keeping public metadata available for public pages.