Open Graph: A Guide to Meta Tags for SEO and AEO
1. What is the Open Graph protocol
The Open Graph protocol is a set of <meta> tags that tell other sites how to display your page when someone shares its URL. Paste a link into Slack, Discord, WhatsApp, or LinkedIn and you usually get a small card with a title, a short description, and an image. That card is the unfurl, and the metadata driving it is usually Open Graph.
Facebook published the spec in 2010 to let third-party pages declare themselves as “objects” in Facebook’s social graph: a movie page could announce itself as a movie, a recipe page as a recipe, and Facebook’s “Like” button would create a typed edge between the user and the object. The graph-of-objects framing mostly didn’t pan out. The metadata format did. Every consumer that wants to render a link preview now reads the same handful of <meta property="og:*"> tags.
OG isn’t a W3C standard or a formally maintained spec. ogp.me is the canonical reference, but it has barely changed since the early 2010s. The protocol stuck because it was good enough and nobody had an incentive to replace it. Twitter, LinkedIn, Slack, and the rest all built parsers around it, and it stuck.
2. The core tags
OG defines four required properties (og:title, og:type, og:image, og:url) plus a small set of practically-required optionals. A working unfurl needs ten tags or so; everything else is niche.
Here’s the minimum for an article-style page:
<meta property="og:title" content="Open Graph Protocol" />
<meta property="og:type" content="article" />
<meta property="og:image" content="https://example.com/og/open-graph-protocol.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="Open Graph Protocol: a general guide" />
<meta property="og:url" content="https://example.com/topics/web-development/open-graph-protocol" />
<meta property="og:description" content="A general guide to the Open Graph protocol, the meta tags that drive social previews, and why it matters for SEO and AEO." />
<meta property="og:site_name" content="example.com" />
<meta property="og:locale" content="en_US" />That’s the actual block of HTML for a typical post. Each tag below.
2.1. og:title
The title shown on the unfurl. Should not duplicate site branding (“Post Name | sitename.com”) because the card already shows the site name separately and the duplicate crowds the preview. In the case of an article, you would set OG title to the post title only (name of the article).
2.2. og:type
Tells consumers what kind of page this is. website is the default for a generic page, article for blog posts and long-form content, profile for an “about me” page. Type gates type-specific properties (an article can declare article:published_time and article:author), and some platforms render article cards differently from website cards. Section 3 goes deeper. For now: pick one of website, article, or profile and you’ve handled 95% of pages.
2.3. og:image
The card’s hero image, and the highest-signal field on the unfurl by a wide margin. A clean, on-brand image dramatically affects whether anyone clicks the link.
Most consumers expect 1200×630 pixels (a 1.91:1 aspect ratio). Cards with smaller images often get downgraded to a small-thumbnail layout or skipped entirely. PNG and JPEG are universally supported; WebP works on most consumers but not all, and iMessage has been historically stubborn. Use an absolute URL — relative paths break in some parsers.
Three companion tags shown in the main block above carry image metadata. og:image:width and og:image:height let consumers reserve layout space before the image loads (the difference between a card that renders cleanly and one that visibly reflows), and og:image:alt is the screen-reader text and should describe the image, not duplicate the title. These are technically optional but their absence is visible. Skipping them is the most common reason an unfurl looks broken.
2.4. og:url
The canonical URL of the page. Must be absolute. Should match the page’s <link rel="canonical"> if one exists. The tag exists because URL shorteners, tracking parameters, and consent-banner query strings routinely produce multiple URLs that all resolve to the same content; og:url tells consumers which one to attribute the share to.
2.5. og:description
A short summary of the page, typically 60-160 characters. Technically optional in the spec, practically required because most card layouts include a description line, and the alternative is for the consumer to pick something itself — usually badly, by grabbing the first paragraph of body copy. Keep it under 160 characters because some consumers truncate around there.
The description should be substantively different from the title. “Open Graph Protocol” plus “Open Graph Protocol explained” wastes the description slot.
2.6. og:site_name and og:locale
og:site_name is the human-readable name of the site the page belongs to (“emrebener.com”, or “The New York Times”). It’s the small text that appears above or below the title on most cards. og:locale is the page’s language tag in language_TERRITORY form (en_US, tr_TR). Most consumers ignore locale, but Facebook uses it to translate platform-injected UI on the card. Set both; don’t expect them to visibly change anything.
3. og:type and what it implies
og:type declares the kind of object your page represents, which gates a set of type-specific properties some consumers read. In practice, three values cover almost every real page: website, article, profile. The rest of the type vocabulary (book, video.movie, music.song, video.episode, and so on) was designed for a world where Facebook would model every domain as typed nodes in a graph, and outside a few large media platforms that world never materialized.
3.1. The three types you’ll likely use
website is the default. Use it for landing pages, marketing pages, app dashboards, anything that isn’t more specifically something else. Most card consumers treat it as the generic case and render a basic card.
When in doubt, use
websiteas the type. It’s the safe default.
article is for any long-form text content: blog posts, news stories, essays, documentation. It unlocks a small set of optional properties under the article: prefix:
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2026-05-08T00:00:00Z" />
<meta property="article:modified_time" content="2026-05-08T00:00:00Z" />
<meta property="article:author" content="https://example.com/about" />
<meta property="article:section" content="Web Development" />
<meta property="article:tag" content="Open Graph" />These show up inconsistently across consumers. LinkedIn and some niche readers surface article:published_time to display “posted X days ago” on the card, and most platforms ignore everything past og:type=article. The properties are cheap to add and don’t hurt, so set them on long-form pages.
profile is for personal “about” or author pages. It unlocks profile:first_name, profile:last_name, profile:username, and profile:gender. Most consumers ignore these too, but Facebook uses them for follow-button rendering on profile cards.
3.2. There is more
OG defines a deep type vocabulary for media-heavy pages: video.movie, music.song, book, and a handful of others, each with its own required property namespace (music.song carries music:duration, music:album, music:musician, and so on). These are useful for IMDb, Spotify, or a publisher whose pages map cleanly onto a media object; for a personal blog or product site, they’re not. Setting one incorrectly can render the card worse than og:type=website would have, because consumers expecting the namespaced properties find them missing.
Use
websiteunless you know you need otherwise.
3.3. When type actually changes the card
Most consumers render every type the same way: hero image, title, description, site name. Type matters in a handful of specific cases:
- LinkedIn has tended to favor
articleshares in feed ranking on the assumption that articles are content people want to read. - Facebook treats articles slightly differently from generic web pages (different “save for later” affordances, different attribution UI).
- Twitter / X mostly ignores
og:typeand falls back to its owntwitter:cardvalue (covered in section 4). - iMessage, Slack, and Discord ignore type entirely and render based on title, image, and description alone.
So og:type is closer to a metadata hint than a layout directive. Set it correctly because the hint occasionally matters, but don’t expect it to transform how your card looks.
4. Twitter Cards: the parallel standard
Twitter Cards is Twitter/X’s own metadata standard for link previews, parallel to OG and largely overlapping with it. In practice the situation is simple. X reads your OG tags for almost everything (title, description, image, URL), and you need one Twitter-specific tag to pick the card layout. Everything else can be cut.
4.1. The short history
Twitter introduced Cards in 2012, two years after OG launched, with its own format and a per-domain manual-review requirement to render. That friction was quietly dropped, and twitter:image and most other twitter:* properties were updated to fall back to their OG equivalents. The spec still exists at developer.x.com, but X’s parser is mostly an OG parser with one extra tag for layout selection.
4.2. The one tag worth setting
You should still set
twitter:card, but most othertwitter:*tags are optional if your OG tags are good.
twitter:card picks the card layout. Two values matter:
<meta name="twitter:card" content="summary_large_image" />
<!-- or -->
<meta name="twitter:card" content="summary" />summary_large_image renders the standard 1200×630 hero card, which is what you almost always want. summary renders a smaller card with a square thumbnail to the left of the title and description, used for pages without a card-quality image.
Two other values exist (app, player) for app-install cards and embedded media players. They require additional Twitter-specific properties and a publisher relationship; for a typical website, ignore them.
Note the attribute name: Twitter Cards use name= (the standard <meta> attribute), not property= like OG. This is a minor inconsistency that trips up implementations copying templates without checking.
4.3. The fallback chain
For everything except twitter:card, X reads twitter:* first and falls back to og:* if the Twitter version is missing. So if you set og:title but no twitter:title, the card uses og:title. The same goes for og:description, og:image, and og:url.
That means the practical minimum on a page that already has full OG metadata is one tag:
<meta name="twitter:card" content="summary_large_image" />Two fields where a Twitter-specific value still adds something: twitter:site (the @username of the site, displayed on the card) and twitter:creator (the @username of the article author). Both are optional but render nicely on the card if you have accounts to point to. They have no OG equivalent so there’s nothing for X to fall back to.
<meta name="twitter:site" content="@example" />
<meta name="twitter:creator" content="@author" />4.4. Should you still set Twitter Cards in 2026?
Yes, for the one twitter:card tag. Possibly for twitter:site and twitter:creator if the accounts exist.
However, don’t bother duplicating twitter:title, twitter:description, or twitter:image; they’re pure redundancy with OG and add maintenance burden when the metadata changes. Whether Twitter Cards itself still matters is a separate question, but the one tag takes thirty seconds; set it.
5. Why OG matters for SEO and AEO
OG isn’t a direct search-ranking signal, but it has real second-order effects on both SEO (search engine optimization, getting your pages ranked for keyword queries) and AEO (answer engine optimization, the newer discipline of getting your content cited or summarized by LLM-driven answer engines). It matters meaningfully for SEO, secondarily for AEO, and the cost of not having it is higher than most people realize.
5.1. The SEO case: indirect, not direct
Google has been clear, repeatedly, that OG tags are not a ranking factor. They don’t appear in the algorithm, they don’t influence keyword scoring, and you cannot game search rank by adding more og:* tags.
What OG does affect is click-through rate and shareability, both of which feed back into rank indirectly:
- Better unfurls drive more clicks. The unfurl is the entire surface area of a shared URL; a clean image, sharp title and concrete description get more clicks than a bare link. Clicks lead to reads, reads can lead to inbound links, and inbound links are a direct ranking signal.
- OG as SERP fallback. When the page’s
<title>and<meta name="description">are weak or missing, Google and Bing have been observed pulling from OG for the SERP (search engine results page) snippet.og:titleandog:descriptionact as a backstop. - Metadata as a quality signal. Pages with complete metadata correlate with well-maintained pages. Search engines don’t list OG as a ranking factor, but the correlation between metadata hygiene and crawler-perceived quality is real.
The honest framing: OG is a low-effort, high-leverage hygiene item. It doesn’t move you up the rankings on its own, but its absence makes every share a worse share. Over a year that compounds.
5.2. The AEO case: real but secondary
Answer engines (ChatGPT, Perplexity, Claude, Google AI Overviews, Bing Copilot) rely on a different signal mix than traditional search. They synthesize answers from page content rather than ranking pages against a query. The metadata they value most is the kind that explicitly describes what the page is about.
OG contributes here, but less directly than its sibling, JSON-LD/schema.org. The rough hierarchy of what answer engines pay attention to:
- Page body content. The actual prose. This is the strongest signal; if the page doesn’t say what you want to be cited for, no metadata fixes it.
- JSON-LD with schema.org types.
Article,FAQPage,HowTo,Person. Answer engines extract author, publish date, and topic from these directly. - Open Graph. Title, description, image, type. Used as a fallback when JSON-LD is missing, and read alongside it as a confidence signal.
- Plain
<meta>tags.<meta name="description">,<title>. The legacy baseline.
So OG matters for AEO, but if you’re optimizing primarily for answer engines, JSON-LD is the larger lever. A separate post on JSON-LD and schema.org will cover that in depth. This section is the short version of why both standards exist and how they overlap.
5.3. The cost of not having OG
The argument for adding OG isn’t that you’ll rank higher. It’s that the absence of OG actively costs you:
- Every share renders as a naked link or a degraded card, and the click rate drops.
- Answer engines fall back to weaker signals when OG is missing, raising the chance of being summarized poorly or skipped for a better-tagged competitor.
- Internal tools (Slack, Notion, Linear, Confluence, Discord) all unfurl links; a teammate sharing your post in a Slack thread sees the same broken card as everyone else.
Table stakes. Not a competitive edge, but the cost of being on the field.
6. Debugging unfurls
When a card looks broken, the answer is almost always one of three things: a stale cache on the consumer side, a missing or malformed tag, or an image the consumer can’t fetch. Each major platform has a validator tool that fetches your URL fresh and shows what its parser sees, which short-circuits the guessing.
6.1. The validators
- Facebook Sharing Debugger (developers.facebook.com/tools/debug/). The reference implementation. Fetches your URL, shows parsed OG values, lists warnings, and exposes a “Scrape Again” button that forces Facebook to re-crawl and bust its cache.
- LinkedIn Post Inspector (linkedin.com/post-inspector/). Similar shape to Facebook’s. LinkedIn’s cache is notably aggressive; the inspector is the only practical way to refresh it.
- X / Twitter Card Validator. X removed the public Card Validator a few years back. The current substitute is to post (or draft) a tweet and check how the card renders, which is awkward but works. Third-party tools fill the gap for layout previews.
- Generic OG previewers (opengraph.xyz, metatags.io, socialsharepreview.com) render an approximation of how a typical consumer parses your tags. Useful for quick checks; less authoritative than the platform-native tools.
6.2. The cache problem
Once a consumer fetches your URL and parses the metadata, it caches the result. Re-sharing the same URL reuses the cached card. That’s what you want for performance, and what you don’t want when you’ve just fixed a typo in og:title and need to verify it.
For Facebook, LinkedIn, and similar platforms, the validators listed above double as cache busters. Slack and Discord cache for hours to a few days; the reliable workaround is to append a no-op query parameter (?v=2) that the consumer treats as a different URL.
iMessage is the worst case. Apple’s Link Presentation service caches results indefinitely and exposes no public way to bust it. The accepted workarounds are ugly: change the URL, wait days, or test on a fresh device. No equivalent of Facebook’s “Scrape Again.”
6.3. A short troubleshooting checklist
When a card is broken:
- Verify the tags are in the server-sent HTML. If your page is rendered client-side (React without SSR, Vue without prerender), the OG tags must be in the HTML the crawler receives, not injected by JavaScript. Most crawlers don’t run JS. Check with
curl -s URL | grep og:or the browser’s view-source. - Run it through Facebook Sharing Debugger. Even if you don’t care about Facebook, the parsed-values panel and warnings list catch most issues (missing required tags, image too small, HTTP-only image URL on an HTTPS page).
- Verify the image fetches. Open
og:imagedirectly in a browser. A 404, a redirect chain, or a URL behind authentication breaks the card silently. - Check the URL matches.
og:urlmust be the canonical absolute URL of the page. Cards that point to the wrong URL attribute engagement to the wrong page. - Bust the cache and retry. If everything looks right but the unfurl is still wrong, the consumer is probably caching a previous version. Use the platform’s debugger or a query-string URL change.
7. Where OG ends and JSON-LD begins
OG and JSON-LD are sibling structured-metadata standards that live in <head> and get consumed by automated readers, but the consumers and the shape of the data are different. OG is a flat list of <meta property="og:*"> tags read by social-media unfurlers. JSON-LD is structured JSON inside a <script type="application/ld+json"> tag, read by search engines and increasingly by answer engines, capable of expressing things OG can’t: typed entities, nested relationships, multiple authors, citations, FAQ pairs.
A typical page wants both. The overlap is real (title, description, and image appear in both formats), and setting them with consistent values across the two is the right move. Different values actively confuse crawlers; consistency matters more than which format “wins” on a given field.
Where OG ends:
- The vocabulary is small and effectively frozen.
- It describes the page, not the entities on it: there’s no way to say “this article is about three people, here are their names and Wikidata IDs.”
- No relationships, no citations, no structured Q&A.
Where JSON-LD picks up:
- It uses schema.org, a vocabulary maintained by Google, Microsoft, Yahoo, and Yandex with hundreds of types.
- It can model the page’s content graph: author as a
Person, article as aBlogPosting, citations as typed references. - Answer engines parse it directly; LLMs extract from structured JSON more accurately than from prose.
OG handles “what does this URL look like when shared.” JSON-LD handles “what does this page mean.” A separate post covers JSON-LD and Schema.org in the same general-guide form. OG is the smaller of the two jobs: set the ten tags from section 2, run a validator when something looks off, and most of the work is done.