Dev.to WebDev πŸ›  Dev πŸ‘ 0 πŸ“– 5 min read

A Metaobject Overview Grid for the Horizon Theme on Shopify

Written by Arno Breitfuss, Full-Stack Developer at Digit-One. Sections on Shopify, such as a grid on an overview page, used to be painfully static: one layout, hardcoded in Liquid, changeable only by a developer. With m

A Metaobject Overview Grid for the Horizon Theme on Shopify

Written by Arno Breitfuss, Full-Stack Developer at Digit-One.

Sections on Shopify, such as a grid on an overview page, used to be painfully static: one layout, hardcoded in Liquid, changeable only by a developer. With metaobjects and theme blocks, it is finally possible to make, for example, such overviews dynamic. We explain how we built such a metaobject overview grid for the Horizon theme.

A grid for more than just events

Once again, one of our projects needed a grid for an overview page, this time for events. Instead of tailoring it to that one case, we wanted to build a metaobject overview grid so it could be reused for any metaobject.

The events consist of:

  • Title & image
  • Short description
  • Date including time
  • Exact address

That is already a very specific use case. If the same grid later shows product manufacturers, for example, the address may still fit as the company address. A date, however, makes no sense at all for manufacturers.

So the grid has to be built in a way that:

  • the filters can be chosen freely
  • the cards are freely configurable
  • the initial sort order is easy to change

Here is the grid in the editor: the metaobject type is selectable, filters are configurable as theme blocks, and the cards are made of theme blocks as well. The code is accessible on GitHub.

Shopify theme editor showing the metaobject grid settings for events and a preview with two event cards

Filters as theme blocks

On the collection page, Shopify provides the filters. Search & Discovery only knows products, though, and there is no facet API for metaobjects. The filters are therefore theme blocks of their own, dragged into the section in the theme editor:

  • _metaobject-filter-text for values such as city or category
  • _metaobject-filter-date for a from/to date range

Each block has two settings: a label and the handle of the field it filters on. For events, that is a text filter on ort_stadt and a date filter on datum. For a manufacturer grid, the text filter stays and the date filter is simply dropped. No code changes.

While rendering, the text filter collects every value of the field across all entries, including list fields, removes duplicates regardless of upper and lower case, and turns them into checkboxes. In addition, each filter writes a JSON map into the page that records which entry has which values:

{
  "yoga-am-see": ["salzburg"],
  "staedte-lauf": ["linz"]
}

Special filters, like the date for events, can then be implemented just as easily:

Theme editor showing the date filter settings and the open from/to field in the preview

The filter state is simply stored in the query string and read with JavaScript:

?ort_stadt=musterhausen&datum_from=2026-10-01&datum_to=2026-10-31

More about metaobjects

GitHub logo digit-one-dev / horizon-metaobject-grid

A fork from the Horizon theme with a fully configurable metaobject overview grid section.

Horizon

This fork adds a metaobject grid section with client-side filters and pagination, built on Horizon's own filter UI. See docs/metaobject-grid.md.

Getting started | Staying up to date with Horizon changes | Developer tools | Contributing | License

Horizon is the flagship of a new generation of first party Shopify themes. It incorporates the latest Liquid Storefronts features, including theme blocks.

  • Web-native in its purest form: Themes run on the evergreen web. We leverage the latest web browsers to their fullest, while maintaining support for the older ones through progressive enhancementβ€”not polyfills.
  • Lean, fast, and reliable: Functionality and design defaults to "no" until it meets this requirement. Code ships on quality. Themes must be built with purpose. They shouldn't support each and every feature in Shopify.
  • Server-rendered: HTML must be rendered by Shopify servers using Liquid. Business logic and platform primitives such as translations and money formatting…

Horizon's product card as the model

Horizon already shows how cards can be composed from theme blocks. The product list does this by passing each card its product as context:

{% content_for 'block',
  type: '_product-card',
  id: 'static-product-card',
  closest.product: product
%}

With static-product-card, the block ID is static and tells Shopify that one configuration of the card applies to all products. The _product-card type passes closest.product on to its blocks: gallery, title, price, text. A text block knows nothing about the loop. The text block's dynamic source points at the current product, and every card in the grid follows.

The same card, a different object

But closest also accepts a metaobject, addressed by the handle of its definition. For events:

{% content_for 'block',
  type: '_metaobject-card',
  id: 'static-metaobject-card',
  closest.metaobject.veranstaltung: entry
%}

Unlike a product, though, a metaobject only has the fields someone has defined. That is why _metaobject-card is only the shell, passing the entry through to Horizon's own blocks:

{% content_for 'blocks', closest.metaobject.veranstaltung: entry %}

Because the block ID is static again, this composition is stored once on the section:

Theme editor with metaobject fields such as date, title and location selected for the card's text block

The date sets the order

The metaobject overview grid can be extended with custom sort orders. If none is selected, entries are sorted alphabetically. For product manufacturers, for example, that is enough.

For events, there is a sort order by date. It is enabled with a checkbox in the section settings and takes the handle of the date field, datum by default. The next event then comes first, and past events drop out, both from the grid and from the filters.

In exactly the same way, the grid could be extended with any other default sort order!

Where Liquid hits its limits

In a single pass, metaobjects[type].values returns at most 250 entries. That is enough for our use case, but since past events should not be shown, it is up to the store owner to delete outdated entries.

Past events are still counted among the 250 and cannot be filtered out beforehand!

Conclusion

With theme blocks and the closest convention, Horizon brings everything needed to display metaobjects as flexibly as products.

Cards, filters and sorting are put together in the theme editor instead of being hardcoded in Liquid, and the same grid can be reused for events, manufacturers or locations. The filters follow the collection page and feel familiar to customers.

This takes load off development and gives merchants the freedom to design overview pages themselves. The limits lie with very large amounts of data, but for most use cases this makes metaobjects in Horizon a big step towards a full-fledged content management system.

This post first appeared on the Digit-One blog. The full section code is on GitHub. Questions about the approach are welcome in the comments.

πŸ“° Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.