TechEarl

How to Filter ACF Relationship Fields by Post Type

ACF Relationship fields let editors pick from any post type by default. The Post Type filter in the field group editor restricts the choice list. For dynamic filtering (taxonomy, status, ACF field), the acf/fields/relationship/query filter is the right tool.

Ishan Karunaratne⏱️ 5 min readUpdated
Share thisCopied
Filter ACF Relationship by post type via field setting; filter dynamically via acf/fields/relationship/query for taxonomy, status, and ACF-field conditions.

ACF Relationship fields default to showing every published post of every post type in the picker. The "Post Type" filter in the field group editor narrows it to specific post types. For dynamic conditions (only show posts in a specific category, only ones with a certain ACF field value, exclude the current post), the acf/fields/relationship/query filter is the right tool. Here is each pattern with concrete examples.

Jump to:

Static post type filter via the field group editor

The simplest filter is the built-in setting. In the field group editor:

  1. Edit the Relationship field.
  2. Find the "Filter by Post Type" setting.
  3. Select the post types you want to include.
  4. Save.

Multiple post types are allowed (a Relationship field that can link to both service and case_study posts, for example). The field group editor also has built-in "Filter by Taxonomy" and "Filter by Post Status" if those static filters cover your use case.

If a static filter is all you need, stop here. The acf/fields/relationship/query filter is for cases where the static settings are not enough.

Dynamic filtering: the acf/fields/relationship/query filter

acf/fields/relationship/query runs every time the Relationship picker queries posts. The filter receives the WP_Query arguments, the field config, and the current post ID, and returns modified arguments:

php
add_filter( 'acf/fields/relationship/query', function ( $args, $field, $post_id ) {
    // Only apply this filter to a specific field by key or name
    if ( $field['name'] !== 'related_services' ) {
        return $args;
    }

    // Modify $args here
    $args['post_status'] = 'publish';

    return $args;
}, 10, 3 );

The $field['name'] (or $field['key']) check is important: without it, the filter applies to every Relationship field on the site, which is rarely what you want.

Filter to a specific taxonomy term

Show only posts in the "featured" category:

php
add_filter( 'acf/fields/relationship/query', function ( $args, $field, $post_id ) {
    if ( $field['name'] !== 'featured_services' ) return $args;

    $args['tax_query'] = [
        [
            'taxonomy' => 'category',
            'field' => 'slug',
            'terms' => 'featured',
        ],
    ];

    return $args;
}, 10, 3 );

The editor now sees only services tagged "featured" in the picker.

Filter by ACF field value

Show only listings where the ACF field is_active is true:

php
add_filter( 'acf/fields/relationship/query', function ( $args, $field, $post_id ) {
    if ( $field['name'] !== 'active_listings' ) return $args;

    $args['meta_query'] = [
        [
            'key' => 'is_active',
            'value' => '1',
        ],
    ];

    return $args;
}, 10, 3 );

Caveat: meta_query against ACF True/False fields stores 1 for true and 0 (or empty string for older ACF versions) for false. The exact storage depends on ACF version; on older sites you may need a more permissive compare.

Exclude the current post from its own Relationship picker

A common need: a "Related posts" field on a post should not allow selecting the post itself. The $post_id argument is the current post being edited:

php
add_filter( 'acf/fields/relationship/query', function ( $args, $field, $post_id ) {
    if ( $field['name'] !== 'related_posts' ) return $args;

    if ( $post_id ) {
        $args['post__not_in'] = [ (int) $post_id ];
    }

    return $args;
}, 10, 3 );

The current post no longer appears in the picker. Editors stop accidentally creating self-references.

Filter based on the editor's role

Show only posts the current editor authored (useful for multi-author sites where editors should only relate their own content):

php
add_filter( 'acf/fields/relationship/query', function ( $args, $field, $post_id ) {
    if ( $field['name'] !== 'my_related_posts' ) return $args;

    $user = wp_get_current_user();
    if ( ! current_user_can( 'edit_others_posts' ) ) {
        $args['author'] = $user->ID;
    }

    return $args;
}, 10, 3 );

The current_user_can check lets administrators and editors with full permissions still see all posts, while restricted users only see their own.

Sort the picker order

The Relationship picker defaults to post_date DESC (newest first). To sort alphabetically:

php
add_filter( 'acf/fields/relationship/query', function ( $args, $field, $post_id ) {
    if ( $field['name'] !== 'related_pages' ) return $args;

    $args['orderby'] = 'title';
    $args['order'] = 'ASC';

    return $args;
}, 10, 3 );

For sorting by a custom meta value (e.g., a "priority" ACF field), use meta_key plus orderby = 'meta_value_num':

php
$args['meta_key'] = 'priority';
$args['orderby'] = 'meta_value_num';
$args['order'] = 'ASC';

The picker now shows posts in priority order, which is useful for curated lists like "featured products."

Performance considerations

The acf/fields/relationship/query filter runs every time the editor opens the Relationship picker, including paginated scrolling. Heavy queries here can make the editor feel slow.

Quick wins:

  • 'posts_per_page' defaults to 20 in the picker. Do not bump it higher than you need.
  • Avoid complex meta_query with many ANDs/ORs. If the filter is "show only posts where ACF field X matches Y," consider mirroring that condition into a custom taxonomy via the acf/save_post pattern in Useful Things You Can Do with acf/save_post, then filtering by taxonomy (which is much faster).
  • Cache where possible. If the filter logic depends on stable input (current user ID, current post ID), the WordPress object cache will handle it. If the filter depends on real-time state, no caching helps.

For directory sites with hundreds of thousands of posts, the picker can become genuinely slow regardless of caching. In that case, consider using a different field type (Post Object with autocomplete, or a custom React-based picker) rather than Relationship.

For the read-side patterns once the Relationship is populated, see Why ACF Relationship Fields Lose Their Selected Order. For the related-posts rendering pattern, see Simple Related Posts System Using ACF Relationship Fields.

Sources

Authoritative references this article was fact-checked against.

TagsWordPressACFRelationship FieldFilters

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts

How to Find the Largest Files on Disk (find, sort, du)

find / -xdev -type f -printf '%s %p\n' | sort -rn | head -20 gives you a ranked list of the biggest files on a full disk. The GNU one-liner, the BSD/macOS stat variant, why -xdev matters, human-readable output with numfmt, when to switch to du or ncdu for per-directory totals, and the mistakes that send a scan into /proc.