Overview
Template tags are helper functions used in theme templates to display post metadata, author information, timestamps, categories, tags, and featured images. These functions are located in /inc/template-tags.php.
All template tag functions check for existence using function_exists() to allow child themes to override them.
zalbi_posted_on()
Prints HTML with meta information for the current post’s publication and modification dates.
Function Signature
function zalbi_posted_on ()
Parameters
None (uses global $post object)
Return Value
Echoes HTML directly to output
Output
Displays formatted date with:
Publication date (always shown)
Modification date (shown separately if post was updated)
Microdata-compatible <time> elements with W3C date format
Link to post permalink
Implementation
function zalbi_posted_on () {
$time_string = '<time class="entry-date published updated" datetime="%1$s">%2$s</time>' ;
if ( get_the_time ( 'U' ) !== get_the_modified_time ( 'U' ) ) {
$time_string = '<time class="entry-date published" datetime="%1$s">%2$s</time><time class="updated" datetime="%3$s">%4$s</time>' ;
}
$time_string = sprintf (
$time_string ,
esc_attr ( get_the_date ( DATE_W3C ) ),
esc_html ( get_the_date () ),
esc_attr ( get_the_modified_date ( DATE_W3C ) ),
esc_html ( get_the_modified_date () )
);
$posted_on = sprintf (
esc_html_x ( 'Posted on %s' , 'post date' , 'zalbi' ),
'<a href="' . esc_url ( get_permalink () ) . '" rel="bookmark">' . $time_string . '</a>'
);
echo '<span class="posted-on">' . $posted_on . '</span>' ;
}
Usage
// In a template file (e.g., single.php, content.php)
< div class = "entry-meta" >
<? php zalbi_posted_on (); ?>
</ div >
Output Example
< span class = "posted-on" >
Posted on
< a href = "https://example.com/post-slug/" rel = "bookmark" >
< time class = "entry-date published" datetime = "2026-03-04T10:30:00+00:00" >
March 4, 2026
</ time >
< time class = "updated" datetime = "2026-03-05T14:20:00+00:00" >
March 5, 2026
</ time >
</ a >
</ span >
CSS Classes
Wrapper span for the entire date output
Applied to the <time> element
Original publication date
Last modification date (only if different from published)
The function automatically detects if a post has been modified and shows both dates for SEO purposes.
zalbi_posted_by()
Prints HTML with meta information for the current post’s author.
Function Signature
function zalbi_posted_by ()
Parameters
None (uses global $post object)
Return Value
Echoes HTML directly to output
Output
Displays:
Author name with link to author archive
Microdata-compatible markup with hCard classes
Translatable “by” prefix
Implementation
function zalbi_posted_by () {
$byline = sprintf (
esc_html_x ( 'by %s' , 'post author' , 'zalbi' ),
'<span class="author vcard"><a class="url fn n" href="' . esc_url ( get_author_posts_url ( get_the_author_meta ( 'ID' ) ) ) . '">' . esc_html ( get_the_author () ) . '</a></span>'
);
echo '<span class="byline"> ' . $byline . '</span>' ;
}
Usage
// Display author info in template
< div class = "entry-meta" >
<? php
zalbi_posted_on ();
zalbi_posted_by ();
?>
</ div >
Output Example
< span class = "byline" >
by
< span class = "author vcard" >
< a class = "url fn n" href = "https://example.com/author/john-doe/" >
John Doe
</ a >
</ span >
</ span >
CSS Classes
Wrapper span for author information
hCard microformat for author (SEO)
Microformat classes for author link
This function uses hCard microformat classes for better SEO:
vcard - Indicates contact information
url - Author URL
fn - Formatted name
n - Name
Prints HTML with metadata for categories, tags, comments link, and edit link in the post footer.
Function Signature
function zalbi_entry_footer ()
Parameters
None (uses global $post object)
Return Value
Echoes HTML directly to output
What It Displays
Categories : Comma-separated list with links
Tags : Comma-separated list with links
Comments Link : If on archive and comments are open
Edit Link : For logged-in users with edit permissions
For Pages & Custom Post Types
Comments Link : If comments are enabled
Edit Link : For logged-in users with edit permissions
No categories or tags (hidden for non-post types)
Implementation
function zalbi_entry_footer () {
// Hide category and tag text for pages.
if ( 'post' === get_post_type () ) {
$categories_list = get_the_category_list ( esc_html__ ( ', ' , 'zalbi' ) );
if ( $categories_list ) {
printf ( '<span class="cat-links">' . esc_html__ ( 'Posted in %1$s' , 'zalbi' ) . '</span>' , $categories_list );
}
$tags_list = get_the_tag_list ( '' , esc_html_x ( ', ' , 'list item separator' , 'zalbi' ) );
if ( $tags_list ) {
printf ( '<span class="tags-links">' . esc_html__ ( 'Tagged %1$s' , 'zalbi' ) . '</span>' , $tags_list );
}
}
if ( ! is_single () && ! post_password_required () && ( comments_open () || get_comments_number () ) ) {
echo '<span class="comments-link">' ;
comments_popup_link (
sprintf (
wp_kses (
__ ( 'Leave a Comment<span class="screen-reader-text"> on %s</span>' , 'zalbi' ),
array ( 'span' => array ( 'class' => array () ) )
),
wp_kses_post ( get_the_title () )
)
);
echo '</span>' ;
}
edit_post_link (
sprintf (
wp_kses (
__ ( 'Edit <span class="screen-reader-text">%s</span>' , 'zalbi' ),
array ( 'span' => array ( 'class' => array () ) )
),
wp_kses_post ( get_the_title () )
),
'<span class="edit-link">' ,
'</span>'
);
}
Usage
// In content template files
< footer class = "entry-footer" >
<? php zalbi_entry_footer (); ?>
</ footer >
Output Example
< footer class = "entry-footer" >
< span class = "cat-links" >
Posted in < a href = "/category/news/" > News </ a > , < a href = "/category/updates/" > Updates </ a >
</ span >
< span class = "tags-links" >
Tagged < a href = "/tag/wordpress/" > WordPress </ a > , < a href = "/tag/themes/" > Themes </ a >
</ span >
< span class = "comments-link" >
< a href = "/post-slug/#respond" > Leave a Comment < span class = "screen-reader-text" > on Post Title </ span ></ a >
</ span >
< span class = "edit-link" >
< a href = "/wp-admin/post.php?post=123&action=edit" > Edit < span class = "screen-reader-text" > Post Title </ span ></ a >
</ span >
</ footer >
CSS Classes
Wrapper for category links
Wrapper for comments link
Wrapper for edit post link
Accessibility text (visually hidden)
Accessibility : The function includes screen-reader-only text with post titles for better context.
zalbi_post_thumbnail()
Displays an optional post thumbnail (featured image) with different markup for singular and archive views.
Function Signature
function zalbi_post_thumbnail ()
Parameters
None (uses global $post object)
Return Value
Echoes HTML directly to output, or returns early if no thumbnail
Behavior
Singular Views Wraps thumbnail in a <div> (no link)
Archive Views Wraps thumbnail in an <a> tag linking to post
Password Protected Returns early - no thumbnail shown
No Featured Image Returns early - nothing displayed
Implementation
function zalbi_post_thumbnail () {
if ( post_password_required () || is_attachment () || ! has_post_thumbnail () ) {
return ;
}
if ( is_singular () ) :
?>
< div class = "post-thumbnail" >
<? php the_post_thumbnail (); ?>
</ div ><!-- . post - thumbnail -->
<? php else : ?>
< a class = "post-thumbnail" href = "<?php the_permalink(); ?>" aria - hidden = "true" tabindex = "-1" >
<? php
the_post_thumbnail (
'post-thumbnail' ,
array (
'alt' => the_title_attribute (
array ( 'echo' => false )
),
)
);
?>
</ a >
<? php
endif ;
}
Usage
// In single.php or content.php
< article >
< header class = "entry-header" >
<? php the_title ( '<h1 class="entry-title">' , '</h1>' ); ?>
</ header >
<? php zalbi_post_thumbnail (); ?>
< div class = "entry-content" >
<? php the_content (); ?>
</ div >
</ article >
Output Examples
Singular View
Archive View
< div class = "post-thumbnail" >
< img width = "1200" height = "800"
src = "https://example.com/wp-content/uploads/image.jpg"
class = "attachment-post-thumbnail size-post-thumbnail wp-post-image"
alt = "Post Title" />
</ div >
Accessibility Features
aria-hidden="true" - Hides from screen readers (title link is primary)
tabindex="-1" - Removes from keyboard navigation
Prevents duplicate links to the same post
Uses the_title_attribute() for proper alt text
Ensures images are descriptive for screen readers
Conditional Display
The function exits early if:
Password Protected
post_password_required() returns true
Attachment Page
is_attachment() returns true
No Thumbnail
has_post_thumbnail() returns false
Customization
// Override in child theme
function zalbi_post_thumbnail () {
if ( ! has_post_thumbnail () ) {
return ;
}
// Custom thumbnail size
the_post_thumbnail ( 'large' , array (
'class' => 'custom-thumbnail' ,
));
}
Performance : The function uses has_post_thumbnail() to avoid unnecessary database queries when no featured image is set.
wp_body_open()
Backward compatibility shim for WordPress sites older than version 5.2. Provides the wp_body_open action hook.
Function Signature
Parameters
None
Return Value
Fires the wp_body_open action hook
Purpose
WordPress Core Function : This is a polyfill for wp_body_open() which became a core function in WordPress 5.2. This shim ensures compatibility with older WordPress versions.
The wp_body_open action allows plugins to inject code immediately after the opening <body> tag, which is useful for:
Analytics scripts (Google Tag Manager)
Accessibility tools
Cookie consent banners
Skip navigation links
Implementation
if ( ! function_exists ( 'wp_body_open' ) ) :
/**
* Shim for sites older than 5.2.
*
* @link https://core.trac.wordpress.org/ticket/12563
*/
function wp_body_open () {
do_action ( 'wp_body_open' );
}
endif ;
Usage in Templates
<!-- header . php -->
<! DOCTYPE html >
< html <? php language_attributes (); ?>>
< head >
< meta charset = "<?php bloginfo( 'charset' ); ?>" >
<? php wp_head (); ?>
</ head >
< body <? php body_class (); ?>>
<? php wp_body_open (); ?>
< div id = "page" class = "site" >
<!-- Rest of header -->
Hook Usage
Plugins can hook into this action:
// Plugin or functions.php
add_action ( 'wp_body_open' , function () {
echo '<div class="skip-link"><a href="#content">Skip to content</a></div>' ;
});
// Google Tag Manager
add_action ( 'wp_body_open' , function () {
?>
<!-- Google Tag Manager ( noscript ) -->
< noscript >< iframe src = "https://www.googletagmanager.com/ns.html?id=GTM-XXXXXX"
height = "0" width = "0" style = "display:none;visibility:hidden" ></ iframe ></ noscript >
<!-- End Google Tag Manager ( noscript ) -->
<? php
});
Modern WordPress : If your site runs WordPress 5.2+, this shim is never loaded and the core function is used instead.
Best Practices
Template Integration
< article id = "post-<?php the_ID(); ?>" <? php post_class (); ?>>
< header class = "entry-header" >
<? php the_title ( '<h1 class="entry-title">' , '</h1>' ); ?>
< div class = "entry-meta" >
<? php
zalbi_posted_on ();
zalbi_posted_by ();
?>
</ div >
</ header >
<? php zalbi_post_thumbnail (); ?>
< div class = "entry-content" >
<? php the_content (); ?>
</ div >
< footer class = "entry-footer" >
<? php zalbi_entry_footer (); ?>
</ footer >
</ article >
< article id = "post-<?php the_ID(); ?>" <? php post_class (); ?>>
<? php zalbi_post_thumbnail (); ?>
< header class = "entry-header" >
<? php the_title ( sprintf ( '<h2 class="entry-title"><a href="%s">' , esc_url ( get_permalink () ) ), '</a></h2>' ); ?>
< div class = "entry-meta" >
<? php zalbi_posted_on (); ?>
</ div >
</ header >
< div class = "entry-summary" >
<? php the_excerpt (); ?>
</ div >
< footer class = "entry-footer" >
<? php zalbi_entry_footer (); ?>
</ footer >
</ article >
Styling Hooks
All template tags output semantic HTML with specific CSS classes for easy styling:
/* Post meta styling */
.entry-meta {
font-size : 0.875 rem ;
color : #666 ;
margin-bottom : 1.5 rem ;
}
.posted-on ,
.byline {
margin-right : 1 rem ;
}
.posted-on a ,
.byline a {
color : inherit ;
text-decoration : none ;
}
/* Entry footer */
.entry-footer {
margin-top : 2 rem ;
padding-top : 1 rem ;
border-top : 1 px solid #eee ;
}
.cat-links ,
.tags-links ,
.comments-link ,
.edit-link {
margin-right : 1 rem ;
}
/* Post thumbnail */
.post-thumbnail {
margin-bottom : 1.5 rem ;
}
.post-thumbnail img {
display : block ;
width : 100 % ;
height : auto ;
}
All functions use function_exists() checks, allowing child themes to override them:
// Child theme functions.php
// Custom posted_on without modification date
function zalbi_posted_on () {
$posted_on = sprintf (
esc_html_x ( 'Posted %s' , 'post date' , 'zalbi' ),
'<time class="entry-date published" datetime="' . esc_attr ( get_the_date ( DATE_W3C ) ) . '">' .
esc_html ( get_the_date () ) . '</time>'
);
echo '<span class="posted-on">' . $posted_on . '</span>' ;
}
// Custom thumbnail with default placeholder
function zalbi_post_thumbnail () {
if ( has_post_thumbnail () ) {
the_post_thumbnail ( 'large' );
} else {
echo '<img src="' . get_stylesheet_directory_uri () . '/images/placeholder.jpg" alt="Placeholder">' ;
}
}
Next Steps Explore Customizer functions for theme settings and live preview