DevToys Web Pro iconDevToys Web ProBlog
Traducido con LocalePack logoLocalePack
Califícanos:
Prueba la extensión del navegador:
← Back to Blog

Meta Tags SEO Guide: Open Graph, Twitter Cards, and JSON-LD

10 min read

Every page you ship has an invisible layer that determines how search engines index it and how it looks when someone shares it on Slack, LinkedIn, or Twitter. That layer is built from HTML meta tags — and getting them right is one of the highest-leverage, lowest-effort SEO tasks available. Use the Meta Tags Generator to build and preview all the tags covered in this guide without leaving your browser.

This guide covers the full stack: the essential head tags every page needs, Open Graph for social sharing, Twitter Cards, the rules for og:image, debugging tools, JSON-LD structured data, framework-specific integration, dynamic OG images, and the pitfalls that catch most developers.

The Essentials

Before Open Graph or Twitter Cards, every HTML page needs a small set of foundational tags. These affect rendering, indexing, and canonical authority.

<head>
  <!-- Character encoding: must be first -->
  <meta charset="UTF-8" />

  <!-- Responsive viewport -->
  <meta name="viewport" content="width=device-width, initial-scale=1" />

  <!-- Page description shown in search results -->
  <meta name="description" content="150–160 character summary of the page." />

  <!-- Indexing directive -->
  <meta name="robots" content="index, follow" />

  <!-- Canonical URL: prevents duplicate content penalties -->
  <link rel="canonical" href="https://example.com/the-canonical-path" />
</head>

What each tag does:

  • charset — Declares UTF-8 encoding. Without it, browsers may mis-render non-ASCII characters. Must appear before any content that references characters outside ASCII, ideally as the very first tag.
  • viewport — Tells mobile browsers not to zoom out to a desktop-width layout. width=device-width, initial-scale=1 is the correct value for nearly every page.
  • description — Search engines use this as the snippet under your title in results pages. Keep it 150–160 characters, include your primary keyword naturally, and make it specific to the page. Google may ignore it and generate its own, but a good description improves click-through rates.
  • robots — Controls crawling and indexing. index, follow is the default behavior even without the tag. Use noindex for staging pages, thank-you pages, and search result pages you do not want indexed.
  • canonical — Not a meta tag technically, but a <link> tag that belongs in the same conversation. It tells search engines which URL is the authoritative version when the same content is accessible at multiple URLs (HTTP vs HTTPS, trailing slash, query strings). Always use absolute URLs here.

Open Graph Tags

Open Graph (OG) was created by Facebook in 2010 to give websites control over how their pages appear in link previews. Today every major platform — Facebook, LinkedIn, Slack, Discord, WhatsApp, iMessage — reads OG tags when generating a share preview.

<meta property="og:title" content="Page Title for Social Sharing" />
<meta property="og:description" content="A clear, engaging description for the preview card." />
<meta property="og:image" content="https://example.com/og-image.png" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://example.com/the-canonical-path" />
<meta property="og:site_name" content="Example Site" />
<meta property="og:locale" content="en_US" />
TagRequiredNotes
og:titleYesCan differ from the HTML <title>. Keep under 60 characters to avoid truncation.
og:descriptionRecommended2–4 sentences. Aim for 200 characters or less.
og:imageYes (for sharing)1200×630 pixels, HTTPS, absolute URL. See the og:image rules section.
og:typeYeswebsite for homepages, article for blog posts, product for e-commerce.
og:urlYesThe canonical URL of the page. Must be absolute.
og:site_nameRecommendedThe name of your site, not the page.
og:localeOptionalFormat: en_US, fr_FR, ru_RU. Defaults to en_US if omitted.

For articles, you can add additional OG tags that some platforms surface: article:published_time, article:author, and article:section. These are optional but improve integration with platforms that understand article types.

Twitter Cards

Twitter (X) uses its own set of meta tags for link previews. The good news: Twitter falls back to Open Graph tags when twitter:* tags are missing. In practice you only need to add a few Twitter-specific tags on top of your OG setup.

<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@YourHandle" />
<meta name="twitter:creator" content="@AuthorHandle" />
<!-- These fall back to og:title / og:description / og:image if omitted -->
<meta name="twitter:title" content="Page Title for Twitter" />
<meta name="twitter:description" content="Description for the Twitter card." />
<meta name="twitter:image" content="https://example.com/twitter-card.png" />

Twitter supports three card types relevant to most sites:

  • summary_large_image — Large image above the title and description. The most common choice for blog posts, landing pages, and articles. Image should be 1200×630 (same as og:image) or at minimum 600×314 with a 2:1 ratio.
  • summary — Small square thumbnail to the left. Use for profile pages, documentation, or any page where a large image preview would look wrong.
  • player — Embeds an inline video player. Requires Twitter developer approval and is primarily used by video platforms.
  • app — Displays app store download buttons. Used by mobile app marketing pages.

If you only set Open Graph tags and skip Twitter tags entirely, Twitter will render a summary card using your og:title, og:description, and og:image. The fallback works reliably in practice.

og:image Rules

The og:image is what makes or breaks a share preview. Get it wrong and you get no image, a stretched image, or a thumbnail so small it is unreadable. The rules are stricter than most developers realize.

  • Dimensions: 1200×630 pixels is the standard baseline. This satisfies both OG (1.91:1 ratio) and Twitter (summary_large_image). Minimum is 600×315 for OG; anything smaller may be ignored.
  • Aspect ratio: 1.91:1 (approximately). LinkedIn crops to this ratio. Facebook displays it at this ratio. Deviations cause unexpected crops.
  • File size: Keep under 1MB for broad compatibility. Facebook accepts up to 8MB. LinkedIn and Slack are stricter. 300–600KB for a JPEG or WebP image is a reasonable target.
  • Format: JPEG and PNG are universally supported. WebP works on most modern scrapers. Avoid SVG — most social scrapers do not render it.
  • HTTPS: The image URL must use HTTPS. HTTP images are silently dropped by Twitter. Some platforms will refuse to load them entirely.
  • Absolute URL: The og:image value must be a fully qualified URL including protocol and domain. Relative paths are not followed.
  • Text readability: The image is displayed at roughly 500px wide on most platforms. Any text in the image needs to be large enough to read at that size. Aim for at least 24px equivalent at the full 1200px width.

Debugging Share Previews

Each major platform caches share previews aggressively. When you update meta tags, you must force a re-scrape — the old preview will continue showing until then.

PlatformToolNotes
FacebookSharing DebuggerClick “Scrape Again” to force cache refresh. Shows all OG tags it found.
LinkedInPost InspectorRequires LinkedIn login. Updates cache on each inspection.
Twitter / XCard ValidatorShows a live preview of the card. Validates twitter:card type.
SlackNo official toolPaste the URL into a Slack message. Add ?t=1 as a cache buster to force re-fetch.
All platformsMeta Tags GeneratorPreview all card types locally before deploying.

The Facebook Sharing Debugger is the most useful general-purpose tool. It shows every OG tag it found, flags missing required tags, reports the image dimensions it detected, and lets you force a cache refresh. Use it as your primary debugging tool even for non-Facebook sharing.

JSON-LD vs Meta Tags

JSON-LD is a separate mechanism from meta tags. It uses a <script type="application/ld+json"> block to embed structured data in the page, following the vocabulary from schema.org. It powers Google rich snippets — the star ratings, FAQ dropdowns, breadcrumbs, and event dates you see in search results.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "Meta Tags SEO Guide",
  "description": "A complete guide to HTML meta tags for SEO and social sharing.",
  "author": {
    "@type": "Organization",
    "name": "DevToys Pro"
  },
  "publisher": {
    "@type": "Organization",
    "name": "DevToys Pro",
    "logo": {
      "@type": "ImageObject",
      "url": "https://devtoys.pro/logo.png"
    }
  },
  "datePublished": "2026-04-20",
  "image": "https://devtoys.pro/og/meta-tags-seo-guide.png"
}
</script>

Common schema types and their effects in search results:

  • Article / BlogPosting — Enables article rich snippets including publication date and author.
  • Organization — Adds a knowledge panel for your brand in Google Search.
  • Product — Enables price, availability, and review stars in product listings.
  • FAQPage — Renders expandable FAQ items directly in the search result.
  • BreadcrumbList — Shows breadcrumb navigation paths in search snippets.
  • SoftwareApplication — Shows app ratings and pricing in search results.

JSON-LD and meta tags serve different purposes and complement each other. Meta tags control how browsers and social platforms display your page. JSON-LD tells search engines what the content means structurally. You need both. A page with perfect OG tags but no JSON-LD misses rich snippet eligibility. A page with JSON-LD but no OG tags will share poorly on social platforms.

Framework Integration

Modern frameworks provide first-class APIs for managing meta tags so you never need to write raw HTML head tags manually.

Next.js (App Router)

The App Router uses a typed metadata export. Next.js generates all the corresponding HTML tags automatically.

// app/blog/my-post/page.tsx
import type { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'My Post Title',
  description: 'A short description of the post.',
  keywords: 'keyword one, keyword two',
  alternates: {
    canonical: '/blog/my-post',
  },
  openGraph: {
    title: 'My Post Title',
    description: 'A short description of the post.',
    images: [{ url: 'https://example.com/og/my-post.png', width: 1200, height: 630 }],
    type: 'article',
    publishedTime: '2026-04-20',
  },
  twitter: {
    card: 'summary_large_image',
    title: 'My Post Title',
    description: 'A short description of the post.',
    images: ['https://example.com/og/my-post.png'],
  },
};

For dynamic pages (e.g. blog posts loaded from a CMS), use generateMetadata instead:

export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
  const post = await fetchPost(params.slug);
  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      images: [{ url: post.ogImage, width: 1200, height: 630 }],
    },
  };
}

Other Frameworks

// Remix
export const meta: MetaFunction = () => [
  { title: 'My Page' },
  { name: 'description', content: 'Page description.' },
  { property: 'og:image', content: 'https://example.com/og.png' },
];

// Nuxt 3 (Vue)
useHead({
  title: 'My Page',
  meta: [
    { name: 'description', content: 'Page description.' },
    { property: 'og:image', content: 'https://example.com/og.png' },
  ],
});

// Gatsby (React Helmet)
<Helmet>
  <title>My Page</title>
  <meta name="description" content="Page description." />
  <meta property="og:image" content="https://example.com/og.png" />
</Helmet>

Per-Route Dynamic OG Images

Static og:image files require manual creation for every page. Dynamic OG image generation renders images on-demand from templates, which is essential for blogs, product pages, and any content that changes frequently.

Next.js with @vercel/og

// app/og/route.tsx
import { ImageResponse } from 'next/og';

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const title = searchParams.get('title') ?? 'Default Title';

  return new ImageResponse(
    (
      <div
        style={{
          display: 'flex',
          width: '1200px',
          height: '630px',
          background: '#0f172a',
          alignItems: 'center',
          justifyContent: 'center',
          padding: '80px',
        }}
      >
        <h1 style={{ color: '#f8fafc', fontSize: '64px', fontWeight: 700 }}>
          {title}
        </h1>
      </div>
    ),
    { width: 1200, height: 630 }
  );
}

Then reference it in your metadata with a URL pointing to the route, passing the page title or other identifiers as query parameters:

openGraph: {
  images: [{
    url: `/og?title=${encodeURIComponent(post.title)}`,
    width: 1200,
    height: 630,
  }],
}

Cloudinary Dynamic Transforms

If you use Cloudinary, you can generate OG images by compositing text overlays onto a base image using URL transforms — no server-side code required:

https://res.cloudinary.com/demo/image/upload/
  w_1200,h_630,c_fill/
  l_text:Arial_56_bold:My%20Post%20Title,co_white,g_south_west,x_80,y_80/
  base-og-template.jpg

Common Pitfalls

  • Cached share previews: When you update og:image or og:title, social platforms serve the old cached version for days. Always use the platform’s scraping debugger to force a refresh after deploying tag changes.
  • Missing og:url: Without og:url, Facebook uses the current request URL, which may include query strings or session tokens. This causes multiple cache entries and split like counts. Always set og:url to the canonical URL.
  • Large og:image files: Images over 1MB will be refused by some scrapers or cause timeouts. Compress your og:image to under 500KB using JPEG or WebP.
  • HTTP og:image URL: Twitter silently drops images served over HTTP. If your og:image URL starts with http://, the Twitter Card will render without an image. Always use HTTPS.
  • Relative og:image paths: /images/og.png is not a valid og:image value. Social scrapers do not know your domain. Always use the full absolute URL.
  • Duplicate meta tags: Having two og:title tags (common when a layout and a page both set them) causes unpredictable behavior. Frameworks like Next.js handle merging automatically, but custom setups need to ensure only one instance of each tag exists.
  • Confusing og:title with the page title: The HTML <title> tag is what appears in browser tabs and search result titles.og:title is what appears in social share previews. They can and often should differ — the og:title can be shorter and more conversational.

Build and preview all the meta tags covered in this guide — including Open Graph, Twitter Cards, and JSON-LD — using the Meta Tags Generator. For more tools in the generators category, see the Generators Guide.