WordPress tags

Open graph protocol WordPress

The open graph protocol wordpress question is about the tags in the head, not a second image format. og:title, og:description, og:image, and og:url describe the page to a crawler. ogp.me lists og:title, og:type, og:image, and og:url as the four required properties. og:description and og:site_name are optional. WordPress core does not print them. A theme wp_head hook or a plugin does. This page is the explainer. Which path should own the image stays on the WordPress lander.

The queries open graph tags wordpress and wordpress open graph meta tags are the same job. og:type, og:site_name, og:image:width, og:image:height, og:image:alt, and twitter:card sit next to those tags. twitter:card is not an Open Graph property. It selects an X card layout. summary_large_image is the large-image card.

Install the WordPress plugin when posts, pages, or products should get a generated card, get an API key to sign CDN URLs from another server, install MCP when an agent should call generate_og_image, read the API docs for JWT claims and the JSON url field, change the OG image when the job is the file rather than the tag names, or check the permalink before you trust a share.

What each tag does

Definitions are from ogp.me. Plugin behavior is from the vendor docs linked on this page, or from the OG Pilot plugin's tag writer.

Tag What it does Where WordPress gets the value Common mistake
og:title Required. The title of the object as it should appear in the graph. WordPress core does not print it. A theme can echo the post title from wp_head. Yoast's Open Graph spec uses a Facebook title, then the social title template, then the SEO title, then the SEO title template, then %%title%% %%page%% %%sep%% %%sitename%%. Rank Math's Open Graph guide calls og:title essential, and the Social tab can set a custom title. That guide does not publish a fallback order past the Social tab. AIOSEO's per-post Facebook settings include a Facebook Title, and its troubleshooting sample includes og:title. OG Pilot prints og:title from the configured title, or the post title when that string is empty, on supported singular content when Open Graph output is on and Meta Ownership is not External SEO plugin. Putting the site name in the title and in og:site_name, or letting two plugins print two titles.
og:description Optional. A one to two sentence description of the object. WordPress core does not print it. A theme can echo the manual excerpt. Yoast uses a Facebook description, then the social description template, then the meta description, then that template, then the excerpt on posts or the term description. Rank Math's Open Graph guide describes og:description as a short description, and the Social tab can set one. That guide does not publish a fallback order. AIOSEO's per-post Facebook settings include a Facebook Description, and its troubleshooting sample includes og:description. OG Pilot prints og:description from the configured description, or the excerpt when that string is empty. Import Existing Social Fields copies a description into overrides. A placeholder such as the excerpt fills the generated card, which is not the same as this meta tag. Expecting the post body to become the share text when the tag is empty.
og:image Required. An absolute http or https image URL that represents the object. WordPress core does not print it. A featured image is an img until wp_head prints the attachment URL. Yoast uses a Facebook image, then the featured image on posts, then a prominent content image, then the social default, then the site fallback. Rank Math's order is the Social-tab OpenGraph image, then the featured image, then the first image in the post, then the default OpenGraph thumbnail. The guide recommends 1200 by 630. AIOSEO's default image source can be the default image, featured image, attached image, first image in content, a custom field, the author image, or the first available image, with the Default Post Facebook Image as the fallback. A post can also set Image Source to Custom Image. OG Pilot prints the generated image URL, or the featured image when no generated URL is ready. It does not print a processing placeholder. The API JSON field is url. MCP generate_og_image returns image_url. A relative path, or two plugins both printing og:image.
og:url Required. The canonical URL, used as the object's permanent ID in the graph. Core's rel_canonical on wp_head is a link element, not this property. A theme can print the permalink. Yoast uses the canonical URL, or the series root on paginated content. Rank Math's Open Graph guide says it inserts the canonical URL. AIOSEO's troubleshooting sample includes og:url with the post URL. OG Pilot prints og:url as the permalink on supported singular content when Open Graph output is on. A staging URL, or a URL that is not the permalink you shared.
og:type Required. An unmarked page is treated as website. article is the global type for an article. WordPress core does not print it. Yoast uses website on the homepage, profile on user profiles, and article on pages, posts, and other templates. Rank Math's guide says the plugin generates og:type from the content, and it describes website for the homepage, profile, article, and product. AIOSEO's troubleshooting sample uses article on a post, and per-post Facebook settings include a Facebook Object Type. OG Pilot prints article for a post or a blog_post template, product for a product, and website otherwise. Using article on the homepage, or inventing a type the protocol does not list.
og:site_name Optional. The name of the larger site, not the post title. WordPress core stores the name as the site title and does not print this property. A theme can echo the site title. Yoast prints the site name on pages where Open Graph output is on. Rank Math's guide says the content should be the website name. AIOSEO's troubleshooting sample includes og:site_name. OG Pilot prints og:site_name from the site name on supported singular content when Open Graph output is on. Repeating the post title here.
og:image:width and og:image:height Optional structured properties. Pixel size of that og:image. Put them after the image they describe. A later og:image starts a new image. A theme can use the width and height from wp_get_attachment_image_src. Yoast prints them only when an og:image is set and the width and height are known. Rank Math's Open Graph guide documents og:image:width and og:image:height, and it says to upload images 1200 pixels wide and 630 pixels tall. AIOSEO's aioseo_thumbnail_size filter changes the image size used for og:image and defaults to fullsize. That filter doc does not say AIOSEO prints these tags. OG Pilot prints og:image:width 1200 and og:image:height 630 when it prints an image URL. The API JSON response includes the same width and height. Numbers that do not match the file, or attaching them to the wrong image.
og:image:alt Optional. A description of what is in the image, not a caption. A page with og:image should also set this. A theme can echo the attachment alt. Yoast's Open Graph functional spec does not list this tag. Rank Math's Open Graph guide documents og:image:alt. AIOSEO's troubleshooting sample does not include it, and the AIOSEO docs linked here do not say whether AIOSEO prints the tag. OG Pilot prints og:image:alt as Social preview image for plus the title when it prints an image URL. Using the post title as the alt when it does not describe the picture.
twitter:card Not an Open Graph property. It selects an X card layout. WordPress core does not print it. A theme can echo it next to twitter:image. Yoast's X tag spec defaults twitter:card to summary_large_image when those tags are on. Rank Math lists Summary Card with Large Image, Summary Card, App Card, and Player Card, set from the Social Twitter tab. That guide does not name a default card value. AIOSEO's troubleshooting sample does not include twitter:card. OG Pilot prints twitter:card as summary_large_image when Twitter output is on. A summary card when you wanted the large image, or a twitter:image that does not match og:image.

Yoast's hierarchy is the Open Graph functional spec at developer.yoast.com. The current help article labels the editor Social media appearance. Rank Math's Open Graph guide and Titles and Meta guide are the Rank Math sources, plus the Twitter card guide. AIOSEO's sample is the Facebook troubleshooting doc. Yoast hooks wp_head from its front-end integration, including Twitter presenters when that setting is on.

See what a page actually outputs

  1. Open the public permalink. A preview inside wp-admin is not what the crawler fetches.
  2. View source and search for og:. Tags belong in the head. wp_head is the action themes and plugins use to print them.
  3. Count the writers. AIOSEO's troubleshooting doc shows an HTML comment before its block and tells you to keep searching for a second OG: block from the theme or another plugin.
  4. Paste the same permalink into the Open Graph debugger. That checker is not Meta, X, LinkedIn, or Slack.
<meta property="og:title" content="Hello World" />
<meta property="og:description" content="A one or two sentence description." />
<meta property="og:image" content="https://cdn.ogpilot.com/..." />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="What the image shows" />
<meta property="og:url" content="https://example.com/hello-world/" />
<meta property="og:type" content="article" />
<meta property="og:site_name" content="Example" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="https://cdn.ogpilot.com/..." />

A theme hook, only when nothing else writes the tags

Do not add this hook while Yoast, Rank Math, AIOSEO, or the OG Pilot plugin is already printing Open Graph tags. Two writers produce duplicate tags. The theme handbook describes featured images as pictures a theme prints with the_post_thumbnail() after add_theme_support('post-thumbnails'). It does not document an og:image tag. rel_canonical can print a link canonical. That is not og:url. get_permalink() is absolute. It is https only when the site is. The description in this sample is the manual excerpt. It does not invent one from the post body. Yoast uses og:type website on the homepage. This sample only runs on singular posts and pages, and it marks those as article.

<?php
// Remove this hook when an SEO plugin or OG Pilot already writes the tags.
add_action( 'wp_head', function () {
    if ( ! is_singular() ) {
        return;
    }

    $post_id = get_queried_object_id();
    $permalink = get_permalink( $post_id );
    if ( ! $permalink ) {
        return;
    }

    echo '<meta property="og:title" content="' . esc_attr( get_the_title( $post_id ) ) . '" />' . "\n";
    echo '<meta property="og:type" content="article" />' . "\n";
    echo '<meta property="og:url" content="' . esc_url( $permalink ) . '" />' . "\n";
    echo '<meta property="og:site_name" content="' . esc_attr( get_bloginfo( 'name' ) ) . '" />' . "\n";

    $description = get_post_field( 'post_excerpt', $post_id );
    if ( is_string( $description ) && $description !== '' ) {
        echo '<meta property="og:description" content="' . esc_attr( wp_strip_all_tags( $description ) ) . '" />' . "\n";
    }

    if ( ! has_post_thumbnail( $post_id ) ) {
        return;
    }

    $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post_id ), 'full' );
    if ( ! $image ) {
        return;
    }

    $image_url = esc_url( $image[0] );
    echo '<meta property="og:image" content="' . $image_url . '" />' . "\n";
    echo '<meta property="og:image:width" content="' . (int) $image[1] . '" />' . "\n";
    echo '<meta property="og:image:height" content="' . (int) $image[2] . '" />' . "\n";
    echo '<meta name="twitter:card" content="summary_large_image" />' . "\n";
    echo '<meta name="twitter:image" content="' . $image_url . '" />' . "\n";
} );

Duplicate tags

ogp.me says that when one property is repeated, the first tag from top to bottom is given preference during conflicts. That is the protocol rule for arrays. Treat a second og:image as a bug you can see in view source.

If Yoast, Rank Math, or AIOSEO should keep the tags, the OG Pilot plugin FAQ says to set Meta Ownership to External SEO plugin so OG Pilot stops outputting social meta tags. Then delete the theme hook. Import Existing Social Fields copies title, description, and image values from those plugins into OG Pilot overrides. That copy is not a reason to leave both writers on.

A generated image fills og:image

The pixels and the tag are different. The generator returns a URL. Something in wp_head has to put that URL in og:image. On a WordPress site, install OG Pilot Dynamic Open Graph Images from the WordPress lander. The listing says the plugin uses OAuth with PKCE, so you do not paste a long-lived API secret into the theme, and it outputs Open Graph and X/Twitter tags including og:image and twitter:image. When Open Graph output is on, the plugin prints og:title, og:description, og:type, og:url, og:site_name, and og:locale. When an image URL is present it also prints og:image, og:image:url, og:image:secure_url on https, og:image:width, og:image:height, og:image:type when the type is known, and og:image:alt. When Twitter output is on it prints twitter:card summary_large_image, plus title, description, and URL, and with an image it prints twitter:image, twitter:image:src, and twitter:image:alt, then twitter:domain and twitter:site when a site handle is set. The WordPress.org changelog for 0.1.0 notes og:image:url, twitter:image:src, and twitter:domain. ogp.me defines og:image:url as identical to og:image.

Outside the plugin, sign the request on a server you control. The JSON url is the value for og:image. Without Accept: application/json, the API docs say the response redirects to the CDN URL. Changing the image itself, featured image versus an SEO-plugin field versus this generated card, is how to change the OG image in WordPress.

POST https://ogpilot.com/api/v1/images
Content-Type: application/json
Accept: application/json

{"token":"YOUR_JWT_TOKEN"}

Required JWT claims: iss (verified domain), sub (API key prefix).
If iat is present, the image cache is valid for 24 hours from that
timestamp. Omit iat and the cache does not expire on its own.
Prefer an official SDK. Docs: https://ogpilot.com/docs

{
  "id": "s_abc123",
  "status": "completed",
  "url": "https://cdn.ogpilot.com/...",
  "width": 1200,
  "height": 630,
  "created_at": "2024-01-15T12:00:00Z",
  "cached": false,
  "stale": false
}

Put url in og:image. width and height match the structured image tags. The template canvas is 1200 by 630.

MCP install, for a client that accepts an mcpServers map. Claude and ChatGPT do not read this file. Do not add command, args, or a bearer token. Setup is on /docs/mcp.

{
  "mcpServers": {
    "og-pilot": {
      "type": "streamable-http",
      "url": "https://ogpilot.com/mcp"
    }
  }
}
Remote MCP URL: https://ogpilot.com/mcp
Transport: Streamable HTTP
Auth: OAuth 2.1 with PKCE

generate_og_image
{ "url": "https://example.com/your-post" }

Returns image_url. Put that URL in og:image.
generate_og_image needs a signed-in account with an active plan
and at least one credit. A trial is not enough.

The plugin FAQ says most images are ready within 5 to 10 minutes depending on queue load and the site traffic that triggers WP-Cron. The plan catalog lists Starter at $5/month ($50/year, 10,000-image quota), Builder at $49/month ($99/year, 100,000-image quota), and Growth at $99/month ($199/year, unlimited image quota). Those defaults are on pricing. A Stripe image_quota feature can replace the quota. The catalog has no per-image price. The API docs require a verified domain via DNS TXT. The plugin FAQ says the WordPress OAuth flow does not add that manual DNS step.