When a shared link shows the wrong headline, the cause is almost always one of five things: the platform cached an older version of the page, there are two og:title tags and the scraper picked the other one, no og:title exists so it fell back to something else, the tag is injected by JavaScript and never reaches the crawler, or the scraper followed a redirect to a different page. A single curl command distinguishes all five, and it is worth running before changing anything.
What You Are Seeing
# You expect:
How We Cut Build Times by 70%
# The card shows one of:
Example Engineering Blog <- site name; no og:title found
How We Cut Build Times by 70% | Example <- fell back to <title>
Untitled <- nothing found at all
Our Q2 Product Update <- a stale cached scrape
Accept cookies to continue <- scraped body textEach of those symptoms points somewhere specific, and the sections below map them to causes.
Read your page's tags in the Open Graph Checker
The Title Precedence Order
Platforms resolve the headline by taking the first thing they find:
1. twitter:title (X only)
2. og:title <- what you almost always want to control
3. <title> <- the SEO title, often with a site-name suffix
4. <h1> or body text <- last-ditch guess
5. the bare URL <- nothing usable foundA card showing your page title complete with an | Example Blog suffix has landed on step 3, which means og:title is missing or unreadable. A card showing a nav label or a cookie banner has landed on step 4.
Why It Happens
1. The platform cached an older scrape
The most common cause by far. Platforms cache by exact URL — Facebook for up to 30 days, LinkedIn and X for about a week — and re-sharing the link does not trigger a fresh fetch. Your fix is correct; it is simply not being read.
Diagnose it by comparing the served HTML with what the card shows. If they disagree, it is a cache.
2. Duplicate og:title tags
Two og:title tags in the same document leaves the choice to the scraper, and different platforms pick differently — which is why the same link can show two different headlines depending on where it is posted.
<!-- from your template -->
<meta property="og:title" content="How We Cut Build Times by 70%">
...
<!-- injected by an SEO plugin further down the head -->
<meta property="og:title" content="Example Engineering Blog">On WordPress this is usually an SEO plugin competing with a theme that also emits Open Graph tags. On other stacks it is often a layout component and a page component both setting the tag.
3. No og:title at all
Without it the platform falls back to <title>, which usually carries an SEO suffix that reads badly in a card and eats the character budget:
<title>How We Cut Build Times by 70% | Example Engineering Blog</title>
<!-- no og:title, so the card shows the whole thing including the suffix -->4. The tag is set by JavaScript
Scrapers do not execute JavaScript. Tags set in a useEffect, by a router transition, by a tag manager, or by any client-only helper are invisible to them — even though they appear perfectly in DevTools.
The tell is a mismatch between curl output and the Elements panel. This is also why a single-page app can show a correct title in the browser and share as a bare URL forever.
5. A redirect sent the scraper somewhere else
The scraper follows redirects and reads the tags on whatever it lands on. If example.com/page redirects to a locale prefix, a canonical host, or a login screen, the card describes the destination.
curl -sIL https://example.com/page | grep -iE '^HTTP|^location'
HTTP/2 301
location: https://www.example.com/en/page
HTTP/2 200A redirect to a consent wall or an interstitial is the usual reason a card shows text nobody wrote.
6. The wrong tag attribute
<meta name="og:title"> is valid HTML and completely ignored by Facebook. Open Graph tags require property. This produces the same symptom as having no og:title at all.
How to Diagnose It
One command separates a caching problem from a markup problem:
# What title sources does the page actually serve?
curl -sL -A "facebookexternalhit/1.1" https://example.com/page \
| grep -iE '<title>|og:title|twitter:title'Read the result against the card:
| curl output | Card shows | Cause |
|---|---|---|
Correct og:title, one of them | Old title | Stale cache — re-scrape |
Two og:title tags | The other one | Duplicate tags — remove one |
No og:title | <title> with suffix | Tag missing — add it |
| Nothing at all | URL or body text | Client-side rendering, or a blocked crawler |
name="og:title" | <title> instead | Wrong attribute — use property |
# Count duplicates explicitly
curl -sL https://example.com/page | grep -c 'property="og:title"'
# 1 = good. 2 or more = the cause of an unpredictable headline.
# Confirm the crawler is not being redirected or blocked
curl -sIL -A "facebookexternalhit/1.1" https://example.com/page | grep -iE '^HTTP|^location'How to Fix It
If the tags are correct: re-scrape
Force a fresh fetch rather than re-sharing. Facebook's Sharing Debugger has a Scrape Again button; LinkedIn's Post Inspector re-scrapes on inspection. X and Slack have no tool and expire on their own. Full detail in How to Clear the Social Preview Cache.
If there are duplicates: find the second source
# See both tags with surrounding context to identify which component emits each
curl -sL https://example.com/page | grep -B2 -A2 'og:title'On WordPress, disable Open Graph output in either the theme or the SEO plugin — not both. In a component-based app, make sure only one place in the tree sets the tag; frameworks that merge head tags will happily emit two if two components ask for it.
If the tag is missing: add it explicitly
<title>How We Cut Build Times by 70% | Example Engineering Blog</title>
<meta property="og:title" content="How We Cut Build Times by 70%">
<meta property="og:description" content="A walkthrough of the caching changes that took our CI from 14 minutes to 4.">Keep og:title under about 60 characters and leave the site name out — that is what og:site_name is for. Deliberately differing from <title> is normal and correct.
If it is client-side: move it server-side
The tags must be in the HTML your server sends. In Next.js that means the App Router metadata export or generateMetadata, or next/head on a server-rendered or statically generated page — never a useEffect. Tag managers cannot do this at all.
curl or View Source — it is the only honest test, and it is the difference between a five-minute fix and a day of confusion.Verify the Fix
# 1. Exactly one og:title, with the right value
curl -sL https://example.com/page | grep -c 'property="og:title"'
1
curl -sL https://example.com/page | grep 'property="og:title"'
<meta property="og:title" content="How We Cut Build Times by 70%">
# 2. Purge your own CDN so the re-scrape sees the new page
# 3. Re-scrape in the Facebook Sharing Debugger and LinkedIn Post Inspector
# 4. Test on a platform with no refresh tool using ?v=2Purging your own cache before re-scraping matters. A re-scrape that fetches a stale CDN copy simply caches the old title again, which is why the same fix sometimes appears to fail on the first attempt.
Frequently Asked Questions
Why does my preview show the old title after I updated it?
The platform cached its earlier scrape — Facebook for up to 30 days — and re-sharing does not refresh it. Confirm the new title is in the served HTML with curl, then force a re-scrape in the Sharing Debugger.
Why is the card showing my site name instead of the article headline?
Either og:title is missing and the platform fell back to <title>, or a second og:title carrying the site name is overriding yours. Count the tags in the served HTML to tell which.
Should og:title and the <title> tag be the same?
Not necessarily, and often they should differ. <title> is for search results and usually carries a site-name suffix; og:title is for the card and should be the clean headline on its own.
Why do Facebook and LinkedIn show different titles for the same link?
Almost always duplicate og:title tags — the two platforms picked different ones — or the two caches were populated at different times, before and after your change.
Can I have a different title on X?
Yes. twitter:title overrides og:title on X only. Just remember it becomes a second place the headline can go stale when you update the page.
The title is right in DevTools but wrong in the preview. Why?
The Elements panel shows the DOM after JavaScript ran; the scraper sees only the server's HTML. If curl does not show your og:title, it is being injected client-side and no platform will ever read it.