• Skip to main content
  • Skip to primary sidebar
  • Skip to footer

nSiteful Web Builders

Building a Better Web - One Site at a Time.

  • Home
  • About
    • Testimonials
    • Resources
    • Partner With Me
    • Frequently Asked Questions
  • Web Sites
  • Online Marketing
  • WordPress Support
    • Customized WordPress Training
    • 60-for-60 Sessions
  • Web Applications
  • Blog
    • At-A-Glance
    • Blog Articles Grouped by Category
    • Case Studies
    • General
    • Portfolio
    • Reviews
    • Snippets
    • Techniques
    • Projects
  • Contact
    • Purchase Retainer Consulting Hours
    • About Retainer Consulting Hours
    • Book a Meeting with Jeff
    • Tell Me About Your Web Project
    • nSiteful Newsletter Archives
    • nSiteful Rewards

By Jeff - 3/10/2023
Cats: Techniques · Tags: Advanced Custom Fields, Custom Fields, Custom Post Types, WordPress

techniques

Use Case for Custom Post Type: “In The News”

On This Page...

Toggle
  • Websites like to display news
  • My Rule of Thumb Test for Custom Post Types:
  • Using the Blog Post Method Presents Problems…
    • Problem #1: Consistency
    • Problem #2: Maintainability
  • Converting to Custom Post Type
    • Register Custom Post Type Code
    • Register Custom Taxonomies Code
  • How the Posts are Added and Edited
  • How the Posts Display on the Website Front End
    • Main Rendering Code
    • Getting the Data for Each Individual “In The News” Post
  • In Closing

Last updated April 25th, 2023 at 05:51 pm

This post assumes you have a basic familiarity with WordPress Custom Post Types. For an introduction or refresher, check out my multipart series of posts about Custom Post Types, starting here. The original version of this post includes code snippets, but I have not explained most of the code. If you have questions about what the code is doing, post those quesions in the comments.

Websites like to display news

Many websites include an “In The News” section — content related to articles, videos, podcasts, etc., that other publishers have published about them. It might be called “News”, “Press”, “Media” or something else.

Here’s a screenshot of the “In The News” section of the wanderBOX website.

Archive page for News custom post type

My Rule of Thumb Test for Custom Post Types:

An “In The News” post is a good use case for a custom post type. This is because it passes my rule-of-thumb test:

  1. All posts share a unique set of properties.
  2. You want to efficiently create and maintain these posts.
  3. You want to uniformly and consistently display these posts.

We can see from the above screenshot that there is a unique set of properties these posts share. They are Publication Name, Publication Date, Author Name, Article Title, and URL of the online article. There are also two “optional” properties: a brief description of the article, and an excerpt from the article.

When my client first started publishing In-The-News content, he created them as blog posts. By assigning these blog posts the category of “News”, we were able to isolate them so that they stood apart from all other blog posts.

Using the Blog Post Method Presents Problems…

But adding these news items as blog posts created a couple of problems:

Problem #1: Consistency

In order to display these posts consistently and uniformly, the authors had to remember exactly where to place the various “properties” as well as how each one is formatted.

Problem #2: Maintainability

What’s more, if the client decided at some time in the future that, for example, all the author names should be displayed differently (different font size, weight, or style; different color; etc.), then someone would have to go back into each “in The News” blog post and make the appropriate changes.

Converting to Custom Post Type

Because of these issues — and because “In The News” content is a perfect use case for a Custom Post Type — I recently converted all the “In The News” posts to posts of the custom post type “News”.

The code for registering the News CPT and the custom taxonomies for the News CPT are in a file named cpt-news.php and stored in the /mu-plugins/ folder.

Register Custom Post Type Code

Here is the code for registering the CPT:

function wb_register_news_cpt() {

	$labels = array(
		'name'                  => _x( 'News Post', 'Post Type General Name', 'news_domain' ),
		'singular_name'         => _x( 'News Posts', 'Post Type Singular Name', 'news_domain' ),
		'menu_name'             => __( 'News', 'news_domain' ),
		'name_admin_bar'        => __( 'News', 'news_domain' ),
		'archives'              => __( 'News Archives', 'news_domain' ),
		'attributes'            => __( 'News Attributes', 'news_domain' ),
		'parent_item_colon'     => __( 'Parent Item:', 'news_domain' ),
		'all_items'             => __( 'All News Items', 'news_domain' ),
		'add_new_item'          => __( 'Add New News Item', 'news_domain' ),
		'add_new'               => __( 'Add New', 'news_domain' ),
		'new_item'              => __( 'New News Item', 'news_domain' ),
		'edit_item'             => __( 'Edit News Item', 'news_domain' ),
		'update_item'           => __( 'Update News Item', 'news_domain' ),
		'view_item'             => __( 'View News Item', 'news_domain' ),
		'view_items'            => __( 'View News Items', 'news_domain' ),
		'search_items'          => __( 'Search News Items', 'news_domain' ),
		'not_found'             => __( 'Not found', 'news_domain' ),
		'not_found_in_trash'    => __( 'Not found in Trash', 'news_domain' ),
		'featured_image'        => __( 'Featured Image', 'news_domain' ),
		'set_featured_image'    => __( 'Set featured image', 'news_domain' ),
		'remove_featured_image' => __( 'Remove featured image', 'news_domain' ),
		'use_featured_image'    => __( 'Use as featured image', 'news_domain' ),
		'insert_into_item'      => __( 'Insert into News', 'news_domain' ),
		'uploaded_to_this_item' => __( 'Uploaded to this News Item', 'news_domain' ),
		'items_list'            => __( 'News list', 'news_domain' ),
		'items_list_navigation' => __( 'News list navigation', 'news_domain' ),
		'filter_items_list'     => __( 'Filter News list', 'news_domain' ),
	);
	$args = array(
		'label'                 => __( 'News', 'news_domain' ),
		'description'           => '',
		'labels'                => $labels,
		'supports'              => array( 'title', 'page-attributes' ),
		'taxonomies'            => array( 'news_cats', 'news_tags' ),
		'hierarchical'          => true,
		'public'                => true,
		'show_ui'               => true,
		'show_in_menu'          => true,
		'menu_position'         => 5,
		'show_in_admin_bar'     => true,
		'show_in_nav_menus'     => true,
		'can_export'            => true,
		'has_archive'           => true,
		'exclude_from_search'   => false,
		'publicly_queryable'    => true,
		'capability_type'       => 'page',
	);
	register_post_type( 'news', $args );

}
add_action( 'init', 'wb_register_news_cpt', 0 );

Register Custom Taxonomies Code

Here is the code for registering the news_cats taxonomy:

function wb_register_news_cats() {

	$labels = array(
		'name'                       => _x( 'News Categories', 'Taxonomy General Name', 'text_domain' ),
		'singular_name'              => _x( 'News Category', 'Taxonomy Singular Name', 'text_domain' ),
		'menu_name'                  => __( 'News Categories', 'text_domain' ),
		'all_items'                  => __( 'All News Categories', 'text_domain' ),
		'parent_item'                => __( 'Parent Item', 'text_domain' ),
		'parent_item_colon'          => __( 'Parent Item:', 'text_domain' ),
		'new_item_name'              => __( 'New News Category Name', 'text_domain' ),
		'add_new_item'               => __( 'Add New News Category', 'text_domain' ),
		'edit_item'                  => __( 'Edit News Category', 'text_domain' ),
		'update_item'                => __( 'Update News Category', 'text_domain' ),
		'view_item'                  => __( 'View News Category', 'text_domain' ),
		'separate_items_with_commas' => __( 'Separate News Categories with commas', 'text_domain' ),
		'add_or_remove_items'        => __( 'Add or remove News Categories', 'text_domain' ),
		'choose_from_most_used'      => __( 'Choose from the most used', 'text_domain' ),
		'popular_items'              => __( 'Popular News Categories', 'text_domain' ),
		'search_items'               => __( 'Search News Catetories', 'text_domain' ),
		'not_found'                  => __( 'Not Found', 'text_domain' ),
		'no_terms'                   => __( 'No News Categories', 'text_domain' ),
		'items_list'                 => __( 'News Categories list', 'text_domain' ),
		'items_list_navigation'      => __( 'News Categories list navigation', 'text_domain' ),
	);
	$args = array(
		'labels'                     => $labels,
		'hierarchical'               => true,
		'public'                     => true,
		'show_ui'                    => true,
		'show_admin_column'          => true,
		'show_in_nav_menus'          => true,
		'show_tagcloud'              => true,
	);
	register_taxonomy( 'news_cats', array( 'news' ), $args );

}
add_action( 'init', 'wb_register_news_cats', 0 );

Here is the code for registering the news_tags taxonomy:

function wb_register_news_tags() {

	$labels = array(
		'name'                       => _x( 'News Tags', 'Taxonomy General Name', 'text_domain' ),
		'singular_name'              => _x( 'News Tag', 'Taxonomy Singular Name', 'text_domain' ),
		'menu_name'                  => __( 'News Tags', 'text_domain' ),
		'all_items'                  => __( 'All News Tags', 'text_domain' ),
		'parent_item'                => __( 'Parent News Tag', 'text_domain' ),
		'parent_item_colon'          => __( 'Parent News Tag:', 'text_domain' ),
		'new_item_name'              => __( 'New News Tag', 'text_domain' ),
		'add_new_item'               => __( 'Add New News Tag', 'text_domain' ),
		'edit_item'                  => __( 'Edit News Tag', 'text_domain' ),
		'update_item'                => __( 'Update News Tag', 'text_domain' ),
		'view_item'                  => __( 'View News Tag', 'text_domain' ),
		'separate_items_with_commas' => __( 'Separate News Tags with commas', 'text_domain' ),
		'add_or_remove_items'        => __( 'Add or remove News Tags', 'text_domain' ),
		'choose_from_most_used'      => __( 'Choose from the most used', 'text_domain' ),
		'popular_items'              => __( 'Popular News Tags', 'text_domain' ),
		'search_items'               => __( 'Search News Tags', 'text_domain' ),
		'not_found'                  => __( 'Not Found', 'text_domain' ),
		'no_terms'                   => __( 'No News Tags', 'text_domain' ),
		'items_list'                 => __( 'News Tag list', 'text_domain' ),
		'items_list_navigation'      => __( 'News Tag list navigation', 'text_domain' ),
	);
	$args = array(
		'labels'                     => $labels,
		'hierarchical'               => false,
		'public'                     => true,
		'show_ui'                    => true,
		'show_admin_column'          => true,
		'show_in_nav_menus'          => true,
		'show_tagcloud'              => true,
	);
	register_taxonomy( 'news_tags', array( 'news' ), $args );

}
add_action( 'init', 'wb_register_news_tags', 0 );

How the Posts are Added and Edited

Using Advanced Custom Fields Pro (but the free version would have sufficed for this implementation), I created a form group for “News”. News items are added and edited from the WordPress back end using this form, based on that form group:

Form for inputting posts for the News custom post type

How the Posts Display on the Website Front End

The nature of these “In The News” posts obviates the need for single post pages. Therefore, the only code that matters is that which renders the News archive.
All of the code that follows in this section is in a file named cpt-news-functions.php in the /mu-plugins/ folder.

Main Rendering Code

<?php
function wb_news_render_archive() {
	if ( ! ( is_post_type_archive( 'news' ) || is_tax('news_cats') || is_tax('news_tags') ) ) return;
	
	/* Call */
	$data = wb_news_get_single(get_the_ID());
	extract($data);
	$pub_date_cos = date('F j, Y', strtotime($data['publication_date']));
	/* Assemble the Categoy Links */
	$cats = $data['news_cat_terms']; /* md array of term stuff for link_cats */
	/* Assemble Category Archive permalinks (for THIS post) into an array that will be imploded for the nav */
	$news_cats_archives = array();
	foreach ( $cats as $cat ) {
		$news_cats_archives[] = '<a href="/' . $cat->taxonomy . '/' . $cat->slug . '/">' . $cat->name . '</a>';
	}
	$news_cats_archives_nav = 
	'<span class="terms">' . implode(' | ', $news_cats_archives) . '</span>';
?>
<div class="news-item-container">
	<div class="publication-name">
		<?php echo $data['publication_name'];?>
	</div>
	<div class="news-item">
		<div class="article-title">
			<?php echo $data['article_title'];?>
		</div>
		<div class="publication-date">
			<span class="prompt">Date Published: </span>
			<?php echo $pub_date_cos;?>
		</div>
		<div class="author-name">
			<span class="prompt">Author: </span>
			<?php echo $data['author_name'];?>
		</div>
		<?php if ( $data['about_this_article'] ) : ?>
			<div class="about-this-article">
				<span class="prompt">About this article: </span>
				<span class="text"><?php echo $data['about_this_article'];?></span>
			</div>
		<?php endif; ?>
		
		<?php if ( $data['money_quote'] ) : ?>
			<div class="money-quote">
				<span class="prompt">Excerpt: </span>
				<blockquote><?php echo $data['money_quote'];?></blockquote>
			</div>
		<?php endif; ?>
		<?php if ( !empty($cats) ) : ?>
		<nav class="cat-links">
			<span class="prompt">Filed Under: </span>
			<?php echo $news_cats_archives_nav;?>
		</nav>
		<?php endif; ?>
		<div class="article-url">
			<?php echo $data['article_url'];?>
		</div>
		<div class="permalink">
			<a class="external button" target="_blank" title="Visit <?php echo $article_url;?>" href="<?php echo $article_url;?>">Read More >></a>
		</div>
	</div>
</div><!-- / .news-item-container -->
<?php
}
add_action('generate_after_entry_title', 'wb_news_render_archive');

Getting the Data for Each Individual “In The News” Post

Here is the code for retrieving the data for each individual News item. This function is called on line 6 of the above code. Notice that even though I’m using Advanced Custom Fields to generate the custom fields, I’m using the native WordPress get_post_meta() function instead of ACF’s the_field() function. I do this to avoid problems in the event that the ACF plugin is ever removed from the website. If the plugin were to be removed, all the “post_meta” content would remain in the database, but any code using ACF functions would fail.

<?php
function wb_news_get_single($id) {
	$data = array(); // init
	$data['news_cat_terms'] 	= wp_get_post_terms($id, 'news_cats', array('fields' => 'all'));	
	$data['news_tag_terms'] 	= wp_get_post_terms($id, 'news_tags', array('fields' => 'all'));	
	$data['publication_name'] 	= get_post_meta($id, 'wbnews_publication_name', true);
	$data['publication_date'] 	= get_post_meta($id, 'wbnews_publication_date', true);
	$data['article_url'] 		= get_post_meta($id, 'wbnews_article_url', true);
	$data['article_title'] 		= get_post_meta($id, 'wbnews_article_title', true);
	$data['author_name'] 		= get_post_meta($id, 'wbnews_author_name', true);
	$data['money_quote'] 		= get_post_meta($id, 'wbnews_money_quote', true);
	$data['about_this_article']	= get_post_meta($id, 'wbnews_about_this_article', true);
	return $data;
}

In Closing

I hope someone finds this post helpful. If you have questions, please ask in the comments section below. Thanks for listening.

Like what you see? Share with others and join my mailing list. No long-term commitment, unsubscribe any time.

Related Posts

  1. Dive Into WordPress Custom Post Types – Part 2
  2. Custom Post Type: How to Create a Simple Custom Events Plugin
  3. Use Custom Fields to Hide Stale Posts
  4. How to use Advanced Custom Fields with Genesis
  5. Dive Into WordPress Custom Post Types – Part 3

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

mailchimp signup

Subscribe to get notified when new articles are published. Unsubscribe any time. No spam. I promise. Check out my newsletter archives.

social

Twitter Facebook LinkedIn

Recent Articles

  • Post-Specific CSS for WordPress October 5, 2026
  • You built an online course, but they haven’t come. September 16, 2026
  • Custom MemberPress Pricing Pages December 19, 2025
  • CSS Data Attribute Override December 11, 2025
  • MemberPress Rules Using Custom Taxonomies and Custom Roles December 10, 2025

Filter By Category/Tag

Categories

  • Case Studies (8)
  • For Staff (1)
  • General (73)
  • Portfolio (7)
  • Reviews (14)
  • Snippets (24)
  • Techniques (52)

Popular Tags

Advanced Custom Fields Blogging Child Themes Content Marketing CSS Customer Service Custom Fields Custom Post Types Diagnostics Domain Names Facebook FooGallery Genesis Hosting HTML Images iPhone Libra Live Chat Marketing Media MemberPress MemberPress Courses Membership Sites Mobile-Friendly MySQL Photo Gallery php Pinterest Plugins Post Formats Pricing Project Management SEBA SEO Seth Godin Shortcodes Social Networking Surveys Taxonomies Twitter Video Web design Web forms WordPress

Footer

Background

Web Sites | WordPress Support | Web Applications.

Formally trained in liberal arts and education (I have a B.A. in Government from Harvard and studied Secondary Education at Rutgers Graduate School), I have honed my skills in the communication arts and sciences as a teacher, trainer, instructional designer, writer, photographer, calligrapher, helpdesk manager, database programmer, and multimedia developer.

(I've also been a group counselor, waiter, bartender, bicycle messenger boy, computer salesman, carpenter's helper, financial analyst, and school board president.)

Tech

Systems since 1983.
Web sites since 1994.
PHP since 2001.
WordPress since 2007.

Contact

Book Meeting
770-772-5134
Email Jeff
Send Money
All Ways

Copyright 2026, nSiteful Web Builders, Inc.

Cookies Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
  • Manage options
  • Manage services
  • Manage {vendor_count} vendors
  • Read more about these purposes
View preferences
  • {title}
  • {title}
  • {title}
https://iframe.mediadelivery.net/embed/392008/42d18bc1-2adc-4741-b733-053d08d09c32
https://vz-000c5976-3ab.b-cdn.net/42d18bc1-2adc-4741-b733-053d08d09c32/play_720p.mp4

Receive occasional emails from Jeff