Back to Blog
Open Graph SEO Social Media Web Standards Cloudflare Pages Australian Business

The og:image Gap: Why Half the Web Shares Its Pages With No Preview Card (And How to Audit Yours in 30 Seconds)

By Ash Ganda | 13 July 2026 | 7 min read

Over the past fortnight, three different sites we run — a web-design agency, a founder personal-brand site, and an unrelated travel-content project — all shipped commits with the same one-line description: “add the missing og:image — shares had no preview card.” Three different codebases, three different frameworks, three different owners, one identical failure. Which suggests it is not a bug specific to any of them. It is a class of web-development hygiene error that a lot of sites are quietly shipping in 2026. This post is the 30-second audit that surfaces it on any site, the two-line fix, and the fallback pattern that makes it impossible for any future page to ship without a preview card again.

What “og:image Gap” Actually Looks Like

Diagram of the Open Graph standard (introduced by Facebook in 2010, now universal across LinkedIn, Twitter/X, Slack, WhatsApp, iMessage, Signal, Discord) showing the three load-bearing meta tags og:title, og:description, og:image — and how missing each degrades the preview card differently: missing og:title usually falls back to the page title tag (fine), missing og:description falls back to body content (still usable), missing og:image renders no card at all — a quiet failure that costs about 50% of typical link-share engagement rates

Open Graph (og:* meta tags) is the standard Facebook introduced in 2010 that LinkedIn, Twitter/X, Slack, WhatsApp, iMessage, Signal, Discord, and every other platform now uses to render the “preview card” you see when someone shares a URL. Three tags do the load-bearing work:

<meta property="og:title"       content="Your Post Title">
<meta property="og:description" content="A one-sentence hook.">
<meta property="og:image"       content="https://your-site/path/hero.jpg">

If any one of these is missing, the preview card degrades:

  • No og:title → most platforms fall back to the <title> tag (usually fine).
  • No og:description → most platforms fall back to the meta description or the first paragraph of body content (still usable).
  • No og:image → almost every platform renders no card at all, or a text-only link with a grey placeholder.

That last failure is the one that quietly happens. Your homepage looks fine. The blog post renders perfectly. Google indexes everything without complaint. But every LinkedIn share, every Facebook post, every message in a Slack channel where someone paste-links to your page shows up as a naked URL with no visual. In the LinkedIn feed specifically, image-less link previews are known to get roughly half the engagement of image-preview versions. That is the tax.

Why This Ships So Often

Three-factor diagram explaining why og:image specifically goes missing while og:title almost always ships correctly: (1) actual file requirement vs text string — og:title is a string from CMS/frontmatter, og:image requires a real image URL that resolves; content editing risk, (2) lack of default template fallbacks in Astro / Next.js / Hugo default themes — if the frontmatter field is empty, the tag is completely missing; developer default settings oversight, (3) silent failure outside of social feeds — Google Lighthouse, WAVE accessibility, and Cloudflare Browser Insights do not flag this omission; the only place the failure is visible is inside other people's LinkedIn scrolls; operational invisibility

The reason og:image is the specific tag that goes missing (as opposed to og:title, which almost always is present) traces to three overlapping factors:

1. It requires an actual file, not just text. og:title and og:description are strings the site’s frontmatter or CMS almost always provides. og:image requires a real image URL that resolves to a real image. It is easier to forget.

2. The default templates in most SSGs do not include a fallback. Astro’s blog starter, Next.js’s app router example, Hugo’s default theme — none of them auto-generate a default og:image for pages that don’t specify one. If the frontmatter is missing the field, the tag is missing entirely.

3. The failure is silent everywhere except social feeds. Lighthouse does not flag missing og:image. WAVE does not. Cloudflare’s browser insights do not. The only place the failure is visible is where you cannot see it — inside other people’s LinkedIn scrolls.

The 30-Second Audit

Three-command 30-second Open Graph audit workflow: (1) Grab your homepage's head — curl the homepage and grep for all og:* meta tags, (2) Grab a random post's head — repeat for a specific blog post or deep-link URL, (3) Specifically check for og:image — the command that isolates only the og:image property and content; if this output is empty, that post has the no-preview-card bug. Repeat for a few random URLs — if the pattern is consistent, the whole site has it. Extra confidence checks: LinkedIn Post Inspector and Facebook Sharing Debugger will render exactly what those platforms would render if the URL were shared right now

For any site you run, run these three commands. If the third one returns nothing, you have the bug.

# 1. Grab your homepage's <head>
curl -sL https://your-site.com/ | grep -oE '<meta[^>]*og:[a-z]+[^>]*>'

# 2. Grab a random blog post's <head>
curl -sL https://your-site.com/blog/some-post/ | grep -oE '<meta[^>]*og:[a-z]+[^>]*>'

# 3. Specifically check for og:image
curl -sL https://your-site.com/blog/some-post/ | grep -oE 'property="og:image"[^>]*content="[^"]+"'

If output 3 is empty, that post is shipping with no preview card. Repeat for a few random URLs — if the pattern is consistent, the whole site has it.

For extra confidence, run the URL through LinkedIn’s official Post Inspector (linkedin.com/post-inspector) and Facebook’s Sharing Debugger (developers.facebook.com/tools/debug). Both will render exactly what those platforms would render if the URL were shared right now.

The Fix in Two Steps

Two-step fix: (1) Create and upload a default og:image file at a stable URL (e.g. /images/og-image.png) — 1200x630 pixels (standard OG dimensions Facebook and LinkedIn crop to), under 8 MB, JPG or PNG for safest cross-platform, branded with logo + tagline + brand colour so fallback shares look intentional rather than generic. (2) Implement og:image logic in the layout — Astro example wiring the frontmatter's ogImage prop through a URL constructor with a fallback to the default, plus og:image:width and og:image:height hints (LinkedIn's crawler guesses wrong without them) and twitter:card=summary_large_image (upgrades X's preview to the big-card layout). With that in place, no page ever ships with a naked share preview again

Step 1 — Add a default og:image file to your site. Create a single fallback image at a stable URL, e.g. /images/og-image.png. It should be:

  • 1200 × 630 pixels (the standard OG dimensions Facebook and LinkedIn crop to).
  • Under 8 MB (some platforms reject larger files, though most crop above 1 MB).
  • JPG or PNG (WebP is now supported by LinkedIn and Facebook but PNG/JPG are safer for cross-platform).
  • Branded — logo + tagline + brand colour, so a share with the fallback still looks intentional rather than generic.

Step 2 — Make the layout emit an og:image tag for every page. In Astro:

---
// src/layouts/BaseLayout.astro
const { ogImage } = Astro.props;
const defaultOg = new URL('/images/og-image.png', Astro.site).toString();
const resolvedOg = ogImage
  ? new URL(ogImage, Astro.site).toString()
  : defaultOg;
---
<meta property="og:image"          content={resolvedOg} />
<meta property="og:image:width"    content="1200" />
<meta property="og:image:height"   content="630" />
<meta name="twitter:card"          content="summary_large_image" />

The og:image:width and og:image:height hints are cheap and prevent LinkedIn’s crawler from occasionally guessing wrong. twitter:card = summary_large_image upgrades X’s preview to the big-card layout.

With that in place, every page has an og:image — the frontmatter’s own if it specifies one, the branded default if it doesn’t. No page ever ships with a naked share preview again.

What Cloudflare Pages Adds (And What It Doesn’t)

Cloudflare Pages behaviour note plus per-platform cache-purge tools: Cloudflare Pages serves what your build produces — it does NOT automatically add OG tags for you. The nuance worth knowing: platform crawlers (LinkedIn, Facebook, Slack) fetch your page for the first time and cache the OG tags for hours to days, so a fix followed by an immediate re-share may still show the broken preview until you purge each platform's cache. Purge tools: (1) LinkedIn — Post Inspector re-fetches on demand when you paste the URL, (2) Facebook — Sharing Debugger has a Scrape Again button, (3) Slack — no user-facing purge; wait 4-24 hours or re-share the URL with a ?v=2 query-string suffix. Purge each cache after the fix and corrected preview cards will render on the next share

If you host on Cloudflare Pages (as three of the constellation sites do), the platform does not automatically add OG tags for you. It serves what your build produces. But Cloudflare’s caching does add one nuance worth knowing:

When a platform’s crawler (LinkedIn’s, Facebook’s, Slack’s) fetches your page for the first time, it caches the OG tags for hours to days. If you fix the missing og:image and re-share the same URL immediately, the preview card may still show as broken because the crawler is serving its cached copy.

The fix is to use each platform’s cache-purge tool:

  • LinkedIn — the Post Inspector re-fetches on demand when you paste the URL.
  • Facebook — the Sharing Debugger has a “Scrape Again” button.
  • Slack — no user-facing purge; wait 4-24 hours or re-share a URL with a ?v=2 query-string suffix.

Purge each cache after the fix and the corrected preview cards will render on the next share.

Add This to CI and Never Ship It Again

A single check in your CI pipeline prevents this class of bug forever:

# In .github/workflows/deploy.yml
- name: Verify og:image on rendered pages
  run: |
    for url in "/" "/blog/latest-post/" "/about/"; do
      count=$(curl -sL "https://your-site.com${url}" | grep -c 'property="og:image"')
      if [ "$count" -eq 0 ]; then
        echo "FAIL: no og:image tag on ${url}"
        exit 1
      fi
    done

Eight lines, one exit code. Catches the failure before deploy, forever. Every static-site pipeline should have this or something equivalent.

Missing og:image sits in a small family of failures that ship silently because the normal deploy pipeline does not notice them:

  • Missing canonical URL — every page canonicalizes to itself instead of the “primary” version. See our post on canonical-domain drift on a live Astro site for the incident write-up.
  • Missing alt text on images — silent accessibility regression and a modest SEO cost.
  • Broken JSON-LD schema.org markup — parses cleanly in JavaScript, invalid to Google’s Rich Results parser. Costs you featured-snippet eligibility.
  • Missing X-Robots-Tag for staging domains — search engines index your staging site alongside production. Devastating for canonical signal.

Each of these has the same shape: shipped silently, invisible to your normal QA, expensive over months. The pattern for all of them is the same as this post: a 30-second audit script + a CI check.

The unglamorous work of web hygiene is doing the “obvious” checks that no framework catches for you. This one costs less than a minute of setup and prevents a slow bleed of half your social-share engagement.

Ready to upgrade your IT and cloud setup?

Let's talk about cloud, infrastructure, or cybersecurity. We help Sydney SMBs cut hosting costs, harden their stack, and stop firefighting.

Bella Vista, Sydney