Query Items
This page covers how to loop over raw data — static arrays, ACF repeater fields, or any dynamic data.
Unlike the Post, Term, and User query types, Item doesn't query the database. It wraps existing data so you can loop over it.
Basic usage
Paste this directly into the Item Source field in the Loop block's sidebar:
[
{"name": "Home", "url": "/"},
{"name": "About", "url": "/about"}
]
Inline arrays
Array of objects
Each object becomes an item with named properties:
[
{"name": "Home", "url": "/"},
{"name": "About", "url": "/about"},
{"name": "Contact", "url": "/contact"}
]
Simple values
When items are plain strings or numbers, item is the value itself:
["Home", "About", "Services", "Contact"]
Numbered items
[0, 1, 2, 3, 4]
Key-value pairs
When items are an object (associative array), each item is a value, as in Twig:
{
"color": "red",
"size": "large",
"weight": "2kg"
}
To get the keys too, name them before the value, separated by a comma. In the sidebar, set the data alias to key, value; in the inspector, write:
{% for key, value in get_items() %}
<dt>{{ key }}</dt>
<dd>{{ value }}</dd>
{% endfor %}
In a list, the key is the position of the item, from 0.
These fields return a map, ready for a key-value loop:
request.getandrequest.postwithout a key: parameter names and valuespost.metaandpost.raw_metawithout a key: meta keys and valuespost.terms('all', {merge: false}): each taxonomy and its termssite.theme: the theme's fields- a product's
default_attributes, and a variation'svariation_attributes: attribute slugs and values
{% for name, value in request.get %}
<dt>{{ name }}</dt>
<dd>{{ value }}</dd>
{% endfor %}
Rows of items
batch groups a list into rows: loop over the rows, then over each row in a nested Loop block.
{% for row in post.meta('gallery', {transform_value: true})|batch(3) %}
<div class="row">
{% for image in row %}
<img src="{{ image.src('medium') }}" alt="{{ image.alt }}">
{% endfor %}
</div>
{% endfor %}
ACF fields
Enter a dynamic expression in the Item Source field to loop over ACF data. A plain name is read first as the name of a Variable, then as an expression.
Repeater fields
Loop over repeater rows — each row's sub-fields become item properties:
post.meta('team_members')
Nested repeaters — use a second Loop block inside the first, whose data alias is member here:
member.social_links
Relationship and post object fields
With transform_value, these return full post objects, whatever the field's return format, so you can access post provider fields directly:
post.meta('related_posts', {transform_value: true})
{% for item in post.meta('related_posts', {transform_value: true}) %}
<a href="{{ item.link }}">{{ item.title }}</a>
{% endfor %}
This also works with user, taxonomy, image, and gallery fields. Without the option, you get what ACF returns, as in Timber: see Relational fields.
More examples
Navigation menu
[
{"label": "Home", "url": "/", "icon": "home"},
{"label": "Products", "url": "/products", "icon": "shop"},
{"label": "Blog", "url": "/blog", "icon": "pen"},
{"label": "Contact", "url": "/contact", "icon": "mail"}
]
Social links
[
{"name": "Twitter", "url": "https://twitter.com/yourhandle", "icon": "twitter"},
{"name": "GitHub", "url": "https://github.com/yourhandle", "icon": "github"},
{"name": "LinkedIn", "url": "https://linkedin.com/in/yourhandle", "icon": "linkedin"}
]
Pricing table
[
{"name": "Starter", "price": "9", "features": "5 projects, 1GB storage"},
{"name": "Pro", "price": "29", "features": "Unlimited projects, 50GB storage"},
{"name": "Enterprise", "price": "99", "features": "Everything, priority support"}
]
Template examples
In the HTML inspector, a Loop block over a JSON list or object shows as get_items(), with empty parentheses: the data stays in the sidebar. An expression source shows as the expression itself. get_items only exists in this tag: it isn't a function you can call in an expression.
Feature list from custom fields
{% for item in post.meta('features') %}
<div class="feature">
<h3>{{ item.title }}</h3>
<p>{{ item.description }}</p>
</div>
{% endfor %}
FAQ accordion from repeater
{% for item in post.meta('faq') %}
<details>
<summary>{{ item.question }}</summary>
<p>{{ item.answer }}</p>
</details>
{% endfor %}
get_items() is for data you already have. If you need to query posts from the database, use get_posts() — not get_items() with a list of post IDs.
Next steps
- Loop — loop concept and data sources
- get_posts() — query posts from the database