# Builderius GraphQL Schema Documentation - V1 (beta-public)
# About This Document
This is a comprehensive reference guide for [Builderius](https://builderius.io) GraphQL - a custom query language for WordPress data. **This document is primarily designed to train AI systems** (like Claude, ChatGPT, etc.) to write correct GraphQL queries for you. We have tried to check this entire document for errors. However, errors happen, so if you find any please leave a comment in this document (you need a free notion account) or write to [support@builderius.io](mailto:support@builderius.io)
## How to Use This Guide
**For AI Training:**
Upload this entire document to your AI assistant, then ask it to write specific GraphQL queries. The AI will use this reference to generate accurate, working code that follows Builderius's unique syntax rules.
## What You'll Find Here
- Complete syntax rules and examples
- Field references for posts, users, terms, and custom fields
- Common query patterns and advanced techniques
- What works and what doesn't (important - this isn't standard GraphQL)
## Example Prompts for Better Results
After uploading this document to your AI assistant, use these prompt patterns to get the best GraphQL queries:
### Basic Data Requests
> Write a GraphQL query to get the 10 most recent blog posts with title, excerpt, featured image, and publication date.
>
> I need a query that shows all users with the 'author' role, including their name, email, and profile photo.
>
> Get all product categories with their names, descriptions, and post counts.
>
---
### Specific Requirements
> Create a query for an events page that shows upcoming events (after today's date) with event title, date, location (ACF field), and featured image. Limit to 12 events.
>
> I need related posts for the current post - same category, exclude current post, limit to 6 posts with title and excerpt.
>
> Query all products under $100 that are in stock, showing title, price, SKU (MetaBox field), and thumbnail image.
>
---
### Troubleshooting & Optimization
> This query isn't working: [paste your query]. Can you fix it and explain what was wrong?
>
> My query is too slow. Can you optimize this and add @private fields where appropriate?
>
> I'm getting an error about data variables. Can you check the scope in this query?
>
---
### Best Practices for Prompting
- **Be specific** about what data you need and where it comes from (ACF, MetaBox, standard WordPress fields)
- **Mention context** (single post page, archive, homepage, etc.)
- **Include pagination requirements** if you need it
- **Specify limits** (how many posts, users, etc.)
- **Ask for explanations** when you want to understand the query structure
- **Provide error messages** when troubleshooting broken queries
---
# Getting Started
## Syntax Fundamentals
Builderius GraphQL uses a **custom implementation** with WordPress-specific syntax. This is NOT standard GraphQL - it’s a specialized query language designed for WordPress data.
**Key Syntax Rules:**
1. **Data variables:** Use `"{{field_name}}"` for local context, `"[[globalVar]]"` for global
2. **Multiple same-field calls:** Always use aliases
3. **Query field before referencing:** Mark private with `@private` if not displaying
4. **MetaBox fields:** Include `option_name` only for root-level settings pages
5. **URL helpers:** Only work at root level, use `php_function_output` in loops
6. **Custom taxonomies:** Use `terms_query` approach, not direct fields
**Arguments Structure:**
All query functions use an `arguments` object to pass parameters:
```graphql
posts_query(
arguments: {
post_type: "post"
post_status: "publish"
posts_per_page: 10
}
) {
posts {
ID
post_title
}
}
```
### GraphQL Aliases
Aliases allow you to call the same field multiple times with different parameters or rename fields for clarity.
**When Aliases Are Required:**
Multiple calls to the same field will cause errors without aliases:
```graphql
# ❌ Wrong - same field called multiple times
featured_image {
file_url(size: THUMBNAIL)
file_url(size: MEDIUM)
file_url(size: LARGE)
}
# âś… Correct - use aliases
featured_image {
thumb: file_url(size: THUMBNAIL)
medium: file_url(size: MEDIUM)
large: file_url(size: LARGE)
}
```
```graphql
# ❌ Wrong - multiple ACF calls without aliases
posts_query {
posts {
acf_value(name: "price")
acf_value(name: "sale_price")
acf_value(name: "member_price")
}
}
# âś… Correct - use aliases
posts_query {
posts {
regular_price: acf_value(name: "price")
sale_price: acf_value(name: "sale_price")
member_price: acf_value(name: "member_price")
}
}
```
```graphql
posts_query {
posts {
# Optional aliases for cleaner naming
title: post_title
content: post_content
published: post_date
author_name: post_author {
display_name
}
}
}
```
### Common GraphQL Errors and Prevention
GraphQL errors are based on schema validation. Here are the most common error patterns:
**Missing Required Arguments:**
```graphql
# ❌ Error - missing required 'name' argument
acf_value()
# âś… Correct - provide required argument
acf_value(name: "field_name")
```
**Non-Existent Sub-Fields:**
```graphql
# ❌ Error - 'fake_field' doesn't exist on Post
posts_query {
posts {
ID
fake_field
}
}
# âś… Correct - use valid fields from schema
posts_query {
posts {
ID
post_title
}
}
```
**String Arguments Must Be Single Line:**
```graphql
# ❌ Error - multiline strings not allowed
expression_result(
expression: "function1() &&
function2()"
)
# âś… Correct - keep on single line
expression_result(
expression: "function1() && function2()"
)
```
**No Spaces in Aliases:**
```graphql
# ❌ Error - spaces in alias names
posts_query {
posts {
blog title: post_title # Space in alias
main content: post_content
}
}
# âś… Correct - use underscores or camelCase
posts_query {
posts {
blog_title: post_title
mainContent: post_content
}
}
```
## Data Variables and Context
### Local Data Variables
Use `"{{localDataVar}}"` syntax to reference data from the current context:
- `"{{ID}}"` - Current post/user/term ID
- `"{{post_author.ID}}"` - Current post’s author ID
- `"{{term_id}}"` - Current term ID
Example:
```graphql
post {
ID @private
related_posts: posts_query(
arguments: {
post_type: "post"
posts_per_page: 6
post__not_in: ["{{ID}}"]
}
) {
posts {
ID
post_title
}
}
}
```
### Global Data Variables
Use `"[[globalDataVar]]"` syntax to reference global context data.
### Expression Language Functions
### String Functions
- `upper(string)` - Uppercase string
- `lower(string)` - Lowercase string
- `count(string)` - Count characters in string
- `limit_words(string, count)` - Limit string to specified word count
- `limit_characters(string, count)` - Limit string to specified character count
- `includes(string, substring)` - Check if string contains substring
- `escape(string)` - Escape HTML characters
- `match(string, pattern)` - Match string against regex pattern
- `strtotime(string)` - Convert date string to timestamp
- `floatval(string)` - Convert to float
- `intval(string)` - Convert to integer
### Array Functions
- `join(array, separator)` - Join array elements
- `pluck(array, key)` - Extract values from array of objects
- `count(array)` - Count elements
- `filter(array, callback)` - Filter array elements
- `foreach(array, callback)` - Transform array elements
- `merge(object1, object2)` - Merge objects
- `split(string, delimiter)` - Split string into array
- `serialize(array)` / `unserialize(string)` - Serialize/unserialize data
- `findIndex(array, callback)` - Find index of element
- `includes(array, value)` - Check if array contains value
- `isset(array, key)` - Check if array key exists
- `joinKeys(array)` / `joinValues(array)` - Join array keys or values
- `push(array, value)` - Add element to array end
- `unshift(array, value)` - Add element to array beginning
- `rsort(array)` / `sort(array)` / `usort(array, callback)` - Sort arrays
- `set(array, key, value)` / `unset(array, key)` - Set/unset array values
- `sum(array)` - Sum numeric array values
### Arithmetic Functions
- `ceil(number)` - Round up to nearest integer
- `floor(number)` - Round down to nearest integer
- `min(array)` / `max(array)` - Find minimum/maximum values
- `round(number, precision)` - Round to specified precision
### Boolean Functions
- `is_email(string)` / `isEmail(string)` - Validate email format
- `is_empty(value)` - Check if value is empty
- `is_url(string)` - Validate URL format
- `is_numeric(value)` - Check if value is numeric
- `is_json(string)` - Check if string is valid JSON
- `is_int(value)` / `is_float(value)` - Check number types
### Multilingual Functions
- `translate(key, textdomain)` - Get translation for key
## Special Directives (@private, @recursive, @transform)
### `@private`
Marks field as private (not rendered in output):
```graphql
post {
ID @private
post_title
}
```
### `@recursive`
Enables recursive field querying:
```graphql
nav_menu(identifier: "slug", value: "main-menu") {
items {
ID
title
children @recursive(depth: 5) {
ID
title
url
}
}
}
```
### @recursive Limitations
**Default Behavior:**
- Default depth: 10 nested levels
- Configurable limit (can be adjusted)
- **Important:** GraphQL itself has no native recursion - this is a Builderius-specific directive
### `@transform`
Transform field value using Expression Language:
```graphql
posts_query {
posts {
post_title
post_date @transform(expression: "date('F j, Y', strtotime(post_date))")
}
}
```
## Critical Limitations and Anti-Patterns
### ❌ Don’t Use WPGraphQL style Syntax
**This is NOT standard GraphQL** - it’s Builderius’s custom implementation with WordPress-specific syntax:
**WPGraphQL patterns DON’T work:**
```graphql
query {
posts(where: {status: "publish"}) {
edges {
node {
title
content
}
}
}
}
```
**WPGraphQL variables DON’T work:**
```graphql
query GetPosts($postType: String!) {
posts(postType: $postType) { ... }
}
```
**GraphQL fragments DON’T work:**
```graphql
fragment PostFields on Post {
title
content
}
```
### ❌ Don’t Use These Patterns
**Non-existent fields:**
```graphql
# These don't exist
queried_post # Use post without arguments instead
queried_term # Use archive.term instead
queried_user # Use current_user instead
```
**Wrong MetaBox syntax:**
```graphql
# Wrong - using old metabox_option_value syntax
metabox_option_value(field_id: "contact_email")
# Wrong - missing option_name for root level
metabox_value(field_id: "contact_email")
# Wrong - including option_name for post level
post {
price: metabox_value(field_id: "price", option_name: "settings")
}
```
**URL helpers in loops:**
```graphql
# Won't work - URL helpers don't work in loops
terms_query {
terms {
category_url: category_archive_url(slug: "{{slug}}") # ❌
}
}
```
### âś… Correct Patterns
**Use context-aware queries:**
```graphql
# For current post context
post { ... }
# For archive context
archive { ... }
# For current user
current_user { ... }
```
**Correct MetaBox syntax:**
```graphql
# Root level - include option_name with metabox_value
metabox_value(field_id: "contact_email", option_name: "site_settings")
# Post level - exclude option_name
post {
price: metabox_value(field_id: "price")
}
```
**Use PHP functions for URLs in loops:**
```graphql
terms_query {
terms {
category_url: php_function_output(
function: "get_category_link"
arguments: ["{{term_id}}"]
)
}
}
```
# Core Query Types
## Post Queries
### posts_query - Basic Examples
Query posts with flexible filtering and pagination.
**Arguments:**
- `post_type` (MixedOrDataVar) - Post type slug
- `post_status` (MixedOrDataVar) - Post status
- `posts_per_page` (IntOrDataVar) - Number of posts
- `meta_query` (WP_Meta_Query) - Custom field filtering
- `tax_query` (WP_Tax_Query) - Taxonomy query filtering
- `orderby` (StringOrDataVar) - Order by field
- `order` (StringOrDataVar) - ASC or DESC
- `author` (IntOrDataVar) - Author ID
- `post__in` (ArrayOrDataVar) - Include specific post IDs
- `post__not_in` (ArrayOrDataVar) - Exclude specific post IDs
- `meta_key` (StringOrDataVar) - Meta key for filtering
- `meta_value` (StringOrDataVar) - Meta value for filtering
**Returns:** `PostsQuery` object
**Example - Basic Posts Loop:**
This code fetches posts using `posts_query` with basic arguments. It limits results to 10 posts per page, orders by publication date newest first, and shows only published posts. Returns each post's ID, title, excerpt, content, publication date, and featured image with URL and alt text. Includes pagination controls and total post count.
```graphql
posts_query(
arguments: {
post_type: "post"
post_status: "publish"
posts_per_page: 10
orderby: "date"
order: "DESC"
}
) {
posts {
ID
post_title
post_excerpt
post_content
post_date
featured_image {
file_url
alt_text
}
}
has_pagination
pagination(
arguments: {
pagination_url_param_name: "posts_page"
}
) {
links
}
posts_count
}
```
### posts_query - Advanced Filtering
**Example - Posts with Meta Query (Custom Fields):**
This code fetches "product" post type and uses `meta_query` filtering with "AND" relation. Filters posts where "featured" custom field equals true (boolean type) and "price" is between 100-500 (numeric type). Orders by price value ascending using `meta_value_num` with `meta_key`. Returns ACF fields for price, featured, and sku.
```graphql
posts_query(
arguments: {
post_type: "product"
post_status: "publish"
posts_per_page: 10
meta_query: {
relation: "AND"
array: [
{
key: "featured"
value: true
compare: "="
type: "BOOLEAN"
}
{
key: "price"
value: [100, 500]
compare: "BETWEEN"
type: "NUMERIC"
}
]
}
orderby: "meta_value_num"
meta_key: "price"
order: "ASC"
}
) {
posts {
ID
post_title
post_excerpt
price: acf_value(name: "price")
featured: acf_value(name: "featured")
sku: acf_value(name: "sku")
}
posts_count
}
```
**Example - Posts with Tax Query (Taxonomy Filtering):**
This code fetches "event" post type and uses `tax_query` filtering with "AND" relation. Filters posts that are in "conference" or "workshop" categories ("IN" operator) but excludes "online" location ("NOT IN" operator). Includes nested `terms_query` to get event categories for each post. The `{{ID}}` data variable passes the current post's ID to `object_ids`, which filters terms to only those assigned to that specific post.
```graphql
posts_query(
arguments: {
post_type: "event"
post_status: "publish"
posts_per_page: 12
tax_query: {
relation: "AND"
array: [
{
taxonomy: "event_category"
field: "slug"
terms: ["conference", "workshop"]
operator: "IN"
}
{
taxonomy: "event_location"
field: "slug"
terms: ["online"]
operator: "NOT IN"
}
]
}
orderby: "date"
order: "DESC"
}
) {
posts {
ID
post_title
post_excerpt
post_date
event_date: acf_value(name: "event_date")
# Get event categories for this post
event_categories: terms_query(
arguments: {
taxonomy: "event_category"
object_ids: ["{{ID}}"]
}
) {
terms {
name
slug
}
}
}
posts_count
}
```
### post - Single Post Access
**Example - Current Post Context:**
This code fetches current post without arguments and creates related posts using nested `posts_query`. Uses `@private` directive on ID field to hide it from output while making it available for data variable. Excludes current post from related results using `post__not_in: ["{{ID}}"]` argument.
```graphql
post {
ID @private
post_title
related_posts: posts_query(
arguments: {
post_type: "post"
posts_per_page: 6
post__not_in: ["{{ID}}"]
}
) {
posts {
ID
post_title
post_excerpt
}
}
}
```
Get single post by identifier.
**Arguments:**
- `identifier` (StringOrDataVar) - “ID” or “slug” (default: “ID”)
- `value` (MixedOrDataVar) - The actual ID or slug value
**Returns:** `Post` object
**Example - Single Post:**
This code fetches a specific post by slug ("about-us" page) using `post` function with `identifier: "slug"` and `value: "about-us"`. Use this to get any specific post from anywhere on the site. Returns the post's basic fields plus ACF field for contact form shortcode.
```graphql
post(identifier: "slug", value: "about-us") {
ID
post_title
post_content
post_date
featured_image {
file_url
alt_text
}
contact_form: acf_value(name: "contact_form_shortcode")
}
```
## User Queries
### users_query
Query users with filtering options.
**Arguments:**
- `role` (StringOrDataVar) - User role
- `include` (ArrayOrDataVar) - Include specific user IDs
- `exclude` (ArrayOrDataVar) - Exclude specific user IDs
- `search` (StringOrDataVar) - Search term
- `number` (IntOrDataVar) - Number of users
- `offset` (IntOrDataVar) - Offset for pagination
- `order` (StringOrDataVar) - ASC or DESC
- `orderby` (StringOrDataVar) - Order by field
**Returns:** `UsersQuery` object
### user and current_user
**`user`** - Get single user by identifier.
**Arguments:**
- `identifier` (StringOrDataVar) - “ID”, “slug”, “email”, or “login” (default: “ID”)
- `value` (MixedOrDataVar!) - The actual identifier value
**Returns:** `User` object
**Example - Specific User:**
This code fetches a specific user by ID (user 1) using `user` function with `identifier: "ID"` and `value: 1`. Returns user fields including nickname, email, login, description, roles array, plus ACF field for custom_field.
```graphql
user(identifier: "ID", value: 1) {
ID
nickname
user_email
user_login
description
roles
custom_field: acf_value(name: "custom_field")
}
```
**`current_user`** - Get currently logged-in user.
**Returns:** `User` object
## Taxonomy and Term Queries
### terms_query
Query taxonomy terms.
**Arguments:**
- `taxonomy` (StringOrDataVar) - Taxonomy name
- `hide_empty` (BooleanOrDataVar) - Hide empty terms
- `include` (ArrayOrDataVar) - Include specific term IDs
- `exclude` (ArrayOrDataVar) - Exclude specific term IDs
- `object_ids` (ArrayOrDataVar) - Filter terms by object IDs
- `name` (ArrayOrDataVar) - Term names
- `slug` (ArrayOrDataVar) - Term slugs
- `number` (IntOrDataVar) - Number of terms
- `offset` (IntOrDataVar) - Offset for pagination
- `orderby` (StringOrDataVar) - Order by field
- `order` (StringOrDataVar) - ASC or DESC
**Returns:** `TermsQuery` object
### term - Single Term Access
Get single term by identifier.
**Arguments:**
- `identifier` (StringOrDataVar) - “term_id”, “term_taxonomy_id”, “slug”, or “name”
- `value` (MixedOrDataVar!) - The actual identifier value
- `taxonomy` (StringOrDataVar!) - Taxonomy name
**Returns:** `Term` object
## Navigation and Menu Queries
### nav_menu and primary_nav_menu
**`nav_menu`** - Get navigation menu by identifier.
**Arguments:**
- `identifier` (StringOrDataVar) - “ID”, “slug”, or “name” (default: “ID”)
- `value` (MixedOrDataVar!) - The actual identifier value
**Returns:** `NavMenu` object
**Example - Recursive Menu:**
This code fetches navigation menu by its name ("Main Navigation") using `nav_menu` function. Returns menu items with ID, title, description, classes, URL, and ACF field. Uses `@recursive` directive on `children` field to get nested submenu items with unlimited depth.
```graphql
nav_menu(
identifier: "name"
value: "Main Navigation"
) {
items {
ID
title
description
classes
url
acf_value(name: "field_name")
children @recursive {
ID
title
url
classes
description
}
}
}
```
**`primary_nav_menu`** - Get the primary navigation menu.
**Returns:** `NavMenu` object
### NavMenuItem Fields
Navigation menu items have extensive field coverage for building complex menu structures with custom functionality.
### H4 Standard NavMenuItem Fields
- `ID` (int) - Menu item ID
- `title` (string) - Menu item display text (most commonly used)
- `url` (string) - Link URL for the menu item
- `description` (string) - Menu item description (if set)
- `classes` (string) - CSS classes assigned to menu item
- `target` (string) - Link target (`_blank`, `_self`, etc.)
- `attr_title` (string) - Title attribute for the link
- `db_id` (int) - Database ID of menu item
- `menu_item_parent` (int) - Parent menu item ID
- `post_parent` (int) - WordPress post parent ID
- `post_title` (string) - Original post/page title
- `object` (string) - Object type (post, page, category, custom, etc.)
- `object_id` (int) - ID of the linked object
- `type` (string) - Menu item type
- `type_label` (string) - Human-readable type label
- `xfn` (string) - XFN relationship attributes
### H4 NavMenuItem Relationships
- `parent` - Parent NavMenuItem object
- `children` - Array of child NavMenuItem objects
- `nav_menu` - Parent NavMenu object
- `meta` - Array of Meta objects for menu item meta fields
- `meta_value(key: StringOrDataVar!)` - Get specific menu item meta value
### Complete NavMenuItem Examples
**Detailed Menu Structure**
This code fetches navigation menu by its name and returns detailed menu item fields including target, attr_title, object, object_id, type, and type_label. Shows explicit parent-child relationships with `parent` object containing ID, title, URL, and `menu_item_parent` field for hierarchy reference.
```graphql
nav_menu(identifier: "name", value: "Main Navigation") {
items {
ID
title
url
description
classes
target
attr_title
object
object_id
type
type_label
# Relationship info
menu_item_parent
parent {
ID
title
url
}
# Child menu items
children @recursive {
ID
title
url
classes
target
description
object
type
}
}
}
```
Menu with Custom Fields and Meta
This code fetches navigation menu by its slug ("header-menu") and adds custom meta fields using `meta_value` with key parameter. Introduces `expression_result` for computed values using conditional logic - `has_children` checks if children count is greater than 0, and `is_external` detects external URLs by checking for "http" but excluding site URL.
```graphql
nav_menu(identifier: "slug", value: "header-menu") {
items {
ID
title
url
classes
description
# ACF fields on menu items
menu_icon: acf_value(name: "menu_icon")
highlight_item: acf_value(name: "highlight_item")
mega_menu_content: acf_value(name: "mega_menu_content")
# Custom meta fields
custom_color: meta_value(key: "menu_color")
badge_text: meta_value(key: "badge_text")
# Enhanced display data
has_children: expression_result(
expression: "count(children) > 0 ? true : false"
)
is_external: expression_result(
expression: "includes(url, 'http') && !includes(url, site_url()) ? true : false"
)
children @recursive {
ID
title
url
classes
menu_icon: acf_value(name: "menu_icon")
}
}
}
```
## Archive Queries
### archive - Archive Context
Get archive context (for archive pages).
**Returns:** `Archive` object
**Example - Archive Page:**
This code fetches archive context using `archive` function and returns title, description, and type fields. Shows nested object access with `post_author { display_name }` to get specific user field. Demonstrates multiple taxonomy arrays with `categories` and `tags` returning name and slug for each.
```graphql
archive {
title
description
type
posts_query {
posts {
ID
post_title
post_excerpt
post_content
post_date
post_author {
display_name
}
categories {
name
slug
}
tags {
name
slug
}
}
}
}
```
### Complete Archive Context Fields
The Archive object provides comprehensive context information for all types of archive pages in WordPress.
### Standard Archive Fields
- `title` (string) - Archive page title
- `description` (string) - Archive description text
- `type` (string) - Archive type (category, tag, author, date, search, etc.)
- `search_keyword` (string) - Search term for search result archives
- `term` (Term) - Term object for taxonomy archives
- `author` (User) - Author object for author archives
- `posts_query` (ArchivePostsQuery) - Posts in this archive
**Author Archive Context**
This code fetches archive context for author archives with detailed author object including user metadata. Uses comparison operator `==` in expressions to verify post authorship.
```graphql
archive {
title
description
type
author {
ID
display_name
user_login
description
avatar_url
user_url
roles
# Author metadata
first_name
last_name
user_email
}
# Author's posts
posts_query {
posts {
ID
post_title
post_excerpt
post_date
post_type
# Verify authorship
is_by_author: expression_result(
expression: "post_author.ID == author.ID ? 'Yes' : 'No'"
)
}
posts_count
has_pagination
pagination {
current_page
total_pages
links
}
}
}
```
**Search Results Context**
This code fetches archive context for search results and introduces `lower()` function for case-insensitive string comparison and `count()` function to get string length. Shows complex string concatenation with quoted text using escaped quotes `\"` in expressions. Uses conditional logic to detect search term presence in content vs title/meta and builds dynamic result summaries with post counts.
```graphql
archive {
title
description
type
search_keyword
# Search context information
search_info: expression_result(
expression: "search_keyword ? 'Searching for: ' . search_keyword : 'No search term'"
)
search_term_length: expression_result(
expression: "count(search_keyword)"
)
# Search results
posts_query {
posts {
ID
post_title
post_excerpt
post_content
post_type
post_date
# Highlight search term in title
highlighted_title: expression_result(
expression: "includes(lower(post_title), lower(search_keyword)) ? post_title : post_title"
)
# Check if search term is in content
has_search_term: expression_result(
expression: "includes(lower(post_content), lower(search_keyword)) ? 'Found in content' : 'Found in title/meta'"
)
}
posts_count
has_pagination
pagination {
current_page
total_pages
links
}
}
# Search statistics
search_results_summary: expression_result(
expression: "posts_query.posts_count > 0 ? 'Found ' . posts_query.posts_count . ' results for \"' . search_keyword . '\"' : 'No results found for \"' . search_keyword . '\"'"
)
}
```
**Date Archive Context**
This code fetches archive context for date archives and introduces `date()` function for formatting dates with format strings like 'F j, Y' (full month, day, year) and 'F Y' (month, year only). Uses `strtotime()` function to parse date strings before formatting. Shows simple expression that just references existing field value in `archive_period`.
```graphql
archive {
title
description
type
# Date archive posts
posts_query {
posts {
ID
post_title
post_excerpt
post_date
post_author {
display_name
}
# Date formatting
formatted_date: expression_result(
expression: "date('F j, Y', strtotime(post_date))"
)
month_year: expression_result(
expression: "date('F Y', strtotime(post_date))"
)
}
posts_count
has_pagination
pagination {
current_page
total_pages
links
}
}
# Date archive summary
archive_period: expression_result(
expression: "title"
)
}
```
# Field Reference
## Post Fields
### Standard Post Fields
- `ID` (int) - Post ID
- `post_author` (User) - Author User object
- `post_date` (string) - Publication date (formatted by default)
- `post_datetime` (string) - Publication datetime
- `post_content(raw: BooleanOrDataVar)` (string) - Post content
- `post_title` (string) - Post title
- `post_excerpt` (string) - Post excerpt
- `post_status` (string) - Post status
- `post_name` (string) - Post slug
- `post_modified_date` (string) - Last modified date
- `post_parent` (int) - Parent post ID
- `post_type` (string) - Post type
- `permalink` (string) - Full post URL
- `guid` (string) - Global unique identifier
### Media Fields
- `has_featured_image` (boolean) - Whether post has featured image
- `featured_image(size: ThumbnailSize)` - Featured image object
### Complete FeaturedImage Field Coverage
The FeaturedImage object provides comprehensive metadata beyond the commonly used `file_url` and `alt_text` fields.
**All FeaturedImage Fields**
- `title` (string) - Image title/filename
- `alt_text` (string) - Alt text for accessibility
- `caption` (string) - Image caption text
- `description` (string) - Image description
- `file_url(size: ThumbnailSize)` (string) - Image URL at specified size
- `sizes` (Json) - Complete size information object
**Basic FeaturedImage Usage**
This code demonstrates featured image object structure with complete field coverage including title, alt_text, caption, description, file_url, and sizes. Introduces `has_featured_image` boolean field and field aliasing to get same `file_url` with different size parameters (THUMBNAIL, MEDIUM, LARGE, ORIGINAL).
```graphql
posts_query {
posts {
ID
post_title
has_featured_image
featured_image {
# Complete field coverage
title
alt_text
caption
description
file_url
sizes
# Multiple sizes
thumbnail: file_url(size: THUMBNAIL)
medium: file_url(size: MEDIUM)
large: file_url(size: LARGE)
original: file_url(size: ORIGINAL)
}
}
}
```
**Image Metadata Analysis**
This code demonstrates metadata validation using empty string checking with `!= ''` operator combined with existence checks. Uses multiple logical operators in single expressions - `&&` for required conditions and `||` for alternative options in `content_richness` field that checks if both caption AND description exist, or either one exists, or neither.
```graphql
posts_query {
posts {
ID
post_title
featured_image {
title
alt_text
caption
description
sizes
# Metadata completeness check
has_alt_text: expression_result(
expression: "alt_text && alt_text != '' ? 'Yes' : 'No'"
)
has_caption: expression_result(
expression: "caption && caption != '' ? 'Yes' : 'No'"
)
has_description: expression_result(
expression: "description && description != '' ? 'Yes' : 'No'"
)
# SEO readiness
seo_ready: expression_result(
expression: "alt_text && alt_text != '' ? 'SEO Ready' : 'Missing Alt Text'"
)
# Content richness
content_richness: expression_result(
expression: "caption && description ? 'Rich' : (caption || description ? 'Partial' : 'Basic')"
)
}
}
}
```
**Image Sizes and Responsive Images**
This code shows additional image size constants including MEDIUM_LARGE, SIZE_1536X1536, and SIZE_2048X2048. Uses field aliases within expressions - `responsive_setup` references the aliased fields (thumb, medium, large, xl) to create breakpoint object with `merge()`. Shows simple existence check with `sizes ?` for conditional messaging.
```graphql
posts_query {
posts {
ID
post_title
featured_image {
title
alt_text
sizes
# All available sizes
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)
# Responsive image setup
responsive_setup: expression_result(
expression: "merge({'mobile': thumb, 'tablet': medium, 'desktop': large, 'retina': xl})"
)
# Size information from JSON
size_info: expression_result(
expression: "sizes ? 'Multiple sizes available' : 'Size data unavailable'"
)
}
}
}
```
**Accessibility and SEO Optimization**
This code demonstrates range checking using `count()` function with multiple conditions `> 10 && < 125` for accessibility scoring. Introduces `filter()` function with arrow function syntax `(field) -> { field && field != '' }` to count non-empty fields. Uses negation operator `!` in expressions like `!alt_text` for negative conditions and complex nested conditionals with multiple logical operators for optimization suggestions.
```graphql
posts_query {
posts {
ID
post_title
featured_image {
title
alt_text
caption
description
file_url(size: MEDIUM)
# Accessibility compliance
accessibility_score: expression_result(
expression: "alt_text && alt_text != '' ? (count(alt_text) > 10 && count(alt_text) < 125 ? 'Excellent' : 'Good') : 'Poor'"
)
# SEO optimization
seo_optimization: expression_result(
expression: "merge({'has_alt': alt_text ? true : false, 'has_title': title ? true : false, 'has_caption': caption ? true : false, 'descriptive': description ? true : false})"
)
# Content completeness
metadata_completeness: expression_result(
expression: "count(filter([title, alt_text, caption, description], (field) -> { field && field != '' })) . '/4 fields completed'"
)
# Image optimization suggestions
optimization_tips: expression_result(
expression: "!alt_text ? 'Add alt text for accessibility' : (!caption && !description ? 'Consider adding caption or description' : 'Well optimized')"
)
}
}
}
```
**Image Performance Optimization**
This code demonstrates building responsive image attributes using `merge()` to create HTML-like properties (src, data-src, data-srcset) with pixel width descriptors like '300w', '768w', '1024w'. Shows file format detection by using `includes()` on original file URL to check for '.webp' extension.
```graphql
posts_query {
posts {
ID
post_title
featured_image {
title
sizes
# Performance-optimized image delivery
mobile_image: file_url(size: THUMBNAIL)
tablet_image: file_url(size: MEDIUM)
desktop_image: file_url(size: LARGE)
retina_image: file_url(size: SIZE_1536X1536)
# Lazy loading setup
lazy_loading_data: expression_result(
expression: "merge({'src': mobile_image, 'data-src': desktop_image, 'data-srcset': mobile_image . ' 300w, ' . tablet_image . ' 768w, ' . desktop_image . ' 1024w'})"
)
# Image optimization status
optimization_status: expression_result(
expression: "sizes ? 'Multiple sizes available' : 'Limited size options'"
)
# WebP alternative check
webp_ready: expression_result(
expression: "includes(file_url(size: ORIGINAL), '.webp') ? 'WebP format' : 'Traditional format'"
)
}
}
}
```
### Taxonomy Fields
- `categories` - Array of Term objects
- `tags` - Array of Term objects
- `terms_query(arguments: WP_Term_Query!)` - Query specific taxonomy
- `category_names` (string) - Comma-separated category names
- `category_links` (string) - HTML links for categories
- `tag_names` (string) - Comma-separated tag names
- `tag_links` (string) - HTML links for tags
### Relationships
- `post_author` - User object of post author
- `children` - Array of child Post objects
- `comments` - Array of Comment objects
- `comments_open` (boolean) - Whether comments are open
### Extended Post Date and Content Fields
Beyond the standard post fields, several advanced options provide more granular control over date formatting and content output.
****
## **GMT Date and Time Fields**
All post date fields have GMT equivalents that return dates in GMT timezone instead of the site's local timezone.
**GMT Date Fields:**
- `post_date_gmt(formatted: BooleanOrDataVar = true)` (string) - Publication date in GMT
- `post_datetime_gmt(formatted: BooleanOrDataVar = true)` (string) - Publication datetime in GMT
- `post_modified_date_gmt(formatted: BooleanOrDataVar = true)` (string) - Last modified date in GMT
- `post_modified_datetime_gmt(formatted: BooleanOrDataVar = true)` (string) - Last modified datetime in GMT
**GMT vs Local Time Comparison**
This code demonstrates GMT date field variants (post_date_gmt, post_datetime_gmt, post_modified_date_gmt) and introduces `formatted: false` parameter to get raw timestamps instead of formatted dates. Shows mathematical operations in expressions using subtraction and division operators to calculate timezone offset by converting seconds to hours with `/ 3600`.
```graphql
posts_query {
posts {
ID
post_title
# Local timezone dates (formatted by default)
local_date: post_date
local_datetime: post_datetime
local_modified: post_modified_date
# GMT timezone dates (formatted by default)
gmt_date: post_date_gmt
gmt_datetime: post_datetime_gmt
gmt_modified: post_modified_date_gmt
# Raw GMT timestamps for calculations
gmt_timestamp: post_date_gmt(formatted: false)
gmt_modified_timestamp: post_modified_date_gmt(formatted: false)
# Time difference calculation
timezone_offset: expression_result(
expression: "(strtotime(post_date) - strtotime(post_date_gmt)) / 3600 . ' hours'"
)
}
}
```
**Date Formatting Control**
All date fields accept a `formatted` parameter to control output format.
### **Raw Content Parameter**
The `post_content` field accepts a `raw` parameter to control content processing.
**Raw vs Processed Content**
This code demonstrates `post_content(raw: true)` parameter to get unprocessed content without WordPress filters or shortcodes. Shows content analysis techniques using `count()` for character length comparison between processed and raw versions. Detects shortcodes by checking for `[` and `]` characters with `includes()` and uses mathematical operations to calculate processing differences.
```graphql
posts_query {
posts {
ID
post_title
# Processed content (default) - WordPress filters applied
processed_content: post_content
# Raw content - no WordPress filters, shortcodes, or processing
raw_content: post_content(raw: true)
# Content analysis
content_length: expression_result(
expression: "count(processed_content)"
)
raw_length: expression_result(
expression: "count(raw_content)"
)
has_shortcodes: expression_result(
expression: "includes(raw_content, '[') && includes(raw_content, ']') ? 'Yes' : 'No'"
)
processing_difference: expression_result(
expression: "(count(processed_content) - count(raw_content)) . ' characters difference'"
)
}
}
```
### Complete Date Field Coverage
**All Available Date Fields**
This code demonstrates complete date field coverage including `modified_datetime` field and shows additional date format codes: 'l' for full day names, 'M' for short month names, and 'g:i A' for time-only format. Provides comprehensive reference for all available date field variants (standard, GMT, and raw timestamp versions).
```graphql
post {
ID
post_title
# Standard formatted dates
publish_date: post_date
publish_datetime: post_datetime
modified_date: post_modified_date
modified_datetime: post_modified_datetime
# GMT formatted dates
publish_date_gmt: post_date_gmt
publish_datetime_gmt: post_datetime_gmt
modified_date_gmt: post_modified_date_gmt
modified_datetime_gmt: post_modified_datetime_gmt
# Raw timestamps for calculations
publish_timestamp: post_date(formatted: false)
publish_timestamp_gmt: post_date_gmt(formatted: false)
modified_timestamp: post_modified_date(formatted: false)
modified_timestamp_gmt: post_modified_date_gmt(formatted: false)
# Custom formatting examples
human_publish_date: expression_result(
expression: "date('l, F j, Y', strtotime(publish_timestamp))"
)
iso_publish_date: expression_result(
expression: "date('c', strtotime(publish_timestamp))"
)
short_date: expression_result(
expression: "date('M j', strtotime(publish_timestamp))"
)
time_only: expression_result(
expression: "date('g:i A', strtotime(publish_timestamp))"
)
}
```
**Timezone and Localization**
**Working with Timezones**
This code demonstrates timezone offset calculations using comparison operators `> 0` for conditional UTC display formatting. Shows escaped literal text `\\U\\T\\C` to output "UTC" in date strings and introduces 'T' format code for timezone abbreviations. Uses mathematical comparison to build user-friendly timezone labels with positive/negative UTC offsets.
```graphql
posts_query {
posts {
ID
post_title
# Compare local vs GMT
local_time: post_datetime(formatted: false) @private
gmt_time: post_datetime_gmt(formatted: false) @private
# Timezone calculations
site_timezone_offset: expression_result(
expression: "(strtotime(local_time) - strtotime(gmt_time)) / 3600"
)
# User-friendly timezone display
timezone_display: expression_result(
expression: "site_timezone_offset > 0 ? 'UTC+' . site_timezone_offset : 'UTC' . site_timezone_offset"
)
# Different timezone representations
utc_time: expression_result(
expression: "date('Y-m-d H:i:s \\U\\T\\C', strtotime(gmt_time))"
)
local_with_tz: expression_result(
expression: "date('Y-m-d H:i:s', strtotime(local_time)) . ' (Local)'"
)
# Event scheduling friendly format
event_time: expression_result(
expression: "date('F j, Y \\a\\t g:i A T', strtotime(local_time))"
)
}
}
```
## Comment Fields
### Standard Comment Fields
Access comments through the `comments` field on Post objects. Each comment has the following fields:
- `ID` (int) - Comment ID
- `comment_ID` (int) - Same as ID, alternative access
- `comment_post_ID` (int) - ID of the post this comment belongs to
- `comment_author` (string) - Comment author name
- `comment_author_email` (string) - Comment author email
- `comment_author_url` (string) - Comment author website URL
- `comment_author_IP` (string) - Comment author IP address
- `comment_date` (string) - Comment publication date
- `comment_date_gmt` (string) - Comment date in GMT
- `comment_content` (string) - Comment text content
- `comment_karma` (mixed) - Comment karma/rating
- `comment_approved` (string) - Comment approval status
- `comment_agent` (string) - User agent string
- `comment_type` (string) - Comment type (comment, pingback, trackback)
- `comment_parent` (int) - Parent comment ID for threaded comments
- `user_id` (int) - WordPress user ID if comment author is registered
### Comment Relationships
- `children` - Array of child Comment objects (for threaded comments)
- `meta` - Array of Meta objects for comment meta fields
- `meta_value(key: StringOrDataVar!)` - Get specific comment meta value
### Comment Query Examples
Basic Post Comments
This code introduces `comments_open` boolean field and `comments` array containing comment objects. Shows comment-specific fields including comment_author, comment_author_email, comment_date, comment_content, comment_approved status, and comment_type for different comment types.
```graphql
post {
ID
post_title
comments_open
comments {
ID
comment_author
comment_author_email
comment_date
comment_content
comment_approved
comment_type
}
}
```
**Threaded Comments with Nested Replies:**
This code demonstrates threaded comment structure using `comment_parent` field for hierarchy and `children` nested objects for comment replies. Shows multiple levels of nesting without `@recursive` directive, manually defining each level depth.
```graphql
post {
ID
post_title
comments {
ID
comment_author
comment_date
comment_content
comment_parent
# Get nested comment replies
children {
ID
comment_author
comment_date
comment_content
comment_parent
# Can nest deeper if needed
children {
ID
comment_author
comment_content
}
}
}
}
```
### Performance Considerations
**Note:** Loading all comments for posts with many comments can impact performance. Consider limiting comment display or implementing pagination at the application level when dealing with high-traffic comment sections.
## Meta Type with Operators
WordPress meta fields support operators for conditional value checking and filtering. The Meta type provides `key` and `value` fields that accept operator parameters.
### Available Operators
```graphql
enum Operator {
equal # Check if value equals specified value
notEqual # Check if value does not equal specified value
}
```
### Meta Field Structure
- `key(operator: Operator)` (string) - Meta key with optional operator
- `value(operator: Operator)` (mixed) - Meta value with optional operator
### Basic Meta Queries with Operators
**Post Meta with Operators**
This code introduces `operator` parameter on `key` and `value` fields with `equal` and `notEqual` operators for conditional meta field checking. Shows multiple aliases on same `meta` field and uses `null` return value in expressions for conditional field display.
```graphql
posts_query(
arguments: {
post_type: "product"
posts_per_page: 10
}
) {
posts {
ID
post_title
# Access all meta fields
meta {
key
value
# Check for specific key equality
is_featured_key: key(operator: equal)
is_not_price_key: key(operator: notEqual)
# Check for specific value equality
is_true_value: value(operator: equal)
is_not_false_value: value(operator: notEqual)
}
# Find specific meta values
featured_meta: meta {
key
value
# Only show if key equals "featured"
matching_key: expression_result(
expression: "key == 'featured' ? key : null"
)
}
}
}
```
## User Fields
### Standard User Fields
- `ID` (int) - User ID
- `user_login` (string) - Username
- `user_email` (string) - Email address
- `user_url` (string) - Website URL
- `display_name` (string) - Display name
- `nickname` (string) - Nickname
- `first_name` (string) - First name
- `last_name` (string) - Last name
- `description` (string) - Bio/description
- `avatar_url` (string) - Avatar image URL
- `roles` (array) - Array of user roles
- `capabilities` (array) - List of user capabilities
## Term Fields
### Standard Term Fields
- `term_id` (int) - Term ID
- `name` (string) - Term name
- `slug` (string) - Term slug
- `term_group` (string) - Term group
- `term_taxonomy_id` (int) - Term taxonomy ID
- `taxonomy` (string) - Taxonomy name
- `description` (string) - Term description
- `count` (int) - Post count
- `parent` (int) - Parent term ID
- `children` - Array of child Term objects
## Available Thumbnail Sizes
```graphql
enum ThumbnailSize {
ORIGINAL # original size
THUMBNAIL # 150x150
MEDIUM # 300x300
MEDIUM_LARGE # 768x0
LARGE # 1024x1024
SIZE_1536X1536 # 1536x1536
SIZE_2048X2048 # 2048x2048
}
```
# Advanced Query Patterns
## Meta Query Examples
### EXISTS/NOT EXISTS Queries
**Posts that HAVE specific custom fields:**
This code introduces `compare: "EXISTS"` operator in `meta_query` to check for meta field presence without validating values. Filters products that have all three required meta keys (product_price, product_sku, featured_product) regardless of their actual values.
```graphql
posts_query(
arguments: {
post_type: "product"
post_status: "publish"
posts_per_page: 15
meta_query: {
relation: "AND"
array: [
{
key: "product_price"
compare: "EXISTS"
}
{
key: "product_sku"
compare: "EXISTS"
}
{
key: "featured_product"
compare: "EXISTS"
}
]
}
orderby: "title"
order: "ASC"
}
) {
posts {
ID
post_title
price: acf_value(name: "product_price")
sku: acf_value(name: "product_sku")
featured: acf_value(name: "featured_product")
}
posts_count
}
```
**Posts that DON’T HAVE specific custom fields:**
This code introduces `compare: "NOT EXISTS"` operator to filter posts that lack specific meta fields. Uses "OR" relation to include posts missing either featured_image_override OR hide_from_homepage meta keys, opposite logic from EXISTS filtering.
```graphql
posts_query(
arguments: {
post_type: "post"
post_status: "publish"
posts_per_page: 10
meta_query: {
relation: "OR"
array: [
{
key: "featured_image_override"
compare: "NOT EXISTS"
}
{
key: "hide_from_homepage"
compare: "NOT EXISTS"
}
]
}
orderby: "date"
order: "DESC"
}
) {
posts {
ID
post_title
post_date
featured_image {
file_url
alt_text
}
}
posts_count
}
```
### LIKE/NOT LIKE Pattern Matching
**Partial text matching:**
This code introduces `compare: "LIKE"` and `compare: "NOT LIKE"` operators for partial text matching in meta queries. Shows using same meta key multiple times with different operators - filtering courses containing "JavaScript" and "beginner" while excluding "advanced" content.
```graphql
posts_query(
arguments: {
post_type: "course"
post_status: "publish"
posts_per_page: 12
meta_query: {
relation: "AND"
array: [
{
key: "course_title"
value: "JavaScript"
compare: "LIKE"
}
{
key: "course_description"
value: "beginner"
compare: "LIKE"
}
{
key: "course_title"
value: "advanced"
compare: "NOT LIKE"
}
]
}
orderby: "title"
order: "ASC"
}
) {
posts {
ID
post_title
course_title: acf_value(name: "course_title")
course_description: acf_value(name: "course_description")
course_level: acf_value(name: "course_level")
}
posts_count
}contacts from multiple approved domains while filtering out spam domains.
```
### REGEXP Pattern Matching
**Phone number format validation:**
This code introduces `compare: "REGEXP"` operator for regex pattern matching in meta queries. Uses pattern `"^[0-9]{3}-[0-9]{3}-[0-9]{4}$"` to validate phone numbers in 123-456-7890 format - matching exactly 3 digits, hyphen, 3 digits, hyphen, 4 digits with start `^` and end `$` anchors.
```graphql
posts_query(
arguments: {
post_type: "business"
post_status: "publish"
posts_per_page: 15
meta_query: {
array: [
{
key: "phone_number"
value: "^[0-9]{3}-[0-9]{3}-[0-9]{4}$"
compare: "REGEXP"
}
]
}
orderby: "title"
order: "ASC"
}
) {
posts {
ID
post_title
phone: acf_value(name: "phone_number")
business_type: acf_value(name: "business_type")
}
posts_count
}
```
### Numeric BETWEEN/NOT BETWEEN Comparisons
**Price range filtering:**
This code demonstrates SKU pattern validation using `"^[A-Z]{2}[0-9]{4}$"` regex pattern requiring exactly 2 uppercase letters followed by 4 digits. Introduces `compare: "NOT REGEXP"` to exclude invalid patterns like all-numeric SKUs `"^[0-9]+$"`. Orders results by meta field value using `orderby: "meta_value"` with `meta_key: "product_sku"`.
```graphql
posts_query(
arguments: {
post_type: "product"
post_status: "publish"
posts_per_page: 15
meta_query: {
relation: "AND"
array: [
{
key: "product_price"
value: [100, 500]
type: "NUMERIC"
compare: "BETWEEN"
}
{
key: "discount_price"
value: [10, 20]
type: "NUMERIC"
compare: "NOT BETWEEN"
}
{
key: "inventory_count"
value: 0
type: "NUMERIC"
compare: ">"
}
]
}
orderby: "meta_value_num"
meta_key: "product_price"
order: "ASC"
}
) {
posts {
ID
post_title
price: acf_value(name: "product_price")
discount: acf_value(name: "discount_price")
inventory: acf_value(name: "inventory_count")
final_price: expression_result(
expression: "price - (price * discount / 100)"
)
}
posts_count
}
```
## Date Query Examples
### Posts from Specific Date Range
**Posts from Specific Date Range:**
This code introduces `date_query` for filtering posts by publication date range using `after: "2024-01-01"` and `before: "2024-12-31"` parameters. Uses `inclusive: true` to include posts from the exact start and end dates in results.
```graphql
posts_query(
arguments: {
post_type: "post"
post_status: "publish"
posts_per_page: 10
date_query: {
array: [
{
after: "2024-01-01"
before: "2024-12-31"
inclusive: true
}
]
}
orderby: "date"
order: "DESC"
}
) {
posts {
ID
post_title
post_date
post_excerpt
}
posts_count
}
```
**Posts from Specific Year and Month:**
This code demonstrates date filtering by specific time periods using `year: 2024` and `month: 12` parameters instead of date ranges, filtering posts from December 2024 only.
```graphql
posts_query(
arguments: {
post_type: "post"
post_status: "publish"
posts_per_page: 10
date_query: {
array: [
{
year: 2024
month: 12
}
]
}
orderby: "date"
order: "ASC"
}
) {
posts {
ID
post_title
post_date
post_excerpt
}
posts_count
}
```
### Posts from Last 30 Days
This code uses relative date string "30 days ago" in `date_query` instead of absolute dates, filtering posts from the last 30 days. Shows single date boundary using only `after` parameter without `before` for open-ended date ranges.
```graphql
posts_query(
arguments: {
post_type: "event"
post_status: "publish"
posts_per_page: 15
date_query: {
array: [
{
after: "30 days ago"
inclusive: true
}
]
}
orderby: "date"
order: "DESC"
}
) {
posts {
ID
post_title
post_date
event_date: acf_value(name: "event_date")
}
posts_count
}
```
### Posts Modified in Last 24 Hours
This code introduces `column: "post_modified"` parameter to filter by modification dates instead of publication dates. Uses `orderby: "modified"` to sort by last modified date and shows relative date string "24 hours ago" for filtering recently updated content.
```graphql
posts_query(
arguments: {
post_type: "post"
post_status: "publish"
posts_per_page: 10
date_query: {
column: "post_modified"
array: [
{
after: "24 hours ago"
inclusive: true
}
]
}
orderby: "modified"
order: "DESC"
}
) {
posts {
ID
post_title
post_date
post_modified_date
last_modified: expression_result(
expression: "human_time_diff(strtotime(post_modified_date), time()) . ' ago'"
)
}
posts_count
}
```
## Author Query Examples
### Posts by Multiple Specific Authors
This code introduces `author__in: [1, 5, 12, 23]` parameter to filter posts by multiple specific author IDs rather than single author filtering. Shows nested `post_author` object with ID, display_name, user_login, and avatar_url fields.
```graphql
posts_query(
arguments: {
post_type: "post"
post_status: "publish"
posts_per_page: 15
author__in: [1, 5, 12, 23]
orderby: "date"
order: "DESC"
}
) {
posts {
ID
post_title
post_date
post_excerpt
post_author {
ID
display_name
user_login
avatar_url
}
}
posts_count
}
```
**Posts Excluding Specific Authors:**
This code introduces `author__not_in: [3, 7, 15]` parameter to exclude posts by specific author IDs, opposite of inclusion filtering. Shows `roles` array field within `post_author` object for user role information.
```graphql
posts_query(
arguments: {
post_type: "post"
post_status: "publish"
posts_per_page: 10
author__not_in: [3, 7, 15]
orderby: "date"
order: "DESC"
}
) {
posts {
ID
post_title
post_date
post_author {
ID
display_name
roles
}
}
posts_count
}
```
# Custom Fields Integration
## ACF (Advanced Custom Fields)
### Basic ACF Access
Access any ACF field with raw value:
```graphql
acf_value(name: "field_name")
```
### Advanced ACF Field Types
**Post Object/Relationship Fields:**
- `acf_post_object_value(name: "field_name")` - Returns Post object
- `acf_post_objects_value(name: "field_name")` - Returns array of Post objects
- `acf_relationship_value(name: "field_name")` - Returns array of related posts
**User Fields:**
- `acf_user_value(name: "field_name")` - Returns User object
- `acf_users_value(name: "field_name")` - Returns array of User objects
**Taxonomy Fields:**
- `acf_taxonomy_value(name: "field_name")` - Returns Term object
- `acf_taxonomies_value(name: "field_name")` - Returns array of Term objects
**Structured Fields:**
- `acf_group_value(name: "field_name")` - Returns AcfGroupField object
- `acf_repeater_value(name: "field_name")` - Returns array of AcfRepeaterRow objects
### ACF Options Page Access
Access ACF Options Page fields from root query:
This code demonstrates root-level ACF access for global site options without post context. Shows `acf_repeater_value` at root level with nested `acf_value` calls for social media platform and URL data.
```graphql
# Global site options
acf_value(name: "site_logo")
acf_value(name: "contact_email")
acf_repeater_value(name: "social_links") {
platform: acf_value(name: "platform")
url: acf_value(name: "url")
}
```
### ACF Repeater with Post Objects
This code demonstrates nested `acf_post_object_value` within `acf_repeater_value` structure, creating post references inside repeater fields. Shows accessing both `meta_value` and `acf_value` fields on referenced post objects within the nested structure.
```graphql
post {
ID
testimonials: acf_repeater_value(name: "manage_testimonials") {
headline: acf_value(name: "headline")
post: acf_post_object_value(name: "post_object") {
ID
post_title
post_content
some_meta_key: meta_value(key: "some_meta_key")
custom_acf_value: acf_value(name: "custom_acf_field_name")
}
}
}
```
### ACF Image Fields with Size Parameters
ACF image fields can return different image sizes similar to featured images, though the exact parameter syntax may vary by ACF field configuration.
**Basic ACF Image Field**
This code demonstrates different ACF image field types (hero_image, product_gallery, company_logo) all accessed using same `acf_value(name: "...")` syntax regardless of field configuration.
```graphql
posts_query {
posts {
ID
post_title
# Standard ACF image field
hero_image: acf_value(name: "hero_image")
# Gallery field
product_gallery: acf_value(name: "product_gallery")
# Logo field
company_logo: acf_value(name: "company_logo")
}
}
```
**ACF Image Fields in Different Contexts**
This code demonstrates ACF fields attached to different object types - root level for global options, terms for taxonomy metadata, users for profile data, and comments for review information. Shows same `acf_value(name: "...")` syntax works across all WordPress object contexts.
```graphql
# Root level (Options Page)
{
site_logo: acf_value(name: "site_logo")
hero_background: acf_value(name: "hero_background")
default_avatar: acf_value(name: "default_avatar")
}
# On Terms
terms_query(arguments: {taxonomy: "product_category"}) {
terms {
term_id
name
category_icon: acf_value(name: "category_icon")
featured_image: acf_value(name: "featured_image")
}
}
# On Users
users_query {
users {
ID
display_name
profile_photo: acf_value(name: "profile_photo")
background_image: acf_value(name: "background_image")
}
}
# On Comments
post {
comments {
comment_content
reviewer_photo: acf_value(name: "reviewer_photo")
product_photo: acf_value(name: "product_photo")
}
}
```
**ACF Image Responsive Transformation**
This code demonstrates complex ACF image object processing using logical OR operator `||` for fallback values like `hero_image_data.sizes.medium || hero_image_data.url`. Shows nested object property access with dot notation `hero_image_data.sizes.medium` and builds responsive image attributes (src, srcset, sizes, alt, width, height, loading) using complex single-line expressions with `filter()` and `join()` functions.
```graphql
posts_query {
posts {
ID
post_title
# Get ACF image field data
hero_image_data: acf_value(name: "hero_image") @private
# Transform to responsive image attributes (for now one line, we will look into wats to enable multiline)
hero_image: expression_result(
expression: "hero_image_data && hero_image_data.sizes ? merge({'src': hero_image_data.sizes.medium || hero_image_data.url, 'srcset': join(filter([hero_image_data.sizes.thumbnail ? hero_image_data.sizes.thumbnail . ' 150w' : null, hero_image_data.sizes.medium ? hero_image_data.sizes.medium . ' 300w' : null, hero_image_data.sizes.medium_large ? hero_image_data.sizes.medium_large . ' 768w' : null, hero_image_data.sizes.large ? hero_image_data.sizes.large . ' 1024w' : null, hero_image_data.sizes.full ? hero_image_data.sizes.full . ' ' . hero_image_data.width . 'w' : null ]), ', '),'sizes': '(max-width: 768px) 100vw, (max-width: 1024px) 768px, 1024px', 'alt': hero_image_data.alt || '', 'width': hero_image_data.width || '', 'height': hero_image_data.height || '', 'loading': 'lazy'}) : null"
)
}
}
```
**Note:** ACF image field size parameters depend on ACF field configuration and may not follow the same pattern as MetaBox `args` parameters. The field may return image URLs, image objects, or arrays depending on ACF settings.
## MetaBox Support
### ⚠️ CRITICAL SYNTAX DIFFERENCES
**Root Level (Settings Pages):** Requires `option_name` parameter
```graphql
metabox_value(field_id: "contact_email", option_name: "site_settings")
```
**Post/Page/Term/User Level:** NO `option_name` parameter
```graphql
metabox_value(field_id: "price")
```
### MetaBox Settings Page Fields (Root Level)
This code demonstrates MetaBox fields at root level requiring `option_name: "site_settings"` parameter. Introduces `metabox_post_value` for post object references and `metabox_group_value` for grouped field structures with nested `metabox_value` calls inside groups. Uses `field_id` parameter instead of `name` for MetaBox field identification.
```graphql
# Settings page fields - REQUIRES option_name parameter
metabox_value(field_id: "contact_email", option_name: "site_settings")
metabox_value(field_id: "company_address", option_name: "site_settings")
# Advanced MetaBox option fields
metabox_post_value(field_id: "featured_page", option_name: "site_settings") {
ID
post_title
permalink
}
metabox_group_value(field_id: "contact_info", option_name: "site_settings") {
phone: metabox_value(field_id: "phone")
email: metabox_value(field_id: "email")
address: metabox_value(field_id: "address")
}
```
### MetaBox Post/Page/Term/User Fields
This code demonstrates MetaBox fields on post objects without `option_name` parameter (unlike root level). Introduces `args: "size=medium"` parameter for image sizing and `metabox_posts_value` for multiple post object relationships. Shows nested MetaBox calls within related post structures, accessing same field types on referenced posts.
```graphql
posts_query(
arguments: {
post_type: "product"
posts_per_page: 12
}
) {
posts {
ID
post_title
# MetaBox fields on Post objects - NO option_name
price: metabox_value(field_id: "price")
sku: metabox_value(field_id: "sku")
product_gallery: metabox_value(field_id: "product_gallery", args: "size=medium")
# Post object field
related_category: metabox_post_value(field_id: "related_category") {
ID
post_title
permalink
}
# Multiple post objects
related_products: metabox_posts_value(field_id: "related_products") {
ID
post_title
price: metabox_value(field_id: "price")
}
}
}
```
### MetaBox Group Fields
**Handle MetaBox group structures:**
This code demonstrates `metabox_group_value` on post objects (not just root level) and shows nested `metabox_post_value` within group structures. The referenced manufacturer post contains its own `metabox_value` fields, creating multi-level MetaBox object relationships.
```graphql
post(identifier: "ID", value: 123) {
specifications: metabox_group_value(field_id: "specifications") {
dimensions: metabox_value(field_id: "dimensions")
weight: metabox_value(field_id: "weight")
material: metabox_value(field_id: "material")
# Nested objects within group
manufacturer: metabox_post_value(field_id: "manufacturer") {
ID
post_title
website: metabox_value(field_id: "website")
}
}
}
```
### Advanced MetaBox Field Types
**MetaBox Post Object Fields**
This code demonstrates MetaBox post object references at both root level (requiring `option_name: "site_settings"`) and post level (no `option_name`). Shows accessing standard WordPress fields (ID, post_title, post_excerpt, permalink) and featured_image with size parameters within MetaBox-referenced post objects.
```graphql
# Root level (settings page)
featured_post: metabox_post_value(
field_id: "featured_post"
option_name: "site_settings"
) {
ID
post_title
post_excerpt
permalink
featured_image {
file_url(size: MEDIUM)
alt_text
}
}
# Post level
posts_query {
posts {
ID
post_title
# Related post object field
related_article: metabox_post_value(field_id: "related_article") {
ID
post_title
post_excerpt
permalink
}
}
}
```
**MetaBox Taxonomy Fields**
Single Taxonomy Term
This code introduces `metabox_taxonomy_value` for single taxonomy term references following same root/post level pattern - root level requires `option_name: "site_settings"` while post level omits it. Returns term objects with standard taxonomy fields (term_id, name, slug, taxonomy, description, count).
```graphql
# Root level (settings page)
default_category: metabox_taxonomy_value(
field_id: "default_category"
option_name: "site_settings"
) {
term_id
name
slug
taxonomy
description
}
# Post level
posts_query {
posts {
ID
post_title
primary_category: metabox_taxonomy_value(field_id: "primary_category") {
term_id
name
slug
count
}
}
}
```
**MetaBox User Fields**
Single user:
This code introduces `metabox_user_value` for single user object references following same root/post level pattern - root level requires `option_name: "site_settings"` while post level omits it. Returns user objects with standard user fields (ID, display_name, user_email, roles, avatar_url, description).
```graphql
# Root level (settings page)
site_manager: metabox_user_value(
field_id: "site_manager"
option_name: "site_settings"
) {
ID
display_name
user_email
roles
avatar_url
}
# Post level
posts_query {
posts {
ID
post_title
reviewer: metabox_user_value(field_id: "reviewer") {
ID
display_name
description
avatar_url
}
}
}
```
### MetaBox Args Parameter
All MetaBox functions support an optional `args` parameter for additional formatting or filtering options.
**Image Field Sizing**
This code demonstrates `args: "size=..."` parameter for MetaBox image field sizing, using different size values (medium, thumbnail, large) to control image output dimensions.
```graphql
posts_query {
posts {
ID
post_title
# Specify image size with args
gallery: metabox_value(field_id: "gallery", args: "size=medium")
thumbnail: metabox_value(field_id: "featured_img", args: "size=thumbnail")
hero_image: metabox_value(field_id: "hero", args: "size=large")
}
}
```
Multiple Values with Limits
This code demonstrates `args: "limit=3"` parameter with `metabox_posts_value` to limit the number of returned post objects instead of image sizing, restricting related features to only 3 items.
```graphql
posts_query {
posts {
ID
post_title
# Limit number of returned items
top_features: metabox_posts_value(
field_id: "related_features"
args: "limit=3"
) {
ID
post_title
}
}
}
```
### Complex MetaBox Relationships
**Nested Post Objects with MetaBox Fields**
This code demonstrates complex nested MetaBox relationships with multiple field types - `metabox_post_value` for instructor posts containing `metabox_groups_value` qualifications and `metabox_taxonomies_value` specialties. Shows deep nesting with `metabox_posts_value` for resources within course module groups, creating multi-level MetaBox object hierarchies.
```graphql
posts_query(arguments: {post_type: "course"}) {
posts {
ID
post_title
course_instructor: metabox_post_value(field_id: "instructor") {
ID
post_title
instructor_bio: metabox_value(field_id: "bio")
qualifications: metabox_groups_value(field_id: "qualifications") {
qualification_name: metabox_value(field_id: "name")
institution: metabox_value(field_id: "institution")
year: metabox_value(field_id: "year")
}
specialties: metabox_taxonomies_value(field_id: "specialties") {
name
slug
description
}
}
course_modules: metabox_groups_value(field_id: "course_modules") {
module_title: metabox_value(field_id: "title")
module_content: metabox_value(field_id: "content")
related_resources: metabox_posts_value(field_id: "resources") {
ID
post_title
permalink
}
}
}
}
```
# Utility Features
## Helper URLs (Root Level Only)
- `front_page_url` - Homepage URL
- `current_url` - Current page URL
- `posts_index_page_url` - Blog index URL
- `page_url(name: StringOrDataVar!)` - Page URL by slug
- `post_url(name: StringOrDataVar!)` - Post URL by slug
- `author_archive_url(username: StringOrDataVar!)` - Author archive URL
- `category_archive_url(slug: StringOrDataVar!)` - Category archive URL
- `tag_archive_url(slug: StringOrDataVar!)` - Tag archive URL
**⚠️ CRITICAL LIMITATION:** These URL helper functions work ONLY at root level, NOT inside loops or nested objects.
## URL Helper Functions Limitations & Alternatives
### ❌ URL Helpers DON’T Work In Loops
These functions are **root level only** and will not work inside:
- `posts_query.posts`
- `terms_query.terms`
- `users_query.users`
- Any nested query results
### âś… Working Alternatives for URLs in Loops
**Terms (Categories, Tags, Custom Taxonomies):**
This code introduces `php_function_output` for calling WordPress functions with `get_term_link` using `{{term_id}}` and `{{taxonomy}}` data variables as function arguments. Shows `get_category_link` as category-specific alternative requiring only `{{term_id}}` parameter instead of taxonomy specification.
```graphql
terms_query(arguments: {taxonomy: "category"}) {
terms {
term_id
slug
name
taxonomy
# Generic - works for any taxonomy
term_url: php_function_output(
function: "get_term_link"
arguments: ["{{term_id}}", "{{taxonomy}}"]
)
# Category-specific alternative
category_url: php_function_output(
function: "get_category_link"
arguments: ["{{term_id}}"]
)
}
}
```
**Users/Authors:**
```graphql
users_query {
users {
ID
user_login
author_url: php_function_output(
function: "get_author_posts_url"
arguments: ["{{ID}}"]
)
}
}
```
## Expression Language Integration
### Basic Data Processing
This code demonstrates `php_function_output` with `get_author_posts_url` function for generating author archive URLs using `{{ID}}` data variable from user context.
```graphql
posts_query(
arguments: {
post_type: "event"
posts_per_page: 10
}
) {
posts {
ID @private
post_title
event_date: acf_value(name: "event_date") @private
ticket_price: acf_value(name: "ticket_price") @private
# String formatting
formatted_date: expression_result(
expression: "date('F j, Y', strtotime(event_date))"
)
formatted_price: expression_result(
expression: "sprintf('$%.2f', ticket_price)"
)
# Boolean logic
is_soon: expression_result(
expression: "strtotime(event_date) - strtotime('now') < 604800 ? true : false"
)
# String manipulation
short_title: expression_result(
expression: "limit_words(post_title, 5)"
)
}
}
```
### Advanced String Processing
This code demonstrates advanced string processing functions including `upper()` for case conversion, `limit_words()` with word count limits, and string concatenation using `~` operator. Introduces `foreach()` with arrow function syntax `(name) -> { name[0] }` for array transformation and `join()` to convert arrays back to strings. Shows array indexing within arrow functions and `is_email()` for email validation.
```graphql
posts_query(
arguments: {
post_type: "article"
posts_per_page: 5
}
) {
posts {
ID
post_title @private
post_content @private
author_name: acf_value(name: "author_name") @private
# String manipulation
title_uppercase: expression_result(
expression: "upper(post_title)"
)
short_excerpt: expression_result(
expression: "limit_words(post_content, 25)"
)
read_time: expression_result(
expression: "ceil(count(split(post_content, ' ')) / 200) ~ ' min read'"
)
author_initials: expression_result(
expression: "upper(join(foreach(split(author_name, ' '), (name) -> { name[0] }), ''))"
)
word_count: expression_result(
expression: "count(split(post_content, ' '))"
)
# Validation
has_valid_email: expression_result(
expression: "is_email(author_email) ? 'Valid' : 'Invalid'"
)
}
}
```
### **Array Manipulation Examples**
This code demonstrates comma-separated string processing using `split(tags_raw, ',')` to convert ACF fields into arrays and `join(...)` to convert back to formatted strings. Introduces `sort()` function for array alphabetization and case-insensitive matching with `lower()` function before checking array membership with `includes()`.
```graphql
posts_query(
arguments: {
post_type: "portfolio"
posts_per_page: 10
}
) {
posts {
ID
post_title
tags_raw: acf_value(name: "project_tags") @private
skills_raw: acf_value(name: "skills_used") @private
# Array processing
tag_list: expression_result(
expression: "join(split(tags_raw, ','), ', ')"
)
skills_count: expression_result(
expression: "count(split(skills_raw, ','))"
)
# Sorting and filtering
sorted_skills: expression_result(
expression: "join(sort(split(skills_raw, ',')), ', ')"
)
# Check for specific skills
has_php: expression_result(
expression: "includes(split(lower(skills_raw), ','), 'php') ? 'Yes' : 'No'"
)
}
}
```
## Available Utility Functions
### Root Level Functions
- `option_value(name: StringOrDataVar!)` - Get WordPress option
- `url_parameter(name: MixedOrDataVar!, fallback: MixedOrDataVar)` - Get URL parameter
- `cookie_parameter(name: MixedOrDataVar!, fallback: MixedOrDataVar)` - Get cookie value
- `server_parameter(name: MixedOrDataVar!, fallback: MixedOrDataVar)` - Get server variable
- `expression_result(expression: StringOrDataVar!)` - Evaluate Expression Language
- `php_function_output(function: StringOrDataVar!, arguments: [MixedOrDataVar], fallback: MixedOrDataVar)` - Call PHP function
## Additional Root Level Functions
These specialized functions provide access to WordPress hooks, forms, and advanced metadata at the root query level
### Hook Arguments
Access arguments passed to WordPress action/filter hooks when GraphQL is executed within hook context
**Function:** `hook_argument(position: Int!)`
This code introduces `hook_argument(position: ...)` function for accessing WordPress hook arguments by zero-based index (0, 1, 2). Shows using hook arguments as data variables - `"{{post_id_from_hook}}"` references first hook argument to fetch specific post data in subsequent `post()` query.
```graphql
# Access hook arguments by position (0-based index)
{
first_arg: hook_argument(position: 0)
second_arg: hook_argument(position: 1)
third_arg: hook_argument(position: 2)
# Use in conditional logic
post_id_from_hook: hook_argument(position: 0) @private
# Get post data from hook argument
current_post: post(identifier: "ID", value: "{{post_id_from_hook}}") {
ID
post_title
post_content
}
}
```
Common Use Cases
- Accessing post ID in `wp_insert_post` hook
- Getting user ID in user registration hooks
- Retrieving term data in taxonomy hooks
### Form Functions
Handle form submissions and security nonces for custom forms.
**Form Submission URL:** `form_submission_url(form: String!)`
This code introduces `form_submission_url(form: "...")` function for generating form action URLs with specific form identifiers like "contact_form", "newsletter_signup", and "user_registration". Shows same function called multiple times with different form names.
```graphql
{
# Get submission URL for specific form
contact_form_url: form_submission_url(form: "contact_form")
newsletter_url: form_submission_url(form: "newsletter_signup")
registration_url: form_submission_url(form: "user_registration")
# Use in form HTML
contact_form_action: form_submission_url(form: "contact_form")
}
```
**Form Nonce:** `form_nonce(form: String!)`
This code introduces `form_nonce(form: "...")` function for generating security nonces with form identifiers. Shows creating nested objects with `contact_form_data: { ... }` syntax combining both `form_submission_url` and `form_nonce` functions plus hardcoded values for complete form configuration.
```graphql
{
# Get security nonce for form validation
contact_nonce: form_nonce(form: "contact_form")
newsletter_nonce: form_nonce(form: "newsletter_signup")
admin_nonce: form_nonce(form: "admin_action")
# Complete form setup
contact_form_data: {
action_url: form_submission_url(form: "contact_form")
nonce_field: form_nonce(form: "contact_form")
form_id: "contact_form"
}
}
```
### Pagination Type Differences
Builderius GraphQL implements two distinct pagination types with different capabilities depending on the query context.
****
**WP_Query_Pagination (Full Pagination**)
Used by: `PostsQuery`, `UsersQuery`, `TermsQuery`
**Available Fields:**
- `current_page` (int) - Current page number
- `total_pages` (int) - Total number of pages
- `posts_per_page` (int) - Items per page
- `links` (string) - HTML pagination links
- All utility functions (option_value, url_parameter, etc.)
**Arguments Required:**
- `pagination_url_param_name` (string) - URL parameter name for pagination
**Example - Posts with Full Pagination**
This code shows pagination object fields including `current_page`, `total_pages`, and `posts_per_page` for building enhanced pagination information. Introduces `min()` function for value limiting and complex mathematical expressions with parentheses for operation order like `((current_page - 1) * posts_per_page + 1)` to calculate item ranges and display counts.
```graphql
posts_query(
arguments: {
post_type: "product"
posts_per_page: 12
}
) {
posts {
ID
post_title
price: acf_value(name: "price")
}
has_pagination
pagination(
arguments: {
pagination_url_param_name: "product_page"
}
) {
current_page
total_pages
posts_per_page
links
# Enhanced pagination info
page_info: expression_result(
expression: "current_page . ' of ' . total_pages . ' pages'"
)
showing_range: expression_result(
expression: "'Showing ' . ((current_page - 1) * posts_per_page + 1) . '-' . min(current_page * posts_per_page, total_pages * posts_per_page) . ' of ' . (total_pages * posts_per_page)"
)
}
posts_count
}
```
**WP_Query_Pagination_Limited (Limited Pagination)**
Used by: `ArchivePostsQuery`
**Available Fields:**
- `current_page` (int) - Current page number
- `total_pages` (int) - Total number of pages
- `posts_per_page` (int) - Items per page
- `links` (string) - HTML pagination links
- All utility functions (option_value, url_parameter, etc.)
**No Arguments Required** - Uses WordPress's built-in archive pagination
**Example - Archive Limited Pagination**
This code demonstrates archive pagination without requiring `arguments` parameter, unlike custom queries. Archive context uses automatic pagination settings from WordPress without needing `pagination_url_param_name` specification.
```graphql
archive {
title
description
type
posts_query {
posts {
ID
post_title
post_excerpt
post_date
}
has_pagination
pagination {
current_page
total_pages
posts_per_page
links
# Archive pagination info
archive_page_info: expression_result(
expression: "'Archive page ' . current_page . ' of ' . total_pages"
)
}
posts_count
}
}
```
**Key Differences Summary**
| **Feature** | **WP_Query_Pagination** | **WP_Query_Pagination_Limited** |
| --- | --- | --- |
| Arguments Required | Yes (`pagination_url_param_name`) | No (automatic) |
| **Used By** | PostsQuery, UsersQuery, TermsQuery | ArchivePostsQuery only |
| **URL Parameter Control** | Custom parameter name | WordPress default |
| Context | Custom queries | Archive pages |
| **Flexibility** | High (custom pagination) | Limited (WordPress defaults) |
### Pagination Best Practices
**URL Parameter Naming**
- Use descriptive names: `products_page`, `team_page`, `portfolio_page`
- Avoid conflicts: Don't use `page` (WordPress default) for custom pagination
- Be consistent: Use same naming pattern across site
**Performance Considerations:**
- Set reasonable `posts_per_page` limits (typically 10-20)
- Use `has_pagination` check before rendering pagination UI
- Consider total post count for large datasets
# Context-Aware Patterns
## Single Post Context Queries
Use `post` without arguments (gets current post):
This code fetches current post without arguments and creates related posts using nested `posts_query`. Uses `@private` directive on ID field to hide it from output while making it available for data variable. Excludes current post from related results using `post__not_in: ["{{ID}}"]` argument.
```graphql
post {
ID @private
post_title
related_posts: posts_query(
arguments: {
post_type: "post"
posts_per_page: 6
post__not_in: ["{{ID}}"]
}
) {
posts {
ID
post_title
post_excerpt
}
}
}
```
## Archive Context Queries
Use `archive` to get context data:
This code fetches archive context and gets term data with `@private` directive. Uses `tax_query` filtering with dot notation data variables `{{term.taxonomy}}` and `{{term.term_id}}` to filter posts by current archive's taxonomy terms using "IN" operator.
```graphql
archive {
term @private {
term_id
taxonomy
}
posts_query(
arguments: {
post_type: "post"
posts_per_page: 12
tax_query: {
array: [
{
taxonomy: "{{term.taxonomy}}"
field: "term_id"
terms: ["{{term.term_id}}"]
operator: "IN"
}
]
}
}
) {
posts {
ID
post_title
post_excerpt
}
}
}
```
## User Context Queries
Posts by Current User:
This code fetches currently logged-in user with `current_user` function and creates nested `posts_query` using `author: "{{ID}}"` to get posts authored by current user. Shows `post_status` field for checking post publication status.
```graphql
current_user {
ID @private
display_name
my_posts: posts_query(
arguments: {
author: "{{ID}}"
post_type: "post"
posts_per_page: 10
}
) {
posts {
ID
post_title
post_status
}
}
}
```
## Related Content Patterns
Related Posts by Taxonomy:
This code fetches current post and gets category terms using `terms_query` with `@private` directive on entire query block. Uses `pluck(terms_query.terms, 'term_id')` function to extract term IDs from previous query results and references them in subsequent `tax_query` filtering to find posts sharing same categories.
```graphql
post {
ID @private
terms_query(
arguments: {
taxonomy: "category"
}
) @private {
terms {
term_id
name
}
}
# Query posts with shared taxonomy terms
related_posts: posts_query(
arguments: {
post_type: "post"
post_status: "publish"
posts_per_page: 10
post__not_in: ["{{ID}}"]
tax_query: {
array: [
{
taxonomy: "category"
field: "term_id"
terms: ["{{pluck(terms_query.terms, 'term_id')}}"]
operator: "IN"
}
]
}
}
) {
posts {
ID
post_title
post_excerpt
}
}
}
}
```
# Common Query Patterns
## Related Posts by Category
This code fetches current post and uses direct `categories` field with `@private` directive instead of `terms_query`. Uses `pluck(categories, 'term_id')` to extract term IDs from post's category array and filters related posts by shared categories with `tax_query`.
```graphql
post {
ID @private
categories @private {
term_id
}
related_posts: posts_query(
arguments: {
post_type: "post"
posts_per_page: 6
post__not_in: ["{{ID}}"]
tax_query: {
array: [
{
taxonomy: "category"
field: "term_id"
terms: ["{{pluck(categories, 'term_id')}}"]
operator: "IN"
}
]
}
}
) {
posts {
ID
post_title
post_excerpt
}
}
}
```
## Category Archive with Posts
This code fetches archive context and gets term data privately while showing archive title and description. Uses `posts_query` without arguments to get default archive posts and includes featured image with `size: MEDIUM` parameter. Shows basic pagination with `has_pagination` check and pagination links.
```graphql
archive {
term @private {
term_id
taxonomy
}
title
description
posts_query {
posts {
ID
post_title
post_excerpt
featured_image {
file_url(size: MEDIUM)
alt_text
}
}
has_pagination
pagination {
links
}
}
}
```
## Nested Terms and Posts
This code queries categories with `hide_empty: true` to show only categories containing posts, ordered alphabetically. Uses nested `posts_query` with `{{term_id}}` data variable to get 5 recent posts per category filtered by `tax_query`. Demonstrates nested loop pattern returning posts within each category term.
```graphql
terms_query(
arguments: {
taxonomy: "category"
hide_empty: true
orderby: "name"
order: "ASC"
}
) {
terms {
term_id
name
slug
description
count
posts_in_category: posts_query(
arguments: {
post_type: "post"
post_status: "publish"
posts_per_page: 5
tax_query: {
array: [
{
taxonomy: "category"
field: "term_id"
terms: ["{{term_id}}"]
operator: "IN"
}
]
}
orderby: "date"
order: "DESC"
}
) {
posts {
ID
post_title
post_excerpt
post_date
featured_image {
file_url
alt_text
}
}
posts_count
}
}
}
```
## Custom Posts with Taxonomy Terms
This code fetches "movie" post type and uses nested `terms_query` with `object_ids: "{{ID}}"` parameter to get genre taxonomy terms assigned to each specific movie post. Shows reverse relationship pattern - getting terms that belong to each post rather than posts belonging to terms.
```graphql
posts_query(
arguments: {
post_type: "movie"
}
) {
posts {
ID
post_title
terms: terms_query(
arguments: {
object_ids: "{{ID}}"
taxonomy: "genre"
}
) {
terms {
name
slug
}
}
}
}
```
---
## Using GraphQL Data in Builderius Builder
After creating GraphQL queries, the returned data is used in the Builderius visual builder through dynamic data tags. This section provides essential context for how query results integrate with builder elements.
### GraphQL Variable Setup
1. **Create Variable**: In the GraphQL editor, create a new "variable"
2. **Write Query**: Add your GraphQL query following the patterns in this documentation
3. **Test Query**: Click "Get Data" to preview the JSON response structure
4. **Use Data**: Reference the data in builder elements using dynamic tags
### Dynamic Data Tag Syntax
**Built-in WordPress Data** (`wp` prefix - automatically available):
Built-in queries are pre-created for each WordPress template context, matching the WordPress template hierarchy. You don't need to create these queries manually:
- **Single Post/Page**: `[[wp.post_title]]`, `[[wp.post_content]]`, `[[wp.featured_image.file_url]]`
- **Archive Pages**: `[[wp.archive.title]]`, `[[wp.archive.posts_query.posts]]` (main query loop)
- **Front Page**: `[[wp.front_page_field]]` (front page specific data)
- **Category/Tag Archives**: `[[wp.archive.term.name]]`, `[[wp.archive.posts_query.posts]]`
**Custom Variables** (queries you create):
```
[[custom.posts_query.posts]]
[[my_data.archive.title]]
[[homepage.acf_value]]
```
**With GraphQL Aliases** (using your custom field names):
```
[[custom.custom_archive.custom_title]]
[[products.featured_items.product_name]]
```
**Loop Data** (inside Collection elements):
```
{{field_name}}
{{post_title}}
{{custom_alias_name}}
```
### Built-in vs Custom Variables
**Built-in (`wp`) Variables:**
- Automatically available based on current WordPress template context
- Match WordPress's main query and template hierarchy
- No GraphQL query creation needed
- Examples: current post data on single templates, archive posts on archive templates
**Custom Variables:**
- Created by you in the GraphQL editor
- For additional data beyond the main WordPress context
- Custom queries, related posts, specific filtering, etc.
- Use your chosen variable name as prefix
### Collection Elements for Loops
**Structure for displaying post loops:**
1. **Collection Element**: Set data source to loop data
- Built-in archive: `[[wp.archive.posts_query.posts]]`
- Custom query: `[[my_variable.posts_query.posts]]`
2. **Template Element**: Automatically added inside Collection
- Individual fields: `{{post_title}}`, `{{ID}}`, `{{post_excerpt}}`
- Custom aliases: `{{my_custom_title}}`, `{{product_price}}`
This system provides both automatic WordPress context data (`wp`) and the flexibility to create custom GraphQL queries for additional functionality.
---
**Note:** This section provides only the essential context needed to understand how GraphQL data integrates with the Builderius builder. For comprehensive tutorials on working with dynamic data, elements, collections, and the visual builder interface, please refer to the **Builderius YouTube channel** and the official documentation (currently being updated to reflect the latest builder features).