Post Queries
Query WordPress posts for dynamic templates and content displays.
What This Guide Covers
Posts are the foundation of most WordPress sites - blog articles, news updates, case studies, product descriptions, and more. This guide shows you how to query WordPress posts using Builderius GraphQL for any content scenario.
You'll learn how to:
- Get current post data for single post templates
- Query multiple posts for archive pages and listings
- Filter posts by categories, tags, custom fields, and dates
- Work with custom post types (products, events, portfolios)
- Access custom fields from ACF and MetaBox
- Build related content sections and post relationships
- Handle pagination for large post collections
Query Single Post
- Current Post
- Specific Post
Get the post you're currently viewing:
{
post {
post_title
post_content
post_date
}
}
Get a post by ID, name or slug:
{
# Query by post ID (default identifier)
post(identifier: "ID", value: 123) { # Int - Post ID number
post_title
}
# Query by post slug
post(identifier: "slug", value: "about-us") { # String - Post slug/permalink
post_title
}
# Query by post name
post(identifier: "post_name", value: "about-us") { # String - Post name (typically same as slug)
post_title
}
}
Complete Post Fields Reference
Here's what's available when querying a post - all standard WordPress fields plus custom field integrations:
{
post {
# Basic Fields
ID
post_title
post_content
post_excerpt
post_date
post_datetime
post_modified_date
post_status
post_name
post_type
post_parent
permalink
guid
# Native WordPress Meta Fields
custom_price: meta_value(key: "_price")
featured_flag: meta_value(key: "_featured")
# All Meta Fields (returns array)
meta {
key
value
}
# Author Information
post_author {
ID
display_name
user_email
user_login
avatar_url
roles
description
}
# Featured Image
has_featured_image
featured_image {
title
alt_text
caption
description
thumb: file_url(size: THUMBNAIL)
medium: file_url(size: MEDIUM)
medium_large: file_url(size: MEDIUM_LARGE)
large: file_url(size: LARGE)
xl: file_url(size: SIZE_1536X1536)
xxl: file_url(size: SIZE_2048X2048)
original: file_url(size: ORIGINAL)
sizes
}
# Taxonomies
categories {
term_id
name
slug
description
count
}
tags {
term_id
name
slug
description
count
}
# Custom Taxonomy Terms
event_categories: terms_query(
arguments: {
taxonomy: "event_category"
object_ids: "{{ID}}"
}
) {
terms {
term_id
name
slug
description
count
}
}
# Comments
comments_open
comments {
ID
comment_author
comment_content
comment_date
comment_approved
}
# ACF Fields
price: acf_value(name: "price")
featured: acf_value(name: "featured")
gallery: acf_value(name: "gallery")
# ACF Relationship Fields
related_products: acf_post_objects_value(name: "related_products") {
ID
post_title
permalink
}
# ACF Repeater Fields
testimonials: acf_repeater_value(name: "testimonials") {
name: acf_value(name: "name")
quote: acf_value(name: "quote")
rating: acf_value(name: "rating")
}
# MetaBox Fields (Post Level)
sku: metabox_value(field_id: "sku")
product_specs: metabox_value(field_id: "product_specs")
# MetaBox Post Object Fields
manufacturer: metabox_post_value(field_id: "manufacturer") {
ID
post_title
website: metabox_value(field_id: "website")
}
}
}
Main Posts Loop
WordPress automatically provides the main query for each archive template. These are the default post loops available without any custom arguments - just the standard WordPress main query for each archive type.
- Blog Page
- Archives
- Search Results
Main blog page - automatically shows latest posts:
{
archive {
title
posts_query {
posts {
ID
post_title
post_excerpt
post_date
post_author {
display_name
avatar_url
}
featured_image {
file_url(size: MEDIUM)
alt_text
}
categories {
name
slug
}
tags {
name
slug
}
}
pagination {
links
current_page
total_pages
}
}
}
}
All archive pages - categories, tags, authors, dates, custom post types:
{
archive {
title
description
posts_query {
posts {
ID
post_title
post_excerpt
post_date
post_author {
display_name
avatar_url
}
featured_image {
file_url(size: MEDIUM)
alt_text
}
categories {
name
slug
}
tags {
name
slug
}
}
pagination {
links
current_page
total_pages
}
}
}
}
Search results page - posts matching search query:
{
archive {
title
description
posts_query {
posts {
ID
post_title
post_excerpt
post_date
post_type
post_author {
display_name
avatar_url
}
featured_image {
file_url(size: MEDIUM)
alt_text
}
categories {
name
slug
}
tags {
name
slug
}
}
pagination {
links
current_page
total_pages
}
}
}
}
Custom Post Queries
Custom post queries Pro feature let you manually specify exactly what content you want, with your own filtering and arguments. Unlike the main query (which WordPress generates automatically based on the current page), custom queries give you complete control.
Main Query vs Custom Query:
- Main Query (
archive.posts_query) - WordPress automatically decides what posts to show based on current page context - Custom Query (
posts_query(arguments: {...})) - You specify exactly what posts to fetch with custom arguments
- Default Posts
- Pages
- Custom Post Type
Recent posts with category filtering:
{
posts_query(
arguments: {
post_type: "post"
post_status: "publish"
posts_per_page: 6
orderby: "date"
order: "DESC"
}
) {
posts {
ID
post_title
post_excerpt
post_date
post_author {
display_name
avatar_url
}
featured_image {
file_url(size: MEDIUM)
alt_text
}
categories {
name
slug
}
}
pagination {
links
}
}
}
Specific pages ordered by menu order:
{
posts_query(
arguments: {
post_type: "page"
post_status: "publish"
posts_per_page: 10
orderby: "menu_order"
order: "ASC"
}
) {
posts {
ID
post_title
post_content
post_date
post_author {
display_name
}
featured_image {
file_url(size: LARGE)
alt_text
}
menu_order: meta_value(key: "menu_order")
}
}
}
Product listings with price and stock filtering:
{
posts_query(
arguments: {
post_type: "testimonial"
post_status: "publish"
posts_per_page: 12
order: "ASC"
}
) {
posts {
ID
post_title
post_excerpt
featured_image {
file_url(size: MEDIUM)
alt_text
}
}
pagination {
links
}
}
}
Query Arguments
Complete Arguments Reference
All arguments available for posts_query
{
posts_query(
arguments: {
# Post Type & Status
post_type: "post" # String/Array - Filter by post type
post_status: "publish" # String/Array - Filter by status
# Pagination & Limits
posts_per_page: 10 # Int - Number of posts to return (-1 for all)
offset: 5 # Int - Number of posts to skip from start
paged: 2 # Int - Page number for pagination
# Ordering
orderby: "date" # String - Sort field (date, title, menu_order, rand, meta_value)
order: "DESC" # String - Sort direction (DESC, ASC)
meta_key: "custom_order" # String - Meta key for meta_value ordering
# Include/Exclude Posts
post__in: [1, 5, 12] # Array - Include only these post IDs
post__not_in: [3, 7] # Array - Exclude these post IDs
# Author Filtering
author: 1 # Int - Posts by specific author ID
author__in: [1, 5, 12] # Array - Posts by any of these author IDs
author__not_in: [3, 7] # Array - Exclude posts by these author IDs
# Hierarchy
post_parent: 10 # Int - Posts with specific parent ID
post_parent__in: [10, 15] # Array - Posts with any of these parent IDs
post_parent__not_in: [5, 8] # Array - Exclude posts with these parent IDs
# Advanced Filtering
meta_query: { # Object - Filter by custom field values
array: [
{
key: "price"
value: 100
compare: ">"
}
]
}
tax_query: { # Object - Filter by taxonomy terms
array: [
{
taxonomy: "category"
field: "slug"
terms: ["news"]
}
]
}
date_query: { # Object - Filter by date ranges
array: [
{
after: "2024-01-01"
before: "2024-12-31"
}
]
}
search: "wordpress" # String - Search posts by keyword
}
) {
posts {
post_title
}
}
}
Basic Filtering
- By Post Type
- By Author
- Ordering
- Include/Exclude
Filter by specific post types:
{
posts_query(
arguments: {
post_type: "page"
}
) {
posts {
post_title
}
}
}
Filter by specific author:
{
posts_query(
arguments: {
author: 1
}
) {
posts {
post_title
}
}
}
Control post order and sorting:
{
posts_query(
arguments: {
orderby: "date" # date, title, menu_order, rand
order: "DESC" # DESC, ASC
}
) {
posts {
post_title
}
}
}
Include or exclude specific posts:
{
posts_query(
arguments: {
post__in: [1, 5, 12] # Only these posts
post__not_in: [3, 7] # Exclude these posts
}
) {
posts {
post_title
}
}
}
Filter by Taxonomy Terms
Filter posts using WordPress taxonomies like categories, tags, or custom taxonomies. Use tax_query to specify taxonomy filtering conditions.
- Single Category
- Multiple (AND)
- Multiple (OR)
- Exclude Terms
Posts from one specific category:
{
posts_query(
arguments: {
tax_query: {
array: [
{
taxonomy: "category"
field: "slug"
terms: ["news"]
operator: "IN"
}
]
}
}
) {
posts {
post_title
}
}
}
Posts that have BOTH specified category AND tag:
{
posts_query(
arguments: {
tax_query: {
relation: "AND"
array: [
{
taxonomy: "category"
field: "slug"
terms: ["tech"]
operator: "IN"
}
{
taxonomy: "post_tag"
field: "slug"
terms: ["tutorial"]
operator: "IN"
}
]
}
}
) {
posts {
post_title
}
}
}
Posts that have EITHER of the specified categories:
{
posts_query(
arguments: {
tax_query: {
relation: "OR"
array: [
{
taxonomy: "category"
field: "slug"
terms: ["news", "updates"]
operator: "IN"
}
]
}
}
) {
posts {
post_title
}
}
}
Posts that DON'T have specified categories:
{
posts_query(
arguments: {
tax_query: {
array: [
{
taxonomy: "category"
field: "slug"
terms: ["private"]
operator: "NOT IN"
}
]
}
}
) {
posts {
post_title
}
}
}
Filter by Custom Field Values
Filter posts based on custom field (meta) values. Use meta_query to specify conditions for ACF fields, MetaBox fields, or native WordPress meta.
- Single Condition
- Multiple (AND)
- Multiple (OR)
- Exclude Values
Posts with a specific meta field value:
{
posts_query(
arguments: {
meta_query: {
array: [
{
key: "featured"
value: true
compare: "="
}
]
}
}
) {
posts {
post_title
featured: acf_value(name: "featured")
}
}
}
Posts that meet BOTH meta field conditions:
{
posts_query(
arguments: {
meta_query: {
relation: "AND"
array: [
{
key: "featured"
value: true
compare: "="
}
{
key: "price"
value: 100
type: "NUMERIC"
compare: "<"
}
]
}
}
) {
posts {
post_title
featured: acf_value(name: "featured")
price: acf_value(name: "price")
}
}
}
Posts that meet EITHER meta field condition:
{
posts_query(
arguments: {
meta_query: {
relation: "OR"
array: [
{
key: "featured"
value: true
compare: "="
}
{
key: "on_sale"
value: true
compare: "="
}
]
}
}
) {
posts {
post_title
featured: acf_value(name: "featured")
on_sale: acf_value(name: "on_sale")
}
}
}
Posts that DON'T have specified meta values:
{
posts_query(
arguments: {
meta_query: {
array: [
{
key: "status"
value: "draft"
compare: "!="
}
]
}
}
) {
posts {
post_title
status: acf_value(name: "status")
}
}
}
Related Content Patterns
Find posts related to the current post based on different relationship types. These queries use the current post's data to find connected content.
- Same Categories
- Same Author
- Child Posts
Find posts that share categories with the current post:
{
post { # curent post
ID @private. # use ID to establish exclude this post
categories @private {
term_id # use terms to base relation on
}
related_posts: posts_query(
arguments: {
posts_per_page: 5
post__not_in: "{{ID}}"
tax_query: {
array: [
{
taxonomy: "category"
field: "term_id"
terms: "{{pluck(categories, 'term_id')}}" # posts that share the current post terms
operator: "IN"
}
]
}
}
) {
posts {
post_title
post_excerpt
}
}
}
}
Find other posts by the same author as the current post:
{
post { # current post
ID @private # exclude current post from list
post_author @private {
ID
}
author_posts: posts_query(
arguments: {
author: "{{post_author.ID}}" # same author as current post
post__not_in: "{{ID}}"
posts_per_page: 5
}
) {
posts {
post_title
post_date
}
}
}
}
Find posts that are children of the current post (hierarchical):
{
post { # current post
ID @private # establish relation
child_posts: posts_query(
arguments: {
post_parent: "{{ID}}" # current post ID is parent ID
orderby: "menu_order"
posts_per_page: 10
}
) {
posts {
post_title
post_excerpt
}
}
}
}
Pagination
Handle pagination for post listings, whether using WordPress default archive pagination or custom query pagination.
- Archive Pagination
- Custom Pagination
Standard pagination for WordPress archives (automatic):
{
archive {
posts_query {
posts {
post_title
}
pagination {
links
current_page
total_pages
}
}
}
}
Pagination for custom post queries (with URL parameter):
{
posts_query(
arguments: {
posts_per_page: 10
}
) {
posts {
post_title
}
has_pagination
pagination(
arguments: {
pagination_url_param_name: "blog_page"
}
) {
links
current_page
total_pages
}
posts_count
}
}
Advanced Filtering
Combine multiple filtering methods for complex queries. These examples show how to layer date ranges, custom field conditions, and taxonomy filters together.
- Date Ranges
- Multiple Meta Conditions
- Combined Filters
Filter posts by publication date ranges:
{
posts_query(
arguments: {
date_query: {
array: [
{
after: "2024-01-01"
before: "2024-12-31"
inclusive: true
}
]
}
}
) {
posts {
post_title
post_date
}
}
}
Filter using multiple custom field conditions (price range + featured status):
{
posts_query(
arguments: {
meta_query: {
relation: "AND"
array: [
{
key: "price"
value: [100, 500]
type: "NUMERIC"
compare: "BETWEEN"
}
{
key: "featured"
value: true
compare: "="
}
]
}
}
) {
posts {
post_title
price: acf_value(name: "price")
}
}
}
Combine taxonomy filtering with custom field filtering:
{
posts_query(
arguments: {
tax_query: {
array: [
{
taxonomy: "product_category"
field: "slug"
terms: ["electronics"]
operator: "IN"
}
]
}
meta_query: {
array: [
{
key: "in_stock"
value: true
compare: "="
}
]
}
}
) {
posts {
post_title
price: acf_value(name: "price")
stock: acf_value(name: "in_stock")
}
}
}
Performance Tips
Optimize your queries for better performance by using these techniques to reduce data transfer and processing time.
- Use @private Fields
- Limit Data
- Efficient Ordering
Use @private to query data you need for variables but don't want in output:
{
post {
ID @private # Hidden from output, available for {{ID}}
post_title
categories @private { # Get categories privately
term_id
}
related_posts: posts_query(
arguments: {
post__not_in: ["{{ID}}"] # Uses hidden ID
}
) {
posts {
post_title
}
}
}
}
Only fetch the fields and posts you actually need:
{
posts_query(
arguments: {
posts_per_page: 12 # Don't fetch more than needed
post_status: "publish" # Only published posts
}
) {
posts {
post_title # Only fields you'll use
post_excerpt
featured_image {
file_url(size: MEDIUM) # Specific image size
}
}
}
}
Use efficient ordering methods for better performance:
{
posts_query(
arguments: {
orderby: "date" # Efficient: date, menu_order
# orderby: "rand" # Expensive: avoid for large datasets
order: "DESC"
}
) {
posts {
post_title
}
}
}
Common Use Cases
Real-world examples of post queries you'll commonly need. These patterns cover the most frequent scenarios for displaying WordPress content.
- Homepage Featured
- Posts with Terms
- Terms with Posts
Homepage featured posts selection based on custom field:
{
posts_query(
arguments: {
meta_query: {
array: [
{
key: "featured_on_homepage" # Custom field name
value: true # Field must be true
compare: "=" # Exact match
}
]
}
posts_per_page: 3 # Limit to 3 posts
}
) {
posts {
post_title
post_excerpt
featured_image {
file_url(size: MEDIUM) # Medium size thumbnail
alt_text
}
permalink # Full URL to post
}
}
}
Posts with their taxonomy terms (categories, tags, custom taxonomies):
{
posts_query(
arguments: {
post_type: "post" # Blog posts only
posts_per_page: 12 # 12 posts per page
}
) {
posts {
post_title
post_excerpt
featured_image {
file_url(size: MEDIUM)
alt_text
}
post_categories: terms_query( # Get categories for each post
arguments: {
taxonomy: "category" # WordPress categories
object_ids: "{{ID}}" # For this specific post
}
) {
terms {
name
slug
}
}
}
}
}
Categories with their recent posts nested inside:
{
terms_query(
arguments: {
taxonomy: "category" # Get all categories
hide_empty: true # Only categories with posts
}
) {
terms {
term_id
name
recent_posts: posts_query( # Nested posts query for each category
arguments: {
posts_per_page: 5 # 5 recent posts per category
tax_query: {
array: [
{
taxonomy: "category"
field: "term_id"
terms: "{{term_id}}" # Posts in this category
operator: "IN"
}
]
}
}
) {
posts {
post_title
post_excerpt
featured_image {
file_url(size: THUMBNAIL) # Small thumbnail for nested display
alt_text
}
}
}
}
}
}