- Qué es un Custom Post Type
- Cuándo crear un Custom Post Type
- Registro de un Custom Post Type
- La URL del archivo y la URL del contenido individual
- Taxonomías propias para un CPT
- CPT y el flush de reglas de reescritura
- CPT y el sitemap
- Para profundizar
WordPress nació con dos tipos de contenido: las entradas (post) y las páginas (page). Las entradas son contenido editorial datado que pertenece a una colección; las páginas son contenido estático sin fecha ni taxonomía. Durante años, muchos desarrolladores intentaron encajar todos los tipos de contenido de sus proyectos en uno de esos dos moldes. El resultado habitual era usar entradas para cosas que no eran artículos de blog, asignarles categorías que no tenían relación con las categorías editoriales del sitio, y acabar con un sistema taxonómico mezclado e incoherente.
Los Custom Post Types (CPT) resuelven ese problema. Son tipos de contenido definidos a medida, con su propio nombre, sus propias URLs, sus propias taxonomías y su propio comportamiento dentro de WordPress.
Qué es un Custom Post Type
Un Custom Post Type es un tipo de contenido registrado en WordPress mediante la función register_post_type(). Desde el punto de vista de la base de datos, todo el contenido de WordPress —entradas, páginas, y cualquier CPT— se almacena en la tabla wp_posts. Lo que diferencia los tipos es el campo post_type.
Desde el punto de vista de la arquitectura de la información, un CPT es la implementación técnica de un tipo de contenido con estructura propia: tiene sus campos específicos (mediante meta fields o bloques), su propia jerarquía de URLs y sus propias taxonomías.
Cuándo crear un Custom Post Type
La pregunta no es “¿puedo usar una entrada para esto?” sino “¿tiene este contenido una estructura y un ciclo de vida lo suficientemente distintos a los de una entrada como para justificar su propio tipo?”
Crear un CPT cuando:
- El contenido tiene campos propios que no comparte con las entradas (un producto tiene precio; un evento tiene fecha de inicio; un curso tiene duración y nivel).
- El contenido necesita una URL con patrón propio distinto al de los artículos (
/productos/nombre/en lugar de/nombre/). - El contenido tiene taxonomías propias que no deben mezclarse con las categorías y etiquetas editoriales.
- El contenido tiene un ciclo de vida distinto al editorial (los productos se descontinúan; los eventos caducan).
No crear un CPT cuando:
- El contenido es simplemente una categoría de artículos. Si todos los contenidos de “Recetas” son artículos con la categoría “Recetas”, no necesitan un CPT.
- El volumen de contenido es muy bajo (tres o cuatro elementos). El coste de configurar un CPT no se justifica para tan poco contenido.
- El contenido no tiene campos propios ni lógica de URL diferenciada.
Registro de un Custom Post Type
function registrar_cpt_producto() {
$args = array(
'labels' => array(
'name' => 'Productos',
'singular_name' => 'Producto',
'add_new_item' => 'Añadir producto',
'edit_item' => 'Editar producto',
'view_item' => 'Ver producto',
'search_items' => 'Buscar productos',
),
'public' => true,
'has_archive' => true,
'rewrite' => array(
'slug' => 'productos',
'with_front' => false,
),
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt' ),
'menu_icon' => 'dashicons-cart',
'show_in_rest' => true, // necesario para el editor de bloques
);
register_post_type( 'producto', $args );
}
add_action( 'init', 'registrar_cpt_producto' );
Parámetros clave:
public — Si es true, el CPT tiene URLs públicas, aparece en búsquedas internas y es accesible desde el frontend.
has_archive — Si es true, WordPress genera una página de archivo para el CPT (equivalente a la página principal del blog para las entradas). La URL del archivo es el mismo slug del CPT: /productos/.
rewrite — Define la estructura de la URL. slug es el prefijo de ruta; with_front en false evita que se añada el prefijo global de WordPress delante del slug.
show_in_rest — Necesario para que el CPT funcione con el editor de bloques (Gutenberg). Sin esto, el editor clásico es el único disponible.
La URL del archivo y la URL del contenido individual
Un CPT con has_archive => true y rewrite slug => 'productos' genera dos tipos de URL:
/productos/ ← página de archivo (lista todos los productos)
/productos/nombre-prod/ ← página individual de cada producto
La página de archivo es el equivalente a /blog/ para los artículos. Puede personalizarse con una plantilla archive-producto.php en el tema o con el editor de bloques si el tema lo soporta.
Taxonomías propias para un CPT
Lo más habitual es registrar taxonomías propias para cada CPT, independientes de las categorías y etiquetas de las entradas. Esto evita que las categorías del blog se mezclen con las categorías de producto.
function registrar_taxonomia_categoria_producto() {
$args = array(
'labels' => array(
'name' => 'Categorías de producto',
'singular_name' => 'Categoría de producto',
),
'hierarchical' => true, // true = comportamiento de categoría; false = comportamiento de etiqueta
'public' => true,
'rewrite' => array( 'slug' => 'categoria-producto' ),
'show_in_rest' => true,
);
register_taxonomy( 'categoria_producto', array( 'producto' ), $args );
}
add_action( 'init', 'registrar_taxonomia_categoria_producto' );
El tercer argumento de register_taxonomy() asocia la taxonomía al CPT producto. Una taxonomía puede asociarse a múltiples CPT si tiene sentido compartirla.
CPT y el flush de reglas de reescritura
Después de registrar un CPT, WordPress necesita regenerar sus reglas de reescritura de URLs. Si las URLs del CPT devuelven 404 después del registro, la causa habitual es que no se ha hecho el flush.
La forma correcta es ir a Ajustes > Enlaces permanentes en el panel de administración y guardar sin cambiar nada. Esto regenera las reglas. Hacerlo mediante código en el activate hook del plugin o tema es la práctica correcta en entornos de producción:
function activar_plugin() {
registrar_cpt_producto();
flush_rewrite_rules();
}
register_activation_hook( __FILE__, 'activar_plugin' );
CPT y el sitemap
Los plugins de SEO (Yoast, Rank Math) detectan automáticamente los CPT registrados y permiten configurar si deben incluirse en el sitemap y si deben indexarse. Es importante revisar esta configuración después de registrar un nuevo CPT: por defecto, algunos plugins incluyen el CPT en el sitemap incluso si el contenido no está listo para indexarse.