Using Plugins
Querying Data
Learn how to query data from your plugins using GraphQL
Query Naming Convention
UDL generates two types of queries for each content type:
| Query Type | Pattern | Returns | Example |
|---|---|---|---|
| Collection | all{Prefix}{Type} | Array | allContentfulProducts |
| Single | {prefix}{Type} | Object or null | contentfulProduct |
Collection Queries
Fetch all entries of a type:
query {
allContentfulProducts {
name
slug
price
description
}
}
Returns an array of matching items:
{
"data": {
"allContentfulProducts": [
{ "name": "Product A", "slug": "product-a", "price": 29.99 },
{ "name": "Product B", "slug": "product-b", "price": 39.99 }
]
}
}
Single Item Queries
Fetch a single item by an indexed field:
query GetProduct($slug: String!) {
contentfulProduct(slug: $slug) {
name
price
description
}
}
Variables:
{
"slug": "product-a"
}
Returns a single object or null if not found:
{
"data": {
"contentfulProduct": {
"name": "Product A",
"price": 29.99,
"description": "A great product"
}
}
}
Working with References
Content often links to other content. Use inline fragments to access referenced entries:
Single Reference
query {
contentfulProduct(slug: "my-product") {
name
# Reference to another entry type
category {
... on ContentfulCategory {
name
slug
}
}
}
}
Array of References
query {
contentfulProduct(slug: "my-product") {
name
# Array of linked entries
variants {
... on ContentfulVariant {
name
sku
price
inStock
}
}
}
}
Asset References
Assets (images, files) use the same pattern:
query {
contentfulProduct(slug: "my-product") {
name
image {
... on ContentfulAsset {
title
description
file {
url
contentType
details {
size
image {
width
height
}
}
}
}
}
}
}
Multiple Image References
query {
contentfulProduct(slug: "my-product") {
name
gallery {
... on ContentfulAsset {
file {
url
}
}
}
}
}
Inline Fragments
Inline fragments (... on Type) are required for polymorphic fields where the actual type isn't known at compile time. This includes:
- Reference fields - Links to entries/assets
- Union types - Fields that can be multiple types
- Interface types - Fields implementing an interface
The pattern is:
fieldName {
... on PossibleType1 {
# fields from PossibleType1
}
... on PossibleType2 {
# fields from PossibleType2
}
}
Nested References
References can be nested to any depth:
query {
contentfulProduct(slug: "my-product") {
name
category {
... on ContentfulCategory {
name
parentCategory {
... on ContentfulCategory {
name
slug
}
}
}
}
}
}
Internal Metadata
Every node includes an internal field with metadata:
query {
allContentfulProducts {
name
internal {
type
contentDigest
}
}
}
This is useful for cache invalidation and debugging.
Query Optimization Tips
- Request only needed fields - GraphQL returns exactly what you ask for
- Use indexed fields for lookups - Configure
indexesin your plugin for O(1) queries - Batch related queries - Fetch related data in a single request
- Use aliases - Fetch the same field with different arguments in one query
Example: Optimized Query
query ProductPage($slug: String!) {
# Main product
product: contentfulProduct(slug: $slug) {
name
description
price
image {
... on ContentfulAsset {
file { url }
}
}
}
# Related products (batch in same request)
featured: allContentfulProducts {
name
slug
price
}
}
Next Steps
- Code Generation - Generate TypeScript types for your queries
- Typed Queries - Full type safety with TypedDocumentNode