Custom Posts
We use fields customPost
and customPosts
to fetch CPT data, both for CPTs that are mapped to the schema (such as Post
and Page
) or not (such as a CPT from some plugin). Because the results can include entities from different types, these fields return the CustomPostUnion
type.
We indicate the CPTs to retrieve via field argument filter.customPostTypes
, which receives a list of strings, with the CPT names as defined in WordPress (such as "post"
, "page"
, etc). For instance:
{
customPosts(
filter: { customPostTypes: ["some-custom-cpt"] }
) {
... on CustomPost {
id
title
}
}
}
Querying CPTs mapped to the schema permalink
There are CPTs which have been mapped to the schema (such as Post
and Page
to represent CPTs "post"
and "page"
). In this case, the query will be resolved using the corresponding GraphQL type for that CPT.

When fetching results from a union type, we need to specify the fields to retrieve through fragments. These can be evaluated on interface CustomPost
, which is implemented by all CPT types, or on each individual type, such as Post
or Page
.
In the query below, we fetch custom posts with CPTs "post"
and "page"
. We display their fields through 3 fragments, which evaluate if the entity implements CustomPost
, or is of type Post
or Page
:
Querying CPTs not mapped to the schema permalink
When a CPT has not been mapped to the schema yet (such as "attachment"
, "revision"
or "nav_menu_item"
, or any CPT installed by any plugin), we still use fields customPost
and customPosts
, and we must pass the corresponding CPT name under the filter.customPostTypes
field arg.
Because their types do not exist in the schema, their data will be retrieved via type GenericCustomPost
, which contains all the common properties to CPTs (title, content, excerpt, date, etc).

In the query below, we fetch custom posts for a variety of CPTs:
Allowing access to unmapped CPT types permalink
The CPTs accessible via the GenericCustomPost
type must be explicitly configured in the plugin Settings page, as explained in guide Adding a custom post type to the schema.
Filtering CPTs by a custom taxonomy permalink
A custom post type can have custom taxonomies (tags and categories) associated to them. For instance, a CPT "product"
may have associated the category taxonomy "product-cat"
and the tag taxonomy "product-tag"
.
We can filter results by these associated taxonomies, via inputs tagTaxonomy
and categoryTaxonomy
in the filter
input.
In the query below, we fetch custom posts filtering by category:
{
customPosts(
filter: {
categoryIDs: [26, 28],
categoryTaxonomy: "product-cat"
}
) {
... on CustomPost {
id
title
}
... on GenericCustomPost {
categories(taxonomy: "product-cat") {
id
}
}
}
}
Fetching custom CPT data permalink
Using GenericCustomPost
, we can only request those fields which are common to all CPTs; fetching custom data from some CPT is not supported (such as fetching the price data for a custom CPT "product"
).
To fetch custom CPT data, instead, we need to create the corresponding resolvers, in PHP code, to map the CPT to the schema:
- Create a type
Product
- Attach a
price
field to it
Now, the CustomPostUnion
type (returned by Root.customPosts
) will resolve all entries from this CPT to a Product
type.
{
customPosts(
filter: {
customPostTypes: "product"
}
) {
__typename
...on CustomPost { # interface implemented by all CPT types
id
title
customPostType
status
}
...on Product { # custom CPT type
price # custom field
}
}
}
We can additionally create field Root.products: [Product!]
, and use it directly:
{
products {
__typename # Product
id
title
status
price # custom field
}
}