Skip to content

Instantly share code, notes, and snippets.

@EarthmanWeb
Last active November 4, 2023 02:01
Show Gist options
  • Save EarthmanWeb/448d574ddb68351bde8abb6318a8baf9 to your computer and use it in GitHub Desktop.
Save EarthmanWeb/448d574ddb68351bde8abb6318a8baf9 to your computer and use it in GitHub Desktop.
SEO / OG Meta Tags
<?php
/**
* Plugin Name: OG Meta Tags
* Description: Adds OG meta tags to the head of the document with dynamic default values.
* Version: 1.0.0
*/
/**
* Adds the SEO meta tags to the head of the document.
*
* @return void
*/
function og_insert_meta_tags() {
// og_log( 'meta', get_post_meta( get_the_ID() ), 1, 1 );
// if this is the home page, use the site description for the description
// and use the site url instead of permalink
// and use the logo image instead of the featured image
if ( is_front_page() ) {
$description = get_bloginfo( 'description' );
$url = home_url( '/' );
$image = wp_get_attachment_image_url( get_theme_mod( 'custom_logo' ), 'full' );
} else {
$post_id = get_the_ID();
$description = get_the_excerpt();
// trim only the first instance of wp_get_document_title()
$description = preg_replace( '/^' . get_bloginfo( 'name' ) . ' /', '', $description, 1 );
$url = get_permalink();
$image = get_the_post_thumbnail_url( $post_id, 'large' );
if ( ! $image ) {
$image = wp_get_attachment_image_url( get_theme_mod( 'custom_logo' ), 'full' );
}
// check for reading time meta
$reading_time = get_post_meta( $post_id, 'estimated_reading_time_minutes', true );
if ( empty( $reading_time ) ) {
$post_content = strip_tags( get_post_field( 'post_content', $post_id ) );
if ( ! empty( $post_content ) ) {
$word_count = str_word_count( strip_tags( $post_content ) );
$reading_time = ceil( $word_count / 300 ) . ' minutes';
}
} else {
$reading_time .= ' minutes';
}
}
// Dynamic defaults based on current site
$values = array(
'og_locale' => get_locale(),
'og_type' => 'website',
'og_title' => wp_get_document_title(),
'og_description' => $description,
'og_url' => $url,
'og_site_name' => get_bloginfo( 'name' ),
'article_modified' => get_the_modified_date( 'c' ),
'og_image' => $image,
'twitter_card' => 'summary_large_image',
'reading_time' => ! empty( $reading_time ) ? $reading_time : '',
);
// get all the locale alternatives from polylang, if they exist
if ( function_exists( 'pll_languages_list' ) ) {
$locale_alternatives = pll_languages_list( array( 'fields' => 'locale' ) );
$locale_alternatives = array_filter( $locale_alternatives );
$locale_alternatives = array_values( $locale_alternatives );
}
// Output the meta tags
echo '<!-- Custom OG Tags -->' . "\n";
echo '<meta property="og:locale" content="' . esc_attr( $values['og_locale'] ) . '" class="og-meta-tag" />' . "\n";
// add all locales atlernatives, one tag for each alternate
if ( ! empty( $locale_alternatives ) ) {
foreach ( $locale_alternatives as $locale ) {
echo '<meta property="og:locale:alternate" content="' . esc_attr( $locale ) . '" class="og-meta-tag" />' . "\n";
}
}
echo '<meta property="og:type" content="' . esc_attr( $values['og_type'] ) . '" class="og-meta-tag" />' . "\n";
echo '<meta property="og:title" content="' . esc_attr( $values['og_title'] ) . '" class="og-meta-tag" />' . "\n";
echo '<meta property="og:description" content="' . esc_attr( $values['og_description'] ) . '" class="og-meta-tag" />' . "\n";
echo '<meta property="og:url" content="' . esc_url( $values['og_url'] ) . '" class="og-meta-tag" />' . "\n";
echo '<meta property="og:site_name" content="' . esc_attr( $values['og_site_name'] ) . '" class="og-meta-tag" />' . "\n";
echo '<meta property="article:modified_time" content="' . esc_attr( $values['article_modified'] ) . '" class="og-meta-tag" />' . "\n";
echo '<meta property="og:image" content="' . esc_url( $values['og_image'] ) . '" class="og-meta-tag" />' . "\n";
echo '<meta name="twitter:card" content="' . esc_attr( $values['twitter_card'] ) . '" class="og-meta-tag" />' . "\n";
// add these only if the value is set for reading time
if ( ! empty( $values['reading_time'] ) ) {
echo '<meta name="twitter:label1" content="Est. reading time" class="og-meta-tag" />' . "\n";
echo '<meta name="twitter:data1" content="' . esc_attr( $values['reading_time'] ) . '" class="og-meta-tag" />' . "\n";
}
echo '<script type="application/ld+json" class="og-schema-graph">' . og_insert_schema_graph() . '</script>' . "\n";
echo '<!-- / Custom OG Tags -->' . "\n";
}
add_action( 'wp_head', 'og_insert_meta_tags' );
/**
* Returns the schema graph for the current post.
*
* @return void
*/
function og_insert_schema_graph() {
$post = get_post();
if ( ! $post ) {
return;
}
$image = get_the_post_thumbnail_url( $post->ID, 'full' );
if ( ! $image ) {
$image = wp_get_attachment_image_url( get_theme_mod( 'custom_logo' ), 'large' );
}
$schema_graph = array(
'@context' => 'https://schema.org',
'@graph' => array(
array(
'@type' => 'WebPage',
'@id' => get_permalink(),
'url' => get_permalink(),
'name' => wp_get_document_title(),
'isPartOf' => array(
'@id' => home_url( '#website' ),
),
'about' => array(
'@id' => home_url( '#organization' ),
),
'primaryImageOfPage' => array(
'@id' => home_url( '#primaryimage' ),
),
'image' => array(
'@id' => home_url( '#primaryimage' ),
),
'thumbnailUrl' => get_the_post_thumbnail_url( $post->ID, 'full' ),
'datePublished' => get_the_date( 'c', $post->ID ),
'dateModified' => get_the_modified_date( 'c', $post->ID ),
'breadcrumb' => array(
'@id' => home_url( '#breadcrumb' ),
),
'inLanguage' => get_locale(),
'potentialAction' => array(
array(
'@type' => 'ReadAction',
'target' => array(
get_permalink(),
),
),
),
),
array(
'@type' => 'ImageObject',
'inLanguage' => get_locale(),
'@id' => home_url( '#primaryimage' ),
'url' => $image,
'contentUrl' => $image,
'width' => 900,
'height' => 675,
'caption' => get_the_post_thumbnail_caption( $post->ID ),
),
array(
'@type' => 'BreadcrumbList',
'@id' => home_url( '#breadcrumb' ),
'itemListElement' => array(
array(
'@type' => 'ListItem',
'position' => 1,
'name' => get_bloginfo( 'name' ),
'item' => home_url(),
),
array(
'@type' => 'ListItem',
'position' => 2,
'name' => wp_get_document_title(),
'item' => get_permalink(),
),
),
),
array(
'@type' => 'WebSite',
'@id' => home_url( '#website' ),
'url' => home_url(),
'name' => get_bloginfo( 'name' ),
'description' => get_bloginfo( 'description' ),
'publisher' => array(
'@id' => home_url( '#organization' ),
),
'potentialAction' => array(
array(
'@type' => 'SearchAction',
'target' => array(
'@type' => 'EntryPoint',
'urlTemplate' => home_url( '/?s={search_term_string}' ),
),
'query-input' => 'required name=search_term_string',
),
),
'inLanguage' => get_locale(),
),
array(
'@type' => 'Organization',
'@id' => home_url( '#organization' ),
'name' => get_bloginfo( 'name' ),
'url' => home_url(),
'logo' => array(
'@type' => 'ImageObject',
'inLanguage' => get_locale(),
'@id' => home_url( '#/schema/logo/image/' ),
'url' => wp_get_attachment_image_url( get_theme_mod( 'custom_logo' ), 'full' ),
'contentUrl' => wp_get_attachment_image_url( get_theme_mod( 'custom_logo' ), 'full' ),
'width' => 200,
'height' => 75,
'caption' => get_bloginfo( 'name' ),
),
'image' => array(
'@id' => home_url( '#/schema/logo/image/' ),
),
),
),
);
return wp_json_encode( $schema_graph );
}
/**
* Adds a reading time meta value to the post.
*
* @param [type] $post_id The post ID.
* @return void
*/
function og_save_estimated_reading_time( $post_id ) {
// only do this for pages and posts
if ( ! in_array( get_post_type( $post_id ), array( 'news', 'page' ) ) ) {
$post_content = get_the_content( 'post_content', $post_id );
$word_count = str_word_count( strip_tags( $post_content ) );
$reading_time = ceil( $word_count / 300 ); // Average reading speed is around 300 words per minute.
update_post_meta( $post_id, 'estimated_reading_time_minutes', $reading_time );
}
}
add_action( 'save_post', 'og_save_estimated_reading_time' );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment