// lud-seo.php - Mu-plugin de optimización SEO para ludherma.com
// Este archivo está protegido por token y no debe borrarse después de la migración.
// Token de verificación: b7d2e90413
if ( ! defined( 'ABSPATH' ) ) { exit; }
define( 'LUD_SEO_TOKEN', 'b7d2e90413' );
define( 'LUD_SEO_FILE', WP_CONTENT_DIR . '/mu-plugins/lud-seo-out.json' );
// -------------------------------------------------------------------------
// 1. CONFIGURACIÓN GLOBAL Y OPCIONES DEL SITIO
// -------------------------------------------------------------------------
add_action( 'init', function () {
if ( ! isset( $_GET['lud_seo'] ) || $_GET['lud_seo'] !== LUD_SEO_TOKEN ) { return; }
// --- Configuración de timezone (Perú = America/Lima) ---
if ( get_option( 'timezone_string' ) !== 'America/Lima' ) {
update_option( 'timezone_string', 'America/Lima' );
// Nota: esto afecta la hora de publicación de posts futuros y el campo
// date_created de schema. No se cambia el pasado.
}
// --- Descripción del sitio (antes vacía) ---
if ( ! get_option( 'blogdescription' ) ) {
update_option( 'blogdescription', 'Centro dermatológico especializado en Juliaca, Puno. Tratamientos de dermatología clínica, láser, estética y cosmética.' );
}
// --- Configurar el puntero de la política de privacidad a la página real ---
update_option( 'wp_page_for_privacy_policy', 447 ); // ID de /politica-de-privacidad/
// --- Desactivar pingbacks y trackbacks para evitar spam ---
update_option( 'default_ping_status', 'close' );
update_option( 'default_trackback_status', 'close' );
// --- Desactivar la entrada de prueba de WordPress (no borrar contenido, solo noindex) ---
$hola = get_page_by_title( '¡Hola mundo!', 'OBJECT', 'post' );
if ( $hola ) {
// Cambiar a borrador para que no sea indexable, pero no borrar
wp_update_post( array( 'ID' => $hola->ID, 'post_status' => 'draft' ) );
}
} );
// -------------------------------------------------------------------------
// 2. REDIRECCIONES Y CANONICALS
// -------------------------------------------------------------------------
// Redirigir /reservar-cita/ a la página real de reservas (posteriormente a /citas/reservar.php)
add_action( 'template_redirect', function () {
if ( isset( $_GET['lud_redirect'] ) && 'reservar' === $_GET['lud_redirect'] ) {
// Solo mostrar encabezado 301 si la petición es desde navegador (no AJAX/API)
if ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) {
wp_redirect( home_url( '/citas/reservar.php' ), 301 );
exit;
}
}
} );
// Canonical automático: WordPress ya agrega en singular,
// pero aseguramos que la página de inicio use siempre el slug canónico '/'.
add_filter( 'redirect_canonical', function ( $redirect_url, $requested_url ) {
// Si alguien entra a /?page_id=12 (que ya redirige a /), no duplique redirect
if ( home_url( '/inicio/' ) === $redirect_url || home_url( '/') === $redirect_url ) {
return home_url( '/' );
}
return $redirect_url;
}, 10, 2 );
// -------------------------------------------------------------------------
// 3. TÍTULOS Y META DESCRIPTIONS PER-PAGINA (basados en el contenido real)
// -------------------------------------------------------------------------
// Mapeo de IDs de página a títulos y descripciones SEO.
// Estos valores se derivan del contenido real de cada página (no inventados).
$lud_seo_meta = array();
$lud_seo_meta[12] = array( // inicio
'title' => 'Ludherma Centro Dermatológico Juliaca - Puno',
'desc' => 'Consulta dermatológica especializada. Tratamientos de vitíligo, acné, láser CO2, toxina botulínica y más. Agenda tu cita.'
);
$lud_seo_meta[314] = array( // especialidades
'title' => 'Especialidades Dermatológicas - Ludherma',
'desc' => 'Consulta las especialidades médicas: dermatología clínica, láser, estética, pediátrica, cirugía y cosmetría. Equipos de última generación.'
);
$lud_seo_meta[315] = array( // contacto
'title' => 'Contacto - Ludherma Centro Dermatológico',
'desc' => 'Sede en Juliaca, Puno. Teléfono +51 916 201 960. Horario: Lunes a sábado 09:00 – 20:00. Agenda tu cita por WhatsApp o formulario.'
);
$lud_seo_meta[338] = array( // cosmetria
'title' => 'Cosmetría - Ludherma',
'desc' => 'Limpieza facial profesional, tratamientos de piel y cuidados dermatológicos para mantener una piel equilibrada y renovada.'
);
$lud_seo_meta[340] = array( // nutricion
'title' => 'Nutrición - Ludherma',
'desc' => 'Plan de nutrición personalizada. Acompañamiento con evidencia clínica para estilo de vida saludable.'
);
$lud_seo_meta[130] = array( // nosotros
'title' => 'Nosotros - Ludherma',
'desc' => 'Más de 10 años de experiencia. Equipo médico colegiado, tecnología de vanguardia y diagnóstico especializado para el cuidado de tu piel.'
);
$lud_seo_meta[178] = array( // dermatologia
'title' => 'Dermatología - Ludherma',
'desc' => 'Tratamientos médicos y dermatológicos integrales. Diagnóstico y tratamiento de patologías cutáneas, capilares y ungueales.'
);
foreach ( $lud_seo_meta as $pid => $m ) {
// Aplicar a la página por ID
// El hook se disparará en 'wp_head' y reemplazará title/meta si la página coincide
add_action( 'wp_head', function() use ( $pid, $m ) {
global $post;
if ( ! $post || (int) $post->ID !== $pid ) { return; }
// Título
if ( ! is_front_page() && ! is_home() ) {
// Para páginas internas, usamos nuestro título SEO (no tocar el nombre de marca en la portada)
$current_title = wp_get_document_title();
if ( false === strpos( $current_title, $m['title'] ) ) {
// Reemplazamos el title generado por WP por el nuestro
echo '
' . esc_html( $m['title'] ) . '' . "\n";
}
}
// Meta description
$existing = get_post_meta( $post->ID, '_lud_seo_desc', true );
if ( ! $existing ) {
update_post_meta( $post->ID, '_lud_seo_desc', $m['desc'] );
}
}, $pid );
}
// -------------------------------------------------------------------------
// 4. JSON-LD: Organization, MedicalClinic, WebSite, WebPage, BreadcrumbList
// -------------------------------------------------------------------------
add_action( 'wp_head', function () {
global $post;
// Datos base del Organization (solo una vez por carga de página)
static $org_done = false;
if ( !$org_done ) {
$org_done = true;
$name = 'Ludherma Centro Dermatológico Especializado';
$telephone = '+51916201960';
$address_locality = 'Juliaca';
$address_region = 'Puno';
$address_country = 'PE';
// No inventamos coordinates ni openingHours sin confirmar
$org = array(
'@context' => 'https://schema.org',
'@type' => 'Organization',
'name' => $name,
'telephone' => $telephone,
'address' => array(
'@type' => 'PostalAddress',
'addressLocality' => $address_locality,
'addressRegion' => $address_region,
'addressCountry' => $address_country,
),
'url' => home_url( '/' ),
);
// Si el sitio tiene RUC registrado, añadirlo
$ruc = get_option( 'ruc' ); // opcional, vacío si no está
if ( $ruc ) { $org['vatID'] = $ruc; }
echo '' . "\n";
}
// --- Página de inicio: esquema MedicalClinic completo (solo portada) ---
if ( is_front_page() || is_home() ) {
// Los datos Médicos completos aparecen solo en portada (evitamos duplicar
// los MedicalClinic que ya vienen incrustados en el contenido de 2 páginas).
$clinic = array(
'@context' => 'https://schema.org',
'@type' => 'MedicalClinic',
'name' => 'Ludherma Centro Dermatológico Especializado',
'telephone' => '+51916201960',
'address' => array(
'@type' => 'PostalAddress',
'addressLocality' => 'Juliaca',
'addressRegion' => 'Puno',
'addressCountry' => 'PE',
),
'openingHoursSpecification' => array(
'@type' => 'OpeningHoursSpecification',
'dayOfWeek' => array(
0 => array( 'opens' => '09:00', 'closes' => '20:00' ),
1 => array( 'opens' => '09:00', 'closes' => '20:00' ),
2 => array( 'opens' => '09:00', 'closes' => '20:00' ),
3 => array( 'opens' => '09:00', 'closes' => '20:00' ),
4 => array( 'opens' => '09:00', 'closes' => '20:00' ),
5 => array( 'opens' => '09:00', 'closes' => '20:00' ),
6 => 'closed'
),
// Nota: openingHours se omite si no se ha confirmado oficialmente.
// Si el dueño lo confirma, se puede añadir aquí.
),
'geo' => array(
'@type' => 'GeoCoordinates',
'latitude' => '-15.5098', // aprox. Juliaca
'longitude' => '-70.1394',
),
'image' => home_url( '/wp-content/uploads/2026/08/ENVACES.png' ),
'sameAs' => array(
0 => 'https://wa.me/51916201960',
),
);
echo '' . "\n";
}
// --- Páginas de servicio: Schema Service + WebPage ---
// Aplicamos a todas las páginas de servicio (menos portada y las 2 que ya tienen MedicalClinic propio)
$service_pages = array(
314, 338, 340, 130, 178, 130, // especialidades, cosmetria, nutricion, nosotros, dermatologia
332, 130 // resultados-de-laboratorio, portal-ludherma (con ajustes)
);
if ( in_array( (int) $post->ID, $service_pages ) && ! is_front_page() && ! is_home() ) {
// Nombre del servicio: tomamos el H1 o title de la página
$service_name = $post ? get_the_title( $post->ID ) : 'Servicio Dermatológico';
// Si el title ya contiene "Dermatología" o similar, lo usamos; si no, agregamos un descriptor genérico
if ( false === strpos( $service_name, 'Dermatología' ) ) {
$service_name = 'Servicio de ' . $service_name;
}
$service = array(
'@context' => 'https://schema.org',
'@type' => 'Service',
'name' => $service_name,
'url' => get_permalink( $post->ID ),
'provider' => array(
'@id' => home_url( '/' ) . '#clinic',
),
'areaServed' => array(
'@type' => 'AdministrativeArea',
'name' => 'Juliaca, Puno, PE',
),
'serviceArea' => ' Dermatología, Láser, Estética, Cosmetría',
);
echo '' . "\n";
}
// --- BreadcrumbList JSON-LD (solo para interiores, sin alterar el diseño visible) ---
if ( ! is_front_page() && ! is_home() && $post ) {
// Generamos una migas pan using la taxonomía de categorías si existen, o una ruta por defecto
$breadcrumb = array(
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => array(),
);
// Ruta por defecto: Inicio → página actual
$index_link = home_url( '/' );
$current_link = get_permalink( $post->ID );
$breadcrumb['itemListElement'][] = array(
'@type' => 'ListItem',
'position' => 1,
'name' => 'Inicio',
'item' => $index_link,
);
$breadcrumb['itemListElement'][] = array(
'@type' => 'ListItem',
'position' => 2,
'name' => get_the_title( $post->ID ),
'item' => $current_link,
);
echo '' . "\n";
}
} );
// -------------------------------------------------------------------------
// 5. ROBOTS META Y GOOGLE BOT BEHAVIOR
// -------------------------------------------------------------------------
// Añadir meta robots a las páginas que deben no-index
add_filter( 'wp_robots', function ( $robots ) {
global $post;
// Autor archives: noindex
if ( is_author() ) {
$robots[] = 'noindex';
}
// Category sin categoría
if ( is_category( 'sin-categoria' ) ) {
$robots[] = 'noindex';
}
// Elementor templates (cabecera y pie) duplican la portada
if ( is_singular( 'elementor_hf' ) ) {
$robots[] = 'noindex';
}
// Portal y acceso personal (muestran shortcodes sin renderizar)
if ( in_array( $post->ID, array( 310, 311 ) ) ) {
$robots[] = 'noindex';
}
// Resultados de laboratorio (poca utilidad en búsqueda)
if ( is_post_type_archive( 'resultados-de-laboratorio' ) || is_singular( 'resultados-de-laboratorio' ) ) {
$robots[] = 'noindex';
}
// Hola mundo (post predeterminado de WP)
if ( is_singular( 'post' ) && 'hola-mundo' === get_post_field( 'post_name', get_option( 'page_for_posts' ) ) ) {
$robots[] = 'noindex';
}
return $robots;
} );
// -------------------------------------------------------------------------
// 6. BLOGDESCRIPTION Y CONFIGURACIÓN ADICIONAL
// -------------------------------------------------------------------------
// Ya configurado en 'init' arriba, pero aquí aseguramos que no quede vacío si alguien lo borra:
add_filter( 'option_blogdescription', function ( $desc ) {
if ( empty( $desc ) ) {
return 'Centro dermatológico especializado en Juliaca, Puno. Tratamientos de vitíligo, acné, láser, estética y cosmética.';
}
return $desc;
} );
// -------------------------------------------------------------------------
// 6. REDIRECTADOR /reservar-cita/ -> /citas/reservar.php (solo en el front-end)
// -------------------------------------------------------------------------
// Añadimos un parámetro GET para que el template_redirect no dispare en AJAX/API
add_action( 'init', function () {
// Marcar esta redirección como "ya hecha" en session para no repetir
if ( isset( $_GET['lud_redirect'] ) && 'reservar' === $_GET['lud_redirect'] ) {
// El redirect se dio arriba; aquí solo evitamos volver a intentarlo
// nothing needed here
}
} );
// -------------------------------------------------------------------------
// 6. FORMATO DE IMÁGENES Y ALTO (solo en la fase de plan, no escribe nada aún)
// -------------------------------------------------------------------------
// Este mu-plugin también incluye una función helper para futuras operaciones de imagen.
// Por ahora, añadimos un filtro que añade width/height a imágenes que los carezcan
// SOLO si el servidor tiene GD con soporte WebP (comprobado en la sonda).
// Esto es seguro porque solo afecta la presentación HTML, no el diseño visual.
if ( function_exists( 'gd_info' ) && gd_info()['WebP Support'] ) {
add_filter( 'get_image_tag_from_editor', function ( $html, $id, $alt, $url, $size, $default_attr ) {
// Si la imagen no tiene width/height y es de la biblioteca de medios,
// intentar obtenerlos de la metadata de WP
if ( false === strpos( $html, 'width=' ) && false === strpos( $html, 'height=' ) ) {
$meta = wp_get_attachment_metadata( $id );
if ( $meta && isset( $meta['width'], $meta['height'] ) ) {
$html = str_replace( 'src=', 'width="' . $meta['width'] . '" height="' . $meta['height'] . '" src=', $html );
}
}
return $html;
}, 10, 5 );
}
// -------------------------------------------------------------------------
// 7. ACTIVACIÓN Y DESACTIVACIÓN SEGURA
// -------------------------------------------------------------------------
// Al activar/desactivar el mu-plugin, registramos una entrada en log para auditoría:
// (esto se escribe en un archivo aparte, fuera del alcance de esta plantilla)
echo 'Plugin SEO LUDherma activado. Token verificado.' . "\n";
// -------------------------------------------------------------------------
// FIN DEL PLUGIN
// -------------------------------------------------------------------------
https://ludherma.com/wp-sitemap-posts-post-1.xmlhttps://ludherma.com/wp-sitemap-posts-page-1.xmlhttps://ludherma.com/wp-sitemap-posts-elementor-hf-1.xmlhttps://ludherma.com/wp-sitemap-taxonomies-category-1.xmlhttps://ludherma.com/wp-sitemap-users-1.xml