From f827b79f8fa16ae50c3bac7541c929011aeed11a Mon Sep 17 00:00:00 2001 From: FrankZamora Date: Tue, 4 Nov 2025 20:24:46 -0600 Subject: [PATCH] ELIMINAR schema-org.php - Rank Math controla TODOS los schemas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Eliminado inc/schema-org.php completamente - Eliminada referencia en functions.php - Rank Math maneja 100% de los schemas - El tema NO debe tocar nada de schemas 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- wp-content/themes/apus-theme/functions.php | 5 - .../themes/apus-theme/inc/schema-org.php | 633 ------------------ 2 files changed, 638 deletions(-) delete mode 100644 wp-content/themes/apus-theme/inc/schema-org.php diff --git a/wp-content/themes/apus-theme/functions.php b/wp-content/themes/apus-theme/functions.php index 815eae39..41691b47 100644 --- a/wp-content/themes/apus-theme/functions.php +++ b/wp-content/themes/apus-theme/functions.php @@ -191,11 +191,6 @@ if (file_exists(get_template_directory() . '/inc/seo.php')) { require_once get_template_directory() . '/inc/seo.php'; } -// Schema.org JSON-LD implementation (Issue #33) -if (file_exists(get_template_directory() . '/inc/schema-org.php')) { - require_once get_template_directory() . '/inc/schema-org.php'; -} - // Performance optimizations if (file_exists(get_template_directory() . '/inc/performance.php')) { require_once get_template_directory() . '/inc/performance.php'; diff --git a/wp-content/themes/apus-theme/inc/schema-org.php b/wp-content/themes/apus-theme/inc/schema-org.php deleted file mode 100644 index b8153d23..00000000 --- a/wp-content/themes/apus-theme/inc/schema-org.php +++ /dev/null @@ -1,633 +0,0 @@ - - */ -function apus_output_schema_jsonld() { - $schemas = array(); - - // Siempre incluir Organization y WebSite - $schemas[] = apus_get_organization_schema(); - $schemas[] = apus_get_website_schema(); - - // Schemas específicos según el contexto - if (is_singular('post')) { - $schemas[] = apus_get_article_schema(); - $schemas[] = apus_get_breadcrumb_schema(); - - // HowTo schema (Issue #42) - $howto_schema = apus_get_howto_schema(); - if ($howto_schema) { - $schemas[] = $howto_schema; - } - - // FAQPage schema (Issue #38) - $faq_schema = apus_get_faqpage_schema(); - if ($faq_schema) { - $schemas[] = $faq_schema; - } - } elseif (is_page()) { - $schemas[] = apus_get_webpage_schema(); - $schemas[] = apus_get_breadcrumb_schema(); - } elseif (is_front_page()) { - // La página principal ya tiene WebSite schema - $schemas[] = apus_get_breadcrumb_schema(); - } else { - // Para archives, categorías, etc. - $schemas[] = apus_get_breadcrumb_schema(); - } - - // Filtrar schemas vacíos - $schemas = array_filter($schemas); - - // Crear graph con todos los schemas - if (!empty($schemas)) { - $graph = array( - '@context' => 'https://schema.org', - '@graph' => $schemas - ); - - echo '' . "\n"; - } -} -add_action('wp_head', 'apus_output_schema_jsonld', 5); - -/** - * Genera el schema Organization - * Información sobre la organización/empresa - * - * @return array Schema Organization - */ -function apus_get_organization_schema() { - $logo = get_theme_mod('custom_logo'); - $logo_url = ''; - - if ($logo) { - $logo_data = wp_get_attachment_image_src($logo, 'full'); - if ($logo_data) { - $logo_url = $logo_data[0]; - } - } - - // Si no hay logo personalizado, usar un fallback - if (empty($logo_url)) { - $logo_url = get_template_directory_uri() . '/assets/images/logo.png'; - } - - $schema = array( - '@type' => 'Organization', - '@id' => home_url('/#organization'), - 'name' => get_bloginfo('name'), - 'url' => home_url('/'), - 'logo' => array( - '@type' => 'ImageObject', - 'url' => $logo_url, - '@id' => home_url('/#logo') - ), - 'description' => get_bloginfo('description'), - 'sameAs' => array() - ); - - // Añadir redes sociales si están configuradas - $social_profiles = array( - 'facebook' => get_theme_mod('social_facebook', ''), - 'twitter' => get_theme_mod('social_twitter', ''), - 'linkedin' => get_theme_mod('social_linkedin', ''), - 'instagram' => get_theme_mod('social_instagram', ''), - 'youtube' => get_theme_mod('social_youtube', '') - ); - - foreach ($social_profiles as $profile_url) { - if (!empty($profile_url)) { - $schema['sameAs'][] = $profile_url; - } - } - - // Eliminar array vacío si no hay redes sociales - if (empty($schema['sameAs'])) { - unset($schema['sameAs']); - } - - return $schema; -} - -/** - * Genera el schema WebSite con SearchAction - * Información del sitio web y funcionalidad de búsqueda - * - * @return array Schema WebSite - */ -function apus_get_website_schema() { - $schema = array( - '@type' => 'WebSite', - '@id' => home_url('/#website'), - 'url' => home_url('/'), - 'name' => get_bloginfo('name'), - 'description' => get_bloginfo('description'), - 'publisher' => array( - '@id' => home_url('/#organization') - ), - 'inLanguage' => 'es-MX' - ); - - // Añadir SearchAction solo si la búsqueda está habilitada - // (el tema desactiva la búsqueda por defecto en Issue #3) - if (!get_option('apus_disable_search', false)) { - $schema['potentialAction'] = array( - '@type' => 'SearchAction', - 'target' => array( - '@type' => 'EntryPoint', - 'urlTemplate' => home_url('/?s={search_term_string}') - ), - 'query-input' => 'required name=search_term_string' - ); - } - - return $schema; -} - -/** - * Genera el schema Article para posts - * Información completa del artículo - * - * @return array|null Schema Article o null si no es un post - */ -function apus_get_article_schema() { - if (!is_singular('post')) { - return null; - } - - global $post; - $post_id = get_the_ID(); - - // Imagen destacada - $image_url = ''; - $image_width = 1200; - $image_height = 630; - - if (has_post_thumbnail($post_id)) { - $image_data = wp_get_attachment_image_src(get_post_thumbnail_id($post_id), 'full'); - if ($image_data) { - $image_url = $image_data[0]; - $image_width = $image_data[1]; - $image_height = $image_data[2]; - } - } - - // Autor - $author_id = $post->post_author; - $author_name = get_the_author_meta('display_name', $author_id); - $author_url = get_author_posts_url($author_id); - $author_description = get_the_author_meta('description', $author_id); - - // Categorías y palabras clave - $categories = get_the_category($post_id); - $category_names = array(); - if (!empty($categories)) { - foreach ($categories as $category) { - $category_names[] = $category->name; - } - } - - // Extracto o descripción - $description = get_the_excerpt($post_id); - if (empty($description)) { - $description = wp_trim_words(strip_tags($post->post_content), 55, '...'); - } - - $schema = array( - '@type' => 'Article', - '@id' => get_permalink($post_id) . '#article', - 'headline' => get_the_title($post_id), - 'description' => $description, - 'datePublished' => get_the_date('c', $post_id), - 'dateModified' => get_the_modified_date('c', $post_id), - 'author' => array( - '@type' => 'Person', - '@id' => $author_url . '#person', - 'name' => $author_name, - 'url' => $author_url - ), - 'publisher' => array( - '@id' => home_url('/#organization') - ), - 'mainEntityOfPage' => array( - '@type' => 'WebPage', - '@id' => get_permalink($post_id) - ), - 'inLanguage' => 'es-MX', - 'isPartOf' => array( - '@id' => home_url('/#website') - ) - ); - - // Añadir imagen si existe - if (!empty($image_url)) { - $schema['image'] = array( - '@type' => 'ImageObject', - 'url' => $image_url, - 'width' => $image_width, - 'height' => $image_height - ); - } - - // Añadir categorías como articleSection - if (!empty($category_names)) { - $schema['articleSection'] = $category_names; - $schema['keywords'] = implode(', ', $category_names); - } - - // Añadir descripción del autor si existe - if (!empty($author_description)) { - $schema['author']['description'] = $author_description; - } - - // Número de palabras - $word_count = str_word_count(strip_tags($post->post_content)); - if ($word_count > 0) { - $schema['wordCount'] = $word_count; - } - - return $schema; -} - -/** - * Genera el schema WebPage para páginas estáticas - * Información de página genérica - * - * @return array|null Schema WebPage o null si no es una página - */ -function apus_get_webpage_schema() { - if (!is_page()) { - return null; - } - - global $post; - $page_id = get_the_ID(); - - // Imagen destacada - $image_url = ''; - if (has_post_thumbnail($page_id)) { - $image_data = wp_get_attachment_image_src(get_post_thumbnail_id($page_id), 'full'); - if ($image_data) { - $image_url = $image_data[0]; - } - } - - // Extracto o descripción - $description = get_the_excerpt($page_id); - if (empty($description)) { - $description = wp_trim_words(strip_tags($post->post_content), 55, '...'); - } - - $schema = array( - '@type' => 'WebPage', - '@id' => get_permalink($page_id) . '#webpage', - 'url' => get_permalink($page_id), - 'name' => get_the_title($page_id), - 'description' => $description, - 'datePublished' => get_the_date('c', $page_id), - 'dateModified' => get_the_modified_date('c', $page_id), - 'isPartOf' => array( - '@id' => home_url('/#website') - ), - 'inLanguage' => 'es-MX' - ); - - // Añadir imagen si existe - if (!empty($image_url)) { - $schema['primaryImageOfPage'] = array( - '@type' => 'ImageObject', - 'url' => $image_url - ); - } - - // Breadcrumb reference - $schema['breadcrumb'] = array( - '@id' => get_permalink($page_id) . '#breadcrumb' - ); - - return $schema; -} - -/** - * Genera el schema BreadcrumbList - * Navegación de migas de pan - * - * @return array Schema BreadcrumbList - */ -function apus_get_breadcrumb_schema() { - $items = array(); - $position = 1; - - // Inicio (Home) - $items[] = array( - '@type' => 'ListItem', - 'position' => $position++, - 'name' => 'Inicio', - 'item' => home_url('/') - ); - - // Para posts - if (is_singular('post')) { - $post_id = get_the_ID(); - $categories = get_the_category($post_id); - - // Añadir la primera categoría si existe - if (!empty($categories)) { - $category = $categories[0]; - $items[] = array( - '@type' => 'ListItem', - 'position' => $position++, - 'name' => $category->name, - 'item' => get_category_link($category->term_id) - ); - } - - // Post actual (sin item ya que es la página actual) - $items[] = array( - '@type' => 'ListItem', - 'position' => $position++, - 'name' => get_the_title($post_id) - ); - } - // Para páginas - elseif (is_page()) { - global $post; - $page_id = get_the_ID(); - - // Si tiene páginas padre - if ($post->post_parent) { - $ancestors = array_reverse(get_post_ancestors($page_id)); - foreach ($ancestors as $ancestor_id) { - $items[] = array( - '@type' => 'ListItem', - 'position' => $position++, - 'name' => get_the_title($ancestor_id), - 'item' => get_permalink($ancestor_id) - ); - } - } - - // Página actual - $items[] = array( - '@type' => 'ListItem', - 'position' => $position++, - 'name' => get_the_title($page_id) - ); - } - // Para categorías - elseif (is_category()) { - $category = get_queried_object(); - $items[] = array( - '@type' => 'ListItem', - 'position' => $position++, - 'name' => $category->name - ); - } - // Para archivos de autor - elseif (is_author()) { - $author = get_queried_object(); - $items[] = array( - '@type' => 'ListItem', - 'position' => $position++, - 'name' => $author->display_name - ); - } - // Para archivos de fecha - elseif (is_date()) { - if (is_year()) { - $items[] = array( - '@type' => 'ListItem', - 'position' => $position++, - 'name' => get_the_date('Y') - ); - } elseif (is_month()) { - $items[] = array( - '@type' => 'ListItem', - 'position' => $position++, - 'name' => get_the_date('F Y') - ); - } elseif (is_day()) { - $items[] = array( - '@type' => 'ListItem', - 'position' => $position++, - 'name' => get_the_date('d F Y') - ); - } - } - // Para búsquedas - elseif (is_search()) { - $items[] = array( - '@type' => 'ListItem', - 'position' => $position++, - 'name' => 'Resultados de búsqueda para: ' . get_search_query() - ); - } - // Para 404 - elseif (is_404()) { - $items[] = array( - '@type' => 'ListItem', - 'position' => $position++, - 'name' => 'Página no encontrada' - ); - } - - $schema = array( - '@type' => 'BreadcrumbList', - '@id' => get_permalink() . '#breadcrumb', - 'itemListElement' => $items - ); - - return $schema; -} - -/** - * Genera Schema HowTo para procesos paso a paso - * Detecta sección con ID #proceso o heading que contenga "proceso" - * - * @return array|null Schema HowTo o null si no aplica - */ -function apus_get_howto_schema() { - if (!is_single()) { - return null; - } - - global $post; - $content = $post->post_content; - - // Verificar si el post tiene sección de proceso - if (stripos($content, 'id="proceso"') === false && - stripos($content, '>proceso<') === false && - stripos($content, '>proceso de') === false) { - return null; - } - - // Usar DOMDocument para parsear - libxml_use_internal_errors(true); - $dom = new DOMDocument(); - $dom->loadHTML('' . $content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); - libxml_clear_errors(); - - $steps = array(); - - // Buscar listas ordenadas
    - $ol_tags = $dom->getElementsByTagName('ol'); - - foreach ($ol_tags as $ol) { - $li_tags = $ol->getElementsByTagName('li'); - - foreach ($li_tags as $index => $li) { - $step_text = trim(strip_tags($li->textContent)); - - if (!empty($step_text)) { - $steps[] = array( - '@type' => 'HowToStep', - 'position' => $index + 1, - 'name' => 'Paso ' . ($index + 1), - 'text' => $step_text - ); - } - } - - // Solo procesar la primera lista ordenada encontrada - if (!empty($steps)) { - break; - } - } - - // Si no hay pasos, retornar null - if (empty($steps)) { - return null; - } - - // Construir schema HowTo - $schema = array( - '@type' => 'HowTo', - '@id' => get_permalink() . '#howto', - 'name' => get_the_title(), - 'description' => get_the_excerpt() ? get_the_excerpt() : wp_trim_words(strip_tags($content), 30), - 'step' => $steps - ); - - // Agregar imagen si existe - $thumbnail_url = get_the_post_thumbnail_url(null, 'large'); - if ($thumbnail_url) { - $schema['image'] = $thumbnail_url; - } - - // Agregar tiempo estimado si se puede extraer (opcional) - // Por ahora, valor por defecto - $schema['totalTime'] = 'PT30M'; // 30 minutos - - return $schema; -} - -/** - * Genera Schema FAQPage automáticamente - * Detecta H3 con signo de interrogación en el contenido - * - * @return array|null Schema FAQPage o null si no aplica - */ -function apus_get_faqpage_schema() { - if (!is_single()) { - return null; - } - - global $post; - $content = $post->post_content; - - // Usar DOMDocument para parsear HTML - libxml_use_internal_errors(true); - $dom = new DOMDocument(); - $dom->loadHTML('' . $content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); - libxml_clear_errors(); - - $h3_tags = $dom->getElementsByTagName('h3'); - $questions = array(); - - foreach ($h3_tags as $h3) { - $question_text = trim($h3->textContent); - - // Solo H3 que terminan con "?" - if (substr($question_text, -1) !== '?') { - continue; - } - - // Buscar el siguiente elemento

    como respuesta - $next_element = $h3->nextSibling; - while ($next_element && $next_element->nodeType !== 1) { - $next_element = $next_element->nextSibling; - } - - if ($next_element && $next_element->nodeName === 'p') { - $answer_text = trim(strip_tags($next_element->textContent)); - - if (!empty($answer_text)) { - $questions[] = array( - '@type' => 'Question', - 'name' => $question_text, - 'acceptedAnswer' => array( - '@type' => 'Answer', - 'text' => $answer_text - ) - ); - } - } - } - - // Mínimo 2 preguntas para generar schema - if (count($questions) < 2) { - return null; - } - - // Limitar a 10 preguntas máximo - if (count($questions) > 10) { - $questions = array_slice($questions, 0, 10); - } - - return array( - '@type' => 'FAQPage', - '@id' => get_permalink() . '#faqpage', - 'mainEntity' => $questions - ); -} - -/** - * Deshabilita los schemas de Rank Math si está activo - * Para evitar duplicación de schemas - */ -function apus_disable_rankmath_schema() { - // Deshabilitar schema de Rank Math si está activo - if (class_exists('RankMath')) { - add_filter('rank_math/json_ld', '__return_false'); - } - - // Deshabilitar schema de Yoast SEO si está activo - if (defined('WPSEO_VERSION')) { - add_filter('wpseo_json_ld_output', '__return_false'); - } -} -add_action('wp_head', 'apus_disable_rankmath_schema', 1);