WordPress "What's New" Feed Integration
How to embed the latest product release notes from the Docusaurus documentation site into a WordPress website using the existing RSS feeds.
How it works
Docusaurus generates a per-product RSS feed for every blog (release notes) plugin instance. No changes to the docs site are needed — the feeds are already available at:
| Product | RSS feed URL |
|---|---|
| contentACCESS | /release/contentaccess/rss.xml |
| officeGATE | /release/officegate/rss.xml |
| Storage Optimizer | /release/storageoptimizer/rss.xml |
| contentACCESS Mobile | /release/camobile/rss.xml |
| mailApp | /release/mailapp/rss.xml |
On the WordPress side, a small plugin fetches these feeds using the built-in fetch_feed() function (SimplePie with automatic 12-hour caching) and exposes a [whats_new] shortcode that can be placed anywhere — pages, widgets, or Gutenberg shortcode blocks.
WordPress plugin
Create the file wp-content/plugins/techarrow-whats-new/techarrow-whats-new.php:
<?php
/**
* Plugin Name: TECH-ARROW What's New Feed
* Description: Displays latest product releases from the documentation site.
* Version: 1.0.0
*/
if ( ! defined( 'ABSPATH' ) ) exit;
define( 'WHATS_NEW_BASE_URL', 'https://YOUR-DOCS-SITE.com' );
const WHATS_NEW_FEEDS = [
'contentaccess' => WHATS_NEW_BASE_URL . '/release/contentaccess/rss.xml',
'officegate' => WHATS_NEW_BASE_URL . '/release/officegate/rss.xml',
'storageoptimizer' => WHATS_NEW_BASE_URL . '/release/storageoptimizer/rss.xml',
'camobile' => WHATS_NEW_BASE_URL . '/release/camobile/rss.xml',
'mailapp' => WHATS_NEW_BASE_URL . '/release/mailapp/rss.xml',
];
const WHATS_NEW_LABELS = [
'contentaccess' => 'contentACCESS',
'officegate' => 'officeGATE',
'storageoptimizer' => 'Storage Optimizer',
'camobile' => 'contentACCESS Mobile',
'mailapp' => 'mailApp',
];
/**
* [whats_new] shortcode
*
* Attributes:
* product – comma-separated product IDs, or "all" (default)
* days – only posts from the last N days (default: 60)
* limit – max items to show (default: 10)
*
* Examples:
* [whats_new]
* [whats_new product="contentaccess" limit="5"]
* [whats_new product="contentaccess,officegate" days="90"]
*/
function whats_new_shortcode( $atts ) {
$atts = shortcode_atts( [
'product' => 'all',
'days' => 60,
'limit' => 10,
], $atts, 'whats_new' );
$days = max( 1, intval( $atts['days'] ) );
$limit = max( 1, intval( $atts['limit'] ) );
$cutoff = time() - $days * DAY_IN_SECONDS;
// Resolve product list
$feed_ids = ( $atts['product'] === 'all' )
? array_keys( WHATS_NEW_FEEDS )
: array_filter(
array_map( 'trim', explode( ',', $atts['product'] ) ),
fn( $id ) => isset( WHATS_NEW_FEEDS[ $id ] )
);
// Fetch and collect items from each feed
$items = [];
foreach ( $feed_ids as $product_id ) {
$feed = fetch_feed( WHATS_NEW_FEEDS[ $product_id ] );
if ( is_wp_error( $feed ) ) continue;
foreach ( $feed->get_items() as $item ) {
if ( $item->get_date( 'U' ) < $cutoff ) continue;
$items[] = [
'title' => $item->get_title(),
'link' => esc_url( $item->get_permalink() ),
'date' => $item->get_date( 'U' ),
'date_str' => $item->get_date( 'M j, Y' ),
'product' => $product_id,
'label' => WHATS_NEW_LABELS[ $product_id ] ?? $product_id,
];
}
}
if ( empty( $items ) ) {
return '<p class="whats-new-empty">No recent releases found.</p>';
}
// Sort newest first, apply limit
usort( $items, fn( $a, $b ) => $b['date'] - $a['date'] );
$items = array_slice( $items, 0, $limit );
ob_start(); ?>
<ul class="whats-new-list">
<?php foreach ( $items as $item ) : ?>
<li class="whats-new-item whats-new-product-<?php echo esc_attr( $item['product'] ); ?>">
<span class="whats-new-badge"><?php echo esc_html( $item['label'] ); ?></span>
<a class="whats-new-title"
href="<?php echo $item['link']; ?>"
target="_blank" rel="noopener noreferrer">
<?php echo esc_html( $item['title'] ); ?>
</a>
<time class="whats-new-date"><?php echo esc_html( $item['date_str'] ); ?></time>
</li>
<?php endforeach; ?>
</ul>
<?php
return ob_get_clean();
}
add_shortcode( 'whats_new', 'whats_new_shortcode' );
CSS
Add to Appearance → Customize → Additional CSS in WordPress, or to the active theme's stylesheet:
.whats-new-list { list-style: none; padding: 0; margin: 0; }
.whats-new-item { display: flex; align-items: baseline; gap: 10px;
padding: 8px 0; border-bottom: 1px solid #eee; }
.whats-new-badge { background: #1a4692; color: #fff; font-size: 11px;
font-weight: 600; padding: 2px 10px; border-radius: 999px;
white-space: nowrap; }
.whats-new-title { flex: 1; font-weight: 500; }
.whats-new-date { font-size: 12px; color: #888; white-space: nowrap; }
/* Per-product badge colours */
.whats-new-product-officegate .whats-new-badge { background: #e67e22; }
.whats-new-product-storageoptimizer .whats-new-badge { background: #27ae60; }
.whats-new-product-camobile .whats-new-badge { background: #8e44ad; }
.whats-new-product-mailapp .whats-new-badge { background: #c0392b; }
Shortcode usage
| Shortcode | Result |
|---|---|
[whats_new] | All products, last 60 days, up to 10 items |
[whats_new product="contentaccess"] | contentACCESS only |
[whats_new product="contentaccess,officegate"] | Two products combined |
[whats_new product="all" days="90" limit="5"] | All products, last 90 days, max 5 items |
Notes
- Caching: WordPress caches each RSS feed for 12 hours automatically via transients — no extra configuration needed.
- Date filtering: The
daysfilter is applied after the feed is fetched (RSS does not support date-range queries). This is fine given the low volume of release posts. - CORS: Fetching is done server-side in PHP, so there are no cross-origin restrictions even if the docs site is on a different domain.
- Adding a new product: Add the new product's feed URL to
WHATS_NEW_FEEDSand its display label toWHATS_NEW_LABELS.