@@ -0,0 +1,239 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Advanced SEO Meta + AI FAQ Schema
|
||||
* Plugin URI: https://my-dev.pro/advanced-seo-meta
|
||||
* Description: Full SEO meta box (Title, Description) + built-in FAQ builder with JSON-LD Schema for AI search engines.
|
||||
* Version: 3.0.0
|
||||
* Author: MYDev
|
||||
* Author URI: https://my-dev.pro
|
||||
* License: GPL-2.0+
|
||||
* Text Domain: advanced-seo-meta
|
||||
* Domain Path: /languages
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||||
|
||||
class Advanced_SEO_Meta {
|
||||
|
||||
public function __construct() {
|
||||
add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
|
||||
add_action( 'save_post', array( $this, 'save_meta_data' ) );
|
||||
add_filter( 'pre_get_document_title', array( $this, 'custom_title' ), 10 );
|
||||
add_action( 'wp_head', array( $this, 'output_meta_tags' ), 1 );
|
||||
add_action( 'wp_head', array( $this, 'output_og_tags' ), 2 );
|
||||
add_action( 'wp_head', array( $this, 'output_faq_schema' ), 5 ); // High priority for AI crawlers
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a tiny JS script to handle adding/removing FAQ rows in the admin.
|
||||
*/
|
||||
public function enqueue_admin_assets() {
|
||||
wp_add_inline_script( 'jquery', '
|
||||
jQuery(document).ready(function($) {
|
||||
// Add FAQ row
|
||||
$(document).on("click", ".add-faq-row", function(e) {
|
||||
e.preventDefault();
|
||||
var index = $(".faq-row").length;
|
||||
var row = \'<div class="faq-row" style="background:#f9f9f9;padding:15px;margin-bottom:15px;border:1px solid #ddd;">\' +
|
||||
\'<p><label>Question:</label><input type="text" name="faq_question[]" style="width:100%;" /></p>\' +
|
||||
\'<p><label>Answer:</label><textarea name="faq_answer[]" rows="2" style="width:100%;"></textarea></p>\' +
|
||||
\'<button class="remove-faq-row button button-small">Remove Question</button>\' +
|
||||
\'</div>\';
|
||||
$(this).before(row);
|
||||
});
|
||||
// Remove FAQ row
|
||||
$(document).on("click", ".remove-faq-row", function(e) {
|
||||
e.preventDefault();
|
||||
$(this).closest(".faq-row").remove();
|
||||
});
|
||||
});
|
||||
' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the main SEO + FAQ meta box.
|
||||
*/
|
||||
public function add_meta_box() {
|
||||
add_meta_box(
|
||||
'advanced_seo_meta_box',
|
||||
__( 'Advanced SEO & AI FAQ Schema', 'advanced-seo-meta' ),
|
||||
array( $this, 'render_meta_box' ),
|
||||
['post', 'page'],
|
||||
'normal',
|
||||
'default'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the meta box (Title, Description, FAQ builder).
|
||||
*/
|
||||
public function render_meta_box( $post ) {
|
||||
wp_nonce_field( 'advanced_seo_nonce', 'advanced_seo_nonce' );
|
||||
|
||||
// Get saved values
|
||||
$seo_title = get_post_meta( $post->ID, '_seo_title', true );
|
||||
$seo_description = get_post_meta( $post->ID, '_seo_description', true );
|
||||
$faq_data = get_post_meta( $post->ID, '_seo_faq', true );
|
||||
if ( ! is_array( $faq_data ) ) $faq_data = array();
|
||||
?>
|
||||
<style>
|
||||
.seo-field { margin-bottom: 20px; }
|
||||
.seo-field label { font-weight: 600; display: block; margin-bottom: 5px; }
|
||||
.seo-field input, .seo-field textarea { width: 100%; max-width: 700px; }
|
||||
.faq-row { background: #f5f5f5; padding: 15px; margin-bottom: 15px; border: 1px solid #ddd; border-radius: 4px; }
|
||||
</style>
|
||||
|
||||
<!-- 1. SEO Title -->
|
||||
<div class="seo-field">
|
||||
<label for="seo_title"><?php esc_html_e( 'SEO Title (For Google search results)', 'advanced-seo-meta' ); ?></label>
|
||||
<input type="text" id="seo_title" name="seo_title" value="<?php echo esc_attr( $seo_title ); ?>" placeholder="e.g., Comprehensive Genomic Profiling (CGP) & WES for Precision Oncology" />
|
||||
</div>
|
||||
|
||||
<!-- 2. Meta Description -->
|
||||
<div class="seo-field">
|
||||
<label for="seo_description"><?php esc_html_e( 'Meta Description (150-160 characters)', 'advanced-seo-meta' ); ?></label>
|
||||
<textarea id="seo_description" name="seo_description" rows="3"><?php echo esc_textarea( $seo_description ); ?></textarea>
|
||||
</div>
|
||||
|
||||
<hr style="margin: 30px 0;" />
|
||||
|
||||
<!-- 3. FAQ Builder (For AI Search Engines) -->
|
||||
<h3 style="margin-top:0;"><?php esc_html_e( 'FAQ Schema for AI Search (Google SGE, Bing Chat)', 'advanced-seo-meta' ); ?></h3>
|
||||
<p class="description"><?php esc_html_e( 'Add questions and answers here. This will be output as JSON-LD structured data so AI engines can display your answers directly in search results.', 'advanced-seo-meta' ); ?></p>
|
||||
|
||||
<div id="faq-container">
|
||||
<?php if ( ! empty( $faq_data ) ) : ?>
|
||||
<?php foreach ( $faq_data as $faq ) : ?>
|
||||
<div class="faq-row">
|
||||
<p><label>Question:</label><input type="text" name="faq_question[]" value="<?php echo esc_attr( $faq['question'] ); ?>" style="width:100%;" /></p>
|
||||
<p><label>Answer:</label><textarea name="faq_answer[]" rows="2" style="width:100%;"><?php echo esc_textarea( $faq['answer'] ); ?></textarea></p>
|
||||
<button class="remove-faq-row button button-small"><?php esc_html_e( 'Remove Question', 'advanced-seo-meta' ); ?></button>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php else : ?>
|
||||
<!-- Default Example Pre-filled (Your Oncology Content) -->
|
||||
<div class="faq-row">
|
||||
<p><label>Question:</label><input type="text" name="faq_question[]" value="What is Comprehensive Genomic Profiling (CGP) in oncology?" style="width:100%;" /></p>
|
||||
<p><label>Answer:</label><textarea name="faq_answer[]" rows="2" style="width:100%;">Comprehensive Genomic Profiling (CGP) is a next-generation sequencing test that analyzes all classes of genomic alterations across hundreds of cancer-associated genes to identify targeted therapy options, immunotherapy biomarkers, and clinical trial opportunities for cancer patients.</textarea></p>
|
||||
<button class="remove-faq-row button button-small">Remove Question</button>
|
||||
</div>
|
||||
<div class="faq-row">
|
||||
<p><label>Question:</label><input type="text" name="faq_question[]" value="What is the difference between WES (Whole Exome Sequencing) and CGP?" style="width:100%;" /></p>
|
||||
<p><label>Answer:</label><textarea name="faq_answer[]" rows="2" style="width:100%;">Whole Exome Sequencing (WES) sequences all protein-coding regions of the entire genome, covering ~20,000 genes. Comprehensive Genomic Profiling (CGP) focuses specifically on a curated panel of known cancer-driver genes, providing deeper coverage (higher read depth) for those specific genes, making it more sensitive for detecting low-frequency tumor mutations in clinical oncology.</textarea></p>
|
||||
<button class="remove-faq-row button button-small">Remove Question</button>
|
||||
</div>
|
||||
<div class="faq-row">
|
||||
<p><label>Question:</label><input type="text" name="faq_question[]" value="How does precision medicine use genomic profiling?" style="width:100%;" /></p>
|
||||
<p><label>Answer:</label><textarea name="faq_answer[]" rows="2" style="width:100%;">Precision medicine uses genomic profiling to identify specific genetic mutations driving a patient's disease. By matching these mutations with FDA-approved targeted therapies or immunotherapies, clinicians can deliver highly personalized treatment plans that improve efficacy and reduce adverse side effects compared to traditional chemotherapy.</textarea></p>
|
||||
<button class="remove-faq-row button button-small">Remove Question</button>
|
||||
</div>
|
||||
<div class="faq-row">
|
||||
<p><label>Question:</label><input type="text" name="faq_question[]" value="Is CGP the same as standard clinical genetics testing?" style="width:100%;" /></p>
|
||||
<p><label>Answer:</label><textarea name="faq_answer[]" rows="2" style="width:100%;">No. Standard clinical genetics testing typically looks for inherited germline mutations (e.g., BRCA1/2). CGP analyzes somatic (tumor-acquired) mutations within the cancer tissue itself. While both fall under clinical genetics, CGP is specifically used for guiding oncology treatment decisions, whereas standard testing assesses hereditary cancer risk.</textarea></p>
|
||||
<button class="remove-faq-row button button-small">Remove Question</button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<button class="add-faq-row button button-primary"><?php esc_html_e( '+ Add New FAQ', 'advanced-seo-meta' ); ?></button>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all the new fields.
|
||||
*/
|
||||
public function save_meta_data( $post_id ) {
|
||||
if ( ! isset( $_POST['advanced_seo_nonce'] ) || ! wp_verify_nonce( $_POST['advanced_seo_nonce'], 'advanced_seo_nonce' ) ) return;
|
||||
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
|
||||
if ( ! current_user_can( 'edit_post', $post_id ) ) return;
|
||||
|
||||
// Save Title & Description
|
||||
if ( isset( $_POST['seo_title'] ) ) update_post_meta( $post_id, '_seo_title', sanitize_text_field( $_POST['seo_title'] ) );
|
||||
if ( isset( $_POST['seo_description'] ) ) update_post_meta( $post_id, '_seo_description', sanitize_textarea_field( $_POST['seo_description'] ) );
|
||||
|
||||
// Save FAQ Array
|
||||
$questions = isset( $_POST['faq_question'] ) ? array_map( 'sanitize_text_field', $_POST['faq_question'] ) : array();
|
||||
$answers = isset( $_POST['faq_answer'] ) ? array_map( 'wp_kses_post', $_POST['faq_answer'] ) : array(); // Allow basic HTML for answers
|
||||
|
||||
$faq_pairs = array();
|
||||
for ( $i = 0; $i < count( $questions ); $i++ ) {
|
||||
if ( ! empty( $questions[ $i ] ) && ! empty( $answers[ $i ] ) ) {
|
||||
$faq_pairs[] = array(
|
||||
'question' => $questions[ $i ],
|
||||
'answer' => $answers[ $i ]
|
||||
);
|
||||
}
|
||||
}
|
||||
update_post_meta( $post_id, '_seo_faq', $faq_pairs );
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the <title> tag.
|
||||
*/
|
||||
public function custom_title( $title ) {
|
||||
if ( is_singular() ) {
|
||||
$custom = get_post_meta( get_queried_object_id(), '_seo_title', true );
|
||||
if ( ! empty( $custom ) ) return $custom;
|
||||
}
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output Description & Keywords.
|
||||
*/
|
||||
public function output_meta_tags() {
|
||||
if ( ! is_singular() ) return;
|
||||
$id = get_queried_object_id();
|
||||
if ( $desc = get_post_meta( $id, '_seo_description', true ) ) echo '<meta name="description" content="' . esc_attr( $desc ) . '" />' . "\n";
|
||||
// (Optional: We leave keywords empty intentionally, but if you insist, uncomment below)
|
||||
// if ( $kw = get_post_meta( $id, '_seo_keywords', true ) ) echo '<meta name="keywords" content="' . esc_attr( $kw ) . '" />' . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Output Open Graph (Facebook/LinkedIn).
|
||||
*/
|
||||
public function output_og_tags() {
|
||||
if ( ! is_singular() ) return;
|
||||
$id = get_queried_object_id();
|
||||
$post = get_post( $id );
|
||||
$title = get_post_meta( $id, '_seo_title', true ) ?: $post->post_title;
|
||||
$desc = get_post_meta( $id, '_seo_description', true ) ?: wp_trim_words( $post->post_content, 30 );
|
||||
echo '<meta property="og:title" content="' . esc_attr( $title ) . '" />' . "\n";
|
||||
echo '<meta property="og:description" content="' . esc_attr( $desc ) . '" />' . "\n";
|
||||
echo '<meta property="og:url" content="' . esc_url( get_permalink() ) . '" />' . "\n";
|
||||
echo '<meta property="og:type" content="article" />' . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Output JSON-LD FAQ Schema (The secret weapon for AI search).
|
||||
*/
|
||||
public function output_faq_schema() {
|
||||
if ( ! is_singular() ) return;
|
||||
$id = get_queried_object_id();
|
||||
$faq_data = get_post_meta( $id, '_seo_faq', true );
|
||||
|
||||
if ( empty( $faq_data ) || ! is_array( $faq_data ) ) return;
|
||||
|
||||
$schema = array(
|
||||
'@context' => 'https://schema.org',
|
||||
'@type' => 'FAQPage',
|
||||
'mainEntity' => array()
|
||||
);
|
||||
|
||||
foreach ( $faq_data as $faq ) {
|
||||
$schema['mainEntity'][] = array(
|
||||
'@type' => 'Question',
|
||||
'name' => $faq['question'],
|
||||
'acceptedAnswer' => array(
|
||||
'@type' => 'Answer',
|
||||
'text' => $faq['answer']
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
echo '<script type="application/ld+json">' . json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) . '</script>' . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
new Advanced_SEO_Meta();
|
||||
Reference in New Issue
Block a user