Aunque WordPress se adapta sorprendentemente bien a proyectos complejos, muchos/as usuarios/as se precipitan instalando plugins innecesarios para resolver problemas que pueden abordarse con un enfoque más limpio y técnico. Uno de los casos más comunes es el de los campos personalizados, donde la solución más inmediata es optar automáticamente por utilizar plugins como Advanced Custom Fields (ACF) sin evaluar antes si realmente son necesarios.
En este artículo aprenderás a crear y gestionar campos personalizados sin depender de plugins, utilizando código limpio, controlado y fácil de mantener. Este enfoque no solo mejora el rendimiento de tu web, sino que te obliga a conocer más a fondo cómo funciona WordPress por dentro, lo que a la larga te hará trabajar mejor.
- ¿Qué son los campos personalizados y para qué se utilizan?
- ¿Por qué evitar un plugin como ACF en ciertos proyectos?
- Cómo crear campos personalizados con código (y sin ACF)
- Cómo mostrar los campos personalizados en el frontend
- ¿Y si quiero algo más visual en el backend?
- Errores comunes al trabajar con campos personalizados
- Cómo conectar campos personalizados con taxonomías y relaciones
- Conclusión: campos personalizados bien pensados, webs que escalan bien
¿Qué son los campos personalizados y para qué se utilizan?
Los campos personalizados —conocidos en inglés como custom fields— son una de las funcionalidades más potentes y a menudo subestimadas de WordPress. Permiten añadir información adicional a cualquier contenido (entradas, páginas o Custom Post Types) de una forma estructurada y extensible, algo crucial cuando queremos que nuestra web sea más que un simple blog o una serie de páginas corporativas estáticas.
Por defecto, WordPress estructura cada contenido (por ejemplo, una entrada) mediante un conjunto de campos preestablecidos: título, contenido, imagen destacada, fecha de publicación, etc. Estos campos son comunes a todos los tipos de contenido, y aunque permiten cierta personalización básica, en realidad se quedan cortos cuando necesitamos organizar o mostrar información más específica. Aquí es donde entran en juego los campos personalizados.
Un campo personalizado permite almacenar datos adicionales en forma de pares key-value (nombre del campo y su contenido).
Un ejemplo: estás creando una web de reseñas de películas. Como información específica de la película, podrías necesitar mostrar la duración de cada película, el director/a, su calificación por edad, su puntuación media en IMDb o Filmaffinity… Ninguno de esos datos tiene cabida natural en los campos estándar de una entrada de WordPress, pero se pueden añadir fácilmente en forma de campos personalizados.
Más allá de simples valores de texto, estos campos pueden admitir diferentes tipos de datos: números, fechas, listas desplegables, casillas de verificación, imágenes, enlaces a otros contenidos… Incluso pueden vincularse a funcionalidades condicionales, cálculos automáticos o integraciones con plugins externos. De hecho, muchos plugins avanzados, como Advanced Custom Fields (ACF), Meta Box o Pods, se basan en la REST API de custom fields de WordPress para permitir al usuario/a crear interfaces personalizadas de edición sin escribir código, pero con total control sobre los datos que se almacenan.
En el plano técnico, cada campo personalizado se guarda como una fila en la tabla wp_postmeta
de la base de datos, relacionada con la entrada o contenido correspondiente. Esto significa que son perfectamente accesibles desde funciones PHP como get_post_meta()
o update_post_meta()
, lo que permite mostrar su contenido en cualquier parte del theme o manipularlo de manera programada. Es decir, los campos personalizados no son solo útiles para enriquecer la experiencia de edición en el panel de administración, sino también para modular el front-end de forma inteligente.
Su utilidad es especialmente evidente en proyectos donde se requiere una gran personalización de la estructura de contenidos: catálogos de productos no gestionados con WooCommerce, fichas de eventos, páginas de miembros de un equipo, portfolios, listados inmobiliarios, agendas culturales, etc. Cada uno de estos casos requiere mostrar información que no encaja en los campos predefinidos, y los campos personalizados ofrecen una solución elegante, escalable y perfectamente integrada con el ecosistema WordPress.
En definitiva, los campos personalizados permiten transformar WordPress en un auténtico gestor de contenidos avanzado, mucho más allá de su concepción original como plataforma de blogs. Saber utilizarlos correctamente —y más aún, saber planificar con criterio qué campos necesita cada tipo de contenido— marca una evidente diferencia entre una web rígida, basada en plantillas genéricas, y una solución profesional, flexible y perfectamente adaptada a las necesidades reales del proyecto.
¿Por qué evitar un plugin como ACF en ciertos proyectos?
Advanced Custom Fields (ACF) es, sin duda, una de las herramientas más populares y versátiles del ecosistema WordPress. Su facilidad de uso, su interfaz visual y la enorme cantidad de documentación disponible lo convierten en una opción atractiva tanto para profesionales del desarrollo como para usuarios/as intermedios que quieren extender WordPress sin escribir código complejo. Sin embargo, y a pesar de sus muchas virtudes, ACF no siempre es la mejor solución. Hay proyectos en los que su uso puede convertirse en un lastre a medio o largo plazo, y conviene saber por qué.
Uno de los principales motivos para evitar ACF en ciertos casos es su dependencia directa del plugin para acceder a los datos desde el front-end. Aunque los valores de los campos personalizados se almacenan en la base de datos de forma estándar (en wp_postmeta
), ACF introduce su propia lógica y funciones para mostrar estos valores en el tema. ¿Qué significa esto? Pues que si, en algún momento, decides prescindir de ACF, tendrás que reescribir buena parte del código del tema para sustituir funciones como the_field()
o get_field()
por funciones nativas como get_post_meta()
. Esta dependencia genera un acoplamiento innecesario que puede dificultar el mantenimiento o la migración del sitio en el futuro.
Además, ACF añade una capa de complejidad y carga adicional al back-end que puede ser excesiva para sitios donde lo único que se necesita son campos personalizados sencillos y/o limitados. El plugin carga sus propios scripts, estilos, interfaces y lógica de validación, lo cual puede ralentizar el panel de administración, especialmente en instalaciones con muchos usuarios, con muchos campos o con una infraestructura limitada. En proyectos ligeros o muy optimizados, donde cada recurso cuenta para arañar recursos que deriven en un rendimiento aún mejor, esta sobrecarga puede llegar a ser contraproducente.
Otro aspecto importante es el factor de rendimiento. Aunque ACF es un plugin muy optimizado, su uso intensivo de campos repetidores, grupos flexibles y relaciones puede llegar a generar un número considerable de consultas a la base de datos, especialmente si se muestran muchos campos personalizados en el front-end. Si no se cachea correctamente o si el sitio tiene mucho tráfico, esto puede llegar a afectar a la velocidad de carga. En cambio, una solución personalizada con código hecho a medida, bien planteado y sin elementos innecesarios, puede ofrecer resultados mucho más eficientes desde el punto de vista del rendimiento.
Tampoco hay que olvidar que ACF, en su versión gratuita, tiene limitaciones. Funcionalidades como los campos repetidores (repeaters), los grupos de campos condicionales o las relaciones entre posts están reservadas para la versión Pro, lo cual puede ser un problema si se quiere prescindir de gastos extra o si lo que se busca es una solución totalmente libre de dependencias externas. En cambio, un enfoque con código nativo o mediante MU-plugins puede resolver la misma necesidad sin depender de licencias comerciales ni de terceros.
Por último, está la cuestión de la filosofía del proyecto y su escalabilidad. En desarrollos a medida para clientes con necesidades muy concretas, utilizar ACF puede ser una solución rápida y cómoda a corto plazo, pero poco alineada con una mentalidad de desarrollo limpio, sostenible y desacoplado. En sitios donde la arquitectura de contenido es clave (por ejemplo, marketplaces, intranets, aplicaciones web basadas en WordPress, etc.), es preferible implementar estructuras personalizadas con funciones como register_meta()
y bloques o pantallas de edición propias mediante add_meta_box()
, register_post_type()
y register_taxonomy()
.
ACF es una herramienta poderosa y muy útil, pero no debe utilizarse automáticamente por defecto. Como siempre suelo comentar, ante cualquier dependencia externa conviene evaluar si realmente aporta valor diferencial al proyecto o si introduce una complejidad innecesaria que se puede resolver de una manera más cómoda o eficiente. En muchos casos, optar por una solución más liviana, nativa y personalizada —incluso aunque requiera algo más de tiempo de desarrollo y personalización— puede ser una decisión mucho más sólida y sostenible a largo plazo.
Cómo crear campos personalizados con código (y sin ACF)
Aunque el plugin ACF ha hecho muy accesible el uso de campos personalizados en WordPress gracias a su interfaz visual, no es indispensable para añadir metadatos personalizados a entradas, páginas o tipos de contenido personalizados (CPTs). WordPress incluye, desde sus primeras versiones, funciones nativas que permiten gestionar este tipo de campos sin necesidad de recurrir a soluciones externas. Esto no solo evita dependencias innecesarias, sino que también permite un mayor control, mejor rendimiento y una arquitectura de proyecto más limpia.
El proceso comienza registrando una metabox, es decir, una caja que aparecerá en el panel de edición del contenido. Para ello, se utiliza la función add_meta_box()
. Este método requiere especificar un ID único, un título, una función de callback que se encargará de mostrar el contenido de la caja, el tipo de contenido donde debe aparecer (por ejemplo, post
, page
o un CPT), y su ubicación dentro del editor.
Un ejemplo básico sería este:
function cbz_add_custom_meta_box() {
add_meta_box(
'cbz_subtitulo_meta', // ID único
'Subtítulo del artículo', // Título visible
'cbz_render_subtitulo_meta_box', // Callback que renderiza el campo
'post', // Tipo de contenido donde aparece
'normal', // Contexto: normal, side, advanced
'default' // Prioridad
);
}
add_action('add_meta_boxes', 'cbz_add_custom_meta_box');
function cbz_render_subtitulo_meta_box($post) {
$valor_actual = get_post_meta($post->ID, '_cbz_subtitulo', true);
?>
<label for="cbz_subtitulo">Escribe aquí el subtítulo:</label>
<input type="text" id="cbz_subtitulo" name="cbz_subtitulo" value="<?php echo esc_attr($valor_actual); ?>" style="width:100%;">
<?php
}
Este código añade una nueva caja al editor de entradas estándar, donde el usuario podrá introducir un subtítulo personalizado para cada post. El valor se recupera con get_post_meta()
para pre-rellenar el campo si ya existe, lo que facilita la edición posterior.
Una vez renderizado el campo, necesitamos guardar su contenido cuando el usuario actualice la entrada. Para ello usamos el hook save_post
, que se dispara en ese momento. Aquí podemos validar, sanitizar (eliminar elementos no deseados o peligrosos) y guardar el dato:
function cbz_guardar_subtitulo_meta($post_id) {
// Evita guardar en autosave o revisiones
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (isset($_POST['cbz_subtitulo'])) {
update_post_meta($post_id, '_cbz_subtitulo', sanitize_text_field($_POST['cbz_subtitulo']));
}
}
add_action('save_post', 'cbz_guardar_subtitulo_meta');
Este patrón se puede replicar para múltiples campos, incluso con inputs más complejos (selects, checkboxes, campos de fecha, etc.). Y si se necesita trabajar con varios tipos de contenido o integrar validación más avanzada, se puede ampliar fácilmente.
Lo interesante de esta metodología es que tú controlas absolutamente todo: desde la interfaz en el back-end hasta el momento del guardado en la base de datos. No hay lógica oculta ni automatismos que puedan generar comportamientos inesperados. Además, como estás escribiendo el código tú mismo/a, puedes documentarlo y adaptarlo a las necesidades exactas del proyecto. Esto cobra especial valor en entornos profesionales en los que se busca reducir dependencias y tener un control total del stack.
Para recuperar estos valores y mostrarlos en el front-end, simplemente se usa get_post_meta()
:
$subtitulo = get_post_meta(get_the_ID(), '_cbz_subtitulo', true);
if (!empty($subtitulo)) {
echo '<h2 class="subtitulo">' . esc_html($subtitulo) . '</h2>';
}
Como ves, en realidad no se necesita ACF o cualquier otro plugin de campos personalizados para conseguir resultados profesionales. De hecho, en proyectos a medida o donde la optimización es clave, esta es la opción más recomendable. Aunque escribir el código requiere algo más de tiempo, a cambio obtienes flexibilidad, rendimiento y, a la larga, un mejor mantenimiento.
Y si necesitas que esos metadatos estén disponibles en la API REST (por ejemplo, en una instalación headless o semidestacada con bloques personalizados), puedes registrar el campo como metadato utilizando register_meta()
con las propiedades adecuadas para exponerlo, validarlo o sanearlo automáticamente. Esta técnica avanzada da un paso más hacia la estandarización y robustez del código.
Cómo mostrar los campos personalizados en el frontend
Una vez que has creado tus campos personalizados y estás guardando correctamente los valores en la base de datos, el siguiente paso lógico es hacer que esa información aparezca de forma visible y útil para las personas que visitan tu web. Mostrar los campos personalizados en el frontend no solo permite enriquecer la experiencia de usuario, sino también mantener una estructura de datos clara y coherente con los objetivos del proyecto, ya sea mostrar una ficha de producto más completa, una agenda de eventos con sus fechas o datos específicos o un portfolio con créditos detallados.
La función principal para recuperar el valor de un campo personalizado en WordPress es get_post_meta()
. Esta función recibe el ID del post, el nombre (clave) del campo, y un booleano que indica si se debe devolver un único valor o un array (cuando hay múltiples valores con la misma clave).
Vamos a recuperar un campo llamado _cbz_subtitulo
que hemos creado previamente en una entrada:
$subtitulo = get_post_meta(get_the_ID(), '_cbz_subtitulo', true);
En este caso, get_the_ID()
nos da el ID del post actual (funciona dentro del loop). La clave que usamos debe coincidir exactamente con la que definimos al guardar el campo personalizado. El tercer parámetro true
indica que queremos un único valor.
Ahora bien, recuperar el valor no significa que automáticamente aparezca en la web. Somos nosotros quienes decidimos dónde, cómo y bajo qué condiciones se muestra. Esto tiene dos ventajas fundamentales: control total sobre la presentación y una arquitectura limpia, donde los datos están separados de la lógica de presentación.
Mostrarlo en una plantilla personalizada
Si estás utilizando plantillas de WordPress (como single.php
, single-cpt.php
o una plantilla de bloque con PHP), puedes insertar el contenido directamente en el lugar que más sentido tenga en tu diseño.
Un ejemplo típico sería mostrar el subtítulo justo debajo del título principal del post:
<h1 class="titulo-principal"><?php the_title(); ?></h1>
<?php
$subtitulo = get_post_meta(get_the_ID(), '_cbz_subtitulo', true);
if (!empty($subtitulo)) {
echo '<p class="subtitulo">' . esc_html($subtitulo) . '</p>';
}
?>
¿Qué logramos con esto? Que el subtítulo se muestre solo si tiene contenido, evitando espacios vacíos. También usamos esc_html()
para sanear la salida y evitar vulnerabilidades XSS.
Condiciones avanzadas de visualización
A medida que el proyecto crece, puedes necesitar mostrar los campos solo en ciertos contextos (por ejemplo, solo en una categoría específica, solo para usuarios logueados, o en una posición determinada del diseño…).
Aquí un ejemplo más avanzado, en el que mostramos un campo solo si el post pertenece a la categoría “recetas”:
if (has_category('recetas')) {
$tiempo_preparacion = get_post_meta(get_the_ID(), '_cbz_tiempo_preparacion', true);
if ($tiempo_preparacion) {
echo '<div class="tiempo-preparacion">Tiempo: ' . esc_html($tiempo_preparacion) . ' minutos</div>';
}
}
También puedes utilizar funciones condicionales como is_single()
, is_page_template()
o comprobar roles de usuario, si quieres restringir el acceso a campos específicos.
Mostrar campos en bucles personalizados
No solo puedes mostrar campos en páginas individuales, sino también dentro de bucles (WP_Query
, get_posts()
, etc.). Esto es útil, por ejemplo, cuando haces un grid de proyectos o una lista de cursos, y quieres que cada elemento muestre, junto al título, un dato personalizado (como precio, fecha, duración…).
$args = array(
'post_type' => 'curso',
'posts_per_page' => 6,
);
$query = new WP_Query($args);
if ($query->have_posts()) {
echo '<div class="grid-cursos">';
while ($query->have_posts()) {
$query->the_post();
$duracion = get_post_meta(get_the_ID(), '_cbz_duracion', true);
?>
<div class="curso-item">
<h3><?php the_title(); ?></h3>
<?php if ($duracion): ?>
<p>Duración: <?php echo esc_html($duracion); ?> horas</p>
<?php endif; ?>
</div>
<?php
}
echo '</div>';
wp_reset_postdata();
}
Con este enfoque, puedes transformar cualquier bucle de WordPress en una interfaz rica y semánticamente estructurada, mostrando solo la información que tiene sentido y que realmente aporta al usuario.
Compatibilidad con constructores visuales
Si estás trabajando con maquetadores como Elementor, muchos de ellos ya permiten acceder a campos personalizados mediante shortcodes, etiquetas dinámicas o incluso widgets de tipo ‘campo personalizado’. Para que esto funcione correctamente, los campos deben estar registrados correctamente como metadatos y no almacenarse en estructuras complejas como arrays serializados. Esto es otra ventaja de usar update_post_meta()
con claves simples: los maquetadores los reconocen de forma natural.
Mostrar campos personalizados en el frontend no es un paso automático, sino una decisión consciente de diseño y arquitectura. Requiere pensar no solo en la lógica de presentación, sino en la accesibilidad, la optimización y la coherencia con el resto del contenido. Cuando se hace bien, el resultado es una web más profesional, más rica en contenido estructurado, y más alineada con los objetivos del proyecto.
¿Y si quiero algo más visual en el backend?
Trabajar con campos personalizados mediante código es muy eficiente y flexible, pero, si no se acompaña de una buena interfaz en el backend, la experiencia del usuario —en este caso, del editor/a o administrador/a que se encargue de gestionar los contenidos— puede resultar árida, confusa o incluso propensa a errores. Aunque WordPress permite guardar y recuperar metadatos fácilmente, la edición de estos campos no siempre está pensada para usuarios no técnicos, especialmente cuando se usan claves internas que no se muestran por defecto.
Por eso, si vas a trabajar con clientes/as o colaboradores/as que no se sienten cómodos editando directamente campos ocultos o configuraciones poco intuitivas, lo ideal es ofrecer una interfaz visual personalizada dentro del editor. De esta forma, puedes presentar los campos que realmente estos usuarios/as necesitan editar, de forma ordenada, con etiquetas claras y en un diseño coherente con el flujo de trabajo de WordPress.
La forma más directa de lograr esto, sin depender de plugins como ACF, es utilizando la función add_meta_box()
, que permite registrar un cuadro personalizado dentro de la pantalla de edición de un post, página o tipo de contenido personalizado (CPT).
Esto sería un ejemplo básico: vamos a crear una caja llamada “Subtítulo” que aparecerá en los posts del tipo post
, y que permitirá editar un campo personalizado _cbz_subtitulo
.
Registro de la meta box:
add_action('add_meta_boxes', 'cbz_registrar_meta_boxes');
function cbz_registrar_meta_boxes() {
add_meta_box(
'cbz_meta_subtitulo', // ID del meta box
'Subtítulo del artículo', // Título visible
'cbz_pintar_campo_subtitulo', // Callback que pinta el contenido
'post', // Pantalla donde aparece ('post', 'page', 'cpt')
'normal', // Contexto ('normal', 'side', 'advanced')
'high' // Prioridad
);
}
Pintado del campo en el backend:
function cbz_pintar_campo_subtitulo($post) {
// Recuperamos el valor actual, si existe
$subtitulo = get_post_meta($post->ID, '_cbz_subtitulo', true);
// Añadimos un nonce para verificar seguridad al guardar
wp_nonce_field('cbz_guardar_subtitulo', 'cbz_subtitulo_nonce');
// Pintamos el campo
echo '<label for="cbz_subtitulo">Escribe el subtítulo que aparecerá bajo el título principal:</label>';
echo '<input type="text" id="cbz_subtitulo" name="cbz_subtitulo" value="' . esc_attr($subtitulo) . '" style="width:100%;" />';
}
Guardado del campo al guardar el post:
add_action('save_post', 'cbz_guardar_campo_subtitulo');
function cbz_guardar_campo_subtitulo($post_id) {
// Comprobaciones básicas de seguridad
if (!isset($_POST['cbz_subtitulo_nonce'])) return;
if (!wp_verify_nonce($_POST['cbz_subtitulo_nonce'], 'cbz_guardar_subtitulo')) return;
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!current_user_can('edit_post', $post_id)) return;
// Guardamos el valor
if (isset($_POST['cbz_subtitulo'])) {
update_post_meta($post_id, '_cbz_subtitulo', sanitize_text_field($_POST['cbz_subtitulo']));
}
}
Este flujo completo nos da una caja visual, editable y perfectamente integrada en el editor clásico de WordPress. El usuario ni siquiera tendría por qué saber qué es un campo personalizado, ni buscar claves ni estructuras: simplemente ve una etiqueta, un campo de texto, lo edita, y el dato queda guardado.
Mejora visual y experiencia de edición
Puedes hacer que estas cajas sean más atractivas visualmente utilizando CSS o incluso campos más avanzados como selectores, checkbox, áreas de texto largas, colores, fechas, etc. Por ejemplo, si quisieras crear un selector desplegable para elegir un valor entre varias opciones, podrías pintar un <select>
en lugar de un <input type="text">
.
Además, si usas el editor de bloques (Gutenberg), también puedes crear paneles de opciones personalizados en el sidebar, aunque esto requiere JavaScript con React (usando el paquete @wordpress/components
). En muchos casos, sin embargo, una buena meta box tradicional es más que suficiente para crear una interfaz intuitiva y ordenada.
¿Cuándo vale la pena hacerlo?
Cuando tú o tu cliente/a necesitáis que un contenido sea fácilmente editable, y no solo almacenado, esta personalización puede ser clave. No es lo mismo que un campo esté técnicamente guardado, que permitir editarlo sin miedo, sin errores y de forma visual. Especialmente en proyectos más complejos con múltiples Custom Post Types, fichas técnicas o contenidos estructurados, tener una interfaz a medida para los campos más relevantes es una inversión en mantenimiento y calidad editorial.
Errores comunes al trabajar con campos personalizados
Trabajar con campos personalizados ofrece una gran flexibilidad, pero también implica asumir una mayor responsabilidad en cuanto a planificación, seguridad, mantenimiento y experiencia de usuario. Aunque la API de metadatos de WordPress es bastante robusta, su uso incorrecto puede generar problemas a medio y largo plazo que afectan al rendimiento, la escalabilidad o la claridad del proyecto.
Uno de los errores más comunes es utilizar campos personalizados como solución rápida y sin una estrategia detrás. Es tentador guardar cualquier dato que no encaje en el contenido principal dentro de un meta
, pero si no existe una estructura clara y una nomenclatura coherente, el sistema acaba convirtiéndose en un almacén desorganizado de claves y valores, difícil de auditar o reutilizar en plantillas o en consultas personalizadas. Este caos suele traducirse en dificultades para escalar la web, problemas de mantenimiento y dependencias innecesarias de documentación interna.
Otro fallo frecuente es no validar ni sanitizar los datos al guardarlos, algo especialmente grave cuando los campos están expuestos a usuarios con roles de edición. Por omisión, update_post_meta()
acepta cualquier valor, incluyendo scripts maliciosos o entradas no esperadas. Este descuido puede derivar en agujeros de seguridad (por ejemplo, inyecciones XSS) o en datos corruptos que rompen la lógica de la plantilla.
Además, es muy habitual ver proyectos donde se accede directamente a los campos personalizados desde el frontend sin comprobar que contienen un valor válido o sin aplicar funciones de escape para mostrar los datos de forma segura. Por ejemplo, imprimir un campo con echo get_post_meta( get_the_ID(), 'precio', true );
directamente en una plantilla puede parecer funcional, pero si el campo está vacío o contiene contenido HTML no esperado, puede romper el diseño o poner en riesgo la seguridad.
Otro error frecuente es la falta de coherencia en los prefijos y nombres de los metadatos. Utilizar claves genéricas como precio
, imagen
, nombre
o email
sin un prefijo propio (_cbz_precio
, por ejemplo) puede generar conflictos con otros plugins o con campos del núcleo de WordPress. Además, los campos sin prefijo suelen mostrarse en el panel de “Campos personalizados” del editor clásico, ensuciando la interfaz.
Tampoco es raro ver proyectos donde se duplican campos personalizados en distintos lugares (por ejemplo, en varios tipos de post) sin centralizar la lógica que los gestiona. Esto da lugar a código repetido, validaciones distintas para un mismo campo, o valores incoherentes. Cuando estos campos tienen implicaciones funcionales (como precios, fechas o URLs), el problema se agrava y termina afectando a la experiencia del usuario o incluso al SEO.
Finalmente, muchos desarrolladores caen en el error de usar campos personalizados para guardar datos que no deberían estar en post_meta
, como relaciones complejas entre entidades (por ejemplo, una relación muchos a muchos entre profesores y cursos). En esos casos, lo correcto sería usar una tabla personalizada o bien una taxonomía jerárquica si encaja con el modelo de datos, en lugar de forzar un uso incorrecto de los metadatos.
Evitar estos errores pasa, casi siempre, por lo mismo: planificación. Antes de añadir un campo personalizado, primero hay que preguntarse si realmente es necesario. Y en el caso de que lo sea, cómo se va a mostrar en el backend, cómo se va a recuperar en el frontend, si hay que traducirlo, si afecta al SEO o si se va a usar en consultas. Con todas estas preguntas resueltas, el desarrollo posterior va a ser, con toda seguridad, mucho más limpio, seguro y mantenible en el tiempo.
Cómo conectar campos personalizados con taxonomías y relaciones
Una de las mayores ventajas de trabajar con campos personalizados es su capacidad para ampliar la estructura de datos de WordPress más allá de los títulos, el contenido y las taxonomías estándar. Pero esa misma flexibilidad, si no se utiliza bien, puede hacer que perdamos una de las cosas más potentes que tiene el sistema: la relación entre contenidos.
Pongamos un ejemplo. Estás creando una web de cursos. En estos casos, es habitual que tengas un Custom Post Type para los cursos y otro para los profesores. En lugar de guardar el nombre del profesor como un simple campo personalizado de texto dentro del curso, lo ideal sería establecer una relación real entre ambos tipos de contenido. De esta forma, si más adelante cambias el nombre o la información del profesor, esa información se actualizará automáticamente en todos los cursos donde aparece, sin necesidad de editar cada uno manualmente.
Estas relaciones pueden construirse de varias formas, pero es importante entender que no todo debe resolverse con post_meta
. A veces es mejor utilizar taxonomías personalizadas. Por ejemplo, si quieres clasificar proyectos por sector (salud, educación, tecnología…), lo lógico es usar una taxonomía llamada sector
, porque eso permite hacer filtros, archivos, navegación jerárquica, etc. Guardar el sector como un campo personalizado sería una decisión limitada, que complica tanto las consultas como la navegación y el SEO.
Cuando realmente necesitas una relación entre entidades distintas (por ejemplo, enlazar un curso con un profesor concreto, o un evento con una sede física), puedes usar campos personalizados, pero referenciando siempre el ID
del post relacionado y no su nombre. Así, se podría hacer algo como:
$profesor_id = get_post_meta( get_the_ID(), 'profesor_relacionado', true );
$nombre_profesor = get_the_title( $profesor_id );
En este ejemplo, el campo profesor_relacionado
guarda el ID de un post del tipo profesor
, y luego recupera su título. Esta estrategia es mucho más robusta que guardar simplemente el nombre del profesor como texto plano, ya que nos permite vincular datos reales, generar enlaces, mostrar el avatar o cualquier otro campo adicional del post relacionado.
Para introducir estas relaciones de forma más cómoda en el backend, es posible utilizar campos de tipo select o autocompletado, donde el usuario pueda elegir entre las entradas disponibles. Esto puede hacerse con código, usando wp_dropdown_pages()
o get_posts()
para poblar un <select>
, o si se necesita algo más refinado, se puede combinar con JavaScript y AJAX para crear búsquedas dinámicas.
Cuando se trata de relaciones más complejas, como relaciones múltiples (por ejemplo, una película con varios actores), puedes almacenar varios IDs separados por comas en un único campo personalizado, o, aún mejor, guardarlos como array serializado:
$actores = get_post_meta( get_the_ID(), 'actores_relacionados', true );
if ( is_array( $actores ) ) {
foreach ( $actores as $actor_id ) {
echo get_the_title( $actor_id );
}
}
Este enfoque es limpio, y aunque trabajar con arrays requiere algo más de cuidado (para no romper la serialización), es perfectamente manejable si controlas bien los datos que estás guardando.
En cuanto a las taxonomías, se pueden combinar fácilmente con campos personalizados para generar interfaces más ricas. Por ejemplo, volviendo al caso de la web de cursos, podrías tener una taxonomía “nivel” (básico, intermedio, avanzado) y un campo personalizado “duración del curso” (en horas). Usando ambos, puedes construir filtros en el frontend o enriquecer tu contenido en el SEO, sin necesidad de duplicar datos.
Por último, conviene recordar que si necesitas trabajar con relaciones complejas y en gran escala, quizá WordPress se te quede algo corto a nivel nativo. En ese caso, existen soluciones más específicas como Pods Framework (para desarrollos avanzados sin escribir tanto código) o incluso, si el volumen de relaciones llega a justificar una estructura más complejas, montar tablas personalizadas.
Conclusión: campos personalizados bien pensados, webs que escalan bien
Los campos personalizados son uno de esos recursos que, si se utilizan con criterio, pueden multiplicar exponencialmente el nivel de cualquier desarrollo WordPress. No son simplemente un añadido técnico, sino que se configuran como una herramienta estructural que permite que el contenido se adapte al negocio, en lugar de forzar el negocio a encajar en una estructura genérica.
Pero precisamente por esa flexibilidad, también requieren un enfoque consciente. Implementarlos sin planificación puede provocar que una web se vuelva difícil de mantener, de escalar y de comprender con el paso del tiempo. En cambio, cuando se definen en base a una lógica clara —alineada con los Custom Post Types, las taxonomías, las relaciones entre entidades y las necesidades reales del usuario o del negocio— se convierten en uno de los pilares más sólidos de una arquitectura web avanzada.
Evitar plugins que a veces pueden no ser del todo necesarios en proyectos donde el código personalizado ofrece más control y ligereza suele ser una decisión inteligente, especialmente cuando se valora el rendimiento, la escalabilidad y la limpieza del backend. Del mismo modo, saber cómo mostrar esa información en el frontend de manera flexible y dinámica aporta valor, tanto al usuario final como al equipo que gestiona el contenido.
En definitiva, los campos personalizados no son una funcionalidad más: son una forma de pensar el contenido con una capa más de precisión. Y eso, cuando se aplica bien, no solo mejora la experiencia de usuario y el SEO, sino que sienta las bases para proyectos duraderos, bien estructurados y con visión a largo plazo.
¿Quieres una web escalable, rápida y bien estructurada?
📸 Imagen: Imagen: Kelly Sikkema en Unsplash