Guides

Developer guide

Metaobjects and dynamic sources for Shopify theme developers

A practical guide to using Shopify metaobjects and dynamic sources in themes, including where they fit with app blocks, where they do not fit with app embeds, and how app-backed systems should model content.

Published by Addora
Updated March 12, 2026
15 min read
Editorial note: This guide is for theme developers and app developers who keep finding the same nasty surprise: structured content is easy right up until the wrong extension surface gets involved.

Why metaobjects matter in real theme builds

The usual progression of a Shopify theme build goes like this. First, a merchant wants a nice little badge row, or a size chart, or a set of buying-guide callouts. Then they want the same thing on five product templates, then in a landing page, then with slightly different copy, then with images, links, and maybe a legal disclaimer. At that point your once-simple section schema is no longer a schema. It is an overgrown settings structure trying to behave like a content model.

That is where metaobjects become genuinely useful. Shopify describes them as structured data with multiple related field values, and that is the important part for theme developers. A metaobject is not just “more custom data.” It is a reusable record with a real shape, which means you can model something like an author, ingredient, badge, FAQ item, review snippet, or warranty card as an entity instead of as a pile of parallel text settings that slowly ruin your weekend.

“Metaobjects let you store structured data with multiple related field values.”

The contrast with metafields matters. Shopify’s own data-modeling guide frames metafields as the equivalent of adding extra fields to existing resources, while metaobjects are closer to defining a new kind of record entirely. In practical theme terms, a metafield is often the glue on a product, collection, or page, and a metaobject is often the thing being referenced by that glue.

ToolWhat it is good atWeakness if overusedTypical example
Section settingsFast, local customization for one section instanceContent gets duplicated and trapped inside presentationA one-off homepage hero
MetafieldsAttach custom data to an existing Shopify resourceSingle fields become awkward when the concept is really a recordProduct warranty reference
MetaobjectsReusable structured entities with multiple related fieldsOverkill for tiny one-off contentIngredient, author, testimonial, feature card
App-data metafieldsHidden installation-level state and flagsTerrible merchant content UXFeature gate for an app block

Metaobjects matter even more once a store matures because they survive theme iteration better than section-only content. Sections come and go. Merchants redesign. Templates get swapped. An app gets installed, uninstalled, and replaced with another app that also wants to read the same conceptual data. Reusable content models age much better than giant schemas full of “heading_7”, “image_7”, and “please forgive me_7”.

Shopify also supports using metaobjects as actual web pages through metaobject templates when the definition has the onlineStore capability enabled, and Shopify recommends enabling renderable as well so SEO fields are exposed to Liquid and the Storefront API. That is a strong reminder that metaobjects are not just storage. They can become a first-class content layer in the storefront architecture.

The useful mental model

Use section settings for presentation-local knobs. Use metafields for resource-attached data. Use metaobjects for reusable content records. Use app-data metafields for hidden app state. Most ugly Shopify architecture starts when those four jobs get mixed together.

Where dynamic sources fit well

Dynamic sources are the bridge between “the data exists somewhere in Shopify” and “a merchant can actually bind that data to a theme surface without calling you in a mild panic.” They let merchants connect settings to Shopify resources, metafields, and metaobjects in the theme editor. That means the win is not only technical reuse. The win is merchant-operable reuse.

Shopify’s docs are explicit that dynamic sources can pull from standard resources like products and collections, as well as metafields and metaobjects. Theme blocks can resolve dynamic sources from the template resource, section resource settings, ancestor block settings, or Liquid-passed resource drops. That makes dynamic sources especially useful in componentized theme architectures where a block should adapt to the current product, collection, article, or whatever object the template is carrying around.

“Dynamic sources allow merchants to connect input settings to data coming from resources.”

The sweet spot is structured content that should vary by resource or template without requiring custom Liquid for every new store request. Good examples include:

  • Product materials, ingredients, or specifications attached through metafields or metaobject references.
  • Collection-level buying guide content rendered into reusable promotional blocks.
  • Editorial modules like trust badges, founder cards, or store guarantees that are shared across templates.
  • Section and block setups where merchants want to swap content in the editor instead of editing code.

There is an important constraint that a lot of people miss on the first pass. Dynamic source support is not universal. Shopify publishes a compatibility matrix between setting types and metafield types, and the platform only lets you wire up combinations that make sense. In other words, you cannot just wave a metaobject at a random setting and expect Liquid to salute.

Theme settingDynamic source shapeWhat that means in practice
text / richtext / inline_textCompatible text-like field typesYou can bind text-like metaobject fields, not arbitrary nested data blobs
image_pickerfile_referenceUseful for image fields on metaobjects like badges, materials, or authors
metaobjectmetaobject_referenceWorks when the referenced type matches the setting schema
metaobject_listlist.metaobject_referenceUseful for repeated records like FAQ items, benefits, or materials

That last pair is particularly worth noting because Shopify added metaobject and metaobject_list theme settings so sections and blocks can consume metaobjects of a specified type. This made metaobject-driven theme design much less hacky than the old world of “please put sixteen references in separate fields and try not to cry.” If you build distributed Theme Store themes, Shopify also documents that only standard definitions are allowed as the metaobject_type there, which is a very real constraint for theme vendors.

Shopify also documents that when selecting a metaobject as a dynamic source, merchants can bind any field that is compatible with the target setting type. That means a single metaobject can feed multiple theme settings cleanly. A “material” metaobject might expose a text field to a rich text setting, an icon to an image setting, and a URL to a link setting, all from one structured record instead of from a circus tent full of disconnected fields.

Example: product-attached structured content

A solid pattern is to attach a list.metaobject_reference metafield to a product and let the theme consume a field from each referenced entry through a compatible setting. Shopify’s dynamic source docs show this exact pattern with a materials metaobject list.

{% if product.metafields.custom.materials.value != blank %}
  <ul class="product-materials">
    {% for material in product.metafields.custom.materials.value %}
      <li>
        {{ material.material_name.value }}
      </li>
    {% endfor %}
  </ul>
{% endif %}

The point is not the loop itself. The point is that the product owns the relationship, while the metaobject owns the reusable structure. That separation gives you cleaner content modeling, cleaner admin UX, and fewer support tickets that start with “we changed the theme and now all our certification badges look haunted.”

One more operational detail: Shopify publishes dynamic-source limits for performance reasons, including limits per JSON template, general theme settings, section groups, single settings, and static sections. If your architecture relies on dynamic sources everywhere, keep an eye on those limits before the theme editor turns into an expensive game of content Tetris.

Where theme app extensions change the rules

This is the section where hopeful developers meet platform reality. Theme App Extensions do not expose one unified capability model. App blocks and app embeds are siblings in the docs, but not in actual behavior.

Shopify positions app blocks as inline content that merchants can add, remove, and reorder at the section level. App blocks can use resource settings with autofill, and Shopify explicitly documents that app blocks are a fit when you want the app to automatically point to dynamic sources. That is a huge signal. It means app blocks are the right extension surface when content needs to inherit context from the surrounding template or section.

App embeds are different. They target global placement surfaces like head, compliance_head, or body, and Shopify’s docs state plainly that app embed blocks only have access to the global Liquid scope for the page where they render. In the migration docs Shopify goes even further and tells you to use app blocks if you want apps to automatically point to dynamic sources.

“App embed blocks only have access to the Global Liquid scope for the page on which they’re rendered.”

SurfaceBest forDynamic-source storyCommon mistake
App blockMerchant-placed content within theme sectionsStrong. Supports app-block settings and autofill for resource settingsTreating it like a sitewide behavior injector
App embedGlobal JS, global CSS, trackers, widgets, behavior togglesConstrained. Global Liquid scope only, not full dynamic-source ergonomicsBuilding it like a rich editorial content block

This is why app-backed content systems go sideways so often. A team builds a good structured content model, usually with metaobjects, then assumes the same model will bind equally well into an app embed, because hey, it is all “theme stuff,” right? Wrong. Very wrong. Almost insultingly wrong.

If your feature needs merchant placement near product information, collection merchandising, or page-specific content modules, an app block is usually the right Shopify-native surface. If your feature needs global runtime behavior, sitewide instrumentation, or page-level activation, app embeds are excellent. But app embeds are not a secret second type of app block. They are a different tool with a different scope model.

Example: autofill on an app block

Shopify documents autofill for resource settings in app blocks. That lets an app block inherit a relevant dynamic source when a merchant adds it to a section that already has the matching resource context. This is precisely the kind of ergonomics you do not get from an app embed.

{{ block.settings.product.handle }}
 
{% schema %}
{
  "name": "Rating summary",
  "target": "section",
  "settings": [
    {
      "type": "product",
      "id": "product",
      "label": "Product",
      "autofill": true
    }
  ]
}
{% endschema %}

In plain English, this means the block can follow the surrounding product context instead of forcing the merchant to manually pick a product every time. That is not just a UX nicety. It is a design boundary. It tells you the surface was built for contextual content.

The boring rule that saves projects

If a merchant should place, move, and contextually bind the thing, prefer an app block. If the thing should run globally, inject assets, or toggle sitewide behavior, prefer an app embed. Do not make the app embed pretend to be a CMS block with better hair.

A good app-backed content architecture

A good architecture starts by separating four concerns: who owns the schema, who edits the content, where the content is attached, and which storefront surface renders it. Once you split those concerns, metaobjects and dynamic sources become much easier to reason about.

1. Decide ownership on purpose

Shopify supports both app-owned and merchant-owned metaobjects. App-owned metaobjects use the reserved app prefix, and Shopify documents them as a fit for app-managed data structures like configuration panels, content templates, or complex product attributes. Merchant-owned metaobjects use a non-reserved type and are better when the store should own and manage the content in Shopify admin or across multiple apps.

That means the choice should follow governance, not developer convenience:

  • Use app-owned metaobjects when your app defines the schema and lifecycle.
  • Use merchant-owned metaobjects when the content should feel like store content, not app internals.
  • Use app-data metafields when the data is installation state, a feature flag, or hidden config.

2. Attach reusable records through metafields where the relationship belongs

A powerful pattern is: metaobject for the reusable record, metafield for the relationship, dynamic source for the theme binding. For example, a product gets a metafield that references one or more “benefit” metaobjects. The theme section or block then consumes compatible fields from those records. That model is stable because it mirrors the actual domain instead of the rendering shortcut.

In database language, which Shopify itself uses in its data-modeling guide, the metaobject is closer to the new table and the metafield reference is closer to the relationship. Shopify literally explains this world in terms of tables, columns, foreign keys, and constraints, which is refreshing because for once the docs are not pretending you are here to build vibes.

3. Let the theme consume Shopify-native data, not your app’s temporary mood

If your app has editorial workflows, it can still be the system that creates or synchronizes the data. But the storefront should consume stable Shopify-native structures whenever possible. That usually means your app writes or syncs definitions and entries, then the theme reads metaobjects, metafields, and compatible dynamic sources.

[metaobjects.app.feature_callout]
name = "Feature callout"
access.admin = "merchant_read_write"
access.storefront = "public_read"
 
[metaobjects.app.feature_callout.fields.heading]
name = "Heading"
type = "single_line_text_field"
 
[metaobjects.app.feature_callout.fields.body]
name = "Body"
type = "multi_line_text_field"
 
[metaobjects.app.feature_callout.fields.icon]
name = "Icon"
type = "file_reference"
 
[metaobjects.app.feature_callout.fields.link]
name = "Link"
type = "link"

This kind of definition is great when the app owns the content model. But remember the architectural question is not just “can I create this definition?” It is also “who should own editing rights, who should understand this in the admin, and does this content need to outlive my app?” If the answer is yes, merchant-owned structures are often the more honest model.

4. Reserve app embeds for behavior, not rich content wiring

Use app embeds for the things they are actually good at: loading scripts, injecting styles, turning on global widgets, or activating page-level behaviors. If you are trying to build a structured editorial system around an app embed, stop and ask whether you are really trying to use the wrong storefront surface.

Typical good app-embed jobs include analytics bootstrapping, consent-aware scripts, global announcement logic, chat launchers, or sitewide personalization behavior. Typical bad app-embed jobs include “merchant places this beside the product title and binds it to a metaobject list that changes per template.” That second sentence is the platform equivalent of trying to butter bread with a socket wrench.

5. Use metaobject pages when the content deserves a URL

Some content should not just be injected into product or page templates. It should have its own page model. If you are building buying guides, authors, brand stories, materials libraries, certification directories, store policies, or location records, metaobject theme templates can be an excellent fit. Shopify documents that you need the onlineStore capability for metaobject webpages and recommends enabling renderable for SEO fields management.

That also means a theme can mix two roles cleanly: using metaobjects as reusable fragments inside sections, and using metaobjects as full page entities when they deserve their own route. Good content models often need both.

6. Design for operational failure, not just the happy path

A few recurring gotchas are worth designing around:

  • Do not assume every setting type can consume every field type. Check compatibility.
  • Do not set product-related defaults in contexts where no product exists.
  • Do not forget storefront visibility when expecting a metaobject to behave like a globally available source.
  • When publishable capability is enabled, remember draft metaobjects resolve to nil in Liquid.
  • Do not let your app own editorial content forever unless that governance choice is intentional.

That last draft-state issue is sneaky. Shopify’s Liquid docs note that when publishable capability is enabled, a metaobject can only be accessed if its status is active. So if a developer says “dynamic sources are broken” there is a non-zero chance the platform is innocent for once and the content is still draft.

A practical default architecture

ConcernRecommended defaultWhy
Reusable content recordMetaobjectGives a stable schema with multiple related fields
Attach that record to a product or collectionReference metafieldKeeps the relationship where it belongs
Merchant-controlled visual placementTheme section, theme block, or app blockFits theme editor placement and contextual binding
Automatic context inheritance in an app surfaceApp block with resource setting autofillShopify supports this directly
Global runtime behaviorApp embedFits global page scope and asset injection
Hidden installation configApp-data metafieldKeeps non-editorial state out of merchant content models

If you follow that shape, your theme stays more portable, your app stays more honest, and your merchant gets a content system that still makes sense three redesigns later. That is the real goal. Not “can I technically make Liquid print a thing today?” but “will this still be sane after the next PM has a brilliant idea at 4:47 PM on a Friday?”

Best internal links

Sources and further reading

FAQ

When should I use a metaobject instead of ordinary section settings?

Use a metaobject when the content should be reusable across pages, shared across multiple resources, or modeled as a stable entity with multiple fields. Use ordinary section settings when the content is truly local to one section instance.

Can app embeds consume dynamic sources the same way app blocks can?

No. Shopify documents that app embed blocks only have access to the global Liquid scope of the page. If you need automatic dynamic-source behavior and merchant placement inside sections, use an app block instead.

Should my app create app-owned or merchant-owned metaobjects?

Use app-owned metaobjects when your app owns the schema and lifecycle. Use merchant-owned metaobjects when the store should own and freely manage the content in Shopify admin and potentially across multiple apps.

Are metaobjects a replacement for app-data metafields?

No. Metaobjects are for structured content or reusable records. App-data metafields are better for hidden installation-level state, feature flags, or config that should not be modeled as merchant-facing editorial content.

Related resources

Keep exploring the playbook

Guides

Shopify app embeds explained for real apps

An operator-focused technical guide to Shopify app embeds: what they are good for, how they differ from app blocks, how activation works, and the architectural constraints real apps run into.

guidesShopify developerapp embeds