Creación de un Custom Post Type en WordPress
WordPress incluye Posts y Pages de forma predeterminada, pero estos dos tipos de contenido no te llevarán muy lejos cuando un cliente necesita un directorio de propiedades inmobiliarias, una lista de personal o un archivo de recetas. Ahí es donde entra en juego un custom post type de WordPress — una estructura de contenido de primera clase que se integra limpiamente en el modelo de datos existente de WordPress sin necesidad de modificar los valores predeterminados.
Puntos Clave
- Un custom post type (CPT) extiende la tabla compartida
wp_postsen lugar de crear una separada, proporcionándote pantallas de administración, endpoints de la REST API y enrutamiento de plantillas de forma predeterminada. - Registra siempre los CPT en un plugin, no en un theme, para que el contenido permanezca accesible independientemente de los cambios de tema.
- Establecer
show_in_restentruees necesario para el soporte del editor de bloques y la exposición en la REST API. - Limpia las reglas de reescritura solo en la activación del plugin — nunca en cada carga de página.
¿Qué es un Custom Post Type?
Un custom post type (CPT) es un tipo de contenido nombrado que registras en WordPress. A pesar del nombre, no es una tabla de base de datos separada. Todos los tipos de post — tanto predeterminados como personalizados — comparten la tabla wp_posts, diferenciándose por la columna post_type. Este es un modelo mental importante: estás extendiendo una estructura existente, no creando una paralela.
Los tipos de post predeterminados incluyen post, page, attachment, revision y nav_menu_item. Cuando registras un CPT como property o recipe, WordPress lo trata con la misma consistencia: pantallas de administración, endpoints de la REST API, enrutamiento de URL y jerarquía de plantillas funcionan de la misma manera.
Custom post types ≠ custom fields. Un CPT define el tipo de contenido. Los custom fields (agregados mediante ACF o la API de metadatos) almacenan datos adicionales adjuntos a ese contenido. Son conceptos separados.
Registro de un Custom Post Type con register_post_type()
La forma canónica de crear un custom post type en WordPress es mediante la función register_post_type(), llamada en el hook init.
Aquí tienes un ejemplo limpio y funcional:
add_action( 'init', 'register_property_post_type' );
function register_property_post_type() {
$labels = [
'name' => 'Properties',
'singular_name' => 'Property',
'add_new_item' => 'Add New Property',
'edit_item' => 'Edit Property',
'not_found' => 'No properties found.',
];
$args = [
'labels' => $labels,
'public' => true,
'has_archive' => true,
'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt' ],
'rewrite' => [ 'slug' => 'properties' ],
'show_in_rest' => true,
];
register_post_type( 'property', $args );
}
Explicación de los Argumentos Clave
public— Hace que el CPT sea visible en el administrador y en el front end. Establécelo enfalsepara tipos de uso exclusivamente interno.labels— Controla todas las cadenas de texto de la interfaz de usuario en el administrador. Vale la pena completarlo correctamente para que los editores no se confundan.supports— Declara qué características del editor aparecen en la pantalla de edición. Valores comunes:title,editor,thumbnail,excerpt,custom-fields.has_archive— Habilita una página de archivo en/properties/. WordPress buscará una plantillaarchive-property.phpcorrespondiente (o recurrirá aarchive.php).rewrite— Establece el slug de la URL. Los posts individuales aparecerán en/properties/post-name/.show_in_rest— Establécelo entrue. Esto expone el CPT a través de la REST API de WordPress y es necesario para que el editor de bloques funcione correctamente con tu tipo de post. Sin esto, el editor vuelve a la interfaz clásica.
Discover how at OpenReplay.com.
Plugin vs. Theme: ¿Dónde Debe Residir el Código?
Este es un punto de confusión común. Registra tu custom post type en un plugin, no en un theme.
Si el registro de tu CPT reside en functions.php y el cliente cambia de tema, todo el contenido de ese tipo se vuelve inaccesible — no se elimina, pero se vuelve invisible. Un plugin dedicado (incluso uno simple de un solo archivo) mantiene el CPT activo independientemente de los cambios de tema.
No limpies las reglas de reescritura en cada petición. Llama a
flush_rewrite_rules()solo una vez — en la activación del plugin medianteregister_activation_hook(). Limpiar en cadainites un problema de rendimiento.
Jerarquía de Plantillas para Custom Post Types
WordPress busca plantillas en este orden para una entrada individual de CPT:
single-{post-type}.php(por ejemplo,single-property.php)single.phpsingular.phpindex.php
Para archivos, sigue: archive-{post-type}.php → archive.php → index.php.
Conclusión
Con register_post_type() correctamente enganchado a init, show_in_rest habilitado y el registro residiendo en un plugin, tienes una base sólida y portable. Desde aquí puedes agregar taxonomías personalizadas, campos meta mediante ACF o la API de metadatos, y columnas personalizadas en el administrador — sin tocar nada que pueda romperse cuando WordPress o tu tema se actualicen.
Preguntas Frecuentes
El contenido permanece en la tabla wp_posts y no se elimina. Sin embargo, WordPress ya no reconoce ese tipo de post, por lo que los posts se vuelven invisibles en el administrador y en el front end. Reactivar el plugin restaura el acceso inmediatamente. Por eso el registro de CPT siempre debe residir en un plugin dedicado en lugar de en un theme.
Sí. Puedes llamar a register_post_type() múltiples veces dentro del mismo callback de init o usar callbacks separados enganchados a init. No hay límite en el número de custom post types que un solo plugin puede registrar, aunque cada uno debe tener un slug de tipo de post único de no más de 20 caracteres.
Esto casi siempre significa que las reglas de reescritura necesitan ser limpiadas. Visita Ajustes y luego Enlaces permanentes en el administrador de WordPress y haz clic en Guardar cambios. Eso activa una limpieza de reescritura. Para plugins, llama a flush_rewrite_rules() dentro de register_activation_hook() para que se ejecute automáticamente en la activación. Nunca limpies en cada carga de página.
No estrictamente, pero aún así es recomendable. Establecer show_in_rest en true expone tu tipo de post a través de la REST API de WordPress, lo cual es útil para configuraciones headless, integraciones externas y compatibilidad futura. Si alguna vez cambias al editor de bloques, ya funcionará correctamente.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.