A Scandinavian furniture marketplace I work on, Mobelglede, runs a brand filter built on shop.vendors. Last quarter a supplier asked why their label was missing from it. The merchant’s first assumption was the one everybody lands on after ten minutes of searching: “Shopify caps shop.vendors at 30.” It does not. The supplier’s products had quietly dropped off the Online Store channel after a sync, so Liquid could not see them. The fix had nothing to do with a limit.
TL;DR: There is no documented 30-item limit on shop.vendors or shop.types. The official Liquid docs say both return all vendors or types for the store, with no cap and no pagination. When the list looks short, the usual cause is vendors whose products are not published to the Online Store, or confusion with the GraphQL Admin API, which is a different surface. For a list that must be complete, build it from metaobjects rather than trusting the raw array.
Why this matters for your store:
- A brand filter or vendor directory that silently drops a supplier looks like a bug to that supplier and costs you a navigation path and an internal link for SEO.
- Chasing a “30 limit” that does not exist sends you down workarounds for the wrong problem while the real cause, an unpublished product, sits untouched.
- On multi-brand and marketplace stores, the vendor list is a navigation and ranking surface. It deserves a deterministic source, not an array whose contents shift with publish state.
What the documentation actually says
The Liquid objects reference for the shop object describes shop.vendors as:
An array of all of the product vendors for the store.
And shop.types as all of the product types. Both ship a short example and a link_to_vendor filter usage. Neither entry mentions a limit, a maximum, pagination, or the number 30. I went looking specifically for it, in the docs and across the community threads, and there is no official source for a hard cap. The “30” is folklore that gets repeated because the symptom (a short list) is real even though the stated cause is not.
{% comment %} The documented, Liquid-native way to list vendors {% endcomment %}
<ul class="brand-list">
{% for vendor in shop.vendors %}
<li>{{ vendor | link_to_vendor }}</li>
{% endfor %}
</ul>
This loop returns every vendor the storefront can see. The phrase doing the quiet work is “the storefront can see,” which is the next section.
Where the short list actually comes from
In my experience auditing these, the incomplete vendor list has two real causes, neither of which is a numeric cap.
One, vendors with no Online-Store-published products. Liquid only renders data that is visible to the Online Store sales channel. A vendor whose products are all draft, archived, or unpublished from the Online Store does not appear in shop.vendors, because from the storefront’s point of view that vendor sells nothing. This is the cause on most stores, and it is why the array count is often lower than the vendor count you see in the admin. Publish the products and the vendor returns on the next render.
Two, conflation with the GraphQL Admin API. The Admin API vendor query has its own pagination behavior and a 250-result ceiling per request. That is a backend API surface, queried from an app or a server, and it has nothing to do with the Liquid shop.vendors object that renders on your storefront. People reading about the Admin API limit assume it applies to Liquid. It does not. They are two different systems.
So before you build any workaround, check the simplest thing: filter your admin products by the missing vendor and confirm at least one is published to the Online Store. That one check resolves most “shop.vendors is broken” tickets.
The reliable pattern for a complete vendor list
shop.vendors is fine for a quick A-to-Z links block. It is the wrong foundation for a brand directory that has to be complete, ordered, and styled, because its contents change with publish state. When a brand page or filter matters for navigation and SEO, give it a deterministic source: a metaobject per brand.
{% comment %}
A brand directory backed by a "brand" metaobject definition.
Fields used: logo (file_reference, image) and collection (collection_reference).
Note the modern syntax: metaobjects.TYPE.values, not the deprecated shop.metaobjects.
{% endcomment %}
<ul class="brand-directory">
{% for brand in metaobjects.brand.values %}
<li>
<a href="{{ brand.collection.value.url }}">
{% if brand.logo != blank %}
<img src="{{ brand.logo.value | image_url: width: 160 }}"
alt="{{ brand.name | escape }}" loading="lazy" width="160">
{% endif %}
<span>{{ brand.name }}</span>
</a>
</li>
{% endfor %}
</ul>
Two syntax notes that trip people up, both verified against the current docs. Iterate a definition with metaobjects.brand.values, because the older shop.metaobjects prefix was deprecated in January 2025. And reach a reference field’s target through .value, so an image field is brand.logo.value | image_url and a linked collection is brand.collection.value.url. A metaobject-backed list gives you a stable order, a logo, and a linked collection per brand, and it does not drop a supplier the day their last in-stock product sells out and gets unpublished. You control exactly what shows. For stores that genuinely need every vendor derived from live product data, the robust route is to generate that list server-side through the Admin API, then cache it into a shop metafield that Liquid reads, rather than recomputing it on every page render. For the mechanics of reading metafield values in Liquid, see my note on the .value accessor.
The takeaway:
- There is no 30-item cap on
shop.vendorsorshop.types. The official docs document no limit at all. - A short list almost always means vendors with no Online-Store-published products, or confusion with the separate Admin API 250 behavior.
- Debug it by confirming the missing vendor has a product published to the Online Store, before building any workaround.
- For a brand directory or filter that must be complete and ordered, back it with metaobjects, not the raw array. The array is a convenience, not a contract.
For the broader set of Liquid object gotchas and the audit I run on every theme, see my Shopify Liquid best practices guide.