I’ll build this as a production-style inc/seo/meta-tags.php file for your RX theme, with SEO meta, Open Graph, Twitter cards, canonical, robots, schema hooks, author/date/article data, thumbnails, pagination, and safe fallbacks.
Yes friend — create this file:
rx-theme/inc/seo/meta-tags.php
Then paste this full advanced code inside it.
WordPress prints head data through the wp_head hook, so this file attaches your RX SEO meta output there. It uses escaping functions like esc_attr() and esc_url() for safer HTML output, and wp_json_encode() for JSON-LD schema output.
<?php
/**
* RX Theme Advanced SEO Meta Tags
*
* File: inc/seo/meta-tags.php
*
* Features:
* - Basic SEO meta title/description/keywords
* - Open Graph tags
* - Twitter Card tags
* - Canonical URL support
* - Robots meta control
* - Article published/modified time
* - Author meta
* - Image meta from featured image/site logo/fallback
* - Pagination meta
* - JSON-LD schema for WebSite, Organization, Article, Breadcrumb
* - WooCommerce support if active
* - Search, archive, taxonomy, author, 404 support
* - Safe escaping and filter-ready architecture
*
* Important:
* In header.php, make sure you have:
* <?php wp_head(); ?>
*
* In functions.php, require this file:
* require_once get_template_directory() . '/inc/seo/meta-tags.php';
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'RX_Advanced_Meta_Tags' ) ) :
final class RX_Advanced_Meta_Tags {
/**
* Theme prefix.
*/
const PREFIX = 'rx';
/**
* Default image fallback.
* You can create: /assets/images/rx-default-og.jpg
*/
const DEFAULT_OG_IMAGE = '/assets/images/rx-default-og.jpg';
/**
* Meta description length.
*/
const DESCRIPTION_LENGTH = 160;
/**
* Constructor.
*/
public function __construct() {
add_action( 'wp_head', array( $this, 'output_meta_tags' ), 1 );
add_action( 'wp_head', array( $this, 'output_json_ld_schema' ), 30 );
add_filter( 'document_title_parts', array( $this, 'filter_document_title_parts' ), 20 );
add_filter( 'wp_robots', array( $this, 'filter_wp_robots' ), 20 );
}
/**
* Main meta output.
*/
public function output_meta_tags() {
if ( is_admin() || is_feed() || wp_doing_ajax() ) {
return;
}
$context = $this->get_context();
$title = $this->get_meta_title();
$description = $this->get_meta_description();
$keywords = $this->get_meta_keywords();
$url = $this->get_current_url();
$canonical = $this->get_canonical_url();
$image = $this->get_meta_image();
$image_data = $this->get_meta_image_data();
$type = $this->get_og_type();
$site_name = get_bloginfo( 'name' );
$locale = $this->get_locale();
$author = $this->get_author_name();
echo "\n<!-- RX Advanced SEO Meta Tags -->\n";
$this->print_meta_name( 'description', $description );
if ( ! empty( $keywords ) ) {
$this->print_meta_name( 'keywords', $keywords );
}
$this->print_meta_name( 'author', $author );
$this->print_meta_name( 'publisher', $site_name );
$this->print_meta_name( 'application-name', $site_name );
$this->print_meta_name( 'generator', 'RX Theme SEO System' );
$this->print_meta_name( 'referrer', 'strict-origin-when-cross-origin' );
$this->print_meta_name( 'format-detection', 'telephone=no' );
$this->print_meta_name( 'theme-color', $this->get_theme_color() );
if ( $canonical ) {
printf(
'<link rel="canonical" href="%s" />' . "\n",
esc_url( $canonical )
);
}
$this->output_prev_next_links();
/**
* Open Graph.
*/
$this->print_meta_property( 'og:locale', $locale );
$this->print_meta_property( 'og:type', $type );
$this->print_meta_property( 'og:title', $title );
$this->print_meta_property( 'og:description', $description );
$this->print_meta_property( 'og:url', $url );
$this->print_meta_property( 'og:site_name', $site_name );
if ( $image ) {
$this->print_meta_property( 'og:image', $image );
$this->print_meta_property( 'og:image:secure_url', $image );
$this->print_meta_property( 'og:image:alt', $this->get_image_alt_text() );
if ( ! empty( $image_data['width'] ) ) {
$this->print_meta_property( 'og:image:width', (string) absint( $image_data['width'] ) );
}
if ( ! empty( $image_data['height'] ) ) {
$this->print_meta_property( 'og:image:height', (string) absint( $image_data['height'] ) );
}
if ( ! empty( $image_data['mime'] ) ) {
$this->print_meta_property( 'og:image:type', $image_data['mime'] );
}
}
if ( is_singular() ) {
$post_id = get_queried_object_id();
$this->print_meta_property( 'article:published_time', get_the_date( DATE_W3C, $post_id ) );
$this->print_meta_property( 'article:modified_time', get_the_modified_date( DATE_W3C, $post_id ) );
$this->print_meta_property( 'og:updated_time', get_the_modified_date( DATE_W3C, $post_id ) );
$this->print_meta_property( 'article:author', $author );
$categories = get_the_category( $post_id );
if ( ! empty( $categories ) && ! is_wp_error( $categories ) ) {
foreach ( $categories as $category ) {
$this->print_meta_property( 'article:section', $category->name );
}
}
$tags = get_the_tags( $post_id );
if ( ! empty( $tags ) && ! is_wp_error( $tags ) ) {
foreach ( $tags as $tag ) {
$this->print_meta_property( 'article:tag', $tag->name );
}
}
}
/**
* Twitter Card.
*/
$this->print_meta_name( 'twitter:card', $image ? 'summary_large_image' : 'summary' );
$this->print_meta_name( 'twitter:title', $title );
$this->print_meta_name( 'twitter:description', $description );
if ( $image ) {
$this->print_meta_name( 'twitter:image', $image );
$this->print_meta_name( 'twitter:image:alt', $this->get_image_alt_text() );
}
$twitter_site = $this->get_twitter_site();
if ( $twitter_site ) {
$this->print_meta_name( 'twitter:site', $twitter_site );
$this->print_meta_name( 'twitter:creator', $twitter_site );
}
/**
* Extra mobile/social meta.
*/
$this->print_meta_name( 'apple-mobile-web-app-title', $site_name );
$this->print_meta_name( 'apple-mobile-web-app-capable', 'yes' );
$this->print_meta_name( 'apple-mobile-web-app-status-bar-style', 'default' );
$this->print_meta_name( 'mobile-web-app-capable', 'yes' );
/**
* Optional RSS discovery.
*/
printf(
'<link rel="alternate" type="application/rss+xml" title="%s Feed" href="%s" />' . "\n",
esc_attr( $site_name ),
esc_url( get_bloginfo( 'rss2_url' ) )
);
/**
* Optional REST API discovery.
*/
printf(
'<link rel="https://api.w.org/" href="%s" />' . "\n",
esc_url( rest_url() )
);
/**
* Custom hook for future RX theme extension.
*/
do_action(
'rx_after_advanced_meta_tags',
array(
'context' => $context,
'title' => $title,
'description' => $description,
'keywords' => $keywords,
'url' => $url,
'canonical' => $canonical,
'image' => $image,
'type' => $type,
)
);
echo "<!-- /RX Advanced SEO Meta Tags -->\n\n";
}
/**
* Filter WordPress document title parts.
*
* WordPress exposes document title parts through document_title_parts.
*/
public function filter_document_title_parts( $parts ) {
if ( is_admin() ) {
return $parts;
}
if ( is_front_page() || is_home() ) {
$parts['title'] = get_bloginfo( 'name' );
if ( get_bloginfo( 'description' ) ) {
$parts['tagline'] = get_bloginfo( 'description' );
}
} elseif ( is_singular() ) {
$parts['title'] = single_post_title( '', false );
} elseif ( is_category() || is_tag() || is_tax() ) {
$parts['title'] = single_term_title( '', false );
} elseif ( is_author() ) {
$parts['title'] = sprintf(
/* translators: %s author name */
__( 'Author: %s', 'rx' ),
get_the_author_meta( 'display_name', get_queried_object_id() )
);
} elseif ( is_search() ) {
$parts['title'] = sprintf(
/* translators: %s search term */
__( 'Search results for: %s', 'rx' ),
get_search_query()
);
} elseif ( is_404() ) {
$parts['title'] = __( 'Page Not Found', 'rx' );
}
return $parts;
}
/**
* Robots meta filter.
*/
public function filter_wp_robots( $robots ) {
if ( is_search() || is_404() ) {
$robots['noindex'] = true;
$robots['nofollow'] = false;
}
if ( is_paged() ) {
$robots['noindex'] = false;
$robots['follow'] = true;
}
if ( is_singular() ) {
$post_id = get_queried_object_id();
if ( $post_id && '0' === get_post_meta( $post_id, '_rx_seo_index', true ) ) {
$robots['noindex'] = true;
}
}
$robots['max-image-preview'] = 'large';
$robots['max-snippet'] = -1;
$robots['max-video-preview'] = -1;
return $robots;
}
/**
* Get current context.
*/
private function get_context() {
if ( is_front_page() ) {
return 'front_page';
}
if ( is_home() ) {
return 'blog_home';
}
if ( is_singular( 'post' ) ) {
return 'single_post';
}
if ( is_singular( 'page' ) ) {
return 'single_page';
}
if ( is_singular() ) {
return 'single';
}
if ( is_category() ) {
return 'category';
}
if ( is_tag() ) {
return 'tag';
}
if ( is_tax() ) {
return 'taxonomy';
}
if ( is_author() ) {
return 'author';
}
if ( is_date() ) {
return 'date_archive';
}
if ( is_search() ) {
return 'search';
}
if ( is_404() ) {
return '404';
}
if ( function_exists( 'is_shop' ) && is_shop() ) {
return 'shop';
}
if ( function_exists( 'is_product' ) && is_product() ) {
return 'product';
}
return 'general';
}
/**
* Get SEO title.
*/
private function get_meta_title() {
$title = '';
if ( is_front_page() || is_home() ) {
$title = get_bloginfo( 'name' );
if ( get_bloginfo( 'description' ) ) {
$title .= ' - ' . get_bloginfo( 'description' );
}
} elseif ( is_singular() ) {
$post_id = get_queried_object_id();
$custom_title = get_post_meta( $post_id, '_rx_seo_title', true );
$title = $custom_title ? $custom_title : get_the_title( $post_id );
$title .= ' - ' . get_bloginfo( 'name' );
} elseif ( is_category() || is_tag() || is_tax() ) {
$title = single_term_title( '', false ) . ' - ' . get_bloginfo( 'name' );
} elseif ( is_author() ) {
$title = sprintf(
__( 'Author: %s', 'rx' ),
get_the_author_meta( 'display_name', get_queried_object_id() )
) . ' - ' . get_bloginfo( 'name' );
} elseif ( is_search() ) {
$title = sprintf(
__( 'Search results for: %s', 'rx' ),
get_search_query()
) . ' - ' . get_bloginfo( 'name' );
} elseif ( is_404() ) {
$title = __( 'Page Not Found', 'rx' ) . ' - ' . get_bloginfo( 'name' );
} else {
$title = wp_get_document_title();
}
return apply_filters( 'rx_meta_title', wp_strip_all_tags( $title ) );
}
/**
* Get SEO description.
*/
private function get_meta_description() {
$description = '';
if ( is_front_page() || is_home() ) {
$description = get_bloginfo( 'description' );
} elseif ( is_singular() ) {
$post_id = get_queried_object_id();
$custom_description = get_post_meta( $post_id, '_rx_seo_description', true );
if ( $custom_description ) {
$description = $custom_description;
} elseif ( has_excerpt( $post_id ) ) {
$description = get_the_excerpt( $post_id );
} else {
$post = get_post( $post_id );
if ( $post ) {
$description = $this->trim_text( wp_strip_all_tags( strip_shortcodes( $post->post_content ) ), self::DESCRIPTION_LENGTH );
}
}
} elseif ( is_category() || is_tag() || is_tax() ) {
$description = term_description();
if ( ! $description ) {
$description = sprintf(
__( 'Read the latest articles about %s on %s.', 'rx' ),
single_term_title( '', false ),
get_bloginfo( 'name' )
);
}
} elseif ( is_author() ) {
$description = get_the_author_meta( 'description', get_queried_object_id() );
if ( ! $description ) {
$description = sprintf(
__( 'Articles written by %s on %s.', 'rx' ),
get_the_author_meta( 'display_name', get_queried_object_id() ),
get_bloginfo( 'name' )
);
}
} elseif ( is_search() ) {
$description = sprintf(
__( 'Search results for %s on %s.', 'rx' ),
get_search_query(),
get_bloginfo( 'name' )
);
} elseif ( is_404() ) {
$description = sprintf(
__( 'The page you are looking for could not be found on %s.', 'rx' ),
get_bloginfo( 'name' )
);
}
if ( empty( $description ) ) {
$description = get_bloginfo( 'description' );
}
$description = wp_strip_all_tags( strip_shortcodes( $description ) );
$description = preg_replace( '/\s+/', ' ', $description );
$description = trim( $description );
$description = $this->trim_text( $description, self::DESCRIPTION_LENGTH );
return apply_filters( 'rx_meta_description', $description );
}
/**
* Get meta keywords.
*
* Meta keywords are not a major modern SEO ranking factor,
* but this is included because you requested as much functionality as possible.
*/
private function get_meta_keywords() {
$keywords = array();
if ( is_singular() ) {
$post_id = get_queried_object_id();
$custom_keywords = get_post_meta( $post_id, '_rx_seo_keywords', true );
if ( $custom_keywords ) {
return apply_filters( 'rx_meta_keywords', sanitize_text_field( $custom_keywords ) );
}
$tags = get_the_tags( $post_id );
if ( $tags && ! is_wp_error( $tags ) ) {
foreach ( $tags as $tag ) {
$keywords[] = $tag->name;
}
}
$categories = get_the_category( $post_id );
if ( $categories && ! is_wp_error( $categories ) ) {
foreach ( $categories as $category ) {
$keywords[] = $category->name;
}
}
} elseif ( is_category() || is_tag() || is_tax() ) {
$keywords[] = single_term_title( '', false );
}
$keywords[] = get_bloginfo( 'name' );
$keywords = array_filter( array_unique( array_map( 'sanitize_text_field', $keywords ) ) );
return apply_filters( 'rx_meta_keywords', implode( ', ', $keywords ) );
}
/**
* Get current URL.
*/
private function get_current_url() {
if ( is_singular() ) {
return get_permalink();
}
if ( is_category() || is_tag() || is_tax() ) {
$term = get_queried_object();
if ( $term && ! is_wp_error( $term ) ) {
$link = get_term_link( $term );
if ( ! is_wp_error( $link ) ) {
return $link;
}
}
}
if ( is_author() ) {
return get_author_posts_url( get_queried_object_id() );
}
if ( is_search() ) {
return get_search_link();
}
$scheme = is_ssl() ? 'https://' : 'http://';
$host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : wp_parse_url( home_url(), PHP_URL_HOST );
$uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '/';
return esc_url_raw( $scheme . $host . $uri );
}
/**
* Get canonical URL.
*/
private function get_canonical_url() {
if ( is_singular() ) {
return get_permalink();
}
if ( is_front_page() || is_home() ) {
return home_url( '/' );
}
if ( is_category() || is_tag() || is_tax() ) {
$term = get_queried_object();
if ( $term && ! is_wp_error( $term ) ) {
$link = get_term_link( $term );
if ( ! is_wp_error( $link ) ) {
return $link;
}
}
}
if ( is_author() ) {
return get_author_posts_url( get_queried_object_id() );
}
if ( is_search() || is_404() ) {
return '';
}
return $this->get_current_url();
}
/**
* Output prev/next pagination links.
*/
private function output_prev_next_links() {
if ( is_singular() ) {
$prev = get_adjacent_post( false, '', true );
$next = get_adjacent_post( false, '', false );
if ( $prev ) {
printf(
'<link rel="prev" href="%s" />' . "\n",
esc_url( get_permalink( $prev ) )
);
}
if ( $next ) {
printf(
'<link rel="next" href="%s" />' . "\n",
esc_url( get_permalink( $next ) )
);
}
return;
}
global $paged, $wp_query;
$current_page = max( 1, absint( $paged ) );
$total_pages = isset( $wp_query->max_num_pages ) ? absint( $wp_query->max_num_pages ) : 1;
if ( $total_pages <= 1 ) {
return;
}
if ( $current_page > 1 ) {
printf(
'<link rel="prev" href="%s" />' . "\n",
esc_url( get_pagenum_link( $current_page - 1 ) )
);
}
if ( $current_page < $total_pages ) {
printf(
'<link rel="next" href="%s" />' . "\n",
esc_url( get_pagenum_link( $current_page + 1 ) )
);
}
}
/**
* Get Open Graph type.
*/
private function get_og_type() {
if ( is_singular( 'post' ) ) {
return 'article';
}
if ( function_exists( 'is_product' ) && is_product() ) {
return 'product';
}
if ( is_front_page() || is_home() ) {
return 'website';
}
return 'object';
}
/**
* Get meta image.
*
* WordPress featured image helpers like has_post_thumbnail()
* and get_the_post_thumbnail_url() are used here.
*/
private function get_meta_image() {
$image = '';
if ( is_singular() ) {
$post_id = get_queried_object_id();
if ( has_post_thumbnail( $post_id ) ) {
$image = get_the_post_thumbnail_url( $post_id, 'full' );
}
}
if ( ! $image ) {
$custom_logo_id = get_theme_mod( 'custom_logo' );
if ( $custom_logo_id ) {
$image = wp_get_attachment_image_url( $custom_logo_id, 'full' );
}
}
if ( ! $image ) {
$fallback = get_template_directory_uri() . self::DEFAULT_OG_IMAGE;
$image = $fallback;
}
return apply_filters( 'rx_meta_image', esc_url_raw( $image ) );
}
/**
* Get image data.
*/
private function get_meta_image_data() {
$data = array(
'width' => '',
'height' => '',
'mime' => '',
);
if ( is_singular() ) {
$post_id = get_queried_object_id();
if ( has_post_thumbnail( $post_id ) ) {
$thumb_id = get_post_thumbnail_id( $post_id );
$meta = wp_get_attachment_metadata( $thumb_id );
$mime = get_post_mime_type( $thumb_id );
if ( ! empty( $meta['width'] ) ) {
$data['width'] = absint( $meta['width'] );
}
if ( ! empty( $meta['height'] ) ) {
$data['height'] = absint( $meta['height'] );
}
if ( $mime ) {
$data['mime'] = sanitize_text_field( $mime );
}
}
}
return apply_filters( 'rx_meta_image_data', $data );
}
/**
* Get image alt.
*/
private function get_image_alt_text() {
$alt = get_bloginfo( 'name' );
if ( is_singular() ) {
$post_id = get_queried_object_id();
if ( has_post_thumbnail( $post_id ) ) {
$thumb_id = get_post_thumbnail_id( $post_id );
$image_alt = get_post_meta( $thumb_id, '_wp_attachment_image_alt', true );
if ( $image_alt ) {
$alt = $image_alt;
} else {
$alt = get_the_title( $post_id );
}
}
}
return apply_filters( 'rx_meta_image_alt', wp_strip_all_tags( $alt ) );
}
/**
* Get locale.
*/
private function get_locale() {
$locale = get_locale();
$locale = str_replace( '-', '_', $locale );
return apply_filters( 'rx_meta_locale', $locale );
}
/**
* Get theme color.
*/
private function get_theme_color() {
$color = get_theme_mod( 'rx_theme_color', '#0f766e' );
if ( ! preg_match( '/^#[a-fA-F0-9]{6}$/', $color ) ) {
$color = '#0f766e';
}
return apply_filters( 'rx_theme_color_meta', $color );
}
/**
* Twitter handle.
*
* Change this to your real Twitter/X handle if needed.
*/
private function get_twitter_site() {
$handle = get_theme_mod( 'rx_twitter_handle', '' );
if ( empty( $handle ) ) {
return '';
}
$handle = sanitize_text_field( $handle );
if ( '@' !== substr( $handle, 0, 1 ) ) {
$handle = '@' . $handle;
}
return apply_filters( 'rx_twitter_site', $handle );
}
/**
* Get author name.
*/
private function get_author_name() {
if ( is_singular() ) {
$post = get_post();
if ( $post ) {
return get_the_author_meta( 'display_name', $post->post_author );
}
}
if ( is_author() ) {
return get_the_author_meta( 'display_name', get_queried_object_id() );
}
return get_bloginfo( 'name' );
}
/**
* Output JSON-LD schema.
*/
public function output_json_ld_schema() {
if ( is_admin() || is_feed() || wp_doing_ajax() ) {
return;
}
$schemas = array();
$schemas[] = $this->get_website_schema();
$schemas[] = $this->get_organization_schema();
if ( is_singular() ) {
$schemas[] = $this->get_article_schema();
}
if ( function_exists( 'is_product' ) && is_product() ) {
$product_schema = $this->get_product_schema();
if ( $product_schema ) {
$schemas[] = $product_schema;
}
}
$breadcrumb_schema = $this->get_breadcrumb_schema();
if ( $breadcrumb_schema ) {
$schemas[] = $breadcrumb_schema;
}
$schemas = array_filter( $schemas );
if ( empty( $schemas ) ) {
return;
}
foreach ( $schemas as $schema ) {
$this->print_json_ld( $schema );
}
}
/**
* WebSite schema.
*/
private function get_website_schema() {
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'WebSite',
'@id' => home_url( '/#website' ),
'url' => home_url( '/' ),
'name' => get_bloginfo( 'name' ),
'description' => get_bloginfo( 'description' ),
'inLanguage' => get_bloginfo( 'language' ),
'potentialAction' => array(
'@type' => 'SearchAction',
'target' => home_url( '/?s={search_term_string}' ),
'query-input' => 'required name=search_term_string',
),
);
return apply_filters( 'rx_website_schema', $schema );
}
/**
* Organization schema.
*/
private function get_organization_schema() {
$logo = '';
$custom_logo_id = get_theme_mod( 'custom_logo' );
if ( $custom_logo_id ) {
$logo = wp_get_attachment_image_url( $custom_logo_id, 'full' );
}
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'Organization',
'@id' => home_url( '/#organization' ),
'name' => get_bloginfo( 'name' ),
'url' => home_url( '/' ),
);
if ( $logo ) {
$schema['logo'] = array(
'@type' => 'ImageObject',
'url' => esc_url_raw( $logo ),
);
}
$social_links = $this->get_social_links();
if ( ! empty( $social_links ) ) {
$schema['sameAs'] = $social_links;
}
return apply_filters( 'rx_organization_schema', $schema );
}
/**
* Article schema.
*/
private function get_article_schema() {
$post_id = get_queried_object_id();
if ( ! $post_id ) {
return array();
}
$image = $this->get_meta_image();
$schema = array(
'@context' => 'https://schema.org',
'@type' => is_singular( 'post' ) ? 'Article' : 'WebPage',
'@id' => get_permalink( $post_id ) . '#article',
'mainEntityOfPage' => array(
'@type' => 'WebPage',
'@id' => get_permalink( $post_id ),
),
'headline' => $this->get_meta_title(),
'description' => $this->get_meta_description(),
'url' => get_permalink( $post_id ),
'datePublished' => get_the_date( DATE_W3C, $post_id ),
'dateModified' => get_the_modified_date( DATE_W3C, $post_id ),
'inLanguage' => get_bloginfo( 'language' ),
'author' => array(
'@type' => 'Person',
'name' => get_the_author_meta( 'display_name', get_post_field( 'post_author', $post_id ) ),
'url' => get_author_posts_url( get_post_field( 'post_author', $post_id ) ),
),
'publisher' => array(
'@id' => home_url( '/#organization' ),
),
);
if ( $image ) {
$schema['image'] = array(
'@type' => 'ImageObject',
'url' => esc_url_raw( $image ),
);
}
$word_count = str_word_count( wp_strip_all_tags( get_post_field( 'post_content', $post_id ) ) );
if ( $word_count ) {
$schema['wordCount'] = absint( $word_count );
}
$categories = get_the_category( $post_id );
if ( ! empty( $categories ) && ! is_wp_error( $categories ) ) {
$schema['articleSection'] = wp_list_pluck( $categories, 'name' );
}
$tags = get_the_tags( $post_id );
if ( ! empty( $tags ) && ! is_wp_error( $tags ) ) {
$schema['keywords'] = implode( ', ', wp_list_pluck( $tags, 'name' ) );
}
return apply_filters( 'rx_article_schema', $schema, $post_id );
}
/**
* Product schema for WooCommerce.
*/
private function get_product_schema() {
if ( ! function_exists( 'wc_get_product' ) ) {
return array();
}
$product_id = get_queried_object_id();
$product = wc_get_product( $product_id );
if ( ! $product ) {
return array();
}
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'Product',
'@id' => get_permalink( $product_id ) . '#product',
'name' => get_the_title( $product_id ),
'description' => $this->get_meta_description(),
'url' => get_permalink( $product_id ),
'image' => $this->get_meta_image(),
'sku' => $product->get_sku(),
);
$price = $product->get_price();
if ( '' !== $price ) {
$schema['offers'] = array(
'@type' => 'Offer',
'price' => $price,
'priceCurrency' => get_woocommerce_currency(),
'availability' => $product->is_in_stock() ? 'https://schema.org/InStock' : 'https://schema.org/OutOfStock',
'url' => get_permalink( $product_id ),
);
}
return apply_filters( 'rx_product_schema', $schema, $product_id, $product );
}
/**
* Breadcrumb schema.
*/
private function get_breadcrumb_schema() {
$items = array();
$items[] = array(
'@type' => 'ListItem',
'position' => 1,
'name' => __( 'Home', 'rx' ),
'item' => home_url( '/' ),
);
if ( is_singular() ) {
$post_id = get_queried_object_id();
if ( is_singular( 'post' ) ) {
$categories = get_the_category( $post_id );
if ( ! empty( $categories ) && ! is_wp_error( $categories ) ) {
$category = $categories[0];
$items[] = array(
'@type' => 'ListItem',
'position' => count( $items ) + 1,
'name' => $category->name,
'item' => get_category_link( $category->term_id ),
);
}
}
$items[] = array(
'@type' => 'ListItem',
'position' => count( $items ) + 1,
'name' => get_the_title( $post_id ),
'item' => get_permalink( $post_id ),
);
} elseif ( is_category() || is_tag() || is_tax() ) {
$items[] = array(
'@type' => 'ListItem',
'position' => count( $items ) + 1,
'name' => single_term_title( '', false ),
'item' => $this->get_current_url(),
);
} elseif ( is_search() ) {
$items[] = array(
'@type' => 'ListItem',
'position' => count( $items ) + 1,
'name' => sprintf( __( 'Search: %s', 'rx' ), get_search_query() ),
'item' => get_search_link(),
);
} elseif ( is_author() ) {
$items[] = array(
'@type' => 'ListItem',
'position' => count( $items ) + 1,
'name' => get_the_author_meta( 'display_name', get_queried_object_id() ),
'item' => get_author_posts_url( get_queried_object_id() ),
);
} else {
return array();
}
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => $items,
);
return apply_filters( 'rx_breadcrumb_schema', $schema );
}
/**
* Social links for Organization schema.
*
* Add your links using this filter from functions.php:
*
* add_filter( 'rx_social_links', function( $links ) {
* $links[] = 'https://www.facebook.com/yourpage';
* $links[] = 'https://x.com/yourhandle';
* return $links;
* });
*/
private function get_social_links() {
$links = array();
$links = apply_filters( 'rx_social_links', $links );
$links = array_filter(
array_map(
static function( $url ) {
return esc_url_raw( $url );
},
(array) $links
)
);
return array_values( array_unique( $links ) );
}
/**
* Print meta name.
*/
private function print_meta_name( $name, $content ) {
$content = trim( (string) $content );
if ( '' === $content ) {
return;
}
printf(
'<meta name="%s" content="%s" />' . "\n",
esc_attr( $name ),
esc_attr( $content )
);
}
/**
* Print meta property.
*/
private function print_meta_property( $property, $content ) {
$content = trim( (string) $content );
if ( '' === $content ) {
return;
}
printf(
'<meta property="%s" content="%s" />' . "\n",
esc_attr( $property ),
esc_attr( $content )
);
}
/**
* Print JSON-LD.
*/
private function print_json_ld( $data ) {
if ( empty( $data ) || ! is_array( $data ) ) {
return;
}
$json = wp_json_encode(
$data,
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT
);
if ( ! $json ) {
return;
}
echo '<script type="application/ld+json">' . "\n";
echo $json . "\n";
echo '</script>' . "\n";
}
/**
* Trim text by character length.
*/
private function trim_text( $text, $length = 160 ) {
$text = trim( (string) $text );
if ( function_exists( 'mb_strlen' ) && function_exists( 'mb_substr' ) ) {
if ( mb_strlen( $text ) <= $length ) {
return $text;
}
return rtrim( mb_substr( $text, 0, $length - 3 ) ) . '...';
}
if ( strlen( $text ) <= $length ) {
return $text;
}
return rtrim( substr( $text, 0, $length - 3 ) ) . '...';
}
}
endif;
/**
* Boot RX advanced meta tags.
*/
function rx_boot_advanced_meta_tags() {
new RX_Advanced_Meta_Tags();
}
add_action( 'after_setup_theme', 'rx_boot_advanced_meta_tags' );
Now add this line in your main functions.php:
require_once get_template_directory() . '/inc/seo/meta-tags.php';
Also make sure your header.php has this before </head>:
<?php wp_head(); ?>
Important: featured images are used for og:image and Twitter image when available. WordPress supports checking featured images with has_post_thumbnail() and retrieving image URLs with get_the_post_thumbnail_url() / wp_get_attachment_image_url().