先判断问题出现在哪里
对于 3C 数码、家用电器、高档护肤品等“重决策”类目,用户在购买前需要在多个相似产品之间反复横跳,对比参数。如果没有对比功能,用户只能打开十几个浏览器标签页,体验极差。

核心逻辑是:结构化数据的提取与横向矩阵渲染。
与 Wishlist 类似,我们将用户选择加入对比的商品 Handle 存储在 LocalStorage 中。在独立的对比页面,通过 Ajax 批量获取这些商品的数据。最关键的是,我们需要利用 Shopify 的 Metafields(元字段)来规范化每个产品的参数(如屏幕尺寸、电池容量),然后在前端用 JavaScript 将这些离散的数据重组为一个清晰的横向对比表格。
实战步骤
步骤 1:规范化后台的产品 Metafields
操作路径:Shopify后台 -> 设置 -> 自定义数据 -> 产品
- 对比功能的前提是数据必须结构化。你不能把所有参数都写在产品描述(Description)的富文本里,代码是无法提取富文本中的特定参数的。
- 必须创建独立的 Metafields。例如,创建一个命名空间为
specs的元字段组:-
specs.screen_size(单行文本) -
specs.battery(单行文本) -
specs.weight(单行文本)
-
- 确保参与对比的同类产品,都规范地填写了这些元字段。
步骤 2:在前端部署“加入对比”按钮与状态管理
操作路径:在 product-card.liquid 中添加按钮
- 添加一个“对比(Compare)”图标按钮,绑定
data-product-handle="{{ product.handle }}"。 - 在
compare.js中监听点击事件,将 handle 存入localStorage.getItem('shopify_compare')数组中。 - 限制数量:由于屏幕宽度有限,通常限制最多只能同时对比 3-4 个产品。如果超出限制,弹出 Toast 提示用户“对比栏已满,请先移除其他产品”。
步骤 3:构建对比页面的数据获取逻辑
操作路径:新建 page.compare.json 和对应的 Section
- 在对比页面加载时,读取 LocalStorage 中的 handle 数组。
- 为了获取包含 Metafields 的完整商品数据,我们不能使用简单的
/search接口(搜索接口返回的数据不包含复杂的元字段)。 - 最佳实践:使用 Shopify 的 Storefront API (GraphQL)。
const query = ` { nodes(ids: ["gid://shopify/Product/1", "gid://shopify/Product/2"]) { ... on Product { title featuredImage { url } priceRange { minVariantPrice { amount } } screenSize: metafield(namespace: "specs", key: "screen_size") { value } battery: metafield(namespace: "specs", key: "battery") { value } } } } `; - 通过发送 GraphQL 请求,一次性精准获取所有对比商品的核心信息和指定的参数元字段。
步骤 4:渲染横向对比矩阵与差异高亮
操作路径:在前端 JS 中拼接 Table DOM
- 拿到 GraphQL 返回的 JSON 数据后,用 JS 动态生成一个
<table>。 - 第一列是参数名称(如“屏幕尺寸”、“电池容量”)。
- 后续的列是各个产品对应的数据。
- 高级交互(差异高亮):在 JS 遍历渲染每一行参数时,检查该行所有产品的数据是否完全一致。如果不一致,给这一行的
<tr>添加一个class="highlight-diff"(如背景色变浅黄),帮助用户一眼看出产品之间的区别。
常见误区与处理方法
误区一:试图用 Liquid 渲染对比页面导致性能灾难
规避方法:很多开发者不想用 GraphQL,试图在对比页面的 Liquid 模板里写一个巨大的 for 循环,遍历全站所有产品,如果产品的 handle 在对比列表中,就把它渲染出来。如果你的店铺有 5000 个产品,这个 Liquid 循环会直接导致服务器渲染超时(Timeout Error),页面彻底白屏。对比页面的数据渲染必须是异步的(Asynchronous)。 页面先加载一个空的表格骨架(Skeleton),然后前端 JS 读取本地存储的 handle,精准地去请求这几个特定产品的数据再填充表格。绝不能在服务器端用 Liquid 去做全站遍历过滤。
误区二:移动端对比表格体验极差,需要疯狂左右滑动
规避方法:在 PC 端,并排展示 4 个产品的详细参数表格非常直观。但在手机屏幕上,一个表格最多只能塞下 1 个半产品。如果强制用户在极其狭窄的屏幕上左右滑动一个巨大的表格,他们会完全失去对比的焦点。移动端的对比功能必须重构 UI。 最好的方案是:在移动端固定第一列(参数名称列),让后面的产品数据列可以横向滑动(CSS: position: sticky; left: 0;)。或者,将横向表格转换为纵向的手风琴折叠面板(Accordion),每次只展开对比一个核心参数。如果实在无法优化,建议在移动端将最大对比数量限制为 2 个。
误区三:跨品类对比导致参数表格出现大量空白
规避方法:用户极其“调皮”,他可能会把一台“笔记本电脑”和一件“纯棉T恤”同时加入对比列表。当渲染表格时,电脑有“CPU型号”和“内存”参数,而 T恤只有“材质”和“洗涤说明”。这会导致对比表格出现大量错位和空白的 <td>,看起来像个 Bug。必须在代码层面建立“同类目对比”的防御机制。 当用户点击“加入对比”时,JS 必须检查该产品的 product.type 或特定的分类标签。如果发现与当前对比列表中的产品不是同一类目,立刻拦截并提示:“只能对比同类别的商品”。保持对比数据的维度一致性,是这个功能成立的前提。

FAQ
产品对比功能应该先检查什么?
先在测试主题或测试页面中操作,并保留修改前版本和验证记录。不要同时改很多位置,先记录当前页面和数据,再处理最明确的问题。
需要马上安装新的 Shopify App 吗?
不一定。先判断主题现有功能、后台字段和少量代码能否解决。只有需要持续同步数据或复杂自动化时,再评估 App 的费用、脚本负担和卸载影响。
修改后怎么验证是否有效?
记录修改日期、页面 URL 和改动内容,再用实际页面、移动端、Google Search Console、Bing Webmaster Tools 或 GA4 检查结果。技术修改还要保留测试记录和回滚版本。
哪些情况不建议马上修改?
数据量太少、追踪没有配置、问题还没有复现,或者正在进行大型主题更新时,不建议一次性重做。先把问题拆开,确认影响范围后再改。