Why og:title matters
The title is the bold line of a link preview, and the first thing people read. Facebook, LinkedIn, WhatsApp, Discord and Slack take it from og:title. X uses twitter:title if you set one, and og:title otherwise, so one tag covers every platform.
Without og:title, many platforms fall back to the page’s <title>. X doesn’t, so a page with neither og:title nor twitter:title gets an X card with no title. And the fallback is often written for search results, with a suffix like “| Example Blog” that wastes space in a card.
How long it should be
Aim for 40 to 60 characters, with the important words first. Platforms cut long titles at different points:
- X cuts after about 70 characters.
- Facebook and WhatsApp after about 100, though on phones a title often wraps to two lines and is cut sooner.
- LinkedIn shows up to about 150, and Discord up to 256.
The checker flags titles over 90 characters, which most platforms cut off. The cheat sheet lists every platform’s limits.
Common reasons the title is wrong
- There’s no og:title
- The card falls back to
<title>, or shows nothing on X. Addog:titleto every page. - Every page has the same title
- A site-wide layout often sets
og:titleonce, so every shared page shows your home page’s title. Set it per page from that page’s own heading. - The tag appears twice
- A theme and an SEO plugin can both write
og:title, and platforms don’t agree on which one wins. Keep exactly one. The checker reports duplicate tags. - Special characters come out garbled
- Write characters such as
&and quotes as HTML entities (&,"), and serve the page as UTF-8. Framework metadata APIs do the escaping for you. - The title is added by JavaScript
- Crawlers don’t run JavaScript, so a title set in the browser is never seen. See why your app’s links show a blank preview.
Code for your framework
These set og:title together with the other tags a preview needs. In each one, use the page’s own title, not a fixed string.
HTML inside <head>
<title>How we cut our build time in half</title>
<meta name="description" content="What we changed in our CI pipeline, and what it saved.">
<link rel="canonical" href="https://example.com/blog/faster-builds">
<!-- Open Graph -->
<meta property="og:title" content="How we cut our build time in half">
<meta property="og:description" content="What we changed in our CI pipeline, and what it saved.">
<meta property="og:url" content="https://example.com/blog/faster-builds">
<meta property="og:type" content="article">
<meta property="og:site_name" content="Example Blog">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="https://example.com/images/faster-builds.jpg">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="A chart of build times dropping from 12 to 6 minutes">
<!-- X (Twitter). X falls back to the og: tags for title, description and image. -->
<meta name="twitter:card" content="summary_large_image">
Next.js (App Router) in page.tsx or layout.tsx
import type { Metadata } from "next";
// app/<route>/page.tsx (or layout.tsx)
export async function generateMetadata(): Promise<Metadata> {
return {
title: "How we cut our build time in half",
description: "What we changed in our CI pipeline, and what it saved.",
alternates: { canonical: "https://example.com/blog/faster-builds" },
openGraph: {
title: "How we cut our build time in half",
description: "What we changed in our CI pipeline, and what it saved.",
url: "https://example.com/blog/faster-builds",
type: "article",
siteName: "Example Blog",
locale: "en_US",
images: [
{
url: "https://example.com/images/faster-builds.jpg",
width: 1200,
height: 630,
alt: "A chart of build times dropping from 12 to 6 minutes",
},
],
},
twitter: {
card: "summary_large_image",
},
};
}
Nuxt in the page component
<script setup lang="ts">
useSeoMeta({
title: "How we cut our build time in half",
description: "What we changed in our CI pipeline, and what it saved.",
ogTitle: "How we cut our build time in half",
ogDescription: "What we changed in our CI pipeline, and what it saved.",
ogUrl: "https://example.com/blog/faster-builds",
ogType: "article",
ogSiteName: "Example Blog",
ogLocale: "en_US",
ogImage: "https://example.com/images/faster-builds.jpg",
ogImageWidth: 1200,
ogImageHeight: 630,
ogImageAlt: "A chart of build times dropping from 12 to 6 minutes",
twitterCard: "summary_large_image",
});
useHead({
link: [{ rel: "canonical", href: "https://example.com/blog/faster-builds" }],
});
</script>
React Router / Remix in the route module
// In a route module (React Router v7 framework mode or Remix v2).
export function meta() {
return [
{ title: "How we cut our build time in half" },
{ name: "description", content: "What we changed in our CI pipeline, and what it saved." },
{ tagName: "link", rel: "canonical", href: "https://example.com/blog/faster-builds" },
{ property: "og:title", content: "How we cut our build time in half" },
{ property: "og:description", content: "What we changed in our CI pipeline, and what it saved." },
{ property: "og:url", content: "https://example.com/blog/faster-builds" },
{ property: "og:type", content: "article" },
{ property: "og:site_name", content: "Example Blog" },
{ property: "og:locale", content: "en_US" },
{ property: "og:image", content: "https://example.com/images/faster-builds.jpg" },
{ property: "og:image:width", content: "1200" },
{ property: "og:image:height", content: "630" },
{ property: "og:image:alt", content: "A chart of build times dropping from 12 to 6 minutes" },
{ name: "twitter:card", content: "summary_large_image" },
];
}
In Next.js, an openGraph object without a title copies the page’s full <title>, including a suffix from title.template such as "%s | Example Blog". Set openGraph.title yourself to keep the suffix out of the card. A page without its own openGraph inherits the one from its layout. If that one sets a title, every page shares it.
After you fix it
Platforms cache previews, so the old title can stay for a while. Ask Facebook to re-fetch the page in the Facebook Sharing Debugger (opens in a new tab) and LinkedIn in the LinkedIn Post Inspector (opens in a new tab). On X, share the URL with a harmless query string such as ?v=2.