Home » WordPress Posts vs Pages vs Custom Post Types Explained

WordPress Posts vs Pages vs Custom Post Types Explained

wordpress Tips and Guides

WordPress Posts vs Pages vs Custom Post Types

WordPress stores several different kinds of content using the same underlying content system, but the distinction between posts, pages and custom post types determines how that content is organised, displayed, queried and managed.

Choosing the correct content type matters most when a website grows beyond a few dozen articles. A small website can operate comfortably with standard posts and pages. A larger site containing hundreds of tutorials, downloadable resources, reference entries or product listings may benefit from custom post types that separate different kinds of material.

Posts are designed primarily for dated, regularly published content. Pages are intended for standalone or hierarchical website content. Custom post types allow developers to create additional content structures for material that does not fit neatly into either category.

These differences are not absolute restrictions. A WordPress page can contain dynamic content, a post can remain relevant for years, and a custom post type can behave much like a standard post. The appropriate choice depends on how content needs to be managed and presented rather than simply how frequently it changes.

How WordPress Stores Different Content Types

WordPress uses the wp_posts database table to store posts, pages and most custom post types.

Despite its name, this table is not limited to blog articles. It also stores other WordPress objects, including attachments, revisions and certain internal content types.

The post_type column identifies the kind of content represented by each database record.

Typical values include:

Post type value Purpose
post Standard blog posts and articles
page Standard WordPress pages
attachment Media attachments
revision Stored content revisions
nav_menu_item Classic navigation menu items
wp_block Reusable or synchronised blocks
product WooCommerce products, when WooCommerce is active
site_resource Example custom post type registered by a developer

The wp_ prefix is the conventional database table prefix, but it can be changed during installation. A site with another prefix will have a correspondingly named posts table.

The important point is that custom post types do not normally create separate database tables for their content.

Registering a custom post type tells WordPress how to recognise, administer, retrieve and display records associated with a particular post_type value.

Metadata for these records is generally stored in the corresponding post metadata table. Taxonomy relationships are managed through WordPress’s taxonomy tables.

This shared architecture means standard WordPress functions such as get_post(), get_post_meta() and WP_Query can work with different content types.

It also means that creating a custom post type does not automatically provide an independent database, specialised permissions system or performance improvement.

WordPress Posts: Content Organised by Publication

Standard posts are the natural choice for material published regularly as part of a website’s editorial content.

Examples include technical tutorials, troubleshooting articles, news, reviews, programming examples and other articles intended to appear in a chronological archive.

Each post has a publication date, and the standard WordPress archive system can organise posts by date, author, category or tag.

Posts also support comments, excerpts, featured images and other features, depending on the theme and WordPress settings.

Categories and Tags

Standard posts have built-in support for two taxonomies:

Categories provide a hierarchical way to group content into broad subjects.

Tags provide a non-hierarchical classification system for more specific topics.

For a WordPress technical reference website, categories might include:

  • WordPress Development

  • WordPress Troubleshooting

  • Performance and Optimisation

  • Security and Maintenance

  • WordPress SEO

  • WooCommerce

Individual articles can then use tags such as php snippets, shortcodes, wp-cli or database errors.

Categories and tags help readers discover related content and allow WordPress to generate corresponding archive pages.

However, they should not be treated as separate content types. A post remains a standard post regardless of the category assigned to it.

A website with 500 technical tutorials does not necessarily require a custom post type. If the articles share broadly the same editing process, publication structure and presentation, standard posts may be sufficient.

Chronological Archives

Posts participate in WordPress’s normal blog and archive queries.

A conventional blog listing usually displays posts in reverse chronological order, with the most recently published material first.

This behaviour suits websites that publish new material regularly.

An evergreen technical article can still be a post. Its original publication date does not prevent it from being updated, linked internally or included in a topic-specific reference section.

The distinction between evergreen and time-sensitive content is editorial rather than a built-in restriction of the post type.

When Standard Posts Are Appropriate

Use posts when the material is primarily an article, tutorial, commentary, review or other publication that belongs within the website’s editorial structure.

Posts are particularly appropriate when the content should appear in category archives, recent-article lists and other normal WordPress discovery mechanisms.

For a website publishing WordPress programming guides, PHP examples, CSS snippets and troubleshooting articles, standard posts will usually provide the simplest structure.

Creating a custom post type for every article category would introduce complexity without necessarily offering additional value.

WordPress Pages: Standalone and Hierarchical Content

Pages are designed for content that occupies a particular position within the website’s structure rather than appearing as part of a chronological stream.

Typical examples include a homepage, About page, Contact page, privacy policy, product information page or a permanent resource index.

Pages have publication and modification dates in the database, but their standard presentation is not primarily organised by date.

By default, pages do not use the standard post categories and tags. Custom code or plugins can associate taxonomies with pages if required.

Parent and Child Pages

A major difference between posts and pages is that standard pages support a hierarchical relationship.

For example, a WordPress website might have the following structure:

Resources
    WordPress Development
        PHP Reference
        JavaScript Reference
    WordPress Troubleshooting
        Database Errors
        Plugin Conflicts
    Downloads
        Free Cheat Sheets
        Premium Bundles

Each entry could be a WordPress page, with child pages assigned to their appropriate parent.

Depending on the permalink configuration, hierarchical page URLs can reflect this structure:

/resources/
/resources/wordpress-development/
/resources/wordpress-development/php-reference/

The hierarchy is represented through the post_parent field in the underlying database record.

Changing a page’s parent can therefore affect its URL and navigation context.

If the page is already indexed by search engines or linked from other websites, changing its URL may require a suitable redirect.

Pages Are Not Automatically Navigation Menus

Pages can be included in WordPress navigation, but creating a page does not always mean it will automatically appear in the site’s menu.

Navigation menus are managed separately.

Classic themes commonly use the Appearance > Menus interface. Block themes generally manage navigation through the Site Editor and Navigation block.

This separation allows pages to exist without being included in the main navigation, which is useful for landing pages, resource documents and specialised information.

When Pages Are Appropriate

Pages are a suitable choice when the content is relatively permanent, occupies a specific place in the website hierarchy or serves as a destination rather than an individual editorial publication.

A comprehensive WordPress resource directory, for example, could be built as a page containing links, category descriptions and dynamically generated article lists.

The underlying tutorials could remain standard posts.

This arrangement provides a stable navigation structure without requiring a custom post type for the resource directory itself.

Pages can also contain shortcodes, Query Loop blocks, custom layouts and interactive tools. They are not restricted to static text.

Custom Post Types: Creating Separate Content Structures

A custom post type is an additional content type registered with WordPress, normally by a plugin or custom PHP code.

It allows content with a particular purpose to be managed independently from standard posts and pages.

Common examples include products, events, testimonials, portfolio projects, directory entries and documentation records.

A custom post type can have its own administration menu, editing interface, URL structure, archive page, supported fields and taxonomies.

For example, a WordPress resource website might contain three distinct kinds of material:

Content Suitable type Reason
Programming tutorials Posts Editorial articles grouped by category
About and contact information Pages Permanent website content
Downloadable reference entries Custom post type Structured resource catalogue
Troubleshooting articles Posts Searchable editorial reference content
Product sales pages WooCommerce products Ecommerce functions and order integration
Resource category landing pages Pages or taxonomy archives Navigation and discovery
Customer testimonials Custom post type, where justified Separate structured records

The benefit of a custom post type becomes apparent when a particular kind of content needs its own management workflow.

Suppose a website has 200 downloadable cheat sheets. Each entry contains a title, description, file format, software version, difficulty level and download information.

These records are different from ordinary articles. They may need a dedicated listing page, custom filters and consistent fields.

A custom post type could provide a better administrative structure than placing all 200 records among standard blog posts.

On the other hand, if the downloads are simply PDF attachments linked from a few resource pages, a new post type may be unnecessary.

A Custom Post Type Is Not a Template

Registering a post type does not automatically create a complete front-end design.

WordPress can recognise the content and make it available to templates, but the presentation is still controlled by the active theme, blocks or page builder.

A custom post type may use existing theme templates until dedicated templates are provided.

It also does not automatically create specialised fields such as file version, licence type or download count. Those must be implemented through metadata, registered fields or another suitable system.

This distinction is particularly important when planning content databases. The post type defines what kind of record exists; its taxonomies, fields and templates define how useful that record becomes.

Posts, Pages and Custom Post Types Compared

Feature Posts Pages Custom post types
Built into WordPress Yes Yes Usually registered separately
Default database storage Posts table Posts table Usually posts table
Default chronological blog listing Yes No No
Default categories and tags Yes No Must be associated if needed
Hierarchical structure No Yes Configurable
Separate administration area Posts menu Pages menu Configurable
Featured images Theme support Theme support Configurable
Excerpts Supported Can be enabled Configurable
Comments Supported Supported, commonly disabled Configurable
Dedicated archive page Built-in archive behaviour No equivalent standard page archive Configurable
Custom URL structure Yes Yes Configurable
REST API availability Yes Yes Configurable
Block editor support Yes Yes Requires suitable registration
Custom fields Supported Supported Supported
Custom templates Yes Yes Yes
Main purpose Editorial content Website structure Specialised content

Several entries are configurable rather than fixed.

For example, a custom post type can be hierarchical like pages or non-hierarchical like posts. It can support excerpts, revisions and featured images, or omit them entirely.

Similarly, a theme may enable features for pages that are not exposed by default in a particular editing interface.

Registering a Custom Post Type with PHP

WordPress provides the register_post_type() function for creating custom post types.

Registration normally takes place on the init action, after WordPress has loaded the functionality required to register content types.

The following example creates a site_resource post type for a collection of downloadable reference materials.

The code is designed to be placed in a site-specific functionality plugin or appropriate PHP snippets environment.

function site_register_resource_post_type() {
    $labels = array(
        'name'               => 'Resources',
        'singular_name'      => 'Resource',
        'menu_name'          => 'Resources',
        'add_new_item'       => 'Add New Resource',
        'edit_item'          => 'Edit Resource',
        'new_item'           => 'New Resource',
        'view_item'          => 'View Resource',
        'search_items'       => 'Search Resources',
        'not_found'          => 'No resources found',
        'all_items'          => 'All Resources',
    );

    $args = array(
        'labels'             => $labels,
        'public'             => true,
        'publicly_queryable' => true,
        'show_ui'            => true,
        'show_in_menu'       => true,
        'show_in_rest'       => true,
        'has_archive'        => true,
        'hierarchical'       => false,
        'menu_icon'          => 'dashicons-media-document',
        'supports'           => array(
            'title',
            'editor',
            'excerpt',
            'thumbnail',
            'revisions',
            'custom-fields',
        ),
        'rewrite'            => array(
            'slug' => 'resources',
        ),
    );

    register_post_type(
        'site_resource',
        $args
    );
}

add_action(
    'init',
    'site_register_resource_post_type'
);

Once the code is active, a Resources menu should appear in the WordPress administration area for users with the necessary permissions.

The new post type uses the normal WordPress editing interface. Its records can have titles, descriptions, excerpts, featured images, revisions and custom fields.

The show_in_rest argument enables REST API exposure, which is also required for normal block editor integration with a custom post type.

The has_archive setting allows WordPress to provide a post-type archive, subject to rewrite configuration and theme support.

The example uses a non-hierarchical structure. Resources are therefore treated more like individual posts than parent-and-child pages.

After initial registration, visit Settings > Permalinks and save the existing settings if the new resource URLs produce 404 errors.

Important Registration Arguments

Argument Purpose
labels Defines administration interface labels
public Sets the general public visibility behaviour
publicly_queryable Controls front-end query availability
show_ui Enables the administration interface
show_in_menu Controls administration menu visibility
show_in_rest Enables REST API exposure
has_archive Enables a post-type archive
hierarchical Enables parent-child relationships
supports Selects available editing features
rewrite Configures pretty permalink handling
menu_icon Specifies the administration menu icon
capability_type Determines the capability naming basis
map_meta_cap Influences mapping of post-related capabilities
taxonomies Associates existing taxonomies with the post type
exclude_from_search Controls participation in conventional WordPress search

The public setting provides default values for several related arguments, but explicit settings can override those defaults.

A custom post type intended for internal administration records should not automatically be registered as public.

Public visibility and permissions are separate concerns. A publicly queryable post type is not automatically appropriate for storing confidential information, even if its administration screen is restricted.

Registering a Custom Taxonomy

A custom post type becomes more useful when its records can be organised according to attributes relevant to the content.

For a reference library, a taxonomy named resource_topic could distinguish PHP, CSS, security and performance resources.

function site_register_resource_topics() {
    register_taxonomy(
        'resource_topic',
        array( 'site_resource' ),
        array(
            'labels' => array(
                'name'          => 'Resource Topics',
                'singular_name' => 'Resource Topic',
            ),
            'public'        => true,
            'hierarchical'  => true,
            'show_ui'       => true,
            'show_admin_column' => true,
            'show_in_rest'  => true,
            'rewrite'       => array(
                'slug' => 'resource-topic',
            ),
        )
    );
}

add_action(
    'init',
    'site_register_resource_topics'
);

The taxonomy is associated with the site_resource custom post type.

Because hierarchical is enabled, it behaves more like categories than tags.

The taxonomy can be used to group resources by topic independently of the categories used for standard blog posts.

For example, a PHP reference cheat sheet could belong to the PHP topic, while a troubleshooting reference could belong to the Maintenance topic.

Taxonomies answer the question of how records should be classified. They do not replace the records themselves.

Custom Fields and Resource Metadata

A custom post type can store additional information through post metadata.

For example:

update_post_meta(
    $resource_id,
    '_site_resource_version',
    '1.2'
);

This stores the value 1.2 against the supplied resource post ID.

The example is a PHP fragment intended for a context in which $resource_id has already been established and authorised. It is not a complete form handler.

Metadata can hold information such as document format, version, approximate page count or an external reference identifier.

If these values must be edited through a user-friendly interface, additional fields and appropriate save handlers are required.

For REST API integration, metadata generally needs explicit registration using appropriate WordPress APIs and visibility rules.

Do not confuse the ability to store metadata with the existence of a complete custom-fields administration system.

Retrieving Different Content Types with WP_Query

The WP_Query class can retrieve standard posts, pages and custom post types.

The principal difference is the post_type query argument.

For example, to retrieve the latest five published standard posts:

$query = new WP_Query(
    array(
        'post_type'      => 'post',
        'post_status'    => 'publish',
        'posts_per_page' => 5,
    )
);

To retrieve pages:

$query = new WP_Query(
    array(
        'post_type'      => 'page',
        'post_status'    => 'publish',
        'posts_per_page' => 5,
        'orderby'        => 'title',
        'order'          => 'ASC',
    )
);

To retrieve records from the resource post type created earlier:

$query = new WP_Query(
    array(
        'post_type'      => 'site_resource',
        'post_status'    => 'publish',
        'posts_per_page' => 10,
        'orderby'        => 'title',
        'order'          => 'ASC',
    )
);

These examples create query objects; they do not display the results by themselves.

The following complete query-and-loop fragment can be placed inside an appropriate theme template or PHP rendering function, with site_resource already registered.

$query = new WP_Query(
    array(
        'post_type'           => 'site_resource',
        'post_status'         => 'publish',
        'posts_per_page'      => 10,
        'orderby'             => 'title',
        'order'               => 'ASC',
        'no_found_rows'       => true,
    )
);

if ( $query->have_posts() ) {
    echo '<ul class="resource-list">';

    while ( $query->have_posts() ) {
        $query->the_post();

        echo '<li><a href="' .
            esc_url( get_permalink() ) .
            '">' .
            esc_html( get_the_title() ) .
            '</a></li>';
    }

    echo '</ul>';
}

wp_reset_postdata();

The no_found_rows argument avoids unnecessary pagination calculations because the example does not provide paginated results.

The wp_reset_postdata() function restores the previous global post context after the custom loop.

To retrieve multiple types together, post_type can accept an array:

$query = new WP_Query(
    array(
        'post_type'      => array(
            'post',
            'page',
            'site_resource',
        ),
        'post_status'    => 'publish',
        'posts_per_page' => 10,
    )
);

This can support a combined resource listing, although a normal WordPress search query and an explicitly constructed WP_Query do not necessarily include the same post types.

Custom queries should specify the required types rather than assuming all public content will be included automatically.

Filtering Custom Post Types by Taxonomy

Custom taxonomies can be used directly in WP_Query.

For example, to retrieve resources assigned to the php topic:

$query = new WP_Query(
    array(
        'post_type'      => 'site_resource',
        'post_status'    => 'publish',
        'posts_per_page' => 10,
        'tax_query'      => array(
            array(
                'taxonomy' => 'resource_topic',
                'field'    => 'slug',
                'terms'    => 'php',
            ),
        ),
    )
);

This is a query fragment, not a complete output routine.

It assumes the taxonomy and term already exist.

The ability to filter by specialised taxonomies is a significant advantage when building directories, searchable references and structured collections.

A standard post could also use additional taxonomies, so taxonomy filtering alone is not a reason to create a new post type.

Templates and Front-End Presentation

WordPress uses its template hierarchy to determine how different types of content are rendered.

For classic PHP themes, dedicated template filenames can be provided for standard posts, pages and custom post types.

Content Example template
Standard post single.php
Standard page page.php
Individual resource single-site_resource.php
Resource archive archive-site_resource.php
Resource topic archive taxonomy-resource_topic.php
General fallback index.php

A classic theme may use more specific templates, and the exact selection depends on the full hierarchy and available files.

Block themes use HTML block templates and the Site Editor, although the same underlying concepts of content type and template selection remain relevant.

A custom post type does not require every possible template to exist. WordPress falls back to other suitable templates when a more specific one is unavailable.

For a resource directory, a dedicated archive template may be useful because it can display download information, resource topics or other fields that would be inappropriate in an ordinary article archive.

However, creating a custom post type solely to obtain a different layout is often unnecessary. WordPress already supports multiple templates, patterns, classes and conditional display techniques for ordinary posts and pages.

Permalinks, Archives and SEO

Choosing a content type affects URL structure and archive behaviour, but it does not automatically improve search engine rankings.

A standard post may have a URL such as:

https://example.com/wordpress-php-snippets/

A page may use a hierarchical URL:

https://example.com/resources/wordpress/

A resource custom post type could produce:

https://example.com/resources/php-reference/

The exact URL depends on the site’s permalink settings and the post type’s rewrite configuration.

Avoiding URL Conflicts

WordPress uses rewrite rules to map incoming URLs to the correct content.

Conflicts can occur when a custom post type’s rewrite slug overlaps with an existing page, archive or taxonomy.

For example, registering a custom post type archive at /resources/ while an ordinary page already occupies /resources/ can create ambiguous routing or unexpected behaviour.

Before registering a custom post type, establish how its URLs will fit into the existing website structure.

If a resource directory page already exists, a different rewrite slug may be appropriate, or the directory could be implemented as the post type archive.

Do not assume WordPress will automatically reconcile every conflicting URL.

Search Engine Indexing

Search engines can index suitable public posts, pages and custom post type entries.

SEO plugins may provide separate settings for each post type, including title templates, meta descriptions and indexing controls.

Custom post types are not automatically superior for SEO.

The important considerations remain the quality of the content, its accessibility, internal linking, canonical URLs and whether the indexable pages provide distinct value.

A catalogue containing hundreds of nearly empty custom post type entries may produce little useful search content.

Similarly, excessive taxonomy archives can create many low-value pages if they simply repeat the same small collection of links.

For a WordPress resource website, decide which archives deserve indexing and which exist mainly for internal navigation.

Changing Content Types and URLs

Converting a post into a page or custom post type can alter its URL, archive membership and template selection.

When existing content has already been published, preserve its URL where practical or establish an appropriate permanent redirect if the URL must change.

Also review internal links, navigation menus, breadcrumbs, sitemap entries and any code that queries the original post type.

Changing the post type value is not merely a visual or administrative adjustment.

Common Content Structure Mistakes

Several problems occur when the distinctions between posts, pages and custom post types are misunderstood.

Problem Cause Better approach
Hundreds of unrelated pages Pages used for every article Use posts and meaningful categories
Custom post type for every topic Content types confused with categories Use taxonomies for classification
Blog articles missing from archives Articles stored as pages or custom types Use posts where standard blog behaviour is needed
Custom resources missing from search Search configuration excludes the post type Review search and post type settings
Custom content URLs return 404 Rewrite rules not refreshed or conflicting Check slugs and regenerate rewrite rules
Content disappears after theme change Post type registered only by the old theme Register persistent content types in a plugin
Duplicate product information Products separately maintained as ordinary posts Use the ecommerce product records
Too many empty archives Excessive taxonomies or post types Consolidate the content structure
Complex queries for simple listings Unnecessary custom implementation Consider native Query Loop blocks
Private records become publicly accessible Incorrect visibility settings Configure querying and permissions explicitly

One particularly costly mistake is introducing custom post types before understanding the data they need to represent.

A custom post type with no specialised fields, taxonomy structure or distinct management requirements may offer little advantage over standard posts.

Conversely, forcing specialised content into ordinary posts can create a cluttered administration area and make future filtering or reporting difficult.

Can Existing Posts Be Converted into Pages or Custom Post Types?

WordPress content can be moved between post types, but the process requires care.

The underlying database records use the same general post structure, so a post type conversion does not inherently require copying the article text into a completely new record.

However, the conversion can affect functionality associated with that record.

Before converting published content, review its existing URLs, categories, tags, templates and relationships with other plugins.

A standard post converted into a page may retain taxonomy relationships in the database, but ordinary page editing interfaces do not necessarily expose those relationships.

Similarly, converting content into a custom post type does not automatically populate the specialised metadata fields that the new type expects.

For a large migration, use a staging environment and verify representative records before processing the entire catalogue.

Keep a database backup and record the original post type values so the operation can be reversed if necessary.

An incorrect migration may affect not only front-end URLs but also search results, internal links and plugin integrations.

Planning a WordPress Content and Product Website

A website that publishes articles and sells downloadable digital resources provides a useful example of how the different content types can work together.

A practical structure could be:

Website content Recommended type
WordPress tutorials Posts
PHP snippet articles Posts
Troubleshooting articles Posts
Plugin development guides Posts
Homepage Page
About and Contact Pages
Free Downloads landing page Page
Cheat Sheet Library landing page Page
WooCommerce ebook listings WooCommerce products
WooCommerce downloadable bundles WooCommerce products
Standalone technical reference records Optional custom post type
WordPress tools and calculators Pages containing plugin shortcodes or blocks

This arrangement keeps the editorial content within the conventional WordPress publishing system.

Product pages are managed through WooCommerce rather than duplicated as a separate collection of standard posts.

Simple tools and calculators can appear on ordinary pages, even when the underlying functionality is provided by a custom WordPress plugin.

A custom post type becomes more attractive when the site contains a substantial reference database requiring structured fields, distinct archive layouts or dedicated administration screens.

For example, a collection of 100 PHP functions might be better represented as structured reference entries if each function needs fields for syntax, arguments, return values, examples and version information.

That same collection could also be published as a conventional long-form article if there is no requirement to query or maintain the individual functions separately.

The decision depends on how the information will be used and maintained.

A Practical Decision Process

Before creating a new content type, consider four questions.

Does the material belong in the normal article archive? If it represents an independently published tutorial or article, a standard post is usually suitable.

Does it occupy a permanent place in the website hierarchy? If it serves as a stable destination, landing page or information page, use a page.

Does it represent a distinct kind of record with specialised fields or workflows? If so, a custom post type may be appropriate.

Does an existing plugin already define the required content type? Ecommerce products, for example, should normally remain within the product system that manages their pricing, downloads and transactions.

The cost of an additional custom post type extends beyond its registration code. Its templates, taxonomies, fields, archive behaviour, search integration and maintenance requirements all become part of the website’s structure.

For most content-heavy WordPress websites, standard posts and pages should remain the foundation. Custom post types are most valuable when they solve a genuine organisational problem rather than simply separating content by subject.

You may also like