Cobra Developers
Blog, WordPress

WordPress custom post types explained with a real example

The short answer

A WordPress custom post type is a kind of content you define yourself, alongside the built-in posts and pages. It gets its own menu in the dashboard, its own URL pattern, and its own template. Use one when you have many items of the same shape that are edited and published like content, such as listings, profiles, or locations.

A custom post type is a kind of content you add to WordPress beyond posts and pages. We lean on them heavily in RankAZona, the Arizona business publication and directory we make. Its 669 firm profiles are a custom post type. So are the nominations for its awards program.

Neither of those is a blog post, and neither is a page. A firm profile is a structured record about one business. Forcing that into the Posts screen would have meant hundreds of entries mixed in with the news, told apart by a category and good intentions.

That is the problem custom post types solve.

What is a custom post type in WordPress?

A custom post type is a content type you register with WordPress so it is stored and managed like posts and pages but kept separate from them. Each type gets its own section in the dashboard, its own address pattern on the site, and can have its own template and fields.

WordPress already uses the mechanism itself. Posts and pages are post types. So are media attachments and navigation menu items. They all live in the same database table, distinguished by a type label. Registering your own adds one more label and tells WordPress how to treat it.

"Post" in the name is misleading. A custom post type does not have to be an article. It is any item with a title and some content that you want WordPress to store, list, and display.

How do you create a custom post type?

Create a custom post type by calling register_post_type in a small plugin. You give the type an internal name, a label for the dashboard, and settings for whether it is public, whether it has an archive page, and what its URLs look like. A dozen lines is enough.

<?php
/* Plugin Name: Firm Profiles */

add_action('init', function () {
    register_post_type('firm_profile', [
        'label'        => 'Firm Profiles',
        'public'       => true,
        'has_archive'  => true,
        'show_in_rest' => true,
        'rewrite'      => ['slug' => 'firm'],
        'supports'     => ['title', 'editor', 'thumbnail', 'custom-fields'],
    ]);
});

That is an illustration, not our production code, but the shape is the same. A few points:

  1. Put it in a plugin, not the theme. If the type is registered by the theme, changing themes makes the content vanish from the dashboard. The data is still there, but nothing knows how to show it.
  2. Set show_in_rest. It enables the block editor for the type and lets scripts read and write it through the REST API.
  3. Choose the slug carefully. It becomes part of every address, and changing it later means redirects.
  4. Refresh permalinks once. Visit the Permalinks settings screen and save, or the new addresses return a not found error.

Plugins with a settings screen can register types without code. The result is the same. We prefer the code version, because it is short and travels with the site.

What does a real custom post type look like?

A real custom post type is a template plus structured fields, repeated for every item. On RankAZona, each firm profile is one entry of the profile type. The fields hold the facts about the firm, and one template turns any entry into a finished page. Change the template and every profile changes.

That structure is what makes the rest of the site possible:

  • The directory is a query. Listing firms in a category means asking WordPress for entries of the profile type, filtered and sorted.
  • Owners can edit their own entry. A business owner gets an emailed link, with no password, and edits their profile. Edits are staged, verified, and applied on a schedule.
  • News links to profiles. The news engine links each story to the firms it mentions, which works because each firm is a distinct, addressable item.
  • Scripts can maintain it. The site is run with Python scripts through the REST API, which treats a custom type like any other content.

Nominations are the same idea used differently. A nomination is a submission to review, not a page for the public. A custom post type can be registered as non-public, so entries show up in the dashboard for staff and never get an address on the site.

We go deeper on the product side in how to build a directory website.

When should you use a custom post type?

Use a custom post type when you have many items of the same shape, each deserving its own page, that people will create and edit like content. Listings, staff profiles, locations, case studies, events, and products in a simple catalog all fit. So does anything you want kept apart from the blog.

A quick test:

  1. Are there more than a handful of them, with more coming?
  2. Do they share a structure: the same fields in the same order?
  3. Should each have its own address and appear in search results?
  4. Will someone edit them in the dashboard?
  5. Do they need a title, a body, and maybe an image, with drafts and revisions?

Mostly yes means a custom post type. If there are only five items and they never change, ordinary pages are simpler, and simple is fine.

When is a database table better than a custom post type?

A custom database table is better when the data is not content: high-volume records, numbers you need to total or filter, or rows with many relationships to each other. Orders, log entries, bookings, and analytics events fit a table. Post types store extra fields inefficiently for that kind of work.

The reason is how WordPress stores fields. Every custom field is a separate row in a shared meta table, as a key and a text value. That is flexible and fine for showing a profile. It is slow for questions such as "total all orders in March by region," which a purpose-built table with proper columns and indexes answers easily.

Custom post typeCustom table
Dashboard editing screenIncludedYou build it
Revisions, drafts, schedulingIncludedYou build them
Public pages and addressesIncludedYou build them
REST APIOne settingYou write endpoints
Filtering on many fieldsGets slowFast with indexes
Sums, counts, reportsAwkwardWhat tables are for
Hundreds of thousands of rowsStrains the shared tablesFine

If you find yourself needing a table for most of your data, the project may be an application and not a website. That is a different decision, covered in website vs web application.

What are custom fields and taxonomies?

Custom fields and taxonomies are the two companions of a custom post type. Custom fields store facts about one item, such as a phone number or a founding year. Taxonomies group items, the way categories and tags group posts. Together they turn a plain entry into structured, sortable data.

For a directory, the split is natural. The firm's address is a field. Its industry is a taxonomy term, because you want a page listing every firm in that industry. A useful rule: if you will ever want to list all items that share a value, make it a taxonomy.

We used a related pattern on a Phoenix law firm's site, where practice pages are rendered from a spec file through one template system. Different mechanism, same principle: structure once, render many times.

Frequently asked questions

Do custom post types slow down WordPress?

No. Registering a type adds almost nothing. Performance depends on how many entries exist and how they are queried. Large numbers of entries filtered by several custom fields can get slow, which is the point where a custom table or better indexing is worth considering.

What happens to custom post types if I change themes?

If the type is registered in a plugin, nothing happens and the content carries on. If it was registered in the old theme, the entries disappear from the dashboard until the type is registered again. The data remains in the database either way.

Can I convert existing posts into a custom post type?

Yes. The type is a single value on each entry, so a script or a conversion plugin can switch it. Plan for the address change, since the URL pattern usually differs, and add redirects from the old addresses.

Do custom post types appear in site search and sitemaps?

Public types can appear in both. Whether they do depends on how the type was registered and on your SEO plugin's settings, which usually let you include or exclude each type from the sitemap.

Are custom post types good for SEO?

They help indirectly. Consistent templates make it easy to give every entry a proper title, headings, and structured data.

If you have content that does not fit posts or pages, tell us what it is and we will say which structure we would use.

Who wrote this

The Cobra Developers team. We are a software studio in Arizona that builds and runs its own products and builds websites, web apps, and automation for clients. This post draws on our work on RankAZona, Tamou Law Group. Everything here comes from projects we shipped; see all 30 of them.

guest@cobra: ~