WordPress

Add Open Graph Tags to WordPress (Code, No Plugin)

By Social Card Studio5 min read

To add Open Graph tags to WordPress without a plugin, hook a function into wp_head in your child theme's functions.php that prints og:title, og:description, og:image, and og:url for the current post. This gives you precise control over every preview with zero plugin overhead — at the cost of maintaining the code yourself. Below is the exact snippet, the values to feed each tag, and how to verify the result.

Should you use code or a plugin?

Both work. The question is who maintains the tags. A plugin like Yoast or Rank Math manages Open Graph for you and adds a UI; a code snippet gives you full control and adds nothing to your page weight, but you own the maintenance. If you already run an SEO plugin, let it handle Open Graph and don't double up — two sources printing og:image is a common cause of duplicate tags.

ApproachControlMaintenancePage overheadBest for
functions.php snippetFullYouNoneDevs, lean sites, custom logic
SEO plugin (Yoast / Rank Math)UI-boundPlugin authorPlugin weightNon-technical owners, content teams
Hard-coded in header.phpOne page onlyBreaks on updateNoneNever — anti-pattern

What Open Graph tags does WordPress need?

The Open Graph protocol is the set of <meta property="og:..."> tags platforms read to build a link preview. Four carry almost all the weight:

<meta property="og:title" content="Your post title" />
<meta property="og:description" content="A one-line summary, 110–160 characters" />
<meta property="og:image" content="https://yoursite.com/wp-content/uploads/card.jpg" />
<meta property="og:url" content="https://yoursite.com/your-post/" />

The image is the part readers actually see. It's also the part most worth getting right.

+114%
more impressions for posts and links that include an image versus those without one — which is why a working og:image is the single highest-leverage tag. CXL, click-through benchmarks

For the full breakdown of every property — og:type, og:site_name, locale — see What Is Open Graph? and the deeper Open Graph meta tags reference.

How do you add the tags in functions.php?

Paste this into your child theme's functions.php. It builds the four core tags from real post data and hooks them into wp_head:

function scs_open_graph_tags() {
	if ( ! is_singular() ) {
		return; // only emit per-post tags on single posts/pages
	}

	global $post;
	$title = get_the_title( $post );
	$desc  = has_excerpt( $post )
		? get_the_excerpt( $post )
		: wp_trim_words( wp_strip_all_tags( $post->post_content ), 30 );
	$url   = get_permalink( $post );

	$image = has_post_thumbnail( $post )
		? get_the_post_thumbnail_url( $post, 'full' )
		: 'https://yoursite.com/default-card.jpg'; // absolute HTTPS fallback

	printf(
		'<meta property="og:type" content="article" />' . "\n" .
		'<meta property="og:title" content="%s" />' . "\n" .
		'<meta property="og:description" content="%s" />' . "\n" .
		'<meta property="og:url" content="%s" />' . "\n" .
		'<meta property="og:image" content="%s" />' . "\n",
		esc_attr( $title ),
		esc_attr( $desc ),
		esc_url( $url ),
		esc_url( $image )
	);
}
add_action( 'wp_head', 'scs_open_graph_tags' );

Three things make this correct rather than just functional:

  • is_singular() guard — you only want per-post tags on actual posts and pages, not archives or the homepage.
  • esc_attr() and esc_url() — escaping is not optional. A post title with a stray quote will break your <head> markup without it.
  • The featured image is output via get_the_post_thumbnail_url( $post, 'full' ) — which returns an absolute URL. The 'full' size gives you the original upload; serve a 1200×630 source for a clean 1.91:1 crop.
+73%
more shares for headlines that contain a number — a reminder that your og:title is marketing copy, not just metadata. Swanky Agency, blog-title research

Why won't my og:image show up?

Almost always: the URL isn't an absolute HTTPS link, or a platform cached an old scrape. Work through these in order:

  • Use an absolute https:// URL. A relative path like /card.jpg is the number-one reason a WordPress preview comes back blank. get_the_post_thumbnail_url() returns an absolute URL — but a hard-coded fallback must include the full https:// prefix.
  • Hit the spec. Export the image at 1200×630 (1.91:1). Facebook accepts up to 8 MB and X up to 5 MB, but keep the file lean — aim for 100–200 KB so scrapers and slow mobile connections don't time out and skip it.
  • Re-scrape after fixing. Platforms cache the first preview they fetch. Paste the URL into the Facebook Sharing Debugger and click Scrape Again to force a refresh.
100–200 KB
is the target file size for a fast-loading social card; a well-compressed 1200×630 JPEG lands around 150 KB. MyOG Image, 2025

If the preview still won't render after a re-scrape, walk through the full diagnostic in Why Your Link Preview Is Broken.

How do you verify the tags are live?

Don't trust "it should work." Confirm it:

  1. View source. Load a published post, view page source, and search for og:image. You should see exactly one of each tag with real values.
  2. Run the Sharing Debugger. The Facebook Sharing Debugger shows precisely what Facebook, Messenger, and WhatsApp will render — and flags missing or malformed tags.
  3. Check X separately. X reads og: tags as a fallback but prefers its own twitter: tags. If your card looks wrong on X specifically, add Twitter Card meta tags.

The takeaway

Hook one function into wp_head, print the four core tags from live post data, output the image as an absolute HTTPS 1200×630 URL, and verify in the Sharing Debugger. That's the entire job — no plugin, no bloat, full control. The only piece a code snippet can't solve for you is generating the image itself.

Frequently asked questions

Can I add Open Graph tags to WordPress without a plugin?

Yes. Add a function to your theme's functions.php (or a small custom plugin) that hooks into wp_head and prints og:title, og:description, og:image, and og:url. This gives you full control and adds zero plugin overhead, but you maintain the code yourself.

Where do Open Graph tags go in WordPress?

In the <head> of every page. You inject them by hooking a function into the wp_head action, which fires inside <head> on the front end. Never hard-code them into header.php — that breaks on theme updates and only handles one page.

Why is my WordPress og:image not showing?

The most common cause is a relative or HTTP image URL. og:image must be an absolute HTTPS URL. After fixing it, re-scrape the page in the Facebook Sharing Debugger to clear the cached old preview.

← All posts