env.dev

Open Graph Protocol: Complete Guide to Social Sharing Meta Tags (2026)

How to use Open Graph meta tags in 2026: required fields, image sizes for Facebook/LinkedIn/X/Slack, Twitter Cards, dynamic OG images, debugging, caching, and measurable SEO impact.

Last updated:

Open Graph is the metadata protocol that turns a URL into a rich social card on Facebook, LinkedIn, X, Slack, Discord, WhatsApp, iMessage, Telegram, and every AI chat that unfurls links. Add four <meta property="og:..." /> tags to your <head> and a page goes from a naked blue hyperlink to a 1200×630 preview with a title, description, and image. Open Graph was published by Facebook in 2010 and remains the de-facto standard in 2026: the ogp.me specification hasn't changed, but platform rendering rules, image size expectations, and the rise of LLM-powered link unfurling have reshaped the best practices around it.

Why Does Open Graph Matter?

Open Graph is the single highest-leverage change you can make to how your URLs perform outside your own site. The cost is four lines of HTML; the upside compounds across every channel a link can be shared in.

  • Click-through rate. A rich preview card lifts CTR on shared links by roughly 30–40% over a naked URL. On a link that gets 10k social impressions, that is 3–4k extra visits per post.
  • First impression for free traffic. Most visitors from LinkedIn, Slack, Reddit, Discord, iMessage, and X see your OG card before they ever see your site. It is your real homepage for 60–80% of social sessions.
  • Brand consistency. Without OG tags, every platform guesses — a random image from your page, a truncated <title>, or nothing at all. With OG tags, every platform shows the exact title, image, and description you chose.
  • AI and LLM citation. GPTBot, ClaudeBot, PerplexityBot, and Google's AI crawlers read og:title, og:description, and article:modified_time when choosing which pages to surface in answers. Fresh, well-described pages get cited; stale or unlabeled ones get skipped.
  • Indirect SEO. OG is not a Google ranking signal, but the downstream effects are: more clicks from shares → more branded search → longer sessions → stronger authority signals for the pages Google does rank.
  • Share consolidation. A canonical og:url makes likes, shares, and reactions aggregate to one URL instead of fragmenting across UTM and tracking variants.
  • It is table stakes in 2026. Missing OG tags read as neglect — the social equivalent of a broken favicon. Competitors have them; readers notice when you don't.

What Is the Open Graph Protocol?

Open Graph (OG) is a set of <meta> tags placed inside the <head> of an HTML document. Each tag uses a property="og:*" attribute instead of the usual name="...", because Open Graph is an RDFa vocabulary — a structured way to attach semantic data to a page. When a platform fetches your URL, its crawler parses these tags and uses them to render a preview card.

Minimal Open Graph setup in <head>
<meta property="og:type"        content="website" />
<meta property="og:url"         content="https://env.dev/guides/opengraph" />
<meta property="og:title"       content="Open Graph Protocol: Complete Guide" />
<meta property="og:description" content="How to use Open Graph meta tags in 2026." />
<meta property="og:image"       content="https://env.dev/og/opengraph.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt"   content="Open Graph guide cover, 1200x630" />

Two critical rules: tags must be server-rendered in the initial HTML — most social crawlers do not execute JavaScript, so client-side frameworks that inject meta tags with useEffect produce empty previews. And URLs must be absolute HTTPS: every major platform drops http:// images silently.

Which Open Graph Tags Are Required?

The spec defines four required properties. Everything else is optional but compounding — the more you add, the better every platform renders your card.

TagRequired?PurposeNotes
og:titleYesPreview headlineKeep ≤ 60 chars desktop, 40 mobile; no brand suffix
og:typeYesContent categorywebsite, article, video.movie, music.song, profile, book
og:imageYesPreview image URLAbsolute HTTPS, JPG/PNG, 1200×630, ≤ 5 MB
og:urlYesCanonical URLStrip query params; this is where shares aggregate
og:descriptionRecommendedPreview body2–4 sentences, ≤ 200 chars
og:site_nameRecommendedSite identityShown above the card on most platforms
og:localeOptionalPrimary languagee.g. en_US; add og:locale:alternate for others
og:image:widthRecommendedImage width in pxLets crawlers render on first share
og:image:heightRecommendedImage height in pxPrevents async re-fetch delays
og:image:altRecommendedImage alt textScreen readers + AI crawler context

The og:type value unlocks an extra namespace of properties. For articles, add article:published_time, article:modified_time, article:author, and article:tag. These feed directly into LinkedIn's freshness signal and are read by LLM crawlers when citing content.

Article-type extension tags
<meta property="og:type"                content="article" />
<meta property="article:published_time" content="2026-04-22T09:00:00Z" />
<meta property="article:modified_time"  content="2026-04-22T09:00:00Z" />
<meta property="article:author"         content="https://env.dev/about" />
<meta property="article:section"        content="Web Standards" />
<meta property="article:tag"            content="opengraph" />
<meta property="article:tag"            content="seo" />

What Are the Correct OG Image Dimensions in 2026?

One image at 1200×630 pixels (1.91:1) satisfies every major platform — Facebook, LinkedIn, Discord, Slack, WhatsApp, iMessage, and Telegram all render it cleanly. X/Twitter prefers 1200×675 (16:9) but crops 1200×630 with minimal loss. Going below 600×315 forces a fallback to the small summary card on most networks.

PlatformRecommended sizeAspect ratioNotes
Facebook1200 × 6301.91:1Minimum 600×315; max 8 MB
LinkedIn1200 × 6271.91:1Cache lives ~7 days; hard to force refresh
X / Twitter1200 × 67516:9Works with 1200×630; falls back to og:image
Discord1200 × 6301.91:1Max 8 MB; supports GIF and WebP
Slack1200 × 6301.91:1Honors og:image:alt for screen readers
WhatsApp1200 × 6301.91:1≤ 300 KB or it may be dropped on mobile
iMessage1200 × 6301.91:1Uses Apple Link Presentation; respects og:image
Telegram1200 × 6301.91:1Caches aggressively; append ?v=2 to URL to bust

File Format and Size Rules

  • JPG or PNG — universally supported. PNG for logos and text, JPG for photos.
  • WebP — works on Facebook, X, LinkedIn, Slack, Discord, but not on every older crawler. Safe as a primary, risky as the only format.
  • AVIF — only Facebook renders it reliably in 2026. Don't use it as your og:image.
  • GIF — shows the first frame as a static image on most platforms. Only Discord animates it.
  • Target file size ≤ 300 KB for WhatsApp compatibility; hard limit is 8 MB on Facebook and Discord.

How Do X (Twitter) Cards Work With Open Graph?

X/Twitter runs its own Twitter Cards protocol, but the crawler falls back to Open Graph when a Twitter-specific tag is missing. That means you only need one extra tag to opt into the large image layout: twitter:card. Everything else can reuse your OG tags.

Twitter Card with Open Graph fallback
<!-- OpenGraph tags (shared with all other platforms) -->
<meta property="og:title"       content="Open Graph Protocol: Complete Guide" />
<meta property="og:description" content="How to use Open Graph meta tags in 2026." />
<meta property="og:image"       content="https://env.dev/og/opengraph.png" />
<meta property="og:url"         content="https://env.dev/guides/opengraph" />

<!-- Twitter-specific additions -->
<meta name="twitter:card"        content="summary_large_image" />
<meta name="twitter:site"        content="@envdotdev" />
<meta name="twitter:creator"     content="@envdotdev" />
<!-- twitter:title, twitter:description, twitter:image are all optional -->
<!-- If omitted, X will fall back to og:title / og:description / og:image -->

Note the attribute difference: Twitter Cards use name="twitter:..." (standard HTML meta attribute), while Open Graph uses property="og:..." (RDFa). Both are valid HTML5 and both work in the same <head>.

twitter:card valueLayoutWhen to use
summarySmall square thumbnail + textShort posts, profile links
summary_large_imageFull-width 1.91:1 image + textBlog posts, articles, marketing pages (default choice)
appApp Store / Play Store cardMobile app landing pages
playerEmbedded video / audio playerVideo content with a playable stream

How Do You Generate Dynamic OG Images?

A static site-wide image is fine for a landing page but looks amateur on a blog. Every blog post sharing the homepage image is one of the most visible signals of poor Open Graph implementation. Dynamic OG images — generated on demand per URL — are the 2026 default for any content site. The two common approaches:

1. Runtime image generation (JSX → PNG)

Vercel's @vercel/og library (bundled into next/og) uses Satori to render a JSX tree to SVG, then Resvg to rasterize to PNG — all inside an edge function. The output is cached at the CDN, so the second render is essentially free.

Next.js App Router: /app/og/[slug]/route.tsx
import { ImageResponse } from 'next/og';

export const runtime = 'edge';

export async function GET(req: Request, { params }: { params: { slug: string } }) {
  const post = await getPost(params.slug);

  return new ImageResponse(
    (
      <div style={{ display: 'flex', flexDirection: 'column', width: '100%', height: '100%',
                    background: '#0b1020', color: 'white', padding: 80, justifyContent: 'space-between' }}>
        <div style={{ fontSize: 72, fontWeight: 700, lineHeight: 1.1 }}>{post.title}</div>
        <div style={{ fontSize: 28, opacity: 0.7 }}>env.dev · {post.date}</div>
      </div>
    ),
    { width: 1200, height: 630 },
  );
}

Then point og:image at the route: <meta property="og:image" content="https://env.dev/og/my-post" />. Constraints: only flexbox layouts, max 500 KB bundle including fonts, and only .ttf / .otf / .woff fonts.

2. Build-time prerendering

For static sites, render images at build with Playwright or Satori and commit the PNGs. Zero runtime cost, but every content change triggers a rebuild. Works well when content volume is low or the build is already fast.

Build-time OG generation with Satori + Resvg
import satori from 'satori';
import { Resvg } from '@resvg/resvg-js';
import { writeFile } from 'node:fs/promises';

for (const post of await loadAllPosts()) {
  const svg = await satori(
    { type: 'div', props: { style: { /* ... */ }, children: post.title } },
    { width: 1200, height: 630, fonts: [/* ttf buffer */] },
  );
  const png = new Resvg(svg).render().asPng();
  await writeFile(`public/og/${post.slug}.png`, png);
}

How Do Open Graph Tags Affect SEO?

Open Graph tags are not a direct Google ranking signal — Google uses its own <title>, <meta name="description">, and structured data. The SEO impact is indirect but measurable:

  • Better previews lift click-through rate on shared links — industry benchmarks put the uplift at +30–40% vs. a naked URL.
  • More clicks → more branded search volume and return visits → signals Google associates with authority.
  • LinkedIn, Reddit, and Hacker News all strip tracking parameters differently. A canonical og:url makes shares aggregate to one URL instead of fragmenting social proof across UTM variants.
  • AI crawlers (GPTBot, ClaudeBot, PerplexityBot) read article:published_time and og:description when deciding whether to cite a page. Content older than three months without a refreshed article:modified_time sees meaningful AI citation drops.

Open Graph does not replace JSON-LD structured data. The two complement each other: OG drives the social card, Schema.org Article drives the Google rich result. Set both with matching titles, descriptions, and dates.

OG + JSON-LD side by side
<meta property="og:title"       content="Open Graph Protocol: Complete Guide" />
<meta property="og:description" content="How to use Open Graph meta tags in 2026." />
<meta property="article:published_time" content="2026-04-22T09:00:00Z" />
<meta property="article:modified_time"  content="2026-04-22T09:00:00Z" />

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "Open Graph Protocol: Complete Guide",
  "description": "How to use Open Graph meta tags in 2026.",
  "datePublished": "2026-04-22",
  "dateModified":  "2026-04-22",
  "author": { "@type": "Organization", "name": "env.dev" }
}
</script>

How Do You Debug and Monitor Open Graph Tags?

Every platform caches previews — typically 24–72 hours on Facebook, up to 7 days on LinkedIn, and indefinitely on Slack and Telegram until a user-side clear. Debugging means two things: inspecting what a crawler sees, and forcing a refresh after you change a tag.

Facebook Sharing Debugger

Parses your URL, shows the exact OG tags seen, and has a "Scrape Again" button that bumps the cache immediately.

developers.facebook.com/tools/debug

LinkedIn Post Inspector

Previews the LinkedIn card. Hitting Inspect bumps the cache, but LinkedIn may still serve the old image for up to a week.

linkedin.com/post-inspector

X Card validator

Deprecated in 2023. Use opengraph.xyz, microlink.io, or a throwaway post in your drafts to preview.

opengraph.xyz

Slack / Discord / WhatsApp

No official debugger. Send the URL to yourself in a private channel — but remember these platforms cache aggressively.

self-test

curl -A "facebookexternalhit"

See exactly what a crawler sees. Swap the user-agent for Twitterbot, LinkedInBot, Slackbot-LinkExpanding, WhatsApp, TelegramBot.

CLI

Cache-buster query

Append ?v=2 to og:url and og:image when you genuinely change content — platforms treat new query strings as new URLs.

manual
Inspect what a crawler actually sees
# Facebook
curl -sL -A "facebookexternalhit/1.1" https://env.dev/guides/opengraph \
  | grep -Eo '<meta (property|name)="(og|twitter):[^"]+" content="[^"]+"'

# X / Twitter
curl -sL -A "Twitterbot/1.0" https://env.dev/guides/opengraph | grep 'twitter:'

# LinkedIn
curl -sL -A "LinkedInBot/1.0 (compatible; Mozilla/5.0; Apache-HttpClient +http://www.linkedin.com)" \
  https://env.dev/guides/opengraph | grep 'og:'

# Slack
curl -sL -A "Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots)" \
  https://env.dev/guides/opengraph | grep 'og:'

For production monitoring, snapshot your OG tags in a scheduled job and alert when og:image returns a non-200 or the tag shape drifts. A single missing tag on a popular page can cost thousands of impressions per day of social traffic.

Tools to Validate and Monitor Your Setup

Two third-party tools cover the one-off and the continuous case:

  • opengraph.xyz — paste any URL and get a side-by-side preview of how it renders on Facebook, X, LinkedIn, Discord, Slack, and more. Useful for a quick sanity check before you ship.
  • sharescan.io — continuous monitoring for Open Graph regressions. Runs post-deploy checks via GitHub Actions, scores every page, diffs metadata between releases, and routes regressions to Slack. Free 10-URL scan without signup.

What Are Common OG Mistakes and How to Fix Them?

MistakeSymptomFix
Tags injected by JSPreview is blank or shows the fallback homepage cardRender tags in SSR/SSG initial HTML; never in useEffect
Relative image URLNo image in preview on any platformAlways use absolute https:// URL for og:image
Same og:image on every pageHomepage image appears on every blog post shareGenerate dynamic images per URL (see section above)
Missing og:image:width / heightImage shows on second share but not firstHardcode width/height so the crawler skips async parsing
Image > 300 KBWhatsApp drops the preview entirely on mobileOptimize to ≤ 300 KB; prefer JPG over PNG for photos
Cached old preview after editNew title/image shows in HTML but not on FacebookUse Sharing Debugger "Scrape Again" or append ?v=2 to og:url
Duplicate title/description tagsRandom tag wins; preview is inconsistent across platformsKeep one og:* tag per property; audit with curl or a debugger
Missing twitter:cardX shows a tiny summary card instead of the large imageAdd <meta name="twitter:card" content="summary_large_image">
og:url differs from canonicalShares aggregate across multiple URLs; social counters fragmentog:url must equal <link rel="canonical">
HTTP image instead of HTTPSPreview image never renders on modern platformsServe OG images over HTTPS; no exceptions

How Do Open Graph Tags Look in Different Frameworks?

Every modern meta-framework has a first-class API for OG tags — the key is that they render into the initial SSR HTML, not the client bundle.

Next.js App Router — export const metadata
// app/guides/opengraph/page.tsx
export const metadata = {
  title: 'Open Graph Protocol: Complete Guide',
  description: 'How to use Open Graph meta tags in 2026.',
  openGraph: {
    type: 'article',
    url: 'https://env.dev/guides/opengraph',
    title: 'Open Graph Protocol: Complete Guide',
    description: 'How to use Open Graph meta tags in 2026.',
    images: [{ url: 'https://env.dev/og/opengraph', width: 1200, height: 630, alt: 'Guide cover' }],
    publishedTime: '2026-04-22T09:00:00Z',
    modifiedTime: '2026-04-22T09:00:00Z',
  },
  twitter: { card: 'summary_large_image', site: '@envdotdev' },
};
TanStack Start / Router — head() function
// apps/web/src/routes/guides/opengraph.tsx
export const Route = createFileRoute('/guides/opengraph')({
  head: () => ({
    meta: [
      { title: 'Open Graph Protocol: Complete Guide' },
      { name: 'description', content: 'How to use Open Graph meta tags in 2026.' },
      { property: 'og:type',        content: 'article' },
      { property: 'og:url',         content: 'https://env.dev/guides/opengraph' },
      { property: 'og:title',       content: 'Open Graph Protocol: Complete Guide' },
      { property: 'og:description', content: 'How to use Open Graph meta tags in 2026.' },
      { property: 'og:image',       content: 'https://env.dev/og/opengraph.png' },
      { property: 'og:image:width', content: '1200' },
      { property: 'og:image:height', content: '630' },
      { name: 'twitter:card', content: 'summary_large_image' },
    ],
  }),
  component: OpengraphRoute,
});
Astro — static HTML in the layout
---
// src/layouts/Base.astro
const { title, description, image = '/og/default.png', type = 'website' } = Astro.props;
const url = new URL(Astro.url.pathname, Astro.site).toString();
const ogImage = new URL(image, Astro.site).toString();
---
<head>
  <title>{title}</title>
  <meta name="description" content={description} />
  <meta property="og:type"        content={type} />
  <meta property="og:url"         content={url} />
  <meta property="og:title"       content={title} />
  <meta property="og:description" content={description} />
  <meta property="og:image"       content={ogImage} />
  <meta name="twitter:card" content="summary_large_image" />
</head>

Frequently Asked Questions

Do Open Graph tags affect Google SEO rankings?

No, not directly. Google does not use og:title or og:description as ranking signals — it has its own <title> and meta description. The impact is indirect: better social previews lift click-through rate by roughly 30-40%, which increases branded traffic and return visits, which are signals Google does care about. Also, AI crawlers that feed LLM answers read Open Graph tags to decide which pages to cite.

What happens if I only add og:title, og:description, og:image, and og:url?

That is the correct minimum. The spec also requires og:type, but most platforms default to "website" when it is missing. For articles, add og:type="article" plus article:published_time and article:modified_time so LinkedIn and AI crawlers can sort by freshness.

What is the ideal OG image size in 2026?

1200 × 630 pixels at a 1.91:1 aspect ratio. One image at this size renders correctly on Facebook, LinkedIn, Discord, Slack, WhatsApp, iMessage, and Telegram, and is cropped acceptably by X. Keep the file under 300 KB if you want WhatsApp to show it on mobile.

Why does Facebook show an old preview after I update my page?

Facebook caches previews for 24-72 hours, keyed by og:url. Open the Sharing Debugger at developers.facebook.com/tools/debug, paste the URL, and click "Scrape Again". If the image URL itself changed, append a query parameter like ?v=2 — platforms treat new URLs as fresh content.

Do I need Twitter Cards if I already have Open Graph tags?

You need one extra tag: <meta name="twitter:card" content="summary_large_image">. Without it, X defaults to the small summary card even if you have a 1200×630 image. Everything else — title, description, image — falls back to your og:* tags automatically.

Can I set Open Graph tags with JavaScript?

Technically yes, practically no. Most social crawlers (Facebook, LinkedIn, X, Slack, WhatsApp) do not execute JavaScript and will see an empty <head>. Your OG tags must be in the server-rendered HTML. Use SSR, SSG, or a head manager that outputs tags during the initial response.

How do I generate a different OG image for every page?

Use a dynamic image generator. On Next.js or edge-function platforms, @vercel/og renders JSX to PNG at request time and caches the result at the CDN. On static sites, pre-render images at build time with Satori + Resvg. Either way, point og:image at a per-URL path like /og/{slug}.

What is the difference between og:url and the canonical link tag?

Functionally they should be identical — both declare the canonical URL for the page. og:url is the social aggregation target (where likes and shares accrue), and <link rel="canonical"> is the search engine signal. Always keep them in sync; mismatches split social counters across URL variants.

References

Was this helpful?

Frequently Asked Questions

Do Open Graph tags affect Google SEO rankings?

No, not directly. Google does not use og:title or og:description as ranking signals — it has its own <title> and meta description. The impact is indirect: better social previews lift click-through rate by roughly 30-40%, which increases branded traffic and return visits, which are signals Google does care about. AI crawlers that feed LLM answers also read Open Graph tags when deciding which pages to cite.

What is the ideal OG image size in 2026?

1200 × 630 pixels at a 1.91:1 aspect ratio. One image at this size renders correctly on Facebook, LinkedIn, Discord, Slack, WhatsApp, iMessage, and Telegram, and is cropped acceptably by X. Keep the file under 300 KB if you want WhatsApp to show it on mobile.

Why does Facebook show an old preview after I update my page?

Facebook caches previews for 24-72 hours, keyed by og:url. Open the Sharing Debugger at developers.facebook.com/tools/debug, paste the URL, and click "Scrape Again". If the image URL itself changed, append a query parameter like ?v=2 — platforms treat new URLs as fresh content.

Do I need Twitter Cards if I already have Open Graph tags?

You need one extra tag: <meta name="twitter:card" content="summary_large_image">. Without it, X defaults to the small summary card even if you have a 1200×630 image. Everything else — title, description, image — falls back to your og:* tags automatically.

Can I set Open Graph tags with JavaScript?

Technically yes, practically no. Most social crawlers (Facebook, LinkedIn, X, Slack, WhatsApp) do not execute JavaScript and will see an empty <head>. Your OG tags must be in the server-rendered HTML. Use SSR, SSG, or a head manager that outputs tags during the initial response.

What is the difference between og:url and the canonical link tag?

Functionally they should be identical — both declare the canonical URL for the page. og:url is the social aggregation target (where likes and shares accrue), and <link rel="canonical"> is the search engine signal. Always keep them in sync; mismatches split social counters across URL variants.

Stay up to date

Get notified about new guides, tools, and cheatsheets.