Skip to main content

Post

Access current post data. Available on single post/page views and inside Loop blocks (via the loop data alias).

All Fields​

FieldArgumentsReturnsDescription
id—intPost ID
title—stringPost title
slug—stringPost name (URL slug)
format—string | falsePost format slug, false when no format
excerpt{options}stringPost excerpt (chainable builder)
contentpage, len, remove_blocksstringPost content (filtered)
paged_content—stringCurrent page content (for paginated posts)
link—stringPermalink URL
path—stringURL path only
edit_link—string | nullAdmin edit URL (null when not authorized)
datedate_formatstringPublish date
timetime_formatstringPublish time
timestamp—intUnix timestamp
modified_datedate_formatstringLast modified date
modified_timetime_formatstringLast modified time
modified_timestamp—intModified unix timestamp
author—UserPost author
modified_author—UserLast editor
thumbnail—ImageFeatured image
thumbnail_id—intFeatured image ID, 0 if none
category—TermPrimary category (comparable to a string)
categories—arrayAll categories
tags—arrayAll tags
termsquery_args, optionsarrayTerms from taxonomy
has_termterm_name_or_id, taxonomyboolCheck if has term
type—stringPost type slug, chainable to .labels.*
parent—Post | falseParent post (false if no parent)
ancestors—arrayAncestor posts
childrenargsarrayChild posts
nextin_same_termPost | falseNext post (false if none)
previn_same_termPost | falsePrevious post (false if none)
commentscount, order, type, statusiterablePost comments (chainable)
comment_count—intNumber of comments
can_edit—boolCurrent user can edit
password_required—boolPassword protected
pagination—objectPagination data for paginated posts
galleryhtmlarrayGalleries in the content
post_classclassstringCSS classes
metafield_namemixedPost meta value
raw_metafield_namemixedMeta value, without plugins
has_fieldfield_nameboolCheck if field exists

Raw Database Fields​

Direct read access to the underlying WP_Post columns — useful when you need the exact stored value (no filtering, no formatting):

FieldReturnsDescription
IDintPost ID (alias of id)
post_titlestringTitle (raw)
post_namestringSlug (alias of slug)
post_authorstringAuthor user ID (numeric string)
post_typestringPost type slug
post_parentintParent post ID, 0 if none
post_statusstringpublish, draft, pending, private, etc.
post_date / post_date_gmtstringPublish date in YYYY-MM-DD HH:MM:SS
post_modified / post_modified_gmtstringModified date in YYYY-MM-DD HH:MM:SS
post_mime_typestringMIME type (mainly for attachments)
post_contentstringRaw post content, as HTML
post_excerptstringRaw post excerpt, as HTML
comment_statusstring'open' or 'closed'
menu_orderintManual order value

post_content and post_excerpt are empty when the visitor can't read the post or it's password protected. meta and raw_meta without a key give all the meta as a map; raw_meta skips the custom field plugins.

Content​

content​

Arguments:

  • page — Page number for paginated content (default: 0 = all)
  • len — Word limit (default: -1 = no limit)
  • remove_blocks — Remove block markup (default: false)
{{ post.content }}
{{ post.content(2) }} <!-- Page 2 only -->
{{ post.content(0, 50) }} <!-- Limit to 50 words, as plain text -->
{{ post.content(0, -1, true) }} <!-- Remove blocks -->

A word limit strips the HTML tags first.

excerpt​

post.excerpt is a chainable builder. You can pass an options object or chain methods to refine it — both styles work and you can mix them.

Options object:

  • words — Word count (default: 50)
  • chars — Character limit (overrides words)
  • end — Suffix text (default: '…')
  • force — Force from content even if excerpt exists (default: false)
  • strip — Strip HTML tags (default: true)
  • read_more — "Read more" link text (default: none)
  • the_content — Use full WordPress excerpt filter (default: false, slower). The other options are then ignored.
{{ post.excerpt }}
{{ post.excerpt({words: 25}) }}
{{ post.excerpt({chars: 150}) }}
{{ post.excerpt({words: 30, end: '...'}) }}
{{ post.excerpt({force: true}) }}
{{ post.excerpt({read_more: 'Continue reading'}) }}

Chained methods:

{{ post.excerpt.length(25) }}                          <!-- 25 words -->
{{ post.excerpt.chars(150) }} <!-- 150 chars -->
{{ post.excerpt.length(30).end('...') }}
{{ post.excerpt.force(true) }}
{{ post.excerpt.read_more('Continue reading') }}
{{ post.excerpt.strip(true).length(20) }}

Dates​

format: PHP date format string (default: WordPress setting)

{{ post.date }}                               <!-- Uses WP date format -->
{{ post.date('F j, Y') }} <!-- January 15, 2024 -->
{{ post.time }} <!-- Uses WP time format -->
{{ post.time('g:i a') }} <!-- 2:30 pm -->
{{ post.timestamp }} <!-- 1705330245 -->
{{ post.modified_date('Y-m-d') }}

Author​

The author field returns a User object with all user fields.

{{ post.author.name }}
{{ post.author.avatar }}
{{ post.modified_author.name }}
Shorthand

post.author is also available as the root author variable. See User & Author for details.

The thumbnail field returns an Image object.

{{ post.thumbnail.src }}
{{ post.thumbnail.src('medium') }}
{{ post.thumbnail.alt }}
{{ post.thumbnail.width }}
{{ post.thumbnail_id }} <!-- 0 when no thumbnail -->

Post Type​

post.type returns the post type slug — you can compare it directly to a string and chain into the post type object's labels:

{{ post.type }}                                <!-- 'post' or 'page' or CPT slug -->
{{ post.type.labels.singular_name }} <!-- 'Post' / 'Page' / etc. -->

Taxonomies​

category / categories / tags / terms​

Term references stringify to the term name and support direct comparison — no need to access .name explicitly:

{{ post.category }}                           <!-- 'News' -->
{{ post.category.link }}
{{ post.category.slug }}

terms​

Arguments:

  • query_args — Taxonomy name, array of names, 'all' (default), or a hash of term query arguments with a taxonomy key. tag and tags stand for post_tag, categories for category, any for all.
  • options — {merge: true} to combine or {merge: false} to group by taxonomy

terms returns a list: join it or loop over it.

{{ post.terms('genre')|map(t => t.name)|join(', ') }}
{{ post.terms(['category', 'tags'])|length }}
{{ post.terms({taxonomy: 'genre', orderby: 'name'})|map(t => t.name)|join(', ') }}
{{ post.terms('all', {merge: false})|keys|join(', ') }} <!-- category, post_tag, … -->

With {merge: false}, the result is a map from each taxonomy to its terms, which you can loop over with {% for taxonomy, terms in post.terms('all', {merge: false}) %}.

has_term​

Arguments:

  • term_name_or_id — Term name, slug, or ID
  • taxonomy — Taxonomy name (default: 'all')
{{ post.has_term('news') }}
{{ post.has_term('news', 'category') }}
{{ post.has_term(5, 'category') }}

Hierarchy​

children​

Arguments:

  • args — Post type to get, 'parent' for same type, or query array (default: 'any')

children returns a list: join it or loop over it.

{{ post.children|length }}
{{ post.children('page')|map(c => c.title)|join(', ') }}
{{ post.children('parent')|length }}
{{ post.children({post_type: 'page', orderby: 'title'})|map(c => c.title)|join(', ') }}

parent / next / prev​

These return false (not null) when there's no adjacent post — match against the value before chaining:

{{ post.parent.title }}
{{ post.next.title }}
{{ post.next(true) }} <!-- Same category -->
{{ post.next('genre') }} <!-- Same genre term -->
{{ post.prev.title }}
{{ post.prev(true) }}

Comments​

post.comments returns an iterable, chainable comment thread.

Arguments:

  • count — Number of comments (default: all)
  • order — 'ASC', 'DESC', or 'wp' for WP setting (default: 'wp')
  • type — Comment type (default: 'comment')
  • status — Comment status (default: 'approve')

'wp' follows Settings › Discussion, which shows the oldest comments first by default. Loop over the comments to display them:

{{ post.comments|length }}
{{ post.comments(5)|length }} <!-- First 5 in the Discussion order -->
{{ post.comments(10, 'DESC')|length }} <!-- Latest 10, newest first -->
{{ post.comments.order('DESC') }} <!-- Chainable order -->
{{ post.comments.orderby('comment_date') }} <!-- Chainable orderby -->
{{ post.comments.order('DESC').orderby('comment_date') }}
{{ post.comment_count }}
PII protection

Comment author email, IP address, and user agent are stripped before iteration — they're never available in templates. Only public-facing comment data (author name, content, date, etc.) is exposed.

Other Fields​

Arguments:

  • html — Return HTML galleries (default: true)

gallery returns the list of galleries found in the post content: their HTML by default, or with false one {ids, src} entry per gallery. Loop over it:

{% for gallery in post.gallery(false) %}
{{ gallery.src|length }} images
{% endfor %}

post_class​

Arguments:

  • class — Extra class(es) to add
{{ post.post_class }}
{{ post.post_class('custom-class') }}

Custom Fields (Meta)​

{{ post.meta('event_date') }}
{{ post.meta('address').city }}
{{ post.has_field('custom_field') }}
Plugin integration

meta('key') integrates with ACF, MetaBox, JetEngine, and Pods — the plugin filter resolves the value through those frameworks when active. Private meta keys (starting with _) are blocked for security.

Common Patterns​

Post card​

{{ post.title }}
{{ post.excerpt({words: 25}) }}
{{ post.date('F j, Y') }}
{{ post.author.name }}
{{ post.thumbnail.src('medium') }}

Custom field with fallback​

{{ post.meta('custom_title') ?: post.title }}
{{ post.meta('custom_excerpt') ?: post.excerpt }}

A missing custom field is an empty string, so ?: falls back where ?? wouldn't.

Post navigation​

{% if post.prev %}<a href="{{ post.prev.link }}">{{ post.prev.title }}</a>{% endif %}
{% if post.next %}<a href="{{ post.next.link }}">{{ post.next.title }}</a>{% endif %}

Taxonomy list​

{{ post.categories|map(c => c.name)|join(', ') }}
{{ post.tags|map(t => t.name)|join(', ') }}
{{ post.thumbnail ? post.thumbnail.src('large') : '/default.jpg' }}
{{ post.thumbnail.alt ?: post.title }}