Make your WordPress site irresistible. Natural SEO attraction with: - robots.txt management - sitemap.xml generation - LLMs.txt support - Google integration (Analytics, Search Console, Tag Manager) - Schema.org structured data - Open Graph / Twitter Card meta tags - AMP support - Visual elements gallery - Built-in backup/restore module Includes build.sh and .distignore for WordPress-installable release ZIPs.
564 lines
22 KiB
PHP
564 lines
22 KiB
PHP
<?php
|
|
/**
|
|
* OpenGraph Module for TigerStyle Heat
|
|
* Implements Facebook OpenGraph meta tags for social sharing optimization
|
|
*/
|
|
|
|
// Prevent direct access
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
class TigerStyleSEO_OpenGraph {
|
|
|
|
/**
|
|
* Single instance
|
|
*/
|
|
private static $instance = null;
|
|
|
|
/**
|
|
* Get instance
|
|
*/
|
|
public static function instance() {
|
|
if (is_null(self::$instance)) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
private function __construct() {
|
|
$this->init();
|
|
}
|
|
|
|
/**
|
|
* Initialize the module
|
|
*/
|
|
private function init() {
|
|
// Frontend hooks
|
|
add_action('wp_head', array($this, 'inject_opengraph_tags'), 5);
|
|
|
|
// Admin hooks
|
|
if (is_admin()) {
|
|
add_action('admin_post_update_opengraph_settings', array($this, 'handle_form_submission'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Inject OpenGraph meta tags into head section
|
|
*/
|
|
public function inject_opengraph_tags() {
|
|
$settings = $this->get_opengraph_settings();
|
|
|
|
if (!$settings['enabled']) {
|
|
return;
|
|
}
|
|
|
|
$tags = $this->generate_opengraph_tags();
|
|
|
|
if (!empty($tags)) {
|
|
echo "\n<!-- TigerStyle Heat - OpenGraph Meta Tags -->\n";
|
|
foreach ($tags as $tag) {
|
|
echo $tag . "\n";
|
|
}
|
|
echo "<!-- End TigerStyle Heat OpenGraph -->\n\n";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generate OpenGraph meta tags based on current page
|
|
*/
|
|
private function generate_opengraph_tags() {
|
|
$tags = array();
|
|
$settings = $this->get_opengraph_settings();
|
|
|
|
// Required tags
|
|
$tags[] = '<meta property="og:url" content="' . esc_attr($this->get_canonical_url()) . '" />';
|
|
$tags[] = '<meta property="og:title" content="' . esc_attr($this->get_page_title()) . '" />';
|
|
$tags[] = '<meta property="og:description" content="' . esc_attr($this->get_page_description()) . '" />';
|
|
$tags[] = '<meta property="og:image" content="' . esc_attr($this->get_page_image()) . '" />';
|
|
|
|
// Optional but recommended tags
|
|
$tags[] = '<meta property="og:type" content="' . esc_attr($this->get_page_type()) . '" />';
|
|
$tags[] = '<meta property="og:locale" content="' . esc_attr($this->get_locale()) . '" />';
|
|
|
|
// Site name
|
|
if (!empty($settings['site_name'])) {
|
|
$tags[] = '<meta property="og:site_name" content="' . esc_attr($settings['site_name']) . '" />';
|
|
}
|
|
|
|
// Facebook App ID
|
|
if (!empty($settings['app_id'])) {
|
|
$tags[] = '<meta property="fb:app_id" content="' . esc_attr($settings['app_id']) . '" />';
|
|
}
|
|
|
|
// Image dimensions if available
|
|
$image_data = $this->get_image_data($this->get_page_image());
|
|
if ($image_data) {
|
|
$tags[] = '<meta property="og:image:width" content="' . esc_attr($image_data['width']) . '" />';
|
|
$tags[] = '<meta property="og:image:height" content="' . esc_attr($image_data['height']) . '" />';
|
|
if (!empty($image_data['type'])) {
|
|
$tags[] = '<meta property="og:image:type" content="' . esc_attr($image_data['type']) . '" />';
|
|
}
|
|
}
|
|
|
|
// Article-specific tags for posts
|
|
if (is_single() && get_post_type() === 'post') {
|
|
$post = get_post();
|
|
$tags[] = '<meta property="article:published_time" content="' . esc_attr(get_the_date('c')) . '" />';
|
|
$tags[] = '<meta property="article:modified_time" content="' . esc_attr(get_the_modified_date('c')) . '" />';
|
|
|
|
// Author
|
|
$author = get_the_author_meta('display_name', $post->post_author);
|
|
if ($author) {
|
|
$tags[] = '<meta property="article:author" content="' . esc_attr($author) . '" />';
|
|
}
|
|
|
|
// Categories as sections
|
|
$categories = get_the_category();
|
|
foreach ($categories as $category) {
|
|
$tags[] = '<meta property="article:section" content="' . esc_attr($category->name) . '" />';
|
|
}
|
|
|
|
// Tags
|
|
$post_tags = get_the_tags();
|
|
if ($post_tags) {
|
|
foreach ($post_tags as $tag) {
|
|
$tags[] = '<meta property="article:tag" content="' . esc_attr($tag->name) . '" />';
|
|
}
|
|
}
|
|
}
|
|
|
|
return apply_filters('tigerstyle_heat_opengraph_tags', $tags);
|
|
}
|
|
|
|
/**
|
|
* Get canonical URL for current page
|
|
*/
|
|
private function get_canonical_url() {
|
|
if (is_home() || is_front_page()) {
|
|
return home_url('/');
|
|
}
|
|
|
|
if (is_singular()) {
|
|
return get_permalink();
|
|
}
|
|
|
|
if (is_category()) {
|
|
return get_category_link(get_queried_object_id());
|
|
}
|
|
|
|
if (is_tag()) {
|
|
return get_tag_link(get_queried_object_id());
|
|
}
|
|
|
|
if (is_author()) {
|
|
return get_author_posts_url(get_queried_object_id());
|
|
}
|
|
|
|
// Fallback to current URL
|
|
global $wp;
|
|
return home_url(add_query_arg(array(), $wp->request));
|
|
}
|
|
|
|
/**
|
|
* Get page title optimized for social sharing
|
|
*/
|
|
private function get_page_title() {
|
|
if (is_singular()) {
|
|
return get_the_title();
|
|
}
|
|
|
|
if (is_home() || is_front_page()) {
|
|
return get_bloginfo('name');
|
|
}
|
|
|
|
if (is_category()) {
|
|
return single_cat_title('', false);
|
|
}
|
|
|
|
if (is_tag()) {
|
|
return single_tag_title('', false);
|
|
}
|
|
|
|
if (is_author()) {
|
|
return get_the_author_meta('display_name', get_queried_object_id());
|
|
}
|
|
|
|
if (is_archive()) {
|
|
return get_the_archive_title();
|
|
}
|
|
|
|
return get_bloginfo('name');
|
|
}
|
|
|
|
/**
|
|
* Get page description for social sharing
|
|
*/
|
|
private function get_page_description() {
|
|
$settings = $this->get_opengraph_settings();
|
|
|
|
if (is_singular()) {
|
|
$post = get_post();
|
|
|
|
// Try excerpt first
|
|
if (!empty($post->post_excerpt)) {
|
|
return wp_strip_all_tags($post->post_excerpt);
|
|
}
|
|
|
|
// Try content excerpt
|
|
$content = wp_strip_all_tags($post->post_content);
|
|
if ($content) {
|
|
return wp_trim_words($content, 30);
|
|
}
|
|
}
|
|
|
|
if (is_category()) {
|
|
$description = category_description();
|
|
if ($description) {
|
|
return wp_strip_all_tags($description);
|
|
}
|
|
}
|
|
|
|
if (is_tag()) {
|
|
$description = tag_description();
|
|
if ($description) {
|
|
return wp_strip_all_tags($description);
|
|
}
|
|
}
|
|
|
|
// Fallback to site description
|
|
return get_bloginfo('description') ?: $settings['default_description'];
|
|
}
|
|
|
|
/**
|
|
* Get appropriate image for the page
|
|
*/
|
|
private function get_page_image() {
|
|
$settings = $this->get_opengraph_settings();
|
|
|
|
// Featured image for posts/pages
|
|
if (is_singular() && has_post_thumbnail()) {
|
|
$image_id = get_post_thumbnail_id();
|
|
$image_url = wp_get_attachment_image_url($image_id, 'large');
|
|
if ($image_url) {
|
|
return $image_url;
|
|
}
|
|
}
|
|
|
|
// Find first image in content
|
|
if (is_singular()) {
|
|
$content = get_post_field('post_content');
|
|
preg_match('/<img[^>]+src="([^">]+)"/', $content, $matches);
|
|
if (!empty($matches[1])) {
|
|
return $matches[1];
|
|
}
|
|
}
|
|
|
|
// Default image from settings
|
|
if (!empty($settings['default_image'])) {
|
|
return $settings['default_image'];
|
|
}
|
|
|
|
// Site logo as fallback
|
|
$custom_logo_id = get_theme_mod('custom_logo');
|
|
if ($custom_logo_id) {
|
|
$logo_url = wp_get_attachment_image_url($custom_logo_id, 'large');
|
|
if ($logo_url) {
|
|
return $logo_url;
|
|
}
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Get OpenGraph type for current page
|
|
*/
|
|
private function get_page_type() {
|
|
if (is_single() && get_post_type() === 'post') {
|
|
return 'article';
|
|
}
|
|
|
|
if (is_page()) {
|
|
return 'website';
|
|
}
|
|
|
|
if (is_author()) {
|
|
return 'profile';
|
|
}
|
|
|
|
return 'website';
|
|
}
|
|
|
|
/**
|
|
* Get locale for OpenGraph
|
|
*/
|
|
private function get_locale() {
|
|
$locale = get_locale();
|
|
|
|
// Convert WordPress locale to OpenGraph format
|
|
$locale_map = array(
|
|
'en_US' => 'en_US',
|
|
'en_GB' => 'en_GB',
|
|
'es_ES' => 'es_ES',
|
|
'fr_FR' => 'fr_FR',
|
|
'de_DE' => 'de_DE',
|
|
'it_IT' => 'it_IT',
|
|
'pt_BR' => 'pt_BR',
|
|
'nl_NL' => 'nl_NL',
|
|
'ru_RU' => 'ru_RU',
|
|
'ja' => 'ja_JP',
|
|
'zh_CN' => 'zh_CN',
|
|
);
|
|
|
|
return isset($locale_map[$locale]) ? $locale_map[$locale] : 'en_US';
|
|
}
|
|
|
|
/**
|
|
* Get image dimensions and type
|
|
*/
|
|
private function get_image_data($image_url) {
|
|
if (empty($image_url)) {
|
|
return false;
|
|
}
|
|
|
|
// Try to get attachment ID from URL
|
|
$attachment_id = attachment_url_to_postid($image_url);
|
|
if ($attachment_id) {
|
|
$metadata = wp_get_attachment_metadata($attachment_id);
|
|
if ($metadata && isset($metadata['width'], $metadata['height'])) {
|
|
return array(
|
|
'width' => $metadata['width'],
|
|
'height' => $metadata['height'],
|
|
'type' => get_post_mime_type($attachment_id)
|
|
);
|
|
}
|
|
}
|
|
|
|
// Try to get image size from URL (if local)
|
|
if (strpos($image_url, home_url()) === 0) {
|
|
$upload_dir = wp_upload_dir();
|
|
$image_path = str_replace($upload_dir['baseurl'], $upload_dir['basedir'], $image_url);
|
|
|
|
if (file_exists($image_path)) {
|
|
$image_info = getimagesize($image_path);
|
|
if ($image_info) {
|
|
return array(
|
|
'width' => $image_info[0],
|
|
'height' => $image_info[1],
|
|
'type' => $image_info['mime']
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get OpenGraph settings
|
|
*/
|
|
private function get_opengraph_settings() {
|
|
$defaults = array(
|
|
'enabled' => true,
|
|
'site_name' => get_bloginfo('name'),
|
|
'app_id' => '',
|
|
'default_description' => get_bloginfo('description'),
|
|
'default_image' => '',
|
|
'include_article_tags' => true,
|
|
'include_author_info' => true
|
|
);
|
|
|
|
$settings = get_option('tigerstyle_opengraph_settings', array());
|
|
return wp_parse_args($settings, $defaults);
|
|
}
|
|
|
|
/**
|
|
* Handle form submission
|
|
*/
|
|
public function handle_form_submission() {
|
|
if (!current_user_can('manage_options')) {
|
|
wp_die(__('You do not have sufficient permissions to access this page.'));
|
|
}
|
|
|
|
if (!wp_verify_nonce($_POST['_wpnonce'], 'tigerstyle_opengraph_settings')) {
|
|
wp_die(__('Security check failed. Please try again.'));
|
|
}
|
|
|
|
$settings = array(
|
|
'enabled' => isset($_POST['og_enabled']) ? 1 : 0,
|
|
'site_name' => sanitize_text_field($_POST['og_site_name'] ?? ''),
|
|
'app_id' => sanitize_text_field($_POST['og_app_id'] ?? ''),
|
|
'default_description' => sanitize_textarea_field($_POST['og_default_description'] ?? ''),
|
|
'default_image' => esc_url_raw($_POST['og_default_image'] ?? ''),
|
|
'include_article_tags' => isset($_POST['og_include_article_tags']) ? 1 : 0,
|
|
'include_author_info' => isset($_POST['og_include_author_info']) ? 1 : 0
|
|
);
|
|
|
|
update_option('tigerstyle_opengraph_settings', $settings);
|
|
|
|
wp_redirect(add_query_arg(array('page' => 'tigerstyle-heat', 'tab' => 'opengraph', 'updated' => 'true'), admin_url('admin.php')));
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Get debug information for current page
|
|
*/
|
|
public function get_debug_info() {
|
|
if (!current_user_can('manage_options')) {
|
|
return array();
|
|
}
|
|
|
|
return array(
|
|
'url' => $this->get_canonical_url(),
|
|
'title' => $this->get_page_title(),
|
|
'description' => $this->get_page_description(),
|
|
'image' => $this->get_page_image(),
|
|
'type' => $this->get_page_type(),
|
|
'locale' => $this->get_locale(),
|
|
'tags' => $this->generate_opengraph_tags()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Render admin page
|
|
*/
|
|
public function render_admin_page() {
|
|
$settings = $this->get_opengraph_settings();
|
|
?>
|
|
<div class="seo-info-box">
|
|
<h2><?php _e('Facebook OpenGraph Configuration', 'tigerstyle-heat'); ?></h2>
|
|
<p><?php _e('Configure OpenGraph meta tags to optimize how your content appears when shared on Facebook, LinkedIn, Twitter, and other social platforms.', 'tigerstyle-heat'); ?></p>
|
|
|
|
<div class="seo-setup-steps">
|
|
<h3><?php _e('What is OpenGraph?', 'tigerstyle-heat'); ?></h3>
|
|
<p><?php _e('OpenGraph is a protocol that enables any web page to become a rich object in a social graph. It allows you to control how your content appears when shared on social media platforms.', 'tigerstyle-heat'); ?></p>
|
|
|
|
<h4><?php _e('Key OpenGraph Meta Tags:', 'tigerstyle-heat'); ?></h4>
|
|
<ul>
|
|
<li><strong>og:title</strong> - <?php _e('The title of your content', 'tigerstyle-heat'); ?></li>
|
|
<li><strong>og:description</strong> - <?php _e('A brief description of your content', 'tigerstyle-heat'); ?></li>
|
|
<li><strong>og:image</strong> - <?php _e('An image representing your content', 'tigerstyle-heat'); ?></li>
|
|
<li><strong>og:url</strong> - <?php _e('The canonical URL of your content', 'tigerstyle-heat'); ?></li>
|
|
<li><strong>og:type</strong> - <?php _e('The type of object (article, website, etc.)', 'tigerstyle-heat'); ?></li>
|
|
</ul>
|
|
|
|
<p><a href="https://developers.facebook.com/docs/sharing/webmasters/" target="_blank"><?php _e('Learn more about OpenGraph protocol', 'tigerstyle-heat'); ?></a></p>
|
|
</div>
|
|
</div>
|
|
|
|
<form method="post" action="<?php echo admin_url('admin-post.php'); ?>">
|
|
<?php wp_nonce_field('tigerstyle_opengraph_settings'); ?>
|
|
<input type="hidden" name="action" value="update_opengraph_settings">
|
|
|
|
<table class="form-table">
|
|
<tr>
|
|
<th scope="row"><?php _e('Enable OpenGraph', 'tigerstyle-heat'); ?></th>
|
|
<td>
|
|
<label>
|
|
<input type="checkbox" name="og_enabled" value="1" <?php checked($settings['enabled']); ?>>
|
|
<?php _e('Enable OpenGraph meta tags', 'tigerstyle-heat'); ?>
|
|
</label>
|
|
<p class="description"><?php _e('Enable automatic generation of OpenGraph meta tags for social sharing.', 'tigerstyle-heat'); ?></p>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<th scope="row"><?php _e('Site Name', 'tigerstyle-heat'); ?></th>
|
|
<td>
|
|
<input type="text" name="og_site_name" value="<?php echo esc_attr($settings['site_name']); ?>" class="regular-text">
|
|
<p class="description"><?php _e('The name of your website. Defaults to site title.', 'tigerstyle-heat'); ?></p>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<th scope="row"><?php _e('Facebook App ID', 'tigerstyle-heat'); ?></th>
|
|
<td>
|
|
<input type="text" name="og_app_id" value="<?php echo esc_attr($settings['app_id']); ?>" class="regular-text">
|
|
<p class="description"><?php _e('Optional: Your Facebook App ID for enhanced social insights.', 'tigerstyle-heat'); ?></p>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<th scope="row"><?php _e('Default Description', 'tigerstyle-heat'); ?></th>
|
|
<td>
|
|
<textarea name="og_default_description" rows="3" class="large-text"><?php echo esc_textarea($settings['default_description']); ?></textarea>
|
|
<p class="description"><?php _e('Default description used when no specific content description is available.', 'tigerstyle-heat'); ?></p>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<th scope="row"><?php _e('Default Image URL', 'tigerstyle-heat'); ?></th>
|
|
<td>
|
|
<input type="url" name="og_default_image" value="<?php echo esc_attr($settings['default_image']); ?>" class="large-text">
|
|
<p class="description"><?php _e('Default image used when no featured image is available. Recommended size: 1200x630 pixels.', 'tigerstyle-heat'); ?></p>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<th scope="row"><?php _e('Article Options', 'tigerstyle-heat'); ?></th>
|
|
<td>
|
|
<label>
|
|
<input type="checkbox" name="og_include_article_tags" value="1" <?php checked($settings['include_article_tags']); ?>>
|
|
<?php _e('Include article tags and categories', 'tigerstyle-heat'); ?>
|
|
</label>
|
|
<br>
|
|
<label>
|
|
<input type="checkbox" name="og_include_author_info" value="1" <?php checked($settings['include_author_info']); ?>>
|
|
<?php _e('Include article author information', 'tigerstyle-heat'); ?>
|
|
</label>
|
|
<p class="description"><?php _e('Enhanced metadata for blog posts and articles.', 'tigerstyle-heat'); ?></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<?php submit_button(__('Save OpenGraph Settings', 'tigerstyle-heat')); ?>
|
|
</form>
|
|
|
|
<?php if ($settings['enabled'] && current_user_can('manage_options')): ?>
|
|
<div class="seo-info-box">
|
|
<h3><?php _e('Current Page OpenGraph Preview', 'tigerstyle-heat'); ?></h3>
|
|
<p><?php _e('Preview how the current page would appear with OpenGraph tags:', 'tigerstyle-heat'); ?></p>
|
|
|
|
<?php
|
|
$debug_info = $this->get_debug_info();
|
|
if (!empty($debug_info)):
|
|
?>
|
|
<div style="border: 1px solid #ddd; padding: 15px; margin: 15px 0; background: #f9f9f9;">
|
|
<h4><?php _e('OpenGraph Data:', 'tigerstyle-heat'); ?></h4>
|
|
<p><strong><?php _e('Title:', 'tigerstyle-heat'); ?></strong> <?php echo esc_html($debug_info['title']); ?></p>
|
|
<p><strong><?php _e('Description:', 'tigerstyle-heat'); ?></strong> <?php echo esc_html($debug_info['description']); ?></p>
|
|
<p><strong><?php _e('URL:', 'tigerstyle-heat'); ?></strong> <?php echo esc_html($debug_info['url']); ?></p>
|
|
<p><strong><?php _e('Type:', 'tigerstyle-heat'); ?></strong> <?php echo esc_html($debug_info['type']); ?></p>
|
|
<?php if (!empty($debug_info['image'])): ?>
|
|
<p><strong><?php _e('Image:', 'tigerstyle-heat'); ?></strong> <br>
|
|
<img src="<?php echo esc_url($debug_info['image']); ?>" style="max-width: 300px; max-height: 150px; border: 1px solid #ddd;" alt="OpenGraph Preview">
|
|
</p>
|
|
<?php endif; ?>
|
|
|
|
<h4><?php _e('Generated Meta Tags:', 'tigerstyle-heat'); ?></h4>
|
|
<pre style="background: #f0f0f0; padding: 10px; overflow-x: auto; font-size: 12px;"><?php
|
|
foreach ($debug_info['tags'] as $tag) {
|
|
echo esc_html($tag) . "\n";
|
|
}
|
|
?></pre>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="seo-info-box">
|
|
<h3><?php _e('Testing Your OpenGraph Tags', 'tigerstyle-heat'); ?></h3>
|
|
<p><?php _e('Use these tools to validate and preview your OpenGraph implementation:', 'tigerstyle-heat'); ?></p>
|
|
<ul>
|
|
<li><a href="https://developers.facebook.com/tools/debug/" target="_blank"><?php _e('Facebook Sharing Debugger', 'tigerstyle-heat'); ?></a></li>
|
|
<li><a href="https://www.linkedin.com/post-inspector/" target="_blank"><?php _e('LinkedIn Post Inspector', 'tigerstyle-heat'); ?></a></li>
|
|
<li><a href="https://cards-dev.twitter.com/validator" target="_blank"><?php _e('Twitter Card Validator', 'tigerstyle-heat'); ?></a></li>
|
|
</ul>
|
|
</div>
|
|
<?php
|
|
}
|
|
}
|