Shop metafields not accessible in liquid

Topic summary

A developer struggled to access shop metafields in Liquid templates despite proper namespace/key configuration (custom.mto_shirt_form_data) and storefront API access enabled. Standard access patterns like shop.metafields.custom.mto_shirt_form_data.value returned null or empty objects.

Troubleshooting attempts included:

  • Verifying storefront access checkbox in Settings > Custom data > Shop
  • Testing various Liquid syntax patterns with JSON filters
  • Switching to metaobjects, which also failed initially
  • All attempts returned null values or error messages

Root cause (resolved):
The developer was incorrectly entering data into the metafield schema definition rather than creating actual metaobject entries. Once proper metaobject entries were created separately from the schema, the Liquid references worked as expected.

Key takeaway: Metaobjects require creating individual entries beyond just defining the schema. The issue highlighted confusion around Shopify’s metafield/metaobject system complexity and poor admin UX for distinguishing schema definitions from actual data entries.

Summarized with AI on October 26. AI used: claude-sonnet-4-5-20250929.

I’m losing my mind here. I’ve declared a shop metafield at this namespace and key (yes there’s only one input box for the both of them separated by a “.”) “custom.mto_shirt_form_data” and have given it a JSON value which is correctly formatted and is only 8 bytes. This is how I try to access it “{% assign form_data = shop.metafields.custom.mto_shirt_form_data.value %}” and it gives me nothing. Nor does “shop.metafields.custom.mto_shirt_form_data”, nor does, “shop.metafields.custom”, nor does “shop.metafields” (I’ve tried them all as JSON and not). But “shop” logs as “DropShop” (from memory), which is supposedly fine so the theme I’m using (Madrid) hasn’t changed it.

I have no clue why this is so hard to access. I can add all the data I need in JS, access it and build the form I want to build with basically just JS, but I wanted to do things the “right” way, which has had me furiously trying to access some data for 4 hours that from everything I’ve seen, should be really simple, but is resulting in nothing but mounting anger.

Please let me know what I’m doing wrong or if there’s something odd that might be preventing this from working. I’m all ears. Trust me I’ve been in circles with check on this from mr GPT himself, and he seems to have nothing for me…

1 Like

Hi @grob :waving_hand: Check the docs

https://shopify.dev/docs/api/liquid/objects/metafield#metafield-accessing-metafields-of-type-json

Try accessing the JSON properties through the value

{{ shop.metafields.custom.mto_shirt_form_data.value.some_property_name_in_the_json }}

Try building up to it

 {{ shop.metafields.custom | json }}
 , {{ shop.metafields.custom.mto_shirt_form_data | json }}
 , {{ shop.metafields.custom.mto_shirt_form_data.value | json }}

:man_technologist: The ‘| json’ filter is only for examination purposes of content it is not actually needed to access a JSON type custom content as an object with properties.

It’s hard because shopify messed the bed and have built a mind-maze in the theme systems custom content of when and how .value applies, poor tooling, and poor UX in the admin(when making a metafield/metaobject it should just give sample code that even merchants can use) etc etc etc ad nauseum. But hey it keeps the chatgpt somewhat at bay.

Hey! @grob ,

It sounds like you’re doing everything right, but the most common reason shop.metafields.custom.mto_shirt_form_data returns nothing is that the metafield hasn’t been exposed to the storefront. Go to Settings > Custom data > Shop in your Shopify admin, find your metafield definition, and ensure the “Storefronts” access option is checked. Without this, Liquid can’t access it even if it exists. Once enabled, shop.metafields.custom.mto_shirt_form_data.value should work as expected.

Yeah that was one of the many things that I ensured was there on the checklist but I let out of my post. But the storefront api access checkbox is ticked

Hahaha yeah you’re right about that last bit, but after having tried all of these again, none of them give me anything but

{}
 , null
 , null  

I’ve now tried using a metaobject instead, but after doing this:

{{ metaobjects.custom_frontend_data.mto_shirt_form_data.value }}
{{ metaobjects.custom_frontend_data }}
{{ metaobjects }}

as well as outputting the json representations of them, and all I’m getting is

MetaobjectDefinitionDrop
MetaobjectDefinitionsDrop

and

null
{"error":"json not allowed for this object"}
{"error":"json not allowed for this object"}
 

respectively. I think I’m just going to declare the object in JS, expose it in window and write the form in JS, because this sunk-cost attitude is currently doing nothing but making me look clueless to my boss haha. If you actually manage to figure it out I’ll stick with the liquid-first approach, but yeah I can certainly think of things I’d rather be doing than saying “please work” to my laptop screen at the mercy of Shopify

1 Like

I’m literally with the same problem, I’ve made the same tests that you made and nothing works, I created an App and a app extension inside of it and just wanted to use ONE metafield inside and nothing.

I’ve actually tried to pass variables to the .liquid using [[extensions.metafields]] inside the shopify.extension.toml and doesnt work too.

Not how troubleshooting works with lack of replication detail.
I’d have to actually replicate everything you’d setup, including the JSON data.

Metaobjects(MOBs) are not singular they have entries.
So you have too loop over the metaobjects entries to get one object.
And MOBs will have .value barnacles as well

App extension metafields can be an entirely different set of issues.

Re-examine lack of detail provided another person would need to even be able to guess at the steps you’ve taken.
Making an MRE can be the sanest approach How to create a Minimal, Reproducible Example - Help Center - Stack Overflow

Then use the developers forum

So I was being very silly. I was putting my data in the declaration for the schema, which occurred to me after wondering why it says schema where I’m entering my data.

What I couldn’t find when initially doing this is how and where to create corresponding meta objects, but that was the key. I then referenced these and they now work as desired, though I have to say the JSON formatter is terrible