一句话总结
Shopify 的集合本身没有层级,所谓"嵌套"是把父子关系存起来、再让主题读出来。这篇给三种能直接抄的写法:菜单、元字段、Tag 前缀,我推荐第二种。嵌套真正值钱的场景有五个——品类分层、双维度交叉、临时活动聚合、会变的维度、SEO 落地页。另外有五个坑必须提前知道:for 循环一次只给 50 条、集合超 5000 个商品筛选器直接空、all_tags 最多 1000 个、sort 过滤器是假排序、跨子集合展示要去重。
上周一个做户外装备的卖家找我,问了个很典型的问题:客户点进「露营装备」,他想先看到帐篷、睡袋、炊具三个分类卡片,往下滚才是具体商品。这个需求在 Shopify 里叫集合嵌套。
我给他的第一句话是:先别急着找设置项,Shopify 压根没给这一层。
一、先泼一盆冷水:Shopify 的集合根本没有层级
很多人把 Shopify 的集合(collection)理解成电脑里的文件夹,一级套一级。这个理解是错的。
更准确的比喻是便利贴。集合是一张贴纸,你把它贴在商品上;一个商品可以同时贴很多张,贴纸和贴纸之间没有任何关系。
技术上讲,集合分两种:自动集合是按条件自动收商品的(比如"商品类型 = 帐篷"),手动集合是你一件一件手工挑进去的。不管哪种,集合对象里都没有"父集合"子集合"这种字段。
自动集合的条件还有个边界要记住:最多 60 个筛选条件,条件之间可以选"全部满足"或"任一满足"。听起来够用了,但它是平铺的 60 个条件,不是 60 层树。
所以嵌套这件事,本质是我们自己另外记一份层级关系,再让主题读这份关系。谁记、记在哪,就是下面三种方案的区别。
顺带说一个 2026 年的新情况:Shopify 正在推新的集合模型,后台里已经能用"集合来源"把别的集合挂成子集合。但按我看到的社区实测,这条关系目前只在 Admin 的 GraphQL 接口里能读到,storefront 的 Liquid 里 collection.sources、collection.sub_collections 这些全是空的。也就是说,你今天在后台配得再高兴,主题代码还是读不出来。
这点我有保留:官方文档没写死"永远不开放",说不定下个季度就通了。但眼下要做嵌套,还得靠下面三种土办法。
二、三种实现方式,代码直接抄
方案一:用菜单当层级表
改后台不碰代码,最快。思路是:导航菜单本来就能套两层,你按品类结构把集合挂进菜单,主题再顺着菜单把子集合卡片画出来。
{%- comment -%}
snippets/subcollections-from-menu.liquid
用法:在集合模板里加一个「自定义 Liquid」区块,粘进去,
再在区块设置里选菜单(后台 → 在线商店 → 导航)
{%- endcomment -%}
{%- assign menu = linklists[section.settings.menu] -%}
{%- if menu != blank and menu.links.size > 0 -%}
<div class="sub-collections">
{%- for link in menu.links -%}
{%- if link.type == 'collection_link' -%}
{%- assign sub = link.object -%}
<a class="sub-collections__card" href="{{ sub.url }}">
{%- if sub.featured_image -%}
{{ sub.featured_image | image_url: width: 600 | image_tag: loading: 'lazy', alt: sub.title }}
{%- endif -%}
<h3>{{ sub.title }}</h3>
<span>{{ sub.all_products_count }} 件</span>
</a>
{%- endif -%}
{%- endfor -%}
</div>
{%- endif -%}
两个关键点:link.type == 'collection_link' 用来过滤掉菜单里那些博客、页面的链接;link.object 会直接把菜单项解析成对应的集合对象,所以标题、封面图、商品数全能拿到,不用再查一遍。
要二级的话,再套一层 link.links:
{%- for link in menu.links -%}
{%- if link.links.size > 0 -%}
{%- for child in link.links -%}
{%- if child.type == 'collection_link' -%}
<a href="{{ child.object.url }}">{{ child.title }}</a>
{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endfor -%}
适合:层级简单、运营自己会改菜单的店。不适合:菜单要兼顾首页导航和集合层级的情况,改一处动全身,迟早乱。
方案二:用元字段存子集合(我推荐这个)
元字段(metafield)就是给 Shopify 的原生对象加自定义字段。给集合加一个"子集合"字段,类型选集合列表,然后在父集合里勾选它下面挂哪几个子集合。
后台配置四步:
1. 设置 → 自定义数据 → 集合 → 添加定义
2. 名称填「子集合」,类型选「集合」,把"接受多个值"勾上(列表类型)
3. 打开父集合页,拉到最下面的元字段区,勾上要挂的子集合,保存
4. 主题 → 集合页模板 → 添加「自定义 Liquid」区块,粘下面这段代码
{%- comment -%}
sections/sub-collections.liquid
字段名假设为 custom.sub_collections(列表型集合引用)
{%- endcomment -%}
{%- assign subs = collection.metafields.custom.sub_collections.value -%}
{%- if subs != blank and subs.size > 0 -%}
<div class="sub-collections">
{%- for sub in subs -%}
<a class="sub-collections__card" href="{{ sub.url }}">
{%- if sub.featured_image -%}
{{ sub.featured_image | image_url: width: 600 | image_tag: loading: 'lazy', alt: sub.title }}
{%- endif -%}
<h3>{{ sub.title }}</h3>
<span>{{ sub.all_products_count }} 件</span>
</a>
{%- endfor -%}
</div>
{%- endif -%}
注意 .value 这个尾巴。列表型元字段不写 .value,拿到的是一坨内部对象,取不出标题和图片。
我推荐它,是因为层级关系跟着集合走,不跟着菜单走。你把菜单改烂了,集合页照样对;反过来也一样。运营在后台点几下就能维护,不用每次来找我。
方案三:用 Tag 前缀做约定
老主题、不敢动结构的时候用。约定一种 tag 写法,比如 sub:camp-tent,冒号后面是子集合的 handle(handle 就是集合在 URL 里的那个名字)。
{%- comment -%}
约定:商品上打 tag 形如 sub:子集合handle
例:sub:camp-tent → 对应 /collections/camp-tent
{%- endcomment -%}
{%- assign prefix = 'sub:' -%}
{%- assign handles = '' -%}
{%- for tag in collection.all_tags -%}
{%- if tag contains prefix -%}
{%- assign one = tag | remove: prefix | handleize -%}
{%- assign handles = handles | append: ',' | append: one -%}
{%- endif -%}
{%- endfor -%}
{%- assign handle_array = handles | remove_first: ',' | split: ',' -%}
{%- for handle in handle_array -%}
{%- assign sub = collections[handle] -%}
{%- if sub != blank -%}
<a class="sub-collections__card" href="{{ sub.url }}">
<h3>{{ sub.title }}</h3>
<span>{{ sub.all_products_count }} 件</span>
</a>
{%- endif -%}
{%- endfor -%}
Liquid 里没有"往数组里追加一个元素"的干净写法,所以这里用字符串拼 handle 再 split 成数组,这是最稳的路子。
有个看起来更聪明的办法我不用:遍历 product.collections 反推子集合。实测它会把商品碰巧所在的所有集合都列出来,包括那些完全不相干的,客户看了一脸问号。
三选一怎么挑
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
三、嵌套一般用来解决这 5 类问题
知道怎么写了,还得知道什么时候值得写。我见过的嵌套需求,翻来覆去就这五类。
1. 品类分层:父集合页先分流
最典型,就是开头那个户外店的场景。父集合页上半部分是子集合卡片,下半部分照常出商品网格。客户想逛就点卡片,想直接看货就往下滚。
不要做成"有子集合就不出商品"的二选一,那是在强迫客户做决定。卡片只是多给一条路。
{%- assign subs = collection.metafields.custom.sub_collections.value -%}
{%- if subs != blank -%}
<div class="sub-collections">
{%- for sub in subs -%}
<a class="sub-collections__card" href="{{ sub.url }}">{{ sub.title }}</a>
{%- endfor -%}
</div>
{%- endif -%}
{%- comment -%} 下面照常渲染主题自带的商品网格,不要 else 掉 {%- endcomment -%}
2. 两个维度交叉:品类 × 属性
客户想看"防水的黑色帐篷",这是品类乘属性的二维筛选,不建集合也能做。Shopify 的集合 URL 支持把 tag 用加号叠起来:
/collections/camp-tent/waterproof+black
加号是"且"的关系,两个 tag 都有才出现。筛选链接别手写,用官方过滤器生成:
{%- for tag in collection.all_tags -%}
{%- if current_tags contains tag -%}
{{ tag | link_to_remove_tag: tag }}
{%- else -%}
{{ tag | link_to_add_tag: tag }}
{%- endif -%}
{%- endfor -%}
link_to_add_tag 会自动把当前已选的 tag 一起拼进 URL,你不用自己算加号。
这类需求我一般先劝一句:能装筛选器 app 就别自己搞 tag 体系。官方自己的文档也说了,tag 筛选属于老办法,优先用前台筛选(storefront filtering),商家在后台勾几下就能出筛选条件,比在 tag 里埋约定省心得多。
3. 临时活动聚合:不建集合
大促要一个"夏季专区",把分散在五个品类里的商品凑一页。这时候建新集合是下策:活动结束你得记得删,删了还要处理 URL 和收录。
我的做法是直接用 tag 组合页,/collections/all/summer-sale,不新建任何集合,同时给它加 noindex,别让临时页进搜索结果:
{%- comment -%} theme.liquid 里,临时组合页不进索引 {%- endcomment -%}
{%- if canonical_url contains '/collections/all/' and current_tags.size > 0 -%}
<meta name="robots" content="noindex,follow">
{%- endif -%}
活动结束,把 tag 从商品上摘掉,页面自己就空了,不用收尾。
4. 会变的维度:库存、地区、价格带
"中国仓现货""清仓价""新品"这类标签会天天变。手工维护必然出错,一定要走自动集合或者元字段加自动化工具,后台那个 Flow 就能干。
这类维度不要拿来做嵌套层级,它跟品类是交叉关系,不是上下关系。把它们做成筛选条件,别做成子集合。判断标准很简单:一个商品会不会同时落在两个子集合里?会,那它就不是层级,是属性。
5. SEO 与广告落地页
父集合页天然是内链枢纽:上面挂子集合卡片,下面放一段 200 字的品类介绍。Google 和用户都能顺着这一页走到店铺深处;广告也能直接拿它当落地页,比投首页强,因为意图更准。
写这段介绍时别只堆关键词。讲清三件事:这个品类你有多少款、适合什么场景、怎么挑。这三句既是给人看的,也是给 AI 搜索摘的。
四、什么时候别做嵌套
不是所有店都需要。满足下面任意一条,我劝你先别动:
• 商品总数不到 80 个,一页就能看完,加层级只会多一次点击
• 层级超过 3 层,客户点三次还没见到货,跑的概率比逛的概率大
• 同一个商品会落进 4 个以上的子集合,说明你在用层级表达属性,方向错了
• 团队没人维护,配完就搁那,半年后子集合和商品对不上,比不做还糟
还有个 SEO 上的提醒:父集合页和子集合页内容高度重合时,别都放出去抢同一个词。我一般让父页吃品类大词,子页吃"品类加属性"的长尾词,介绍文案各写各的,别复制。
五、5 个坑,越早知道越好
坑一:for 循环一次只给你 50 条
这是新手最懵的一个。你在子集合里写 {% for product in sub.products %},写一百件商品也只出 50 件。Shopify 的 for 循环每页最多 50 次迭代,collection.products 默认也只给你拉 50 条。
正常集合页用 paginate 解决,每页能设到 250 条。但paginate 只认当前集合的 collection.products,你往它里面塞 sub.products 是无效的。所以跨子集合合并展示时,只能用 limit 截断,翻页别想了。
{%- comment -%} 子集合里最多取 8 件,不能分页 {%- endcomment -%}
{%- for product in sub.products limit: 8 -%}
{%- render 'card-product', product: product -%}
{%- endfor -%}
顺带一提,paginate 最深只能翻到第 25000 条,再往后的商品翻不到。真有那种体量的店,先把集合切细再谈分页。
坑二:商品超过 5000 个,筛选器直接空掉
这条是官方文档白纸黑字写的:集合里的商品超过 5000 个时,collection.filters 返回空数组,前台筛选器一个都渲染不出来。
很多店是这么踩坑的:为了省事把所有商品塞进一个"全部商品"集合,然后在上面做嵌套和筛选。商品一多,筛选全废。
对策就是把大集合按品类切开,正好也是嵌套该做的事。
坑三:all_tags 最多返回 1000 个
方案三依赖 collection.all_tags,而这个数组上限 1000 个。SKU 多、tag 打得细的店很容易撞线,撞了以后后面的 tag 读不到,子集合卡片莫名其妙少几个。
这也是我更推荐元字段的原因之一:元字段是按集合显式挂的,不存在"读不全"。
坑四:sort 过滤器是假排序
很多人想"按价格从低到高展示子集合商品",于是写:
{%- assign sorted = sub.products | sort: 'price' -%}
看着对,实际只是把这 50 条里的 50 条排了个序,不是全集合排序。真正的排序要用 URL 参数 ?sort_by=price-ascending,让系统在取数的时候就排好。
Shopify 认的排序值就那几个:manual、best-selling、title-ascending、title-descending、price-ascending、price-descending、created-ascending、created-descending。
坑五:跨子集合展示会出现重复商品
把多个子集合的商品并在一起展示,同一件商品可能在两个子集合里都有,页面上就出现两次。客户会觉得你在凑数。
去重要自己写,判断时给 id 前后都加逗号,避免 123 命中 1234 这种子串误判:
{%- assign seen = '' -%}
{%- for sub in subs -%}
{%- for product in sub.products limit: 8 -%}
{%- assign key = product.id | prepend: ',' | append: ',' -%}
{%- unless seen contains key -%}
{%- render 'card-product', product: product -%}
{%- assign seen = seen | append: key -%}
{%- endunless -%}
{%- endfor -%}
{%- endfor -%}
六、上线前的 6 步检查
1. 先把层级画在纸上,确认不超过 3 层,每层子集合数量在 3 到 8 个之间
2. 建元字段定义(只做一次),类型确认是列表型的集合引用
3. 给每个父集合挂子集合,一个集合大概一分钟
4. 主题里加「自定义 Liquid」区块,先只在一个集合模板上试,别一上来全站套
5. 手机端点进去看卡片排布,两列还是三列,图片比例是不是被拉变形了
6. 上线一周后看 GSC 的网页索引报告,子集合页有没有被收录;再从父集合页点一遍,确认每个卡片都通
我的判断是:Shopify 店铺做到 200 个 SKU 以上,集合嵌套迟早要做,早做比晚做省事——晚做意味着商品和 tag 已经乱成一团,光理清层级就要多花两天。
如果你卡在"知道该分层,但不知道自己的店该分几层、按什么维度分",那不是代码问题,是结构问题。这类问题我在训练营里一般都让学员先把商品表拉出来,按品类和属性做一遍交叉统计,统计完答案自己就出来了。
相关词:Shopify 独立站 | Shopify 建站 | Shopify 运营 | Shopify 教程 | 跨境电商独立站

