The PostPost Plugin provides a powerful way to append dynamic content, such as Calls-to-Action (CTAs), to your blog posts based on categories or universally across your site. This is particularly useful for marketers and content managers who want to:
- Target specific categories with tailored CTAs.
- Update content dynamically across the entire site with minimal effort.
Here’s how you can leverage the plugin:
Use Case 1: Append Dynamic CTAs by Category
Imagine you run a blog with categories such as Fitness, Technology, and Lifestyle. Each category can have its own CTA:
- Subscribe to Fitness Tips for the Fitness category.
- Download the Latest Tech Guide for the Technology category.
- Explore Our Lifestyle Products for the Lifestyle category.
Using the PostPost Plugin:
- Create a new
postpost
entry for each category. - Use the meta box to select the specific categories in which the CTA should appear.
- Save and let the plugin dynamically append the CTA to relevant posts.
Use Case 2: Add and Update Content Universally Across All Posts
If you want to add disclaimers, announcements, or promotional content to all blog posts:
- Create a single
postpost
entry. - Select the All Posts option in the meta box.
- Save and watch the content get dynamically appended to every post on your site.
When the content needs updating, edit the postpost
entry, and the changes will reflect across all posts instantly.
PostPost Plugin Code
Below is the full plugin code, which you can use to implement this functionality on your WordPress site:
<?php
/*
Plugin Name: PostPost
Description: Create reusable Gutenberg content blocks (PostPost) to append seamlessly to blog posts.
Version: 1.1
Author: Douglas Karr
Author URI:
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class PostPostPlugin {
public function __construct() {
add_action( 'init', [ $this, 'register_postpost_cpt' ] );
add_action( 'add_meta_boxes', [ $this, 'register_meta_box' ] );
add_action( 'save_post', [ $this, 'save_meta_box_data' ] );
add_filter( 'the_content', [ $this, 'append_postpost_to_content' ] );
add_filter( 'wp_robots', [ $this, 'exclude_postpost_from_indexing' ] );
add_filter( 'wp_sitemaps_post_types', [ $this, 'exclude_from_sitemap' ] );
}
// Register custom post type
public function register_postpost_cpt() {
$args = [
'label' => 'PostPost',
'public' => false,
'show_ui' => true,
'show_in_menu' => true,
'supports' => ['title', 'editor', 'revisions', 'custom-fields'],
'show_in_rest' => true,
];
register_post_type( 'postpost', $args );
}
// Exclude from sitemaps
public function exclude_from_sitemap( $post_types ) {
unset( $post_types['postpost'] );
return $post_types;
}
// Exclude from search engine indexing
public function exclude_postpost_from_indexing( $robots ) {
if ( is_singular( 'postpost' ) ) {
$robots['noindex'] = true;
}
return $robots;
}
// Register the meta box
public function register_meta_box() {
add_meta_box(
'postpost_meta_box',
'PostPost Settings',
[ $this, 'render_meta_box' ],
'postpost',
'side'
);
}
// Render the meta box
public function render_meta_box( $post ) {
$selected_option = get_post_meta( $post->ID, '_postpost_option', true );
$selected_categories = get_post_meta( $post->ID, '_postpost_categories', true );
$categories = get_categories();
wp_nonce_field( 'postpost_meta_box', 'postpost_meta_box_nonce' );
echo '<label><input type="radio" name="postpost_option" value="all" ' . checked( $selected_option, 'all', false ) . '> All Posts</label><br>';
echo '<label><input type="radio" name="postpost_option" value="categories" ' . checked( $selected_option, 'categories', false ) . '> Specific Categories</label><br><br>';
echo '<div id="postpost-categories" style="' . ( $selected_option === 'categories' ? '' : 'display:none;' ) . '">';
foreach ( $categories as $category ) {
echo '<label><input type="checkbox" name="postpost_categories[]" value="' . $category->term_id . '" ' . ( is_array( $selected_categories ) && in_array( $category->term_id, $selected_categories ) ? 'checked' : '' ) . '> ' . $category->name . '</label><br>';
}
echo '</div>';
echo '<script>
document.querySelectorAll(\'input[name="postpost_option"]\').forEach(radio => {
radio.addEventListener("change", function() {
document.getElementById("postpost-categories").style.display = this.value === "categories" ? "" : "none";
});
});
</script>';
}
// Save meta box data
public function save_meta_box_data( $post_id ) {
if ( ! isset( $_POST['postpost_meta_box_nonce'] ) || ! wp_verify_nonce( $_POST['postpost_meta_box_nonce'], 'postpost_meta_box' ) ) {
return;
}
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
if ( isset( $_POST['postpost_option'] ) ) {
update_post_meta( $post_id, '_postpost_option', sanitize_text_field( $_POST['postpost_option'] ) );
}
if ( isset( $_POST['postpost_categories'] ) && is_array( $_POST['postpost_categories'] ) ) {
update_post_meta( $post_id, '_postpost_categories', array_map( 'sanitize_text_field', $_POST['postpost_categories'] ) );
} else {
delete_post_meta( $post_id, '_postpost_categories' );
}
}
// Append PostPost content to the_content
public function append_postpost_to_content( $content ) {
if ( is_singular( 'post' ) ) {
$post_id = get_the_ID();
$query = new WP_Query( [
'post_type' => 'postpost',
'posts_per_page' => -1,
] );
$postpost_content="";
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
$option = get_post_meta( get_the_ID(), '_postpost_option', true );
$categories = get_post_meta( get_the_ID(), '_postpost_categories', true );
if ( $option === 'all' ) {
$postpost_content .= apply_filters( 'the_content', get_the_content() );
} elseif ( $option === 'categories' && has_category( $categories, $post_id ) ) {
$postpost_content .= apply_filters( 'the_content', get_the_content() );
}
}
}
wp_reset_postdata();
return $content . $postpost_content;
}
return $content;
}
}
new PostPostPlugin();
How to Use This Code:
- Copy and paste this code into a file named
postpost-plugin.php
. - Place the file in the
wp-content/plugins/postpost/
directory. - Activate the plugin from the WordPress admin panel.
- Create
postpost
entries with your CTAs or content and configure the settings.
This plugin provides a versatile solution for managing dynamic CTAs or global content updates, enhancing your content strategy easily and efficiently.