Learn/How to Add OG Image
How to Add an OG Image (HTML, Next.js, React)
Adding an OG image is mostly about doing boring things correctly: an absolute image URL, correct meta tags in the server-rendered HTML, and validating like a bot. This guide shows the exact tags and the common mistakes that break previews.
Step 1: create a 1200x630 image
Start with a universal size. If you are optimizing for one platform, you can go deeper later. For most sites, a single 1200x630 image is enough. Use the OG Image Generator to create one quickly.
Step 2: host the image on a public HTTPS URL
Social scrapers need to fetch the image without your browser. That means:
- No cookies required
- No login wall
- No IP restrictions
- No expiring signed URLs (or set long expirations)
If you use a CDN, make sure it does not block unknown user agents. If you use a storage provider, confirm the object is publicly readable.
Two extra checks that catch subtle failures:
- The image URL should return a real image content-type:
image/pngorimage/jpeg. - The image should be fast to fetch. If it is generated dynamically, cache it aggressively.
If you are choosing a hosting approach, here is the pragmatic ranking:
- Static file in your public assets (simplest, most reliable)
- CDN-backed static file (best performance, still reliable)
- Dynamic image endpoint (powerful, but adds failure modes)
"Reliable" matters because social bots are unforgiving. If your dynamic endpoint times out once, your preview may be cached in a broken state for hours.
Step 3: add Open Graph meta tags in your HTML head
Open Graph tags are HTML meta tags that describe your page to scrapers. The minimum useful set is:
<meta property="og:type" content="website" />
<meta property="og:url" content="https://example.com/page" />
<meta property="og:title" content="Your page title" />
<meta property="og:description" content="A short description of the page" />
<meta property="og:image" content="https://example.com/og.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />You can generate the full tag block (including Twitter tags) with Meta Tag Generator.
If you want a more complete, "boring but safe" head setup, this is a good baseline for most pages:
<link rel="canonical" href="https://example.com/page" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://example.com/page" />
<meta property="og:title" content="Your page title" />
<meta property="og:description" content="A short description of the page" />
<meta property="og:image" content="https://example.com/og.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="A short description of the OG image" />Optional but useful additions:
og:image:altfor accessibility and clarity in some preview surfaces.og:image:secure_urlif you want to explicitly provide the HTTPS variant.
Step 4: add Twitter Card tags
Twitter/X uses its own tags. The most common winning setup is a large image card:
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Your page title" />
<meta name="twitter:description" content="A short description of the page" />
<meta name="twitter:image" content="https://example.com/og.png" />If you run a brand account, you can also add twitter:site (your handle). It will not fix sizing, but it improves attribution and makes debugging a bit clearer.
Where to put the tags (and why ordering matters)
Put OG and Twitter tags in the <head> of the document and make sure they exist in the initial HTML response. Many preview failures come from tags that are injected late by client-side code, or from templates that accidentally output duplicates.
Practical rule: output one canonical set of tags per page. If your framework or CMS has a "default OG image", ensure page-level overrides replace it rather than adding a second og:image.
Do you need multiple og:image tags?
Open Graph supports multiple og:image tags, and some platforms may pick different images. For most teams, that flexibility is not worth the complexity. Start with one image and get it working everywhere.
Only consider multiple images if you have a clear reason, like a dedicated square image for a specific surface, and you are willing to test and maintain it.
Next.js (App Router) implementation notes
In Next.js App Router, do not rely on client-side effects to set meta tags. Scrapers often fetch the initial HTML. Use Next metadata APIs so the tags exist on first response.
A common mistake is generating an og:image URL without a fully-qualified base URL. In Next.js, you can set metadataBase (site origin) and then reference image paths safely.
// app/layout.tsx
export const metadata = {
metadataBase: new URL("https://example.com"),
};For a page-level OG image, you can set metadata in the page route:
// app/blog/[slug]/page.tsx
export const metadata = {
title: "Your page title",
openGraph: {
images: [{ url: "https://example.com/og/blog-post.png", width: 1200, height: 630 }],
},
twitter: {
card: "summary_large_image",
images: ["https://example.com/og/blog-post.png"],
},
};For a full walkthrough, see our Next.js guide. If you want a dynamic OG image endpoint, also read Dynamic OG.
React apps (non-SSR) and why previews fail
If your React app is purely client-rendered (SPA) and does not server-render meta tags, many scrapers will see an empty shell HTML. The result: missing OG tags, and broken previews.
This is why people say "OG tags do not work in my SPA". They do work, but only if the tags are in the HTML response. If you cannot server-render, consider pre-rendering important marketing pages or moving them to a framework route that supports SSR.
Fix options:
- Use an SSR framework (Next.js, Remix, etc.) for pages that need previews.
- Pre-render static pages with correct meta tags.
- Use a server/edge OG image endpoint for dynamic content (advanced).
Validate and refresh caches
After you deploy, validate the live URL. Do not validate your local dev server. Use:
- OG Validator for tag presence and basic preview correctness
- Site Audit if you need to check many pages
If the preview still shows the old image, it is almost always caching. See OG image not showing for a platform-by-platform cache flow.
How to verify like a scraper (quick tests)
If you want to debug confidently, test outside your browser. Browsers hide problems with cached responses, cookies, and dev tools. Scrapers are much simpler: they fetch HTML, then fetch the image.
A quick sanity check is to confirm the image URL returns an image content-type and a 200 status.
curl -I https://example.com/og.png
# Expect: 200 OK
# Expect: Content-Type: image/png (or image/jpeg)Then validate the HTML contains the tags you think it does:
curl -s https://example.com/page | rg "og:image|twitter:image|og:title"If these commands already look wrong, the platform preview will be wrong too. Fix the basics first.
If you have many pages: build-time generation vs dynamic generation
If you are adding OG images to one landing page, static images are perfect. If you have hundreds of blog posts, you need a strategy. There are two common approaches:
- Build-time generation: generate all images during your build and store them as static assets. This is reliable and cheap at runtime, but increases build time.
- Dynamic generation: generate images on-demand via an endpoint. This keeps builds fast but adds runtime complexity (caching, reliability, timeouts).
If you are unsure, start with build-time generation for critical pages. It is the most boring option, and boring is good for OG previews.
Checklist before you ship
If you want to avoid "it works on my machine" preview problems, run this checklist before you announce a link:
- Absolute URLs:
og:urlandog:imageare absolute HTTPS URLs. - One canonical image: you do not output multiple
og:imagetags. - Correct size: use a 1200x630 image (or a very close ratio).
- Public access: image loads without cookies or auth.
- Validate: run Validator on the deployed URL.
- Refresh caches: re-scrape via platform tools if you changed the image.
Common mistakes (quick fixes)
- Relative og:image URL: switch to an absolute HTTPS URL.
- Image blocked: disable hotlink protection and allow scrapers.
- Wrong format: export PNG or JPG instead of WebP.
- Client-only tags: ensure tags are server-rendered.
- CDN caching: purge or version image URLs when you update them.
Quick path: generate, tag, validate
If you want to be done fast, use the toolkit in this order.