I'm working on a new content type. Let's call it hotel rooms (it is not but the similarities are good enough).

Now, for each room, I will have a title and a description but I will also have a lot of metadata - beds, sea view, room number, size, summer price, winter price, and so on.

I would like my custom type to work on any theme. That means I need to provide a way to layout the post for index.php, single.php, and so forth. Obviously, presenting metadata is a large part of this.

How do I do this?

2 Answers 2


I assume that you're making your custom post type in a plugin if you mean for it to work with any theme.

In that case, I would suggest building your templates in your plugin, and call all your meta data there.


/* Filter the single_template with our custom function*/
add_filter('single_template', 'my_custom_template');

function my_custom_template($single) {

    global $post;

    /* Checks for single template by post type */
    if ( $post->post_type == 'POST TYPE NAME' ) {
        if ( file_exists( PLUGIN_PATH . '/Custom_File.php' ) ) {
            return PLUGIN_PATH . '/Custom_File.php';

    return $single;


You can refine that further and add a function to check to see if the theme has single-yourposttype.php and to use that one if it exists instead of your plugin version, allowing for easy overrides by developers. Example:

    $themeurl  = get_theme_file_path("/single-yourposttype.php");
    $pluginurl = plugin_dir_path( dirname( __FILE__ ) ) . 'single-yourposttype.php';

    if( file_exists( $themeurl ) ) {
        include( $themeurl );
    } elseif( file_exists( $pluginurl ) ) {

        require "$pluginurl";

I hope that helps.

  • 1
    Upvoted. That's absolutely a valid option.
    – kaiser
    Jan 16, 2020 at 21:24
  • Thanks Kaiser, I appreciate it! Not sure what the downvote was for, but to each their own. I like your solution too.
    – Faye
    Jan 17, 2020 at 21:45

I'd suggest to not add layout, but MarkUp and offer an option to override it. The best way to do this would be to add to a hook that your users can add to their themes templates.

// Theme template file
do_action( 'hotel_rooms' );

// Your plugin hooks in there:
add_action( 'hotel_rooms', 'callback' );
function callback() {
    echo "I am displaying details about a hotel room";

You could also make this a two step process to offer more refined control:

// Themes template or another (child?) plugin
// [] is an array and the default.
$data = add_filter( 'hotel_room_data', [] );

// Plugin
apply_filters( 'hotel_room_data', …etc. );

Two stepped: Eat your own dog food and apply the filter to your own loops and MarkUp as well.

add_action( 'hotel_rooms', 'callback' );
function callback() {
    $data = apply_filters( 'hotel_room_data', …etc. );
    foreach ( $data as $room ) {
        print $room['size'];
  • If I could, I accept both this answer and Faye's. This answer shows me exactly how to take Faye's and end up with a professional result. Jun 1, 2020 at 16:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.