Docs
Add Open Graph and X card tags
Add Open Graph and X card tags
When someone shares a link on Facebook, LinkedIn, Slack, WhatsApp, Teams or X, the platform builds a preview card: a title, a short description and an image. It takes them from the Open Graph tags in the page. Without them, each platform guesses: a menu label as the title, a cookie notice as the description, a random logo or no image at all. A link with a clean, large image gets noticeably more clicks than a bare URL.
The site checklist checks the three tags every preview needs: og:title, og:description and og:image. It also reports whether the page has an X card tag; that one is a suggestion, because X falls back to Open Graph when it is missing.
The tags
These go inside <head>, with values for each page:
<meta property="og:title" content="Spring sale: 20 % off all bikes">
<meta property="og:description" content="Road, gravel and city bikes, with free delivery until 30 April.">
<meta property="og:image" content="https://example.com/images/share/spring-sale.jpg">
<meta property="og:url" content="https://example.com/spring-sale">
<meta property="og:type" content="website">
<meta name="twitter:card" content="summary_large_image">
| Tag | What to put in it |
|---|---|
og:title |
the page title without the site name; up to about 60 characters |
og:description |
one or two sentences, about 100–160 characters |
og:image |
an absolute https:// address of the image |
og:url |
the canonical address of the page |
twitter:card |
summary_large_image for a wide image, summary for a small square one |
The image is what people notice, and where most previews break:
- 1200 × 630 px (1.91 : 1). Keep text and logos away from the edges; some apps crop it to a square.
- JPG or PNG, under 5 MB. SVG is not supported anywhere; X rejects images over 5 MB.
- An absolute
https://address. A relative path (/images/share.jpg) does not work on most platforms. - Publicly reachable. Not behind a login, a password or a firewall rule that blocks bots: Facebook fetches it as
facebookexternalhit, LinkedIn asLinkedInBot, X asTwitterbot.
Check it yourself
Replace example.com with your page:
curl -s https://example.com | grep -ioE '<meta[^>]*(og|twitter):[^>]*>'
curl -sI https://example.com/images/share/spring-sale.jpg | grep -iE '^(HTTP|content-type|content-length):'
curl -s -o /dev/null -w '%{http_code}\n' -A 'facebookexternalhit/1.1' https://example.com
The first command lists the tags; og:title, og:description and og:image must all be there. The second checks the image from og:image: 200, an image type, and a size under 5 MB (content-length in bytes). The third requests the page as Facebook does; anything other than 200 means a firewall or bot protection is blocking previews.
How to fix
Pick how your site is built. Set a default image for the whole site first, so every page has some preview, and then a better one for the pages people share most.
WordPress
WordPress has no Open Graph tags of its own; an SEO plugin adds them. Use one plugin for this: two plugins writing the same tags give platforms conflicting values.
Yoast SEO. Open Graph is on by default (Yoast SEO → Settings → Site features → Open Graph data). Set the default image in Yoast SEO → Settings → Site basics → Site image. For a single post or page, open the Social tab in the Yoast panel in the editor and set the title, description and image for sharing. Yoast also writes twitter:card.
Rank Math. Set the default image in Rank Math SEO → Titles & Meta → Global Meta → OpenGraph Thumbnail, and the card type under Twitter Card Type on the same page. For a single post, open the Rank Math panel in the editor, Edit Snippet → Social.
Without a custom image, both plugins use the post's featured image, so set featured images on the posts you share. Then clear the page cache.
Node.js and Next.js
Next.js, App Router. Use the Metadata API in a layout or page:
export const metadata = {
metadataBase: new URL('https://example.com'),
title: 'Spring sale: 20 % off all bikes',
description: 'Road, gravel and city bikes, with free delivery until 30 April.',
openGraph: {
title: 'Spring sale: 20 % off all bikes',
description: 'Road, gravel and city bikes, with free delivery until 30 April.',
images: [{ url: '/images/share/spring-sale.jpg', width: 1200, height: 630 }],
},
twitter: {
card: 'summary_large_image',
},
};
metadataBase turns relative image paths into absolute addresses. For pages built from data, export generateMetadata() instead. Alternatively, put an opengraph-image.jpg (or .png) file in the route's folder and Next.js adds the image tags for it.
Note:
openGraphin a page replaces the layout'sopenGraphas a whole, it does not merge with it. If a page sets only the title, it loses the image from the layout. Repeat the image, or keep shared values in a variable.
Pages Router and other Node.js apps: write the tags from the table above into the page head (next/head in Next.js, the layout template elsewhere), with values from each page's data.
Laravel
Add the tags to the main layout with a default, and let each view override the values:
<meta property="og:title" content="@yield('og_title', config('app.name'))">
<meta property="og:description" content="@yield('og_description', 'Road, gravel and city bikes.')">
<meta property="og:image" content="@yield('og_image', asset('images/share/default.jpg'))">
<meta property="og:url" content="{{ url()->current() }}">
<meta property="og:type" content="website">
<meta name="twitter:card" content="summary_large_image">
In a view:
@section('og_title', $post->title)
@section('og_image', asset('storage/'.$post->share_image))
asset() and url() build absolute addresses from APP_URL, so make sure APP_URL in production is the real https:// address. With http://localhost there, every preview breaks.
Static HTML
Add the tags from the table above inside <head> on each page, with that page's title, description and image. With a site generator (Hugo, Jekyll, Eleventy), add them once to the base layout and fill them from each page's front matter, with a default image for pages that have none.
Shopify
Shopify themes write the Open Graph and X tags themselves, from the page title, the SEO description and the product or collection image.
- Default image: Online Store → Preferences → Social sharing image. It is used for the home page and for pages without an image of their own.
- Products and collections: the main product image is used for sharing, so the first image of a product should look good cropped to a wide rectangle.
- Title and description: set them in Search engine listing at the bottom of each product, collection or page.
Wix
Wix writes the tags from each page's SEO settings. In the editor, open the page's settings (⋯ next to the page in the pages menu) and go to Social share: set the image, title and description used when the page is shared. Without one, Wix uses an image from the page or the site's default.
Webflow
Open the Pages panel, click the gear next to the page, and fill in Open Graph settings: title, description and image URL. On CMS template pages, bind the fields to the collection (for example the post's main image), so every item gets its own preview. Then publish the site again.
Squarespace
In the page's settings, open the Social image tab and upload the image for that page. For blog posts and products, the post or product image is used. For pages without their own image, Squarespace uses the site-wide social sharing image from the site settings, so set that one first.
Platforms keep old previews
Facebook, LinkedIn, Slack and WhatsApp cache the preview when a link is shared the first time, sometimes for weeks. After you fix the tags, ask them to read the page again:
- Facebook: the Sharing Debugger: paste the address and click Scrape Again. It also shows which tags Facebook saw and any problem with the image.
- LinkedIn: the Post Inspector fetches the page again and shows the preview.
- X has no public preview tool any more. It refreshes its cache after about a week; a new address (for example with
?v=2) gets a fresh preview straight away.
Confirm the fix
Run the curl commands from Check it yourself again, then open the target in PulseKeeper and click Check now on the Checklist tab. The item turns OK within a few minutes instead of at the next daily run, and the Checklist tab shows the new preview.