The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Use the Mark New Posts plugin if you want per-visitor unread tracking with minimal setup. It stores each visitor’s state in a browser cookie and can place a “New” label or orange marker beside posts they have not read. For a logged-in membership site, compare post dates with each user’s last-login value instead; for a simple announcement, use a sticky post or the native Latest Posts block.
Choose the right type of “new” indicator
WordPress has no built-in feature that remembers which posts each anonymous visitor has opened. The best method depends on whether “new” means new to everyone or unread by this particular person.
| Method | Per-visitor unread state | Setup | State storage | Best use |
|---|---|---|---|---|
| Mark New Posts plugin | Yes | Low | Browser cookie | Most public blogs and news sites |
| WPCode custom PHP and CSS | Yes, if implemented correctly | Medium to high | Browser cookie | Sites needing custom markup or styling |
| Latest Posts block | No | Low | None | A current-posts list for every reader |
| Sticky posts | No | Low | Editorial setting | One or two important announcements |
| Login-based last-login comparison | Yes | High | User account data | Membership sites where readers switch devices |
Option 1: Mark New Posts plugin
Install and enable it
- In the WordPress dashboard, open Plugins > Add New.
- Search for Mark New Posts, install the plugin shown in the WordPress directory, and activate it.
- Open its settings and choose where the marker should appear, such as beside the post title.
The plugin requires no visitor account or authorization. It uses a cookie to remember which posts are considered read in that browser.
Configure the marker and read rule
Choose a marker that fits your design. The documented choices include a text label such as “New” and an orange circle. Then select when a post becomes read:
- After the visitor opens the post: the clearest match for an unread-post system.
- After the post is listed: useful when seeing a listing counts as exposure.
- After any page is opened: removes all current markers quickly, but does not represent individual reading.
Set how many days a marker remains active. A practical starting point is about seven days or until the visitor opens the post. Increase the period for an infrequently updated site; shorten it for a high-volume publication so the badge does not accumulate indefinitely.
#1 Best Overall
Decide what first-time visitors should see
The plugin can treat existing posts as new for first-time visitors. That gives a newcomer immediate guidance, but marking a large archive may overwhelm them. Consider enabling it only when your archive is small or when a recent-content window is more important than the full back catalogue.
Use the plugin’s theme functions when needed
For theme-level layouts, the WordPress.org listing documents mnp_is_new_post() to test a post’s state and mnp_new_posts_count() to retrieve the number of new posts. You can use those functions in a custom loop to add a badge, display a “You have 4 new posts” message, or alter sorting without replacing the plugin’s cookie logic.
Option 2: Build a cookie-based badge with WPCode
A custom implementation is appropriate when you need a specific HTML location, class name, or visual treatment and are comfortable maintaining PHP. The approach described by WPBeginner reads a lastvisit cookie, compares it with each post’s publication timestamp, and appends a new-article badge when the post is newer.
Rank #2
Add the PHP logic
Create a PHP snippet in WPCode and run it on the front end. This example follows that pattern and updates the cookie after the page has rendered, so the current request still uses the previous visit time:
<?php
function freedom251_new_post_title_badge($title, $post_id) {
if (is_admin() || !in_the_loop() || !is_main_query()) {
return $title;
}
$last_visit = isset($_COOKIE['lastvisit']) ? (int) $_COOKIE['lastvisit'] : 0;
$published = (int) get_post_time('U', true, $post_id);
if ($published > $last_visit) {
$title .= ' <span class="new-article" aria-label="New post">New</span>';
}
return $title;
}
add_filter('the_title', 'freedom251_new_post_title_badge', 10, 2);
function freedom251_record_visit() {
if (!is_admin() && !headers_sent()) {
setcookie('lastvisit', (string) time(), time() + (30 * DAY_IN_SECONDS), COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true);
}
}
add_action('shutdown', 'freedom251_record_visit');
Test the snippet in a staging site first. If your theme renders titles through a custom query or block rather than the_title, add the badge in that template instead of assuming this filter covers every listing.
Style the badge with CSS
.new-article {
display: inline-block;
margin-left: .4rem;
padding: .12rem .4rem;
border-radius: .25rem;
background: #f28c28;
color: #fff;
font-size: .72em;
font-weight: 700;
line-height: 1.2;
text-transform: uppercase;
vertical-align: middle;
}
Keep the badge visually clear but modest. Avoid persistent animation, which can distract readers and create accessibility problems. The tutorial’s recommended behavior is to mark a post read when it is opened, rather than clearing every other label when one post is viewed.
Rank #3
Understand the custom-code limitations
- A cookie is tied to one browser. Clearing cookies, using private browsing, or changing devices resets the reader’s state.
- Full-page caching can serve one visitor’s rendered HTML to another. Cache the page in a way that does not freeze personalized badges, or render the badge client-side.
- Cookie-consent tools, security headers, and other plugins may block or alter the cookie.
- The code compares publication time, so updating an old post does not automatically make it “new” unless you change the comparison to use the modified timestamp.
Native WordPress alternatives
Latest Posts block
The official WordPress documentation describes the Latest Posts block as displaying your most recent posts so readers can see what is new. In the block editor, add Latest Posts and choose the number of posts, excerpts or full content, author and date metadata, featured images, and sorting options.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsThis is a shared recent-post list, not per-visitor unread tracking: every reader sees the same ordering and no post is removed because someone opened it.
Sticky posts
Mark a post as sticky when one announcement must remain at the top. WordPress.com support explains that sticky posts stay above other posts while the sticky setting remains enabled. This is effective for a launch notice or service update, but it cannot tell whether an individual visitor has read it.
Logged-in sites: store state with the account
For a membership site, compare each post’s publication timestamp with a stored last-login value instead of relying only on a browser cookie. The state then follows the account across browsers and devices. Decide whether logging in, opening a post, or explicitly marking all posts read should advance that value, and make the rule consistent across archive, search, and home-page templates.
Quick Recap
Check the result before publishing
- Open the site in a fresh private window and confirm that the intended posts receive the badge.
- Open one marked post and verify that your selected read rule removes only the expected marker.
- Return to the listing in a second browser or after clearing cookies to confirm the first-visit behavior.
- Check mobile layouts, keyboard focus, color contrast, and screen-reader text for the badge.
- Test with your page-cache and cookie-consent settings enabled; personalized HTML must not be cached for all visitors.
- Confirm that feeds, search results, custom loops, and pagination do not show inconsistent states.
Which approach should you choose?
Choose Mark New Posts for the quickest reliable setup and its built-in controls for marker type, duration, first-time visitors, and read behavior. Choose WPCode when you need custom markup and accept responsibility for cookie, caching, and theme maintenance. Use Latest Posts or a sticky post when a shared editorial list is enough. On a logged-in site, account-based last-login tracking is the most consistent way to preserve read state across devices.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

