ACF in Custom Queries
ACF fields work automatically in Builderius without writing any GraphQL code. Fields appear in the Dynamic Data dropdown and can be added to any element with a click. Learn about built-in ACF integration →
This article provides guidelines for when you need to use ACF within your custom queries Pro Feature, or when you need specific control not aviailble out of the box.
When to Use Custom ACF GraphQL Queries
Built-in ACF integration covers many use cases. Use custom GraphQL queries when you need:
- Filtering - Use ACF fields in query arguments
- Complex relationships - Complex ACF connections
- Custom formatting - Transform field values with expressions
- Performance control - Optimize expensive queries to get only the data you need
- Cross-context access - ACF fields from different post types together
ACF Field Access Methods
Understanding the difference between acf_value() and other ACF methods:
Builderius provides two approaches for accessing ACF fields - simple value retrieval and advanced object access. The choice depends on your needs when it comes to what data you need and how much control you need.
Simple vs Other Methods
Simple Method (acf_value):
Returns whatever format the ACF field is configured to return (with some exceptions) - could be just an ID, URL, or basic object depending on field settings. It is simple to use, but offers less control over what you can retrieve and how.
Advanced Methods (acf_post_object_value, acf_user_value, etc.) Pro Feature:
These methods require a couple more steps but they come with a lot of benefits. You get way more control. You can pick and choose what data you can retrieve and how. You get — complete control.
Post Object Example
Simple Method
- GraphQL
- JSON
GraphQL with acf_value():
{
post {
# Returns whatever the ACF field return format is set to
featured_article: acf_value(name: "featured_article")
}
}
JSON Output (depends on ACF field settings):
{
"featured_article": {
"ID": 123,
"post_author": "5",
"post_date": "2024-11-21 10:30:00",
"post_date_gmt": "2024-11-21 10:30:00",
"post_content": "<!-- wp:paragraph --><p>Full article content here...</p><!-- /wp:paragraph -->",
"post_title": "How to Build Better Websites",
"post_excerpt": "Learn the fundamentals...",
"post_status": "publish",
"comment_status": "open",
"ping_status": "open",
"post_password": "",
"post_name": "how-to-build-better-websites",
"post_modified": "2024-11-21 15:45:00",
"post_modified_gmt": "2024-11-21 15:45:00",
"post_parent": 0,
"guid": "https://site.com/?p=123",
"menu_order": 0,
"post_type": "post",
"post_mime_type": "",
"comment_count": "12"
}
}
Advanced Method
- GraphQL
- JSON
GraphQL with acf_post_object_value():
{
post {
# Select only the fields you need
featured_article: acf_post_object_value(name: "featured_article") {
post_title
permalink
featured_image {
file_url
alt_text
}
# Access ACF fields on the related post
reading_time: acf_value(name: "reading_time")
}
}
}
JSON Output (have their own subfields, from core or from ACF):
{
"featured_article": {
"post_title": "How to Build Better Websites",
"permalink": "https://site.com/how-to-build-better-websites/",
"featured_image": {
"file_url": "https://site.com/wp-content/uploads/hero.jpg",
"alt_text": "Website screenshot"
},
"reading_time": "8 minutes"
}
}
The key difference: The acf_post_object_value requires you to define at least one subfield. In the case of Post Object field, these can be any field attatched to a post object; native ones like post_title, post_excerpt etc. or other acf fields tieh a location set to post.
With out autocomplete it's easy to add these fields, and the benefits are important. The advanced method gives you control over which data you retrieve, making queries more efficient by requesting only what you need, rather than getting the entire object dump.
How do you later access these subfields? Use the Dynamic Data dropdown, click the post object field that appears, and select the subfield when the object expands in the dropdown. A [[custom.post.featured_article.post_title]] will be added to your element and it will render in the canvas.
Querying ACF Fields
- Simple Values
- Object Relationships
- Array Data
acf_value(name: "field_name") - Returns the field value
Applies to all basic field types:
- Text, Textarea, Number, Email, URL, Password
- Select, Radio, Checkbox, Button Group
- True/False (boolean)
- Date Picker, Time Picker, Date Time Picker
- Color Picker, Range, WYSIWYG Editor
- Image/File fields (when return format = URL or ID)
- Single selections from relationship fields
{
post {
# Text and content fields
subtitle: acf_value(name: "subtitle")
price: acf_value(name: "price")
featured: acf_value(name: "featured")
event_date: acf_value(name: "event_date")
brand_color: acf_value(name: "brand_color")
# Image field (URL format)
hero_image_url: acf_value(name: "hero_image")
# Transform values
formatted_price: expression_result(
expression: "'$' . price"
)
formatted_date: expression_result(
expression: "date('F j, Y', strtotime(event_date))"
)
}
}
Object fields return single structured data with named properties:
acf_group_value(name: "field_name")- Group fields (organized related data)acf_post_object_value(name: "field_name")- Single post relationshipacf_user_value(name: "field_name")- Single user relationshipacf_taxonomy_value(name: "field_name")- Single term relationship- Image fields - Use
acf_value()when return format = Array (single image object) - File fields - Use
acf_value()when return format = Array (single file object)
{
post {
# Group field - organized related data
contact_info: acf_group_value(name: "contact_details") {
phone: acf_value(name: "phone")
email: acf_value(name: "email")
address: acf_value(name: "address")
}
# Single post relationship
featured_article: acf_post_object_value(name: "featured_article") {
post_title
permalink
# Access ACF fields on related post
article_type: acf_value(name: "article_type")
reading_time: acf_value(name: "reading_time")
}
# Single user relationship
author: acf_user_value(name: "guest_author") {
display_name
user_email
# User ACF fields
job_title: acf_value(name: "position")
bio: acf_value(name: "bio_extended")
}
# Single taxonomy relationship
primary_category: acf_taxonomy_value(name: "main_category") {
name
slug
# Term ACF fields
category_color: acf_value(name: "color")
icon: acf_value(name: "category_icon")
}
# Image field (Array format) - single image object
hero_image: acf_value(name: "hero_image")
# File field (Array format) - single file object
brochure: acf_value(name: "product_brochure")
# Access object properties
hero_url: expression_result(
expression: "hero_image.url"
)
contact_email: expression_result(
expression: "contact_info.email"
)
}
}
Array fields return multiple values or collections:
acf_repeater_value(name: "field_name")- Repeater fields (array of row objects)acf_relationship_value(name: "field_name")- Relationship fields (array of post objects)acf_post_objects_value(name: "field_name")- Post Object fields set to multiple (array of post objects)acf_users_value(name: "field_name")- User fields set to multiple (array of user objects)acf_taxonomies_value(name: "field_name")- Taxonomy fields set to multiple (array of term objects)- Gallery fields - Use
acf_value()(array of image objects) - Select fields (multiple) - Use
acf_value()(array of selected values) - Checkbox fields - Use
acf_value()(array of checked values)
{
post {
# Repeater field - multiple instances
team_members: acf_repeater_value(name: "team") {
name: acf_value(name: "member_name")
role: acf_value(name: "position")
photo: acf_value(name: "headshot")
# Calculate within repeater
display_name: expression_result(
expression: "name . ' - ' . role"
)
}
# Relationship field (multiple posts)
related_articles: acf_relationship_value(name: "related_content") {
post_title
permalink
excerpt: acf_value(name: "custom_excerpt")
}
# Multiple post objects
recommended_products: acf_post_objects_value(name: "products") {
post_title
price: acf_value(name: "price")
in_stock: acf_value(name: "available")
}
# Multiple taxonomy terms
skill_areas: acf_taxonomies_value(name: "expertise") {
name
slug
proficiency: acf_value(name: "skill_level")
}
# Gallery field (array of images)
gallery: acf_value(name: "project_gallery")
# Multiple select field (array of selected options)
features: acf_value(name: "product_features")
# Checkbox field (array of checked values)
amenities: acf_value(name: "available_amenities")
# Process arrays
gallery_count: expression_result(
expression: "count(gallery)"
)
first_image: expression_result(
expression: "gallery[0].url"
)
features_list: expression_result(
expression: "join(features, ', ')"
)
total_skills: expression_result(
expression: "count(skill_areas)"
)
team_size: expression_result(
expression: "count(team_members)"
)
}
}
Filtering with ACF Fields
Use ACF fields in query arguments to filter posts, users, and terms based on custom field values.
Meta Query Syntax Reference
- Single Condition
- Multiple Conditions
- Data Types
- Comparison Operators
Basic single condition syntax:
meta_query: {
array: [
{
key: "field_name"
value: "field_value"
compare: "="
}
]
}
Examples:
# Text field
{
key: "status"
value: "published"
compare: "="
}
# Number field
{
key: "rating"
value: 5
compare: "="
type: "NUMERIC"
}
# Boolean field
{
key: "featured"
value: true
compare: "="
type: "BOOLEAN"
}
Combining conditions with AND/OR:
meta_query: {
relation: "AND" # or "OR"
array: [
{
key: "field1"
value: "value1"
compare: "="
}
{
key: "field2"
value: "value2"
compare: "="
}
]
}
Nested conditions:
meta_query: {
relation: "AND"
array: [
{
key: "status"
value: "active"
compare: "="
}
{
relation: "OR"
array: [
{
key: "priority"
value: "high"
compare: "="
}
{
key: "urgent"
value: true
compare: "="
type: "BOOLEAN"
}
]
}
]
}
Data type specifications:
Text fields (default):
{
key: "category"
value: "tutorial"
compare: "="
# No type needed - default is text
}
Numeric fields:
{
key: "price"
value: 100
compare: ">"
type: "NUMERIC"
}
Date fields:
{
key: "event_date"
value: "2024-12-01"
compare: ">="
type: "DATE"
}
Boolean fields:
{
key: "featured"
value: true
compare: "="
type: "BOOLEAN"
}
Decimal fields:
{
key: "rating"
value: 4.5
compare: ">="
type: "DECIMAL"
}
Comparison operators:
Equality:
compare: "=" # Equals
compare: "!=" # Not equals
Numeric comparisons:
compare: ">" # Greater than
compare: ">=" # Greater than or equal
compare: "<" # Less than
compare: "<=" # Less than or equal
Range comparisons:
{
key: "price"
value: [50, 200]
compare: "BETWEEN"
type: "NUMERIC"
}
{
key: "price"
value: [50, 200]
compare: "NOT BETWEEN"
type: "NUMERIC"
}
Text matching:
compare: "LIKE" # Contains text
compare: "NOT LIKE" # Does not contain text
Multiple values:
{
key: "status"
value: ["active", "pending"]
compare: "IN"
}
{
key: "status"
value: ["inactive", "deleted"]
compare: "NOT IN"
}
Field existence:
compare: "EXISTS" # Field has any value
compare: "NOT EXISTS" # Field is empty or missing
Use ACF filtering to find posts with specific field values, creating dynamic content based on custom field criteria.
Queries With ACF Filtering
- Basic Filtering
- Multiple Conditions
- Common Patterns
Simple field value filtering:
{
# Featured articles
featured_articles: posts_query(
arguments: {
post_type: "article"
meta_query: {
array: [
{
key: "featured"
value: true
compare: "="
type: "BOOLEAN"
}
]
}
}
) {
posts {
post_title
featured: acf_value(name: "featured")
}
}
Combining multiple field conditions:
{
# Articles that are both featured AND published
featured_published: posts_query(
arguments: {
post_type: "article"
meta_query: {
relation: "AND"
array: [
{
key: "featured"
value: true
compare: "="
type: "BOOLEAN"
}
{
key: "article_status"
value: "published"
compare: "="
}
]
}
}
) {
posts {
post_title
featured: acf_value(name: "featured")
status: acf_value(name: "article_status")
}
}
Common filtering patterns:
{
# Posts missing required fields (quality check)
incomplete_articles: posts_query(
arguments: {
post_type: "article"
meta_query: {
array: [
{
key: "author_bio"
compare: "NOT EXISTS"
}
]
}
}
) {
posts {
post_title
has_bio: expression_result(
expression: "acf_value('author_bio') ? 'Yes' : 'No'"
)
}
}
# Order by ACF field value
events_by_date: posts_query(
arguments: {
post_type: "event"
orderby: "meta_value"
meta_key: "event_date"
order: "ASC"
}
) {
posts {
post_title
event_date: acf_value(name: "event_date")
}
}
# Filter by relationship field
posts_by_author: posts_query(
arguments: {
post_type: "article"
meta_query: {
array: [
{
key: "guest_author"
value: 123
compare: "="
type: "NUMERIC"
}
]
}
}
) {
posts {
post_title
author: acf_user_value(name: "guest_author") {
display_name
}
}
}
}
Query ACF Based on Different Contexts
- Post Context
- Term Context
- User Context
- Navigation Context
- Options Context
Current Post:
{
post {
post_title
subtitle: acf_value(name: "subtitle")
event_date: acf_value(name: "event_date")
featured: acf_value(name: "featured")
}
}
Specific Post:
{
about_page: post(identifier: "slug", value: "about") {
post_title
company_name: acf_value(name: "company_name")
founding_year: acf_value(name: "founded")
}
}
Posts Loop:
{
articles: posts_query(
arguments: {
post_type: "article"
posts_per_page: 5
}
) {
posts {
post_title
reading_time: acf_value(name: "reading_time")
author_bio: acf_value(name: "author_bio")
}
}
}
Current Term (Archive Context):
{
archive {
term {
name
description
category_color: acf_value(name: "brand_color")
category_icon: acf_value(name: "icon")
}
}
}
Specific Term:
{
marketing_category: term(
identifier: "slug"
value: "marketing"
taxonomy: "category"
) {
name
description
header_image: acf_value(name: "category_header")
featured_on_homepage: acf_value(name: "featured")
}
}
Terms Loop:
{
categories: terms_query(
arguments: {
taxonomy: "category"
hide_empty: true
}
) {
terms {
name
slug
category_color: acf_value(name: "brand_color")
commission_rate: acf_value(name: "commission_rate")
}
}
}
Current User:
{
current_user {
display_name
user_email
job_title: acf_value(name: "position")
bio: acf_value(name: "bio_extended")
}
}
Specific User:
{
author_profile: user(identifier: "ID", value: 5) {
display_name
author_bio: acf_value(name: "author_bio")
website: acf_value(name: "personal_website")
}
}
Users Loop:
{
team_members: users_query(
arguments: {
role: "author"
number: 10
}
) {
users {
display_name
department: acf_value(name: "department")
hire_date: acf_value(name: "start_date")
}
}
}
Navigation Menu Items:
{
nav_menu(identifier: "slug", value: "main-menu") {
items {
title
url
menu_icon: acf_value(name: "menu_icon")
highlight_item: acf_value(name: "featured_menu_item")
children @recursive {
title
url
menu_icon: acf_value(name: "menu_icon")
}
}
}
}
Global Options (No Context Wrapper):
{
# Direct access at root level
site_logo: acf_value(name: "company_logo")
contact_email: acf_value(name: "main_contact_email")
# Group field
site_branding: acf_group_value(name: "brand_settings") {
primary_color: acf_value(name: "primary_color")
logo_dark: acf_value(name: "logo_dark_mode")
}
# Repeater field
social_links: acf_repeater_value(name: "social_media") {
platform: acf_value(name: "platform_name")
url: acf_value(name: "profile_url")
}
}
Key Context Rules
Posts: ACF fields accessed within post { ... } or posts { ... }
Terms: ACF fields accessed within term { ... } or terms { ... }
Users: ACF fields accessed within current_user { ... } or users { ... }
Navigation: ACF fields accessed within menu items { ... }
Options: ACF fields accessed directly at root level (no wrapper needed)
Advanced Field Metadata Access
ACF Field Configuration
Beyond accessing field values, you can also query the field configuration and metadata using acf_field_object(). This returns information about how the field is set up rather than the data it contains.
Here is an example of the acf_field_object() for acf image field
"acf_field_object": {
"ID": 148,
"key": "field_692155ef32f1e",
"label": "img",
"name": "img",
"aria-label": "",
"prefix": "acf",
"type": "image",
"value": null,
"menu_order": 2,
"instructions": "",
"required": 0,
"id": "",
"class": "",
"conditional_logic": 0,
"parent": 131,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"return_format": "array",
"library": "all",
"min_width": "",
"min_height": "",
"min_size": "",
"max_width": "",
"max_height": "",
"max_size": "",
"mime_types": "",
"allow_in_bindings": 0,
"preview_size": "medium",
"_name": "img",
"_valid": 1
}
When to use acf_field_object():
- Build dynamic interfaces that adapt based on field configuration
- Create conditional content based on field types and settings
- Access field choices for select/radio/checkbox fields
- Validate data against field constraints
- Display field labels and instructions dynamically
The key difference: acf_value() gives you the data, acf_field_object() gives you the schema.
Get Field Choices and Options
Access the available choices for select, radio, and checkbox fields:
{
color_field_config: acf_field_object(name: "product_color")
size_field_config: acf_field_object(name: "product_size")
}
Returns field configuration with choices:
{
"color_field_config": {
"type": "select",
"label": "Product Color",
"choices": {
"red": "Red",
"blue": "Blue",
"green": "Green"
}
}
}
Use case: Build dynamic dropdowns, display all available options, or show human-readable labels for selected values.
Field Labels and Instructions
Get field metadata for display purposes:
{
image_field_info: acf_field_object(name: "hero_image")
}
Returns field configuration:
{
"image_field_info": {
"type": "image",
"label": "Hero Image",
"instructions": "Upload a high-resolution image for the hero section",
"required": 1
}
}
Use case: Show field labels in forms, display help text, or add required field indicators.
Conditional Content Based on Field Types
Use field type information for conditional display in Builderius conditions tool:
{
dynamic_field_config: acf_field_object(name: "content_block")
dynamic_field_value: acf_value(name: "content_block")
}
Use case: In Builderius conditions, check if dynamic_field_config.type equals "image" to show image components, "wysiwyg" to show rich text, or "select" to display choice-based content. This allows one template to handle multiple field types dynamically.
Validation Rules and Constraints
Access field constraints for validation or display logic:
{
upload_constraints: acf_field_object(name: "profile_photo")
}
Returns validation rules:
{
"upload_constraints": {
"type": "image",
"required": 1,
"min_width": "300",
"max_width": "1200",
"mime_types": "jpg,jpeg,png",
"return_format": "array"
}
}
Use case: Display upload requirements to users, validate file dimensions, or determine how to process the field value based on return_format.
Dynamic Form Building
Query multiple field configurations to build forms dynamically:
{
contact_form_fields: {
name_field: acf_field_object(name: "contact_name")
email_field: acf_field_object(name: "contact_email")
country_field: acf_field_object(name: "contact_country")
message_field: acf_field_object(name: "contact_message")
}
}
Use case: Build contact forms or user input interfaces that adapt based on field configurations, showing appropriate input types and validation rules for each field.
Layout and Styling Configuration
Access wrapper attributes set in ACF field configuration (available on any field type):
{
# Any field type can have wrapper settings
name_field_config: acf_field_object(name: "contact_name")
image_field_config: acf_field_object(name: "hero_image")
}
Returns wrapper configuration from ACF admin settings:
{
"name_field_config": {
"type": "text",
"wrapper": {
"width": "50",
"class": "required-field",
"id": "contact-name"
}
}
}
Use case: Apply the same CSS classes, widths, and IDs that were configured in the ACF admin to your frontend elements for consistent styling.
Conditional Logic Rules
Access ACF conditional logic to replicate admin behavior on frontend:
{
membership_value: acf_value(name: "membership_type")
company_field_config: acf_field_object(name: "company_size")
premium_field_config: acf_field_object(name: "premium_features")
}
Returns conditional logic rules:
{
"membership_value": "premium",
"company_field_config": {
"conditional_logic": [
[
{
"field": "membership_type",
"operator": "==",
"value": "enterprise"
}
]
]
},
"premium_field_config": {
"conditional_logic": [
[
{
"field": "membership_type",
"operator": "==",
"value": "premium"
}
]
]
}
}
Practical use case:
- In Builderius conditions, show company size field only when
[[custom.membership_value]]equals "enterprise" - Display premium features section when
[[custom.membership_value]]equals "premium" - Build dynamic forms where field visibility matches exactly what users see in WordPress admin
- Create conditional content blocks that appear/disappear based on user selections, keeping frontend behavior synchronized with backend field logic
Field Object vs Field Value Summary
acf_value(name: "field_name")→ The actual data (what users entered)acf_field_object(name: "field_name")→ The configuration (how the field is set up)
Use acf_field_object() when building flexible, dynamic interfaces that need to adapt based on field configuration rather than field values.