Open Graph tags for your app: the link preview checklist
Every time someone shares your link, the preview is your ad. Here are the tags that control it, the image size that works everywhere, and how to force a stale one to update.
- Written by
- SpacerrApps
- Published
- Reading time
- 4 min read
When someone pastes your link into X, LinkedIn, Slack, Discord, iMessage or WhatsApp, the app fetches your page and builds a card from a handful of tags in the page's head. Those tags are Open Graph, a format Facebook introduced and everyone else adopted.
Get them right and a shared link becomes a small ad with your name, your pitch and a picture. Get them wrong and it is a bare URL, or worse, a card with your cookie banner as the image.
The short answer
Put these in the head of every page, with absolute URLs:
<meta property="og:title" content="YourApp: a focus timer for Mac" />
<meta property="og:description" content="A menu bar timer that blocks distracting sites while it runs." />
<meta property="og:image" content="https://yourapp.com/og.png" />
<meta property="og:url" content="https://yourapp.com/" />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary_large_image" />
Make the image 1200 by 630 pixels, PNG or JPG, under a few hundred kilobytes. That is the whole checklist. The rest of this guide is the detail behind each line.
The tags, one at a time
og:title
The bold line on the card. It does not have to match your page title: the page title is written for a search result, the card title for a feed. Keep it under about 60 characters so it does not get cut, and lead with the product name.
og:description
The grey line under the title. One sentence on what the product does, for whom. Some platforms show two lines, some show none, and X shows none on a large image card, so never put anything essential only here.
og:image
The picture, and the part that decides whether anyone clicks. It must be an absolute URL starting with https, not a path like /og.png. A relative path is the single most common reason a preview shows no image.
og:url
The canonical address of the page. Platforms use it to group shares of the same page, so point it at the one version you want counted, the same one your canonical tag names.
og:type
website for the home page and most product pages, article for a blog post. It changes
little in practice, but a missing type is one more warning in every debugger.
twitter:card
X reads the Open Graph tags for the title, description and image, and only needs this one extra
tag to choose the layout. summary_large_image gives you the full width picture.
summary gives you a small square thumbnail beside the text, which almost always looks worse for
a product. You only need twitter:title and friends if you want X to show something different
from everywhere else.
The image
Size. 1200 by 630 pixels, a ratio of 1.91 to 1. Facebook, LinkedIn, Slack and Discord all display it well, and X crops it only slightly for its 2 to 1 large card. Build the image with a little margin on every side so that crop never cuts your text.
Format and weight. PNG for screenshots and text, JPG for photographs. Keep it small: some platforms give up on a slow image and show the card without it. X's own limit is 5 MB, but aim far below that.
What to put on it. Your product name, one line saying what it does, and either the product itself or your logo. Text large enough to read on a phone, because that is where most previews are seen. A screenshot of your whole dashboard shrunk to a thumbnail reads as noise.
One per page, if you can. A blog post with its own title on the image gets shared more than one
that reuses the home page picture. On Next.js, an opengraph-image.tsx file beside a route
generates that route's image from JSX at build or request time, so every page can have one without
anyone opening a design tool.
Why a preview shows the wrong thing
It is cached. Every platform stores the card the first time it sees a URL and does not look again for a while. Fix the tags, then force a refresh:
- Facebook and WhatsApp: the Sharing Debugger, then Scrape Again.
- LinkedIn: the Post Inspector, which refetches on every inspection.
- X, Slack, Discord and iMessage have no public refresh button. Change the image's URL instead,
for example
/og.png?v=2, and the next share fetches it fresh.
The tags are added by JavaScript. The fetchers that build previews mostly do not run JavaScript. If your head tags are injected in the browser, the card never sees them. Render them into the HTML on the server.
The page needs a login or blocks bots. A preview fetcher is a bot with no cookies. If your page redirects it to a sign-in screen, or a firewall rule blocks unknown user agents, the card is built from the wrong page or from nothing.
The image URL is relative, or on http. Absolute and https, every time.
Where it matters most for an app
Three pages get shared far more than the rest, and each deserves its own card:
- The home page. What gets pasted in every launch post and reply.
- Your launch and listing pages elsewhere. On a directory or launch site the card is built from their tags, not yours, which is one reason a clear listing description matters.
- Blog posts and changelogs. Each one is a fresh reason to share the link, and a fresh chance for a good card.
Open Graph decides how your link looks when a person shares it. Two neighbouring files decide how your product reads to machines: SoftwareApplication schema for search engines, and llms.txt for AI answer engines. A product site should have all three.
