Shopify 对象参考
Liquid 里所谓「对象」,就是 Shopify 在渲染某一页时已经帮你准备好的 数据入口(商店、购物车、当前产品、集合等)。写主题时真正省时间的,不是背每个字段名,而是搞清楚:当前模板里哪些对象一定有、哪些是 nil、和 routes / request 怎么配合。
官方完整字段以 Liquid 对象索引 为准;本文做 地图 + 速查 + 常见写法,细节深挖见站内各篇。
1. 建议怎么读这篇
- 先看下面 「按页面类型,对象是否可用」,避免在
footer.liquid里写product.title却纳闷为什么是空的。 - 需要某个对象的字段时,用文中 速查表 定位常用属性,再点进 全局对象、产品对象 等专题。
- 链接与跳转一律优先用
routes.*,少写死/cart、/account/login,多市场、子路径、自定义域名时更稳。
2. 按页面类型:对象可用性(简表)
| 对象 / 情境 | 全局(layout、多数 section) | 仅部分模板有「当前」实例 |
|---|---|---|
shop | 有 | — |
routes | 有 | — |
request | 有 | — |
settings(主题设置) | 有 | — |
section / block | 在对应 section 内 | — |
cart | 有(空购物车也是对象) | 结账页 Liquid 能力受限,勿假设与店面一致 |
customer | 登录后有 | 未登录为 nil,用 {% if customer %} |
product | 仅产品页(及显式 all_products 等上下文) | 集合循环里是 for 里的局部变量 |
collection | 集合页、部分 section 赋值后 | — |
blog / article | 博客列表 / 文章页 | 文章页用 article,列表用 blog.articles |
page | 仅自定义页面模板 | — |
search | 搜索模板执行搜索后 | search.performed 区分是否已搜 |
template | 有 | 分支判断更推荐 request.page_type(见下文) |
paginate | 仅在 {% paginate %}…{% endpaginate %} 内 | — |
记忆口诀:跟「当前 URL 代表的是谁」绑定的对象(product、collection、article…),出了对应模板就不要指望还在「当前」上下文里;全局展示用 section.settings 选资源,或 all_products[handle] 显式取。
3. routes:链接不要写死路径
storefront 与账户、搜索、购物车等 URL 会随商店配置变化,应使用 routes(见 routes 对象 )。
| 常见用途 | Liquid 示例 |
|---|---|
| 购物车 | {{ routes.cart_url }} |
| 搜索提交 | {{ routes.search_url }}(form 的 action) |
| 登录 / 注册 | {{ routes.account_login_url }} / {{ routes.account_register_url }} |
| 首页 | {{ routes.root_url }} |
| 全店商品集合 | {{ routes.all_products_collection_url }} |
示例(搜索表单):
<form action="{{ routes.search_url }}" method="get" role="search">
<label class="visually-hidden" for="q">搜索</label>
<input id="q" type="search" name="q" value="{{ search.terms | escape }}" placeholder="搜索…">
<button type="submit">搜索</button>
</form>4. shop 对象(商店)
包含店名、域名、货币、政策链接、地址等。站内扩展阅读:全局对象详解。
常用属性速查
| 属性 | 含义 |
|---|---|
shop.name / shop.domain / shop.url | 名称、主域、店铺 URL |
shop.currency | 店铺货币代码 |
shop.email | 店铺联系邮箱(展示用) |
shop.address | 地址对象(多级字段) |
shop.privacy_policy 等 | 政策页面对象,用 .url 链出 |
shop.secure_url | HTTPS 根 URL,拼 canonical 时常用 |
<h1>{{ shop.name }}</h1>
{% if shop.description != blank %}
<p>{{ shop.description }}</p>
{% endif %}
<address>
{{ shop.address.address1 }}<br />
{% if shop.address.address2 != blank %}{{ shop.address.address2 }}<br />{% endif %}
{{ shop.address.city }}, {{ shop.address.province_code }} {{ shop.address.zip }}<br />
{{ shop.address.country }}
</address>
<p><a href="mailto:{{ shop.email }}">{{ shop.email }}</a></p>
{% if shop.privacy_policy %}
<a href="{{ shop.privacy_policy.url }}">隐私政策</a>
{% endif %}5. cart 对象(购物车)
cart 在店面主题里几乎始终存在;cart.item_count == 0 表示空车。行项目用 cart.items。详解:购物车对象。
| 属性 | 含义 |
|---|---|
cart.items | 行项目数组 |
cart.item_count | 件数(数量之和) |
cart.total_price | 总价(配合 | money) |
cart.currency | 购物车货币 |
cart.taxes_included | 是否含税价展示 |
<p>小计 {{ cart.total_price | money }}{% if cart.currency != shop.currency %}({{ cart.currency }}){% endif %}</p>
{% for item in cart.items %}
<div class="cart-line" data-line-key="{{ item.key }}">
{% if item.image %}
{{ item.image | image_url: width: 120 | image_tag: alt: item.image.alt | default: item.title, loading: 'lazy' }}
{% endif %}
<div>
<a href="{{ item.url }}">{{ item.product.title }}</a>
{% unless item.product.has_only_default_variant %}
<p>{{ item.variant.title }}</p>
{% endunless %}
<p>{{ item.final_line_price | money }} × {{ item.quantity }}</p>
</div>
</div>
{% endfor %}
{% if cart.item_count == 0 %}
<p>购物车是空的。</p>
<a href="{{ routes.all_products_collection_url }}">去逛逛</a>
{% endif %}6. customer 对象(当前客户)
仅登录后存在;未登录务必 {% if customer %}。详解:客户对象。
{% if customer %}
<p>欢迎,{{ customer.first_name | default: '顾客' }}</p>
<p>{{ customer.email }}</p>
{% if customer.default_address %}
<p>{{ customer.default_address.city }}</p>
{% endif %}
<a href="{{ routes.account_url }}">账户</a>
{% else %}
<a href="{{ routes.account_login_url }}">登录</a>
<a href="{{ routes.account_register_url }}">注册</a>
{% endif %}7. request 对象(当前请求)
做 hreflang、canonical、调试、按语言切换 class 时都会用到。
| 属性 | 含义 |
|---|---|
request.page_type | 页面类型字符串,如 product、collection、index |
request.path | 路径部分 |
request.origin | 源站 origin,拼绝对 URL |
request.locale | 当前区域 / 语言相关 |
request.design_mode | 主题编辑器预览中为 true |
按页面类型分支:优先用 request.page_type,不要依赖把 template 当字符串的 {% case template %}(template 在新主题里多为 对象,应用 template.name 或直接用 request.page_type)。
{% case request.page_type %}
{% when 'index' %}
{% comment %} 首页 {% endcomment %}
{% when 'product' %}
{% comment %} 产品页 {% endcomment %}
{% when 'collection' %}
{% comment %} 集合页 {% endcomment %}
{% when 'cart' %}
{% comment %} 购物车 {% endcomment %}
{% else %}
{% comment %} 其他类型 {% endcomment %}
{% endcase %}调试(仅开发环境或 settings 开关):
{% if request.design_mode %}
<p class="theme-debug">page_type={{ request.page_type }}</p>
{% endif %}8. product 对象(当前产品)
仅在 产品模板(或你显式传入的 product)上下文。价格、变体、图、SEO 等见 产品对象详解。
<h1>{{ product.title }}</h1>
<p>{{ product.vendor }}</p>
<div class="price">
{% if product.compare_at_price > product.price %}
<span class="compare">{{ product.compare_at_price | money }}</span>
<span class="sale">{{ product.price | money }}</span>
{% else %}
<span>{{ product.price | money }}</span>
{% endif %}
</div>
{% if product.description != blank %}
<div class="rte">{{ product.description }}</div>
{% endif %}
{% if product.featured_image %}
{{ product.featured_image | image_url: width: 800 | image_tag: alt: product.featured_image.alt | default: product.title, loading: 'eager', fetchpriority: 'high' }}
{% endif %}9. collection 对象(集合)
集合页有「当前」collection;collection.products 在 未分页 时注意性能,列表页应用 {% paginate %} 或限制 limit:。
<h1>{{ collection.title }}</h1>
{% if collection.description != blank %}
<div class="rte">{{ collection.description }}</div>
{% endif %}
{% paginate collection.products by 24 %}
{% for product in collection.products %}
{% render 'product-card', product: product %}
{% endfor %}
{% if paginate.pages > 1 %}
<a href="{{ paginate.next.url }}" rel="next">下一页</a>
{% endif %}
{% endpaginate %}空集合:
{% if collection.products_count == 0 %}
<p>该集合暂无商品。</p>
{% endif %}10. blog 与 article
- 博客列表页:
blog有title、articles等。 - 文章详情页:当前文章多为顶层
article(与模板有关,以你主题article.json/article.liquid为准)。
<h1>{{ blog.title }}</h1>
{% for article in blog.articles limit: 10 %}
<article>
<h2><a href="{{ article.url }}">{{ article.title }}</a></h2>
<time datetime="{{ article.published_at | date: '%Y-%m-%d' }}">{{ article.published_at | date: '%Y-%m-%d' }}</time>
{% if article.excerpt != blank %}
<p>{{ article.excerpt | strip_html | truncate: 160 }}</p>
{% endif %}
</article>
{% endfor %}11. page 对象(自定义页面)
用于 page 模板。字段以 page 对象 为准;author 等是否出现取决于后台是否填写或使用 metafield。
<h1>{{ page.title }}</h1>
<div class="rte">{{ page.content }}</div>12. template 对象
提供当前渲染的模板名、后缀等。做条件时推荐 request.page_type 或 template.name,与旧版「template 当作字符串」的写法区分开。
{% if template.name == 'product' %}
{% comment %} 产品 JSON 模板等 {% endcomment %}
{% endif %}13. paginate 对象
只在 {% paginate collection.products by n %}…{% endpaginate %}(或 blog、search 等可分页集合)内部可用,提供 paginate.previous、paginate.next、paginate.parts、paginate.current_page 等。
{% paginate collection.products by 12 %}
{% for product in collection.products %}…{% endfor %}
{% if paginate.pages > 1 %}
<nav aria-label="分页">
{% if paginate.previous %}<a href="{{ paginate.previous.url }}" rel="prev">上一页</a>{% endif %}
{% for part in paginate.parts %}
{% if part.is_link %}<a href="{{ part.url }}">{{ part.title }}</a>{% else %}<span>{{ part.title }}</span>{% endif %}
{% endfor %}
{% if paginate.next %}<a href="{{ paginate.next.url }}" rel="next">下一页</a>{% endif %}
</nav>
{% endif %}
{% endpaginate %}14. search 对象
search.performed 为真表示用户已提交搜索;结果在 search.results,类型可用 item.object_type 分支(以官方文档枚举为准)。
{% if search.performed %}
<h1>「{{ search.terms | escape }}」的搜索结果</h1>
<p>共 {{ search.results_count }} 条</p>
{% for item in search.results %}
{% case item.object_type %}
{% when 'product' %}
<a href="{{ item.url }}">{{ item.title }}</a>
{% when 'article' %}
<a href="{{ item.url }}">{{ item.title }}</a>
{% when 'page' %}
<a href="{{ item.url }}">{{ item.title }}</a>
{% endcase %}
{% endfor %}
{% endif %}15. section 与 settings(分区与主题配置)
section:在sections/*.liquid内,section.id、section.settings、section.blocks最常用。实践见 自定义分区开发。settings:config/settings_schema.json定义的全局主题设置,全站片段、layout 里都能读。
16. 使用注意(合并成几条硬规则)
- 先判断再输出:
{% if product %}、{% if collection.products_count > 0 %},避免 nil 上点属性。 - 价格与货币:展示用
\| money;JSON-LD 或结构化数据里常用money_without_currency等,注意与币种字段一致。 - 性能:大集合不要无分页一次扫光;同一字段在循环里多次访问可先
{% assign img = product.featured_image %}。 - HTML 安全:用户输入、标题等输出到属性或 JSON 时用
\| escape;description类富文本用strip_html再进 meta。 - 结构化数据:示例 JSON-LD 仅作参考,变体、多币种、预售等场景建议用主题或 App 统一维护,避免与后台真实库存不同步。
{% if product.featured_image %}
{% assign img = product.featured_image %}
{{ img | image_url: width: 600 | image_tag: alt: img.alt | default: product.title | escape, loading: 'lazy' }}
{% endif %}17. 延伸阅读
字段名、新增对象以 shopify.dev 当前页 为准;主题升级后若某属性废弃,以 Theme Check 与发布说明为准。