跳到主要内容

Theme extension 参考

本页是 Theme App Extension 的查阅手册:配置文件、两种区块、Snippets、Schema、资源引用与多语言。开发流程见 创建一个主题扩展

配置文件(shoplazza.extension.toml)

每个 Theme App Extension 根目录下有一个 shoplazza.extension.toml 配置文件:

id = "617189634367044154"
name = "my-theme-app-extension"
type = "theme"

字段说明:

字段说明
id扩展的唯一 ID,由 CLI 创建扩展时自动生成,不可手动修改。
name扩展名称,在 CLI 操作和后台管理中使用。
type固定为 "theme",表示这是一个 Theme App Extension。

App Block(应用区块)

App Block 用于在页面中注入内联内容。商家可以在主题编辑器的 Apps 区域将 App Block 手动添加到支持的 Section 中。

Image

适合使用 App Block 的场景:

  • 需要指向动态数据源的功能,如商品评分、评论展示。

  • 商家可能需要在页面上调整位置的功能。

  • 需要横跨页面全宽显示的功能。

注意:App Block 默认不会在安装应用后自动出现在主题中,需要商家在主题编辑器中手动添加。

App Block 对主题的要求

App Block 要正常运行,主题的 Section 必须支持并渲染 @app 类型的 Block。

示例:app_block.liquid

我们将展示一个获取用来获取商品评分元数据的 App Block 的完整示例。

为了能够使代码能够正确允许,我们需要新增average_rating的元数据,并在商品的后台配置该元数据的值:

1、新增元数据字段average_rating

Image

2、在商品后台设置average_rating 的值

Image

3、在商店主题编辑中,在商品详情中,添加该 theme extension

Image

具体代码(blocks/app_block.liquid):

{% use "app_block.css" %}
{%- comment -%} 商品未配置 average_rating 时 default 为 0,避免 nil 导致渲染异常 {%- endcomment -%}
{% assign avg_rating = product.metafields.custom.average_rating | metafield_text | default: 0 | plus: 0 | round %}

<span style="color:{{ block.settings.color }}">
{% render 'rating_stars', rating: avg_rating %}
</span>

{% if avg_rating >= 4 %}
<div class="recommendation-text">
<img src="{{ 'thumbs_up.svg' | asset_abs_url }}" style="width:20px; height:20px;">
{{ 'i18n.ratings.recommendation_text' | t }}
</div>
{% endif %}

{% schema %}
{
"name": {
"en-US": "Product Rating",
"zh-CN": "商品评分"
},
"settings": [
{
"type": "color",
"id": "color",
"label": {
"en-US": "Star Color",
"zh-CN": "星星颜色"
},
"default": "#ff0000"
}
]
}
{% endschema %}

assets/app_block.css

.recommendation-text {
color: green;
}
.myapp-floating-button-wrapper {
color: red;
}

效果展示:

Image

代码说明:

  • {% use "app_block.css" %}:Shoplazza 特有的资源加载方式,用于引入 assets/ 目录中的 CSS 文件(详见后文的 "资源引用" 章节)。

  • block.settings.color:读取 Schema 中定义的 color 设置项的值,商家可在主题编辑器中修改。

  • {% render 'rating_stars', rating: avg_rating %}:引用 snippets/rating_stars.liquid 代码片段,并传入参数。

  • {{ 'thumbs_up.svg' | asset_abs_url }}:获取 assets/ 目录中图片的绝对 URL。

  • {{ 'i18n.ratings.recommendation_text' | t }}:多语言翻译,从 locales/ 文件中读取对应语言的文本。

  • Schema 中不设置 target 字段时,默认为 App Block(作用于 Section)。

App Embed Block(应用嵌入区块)

App Embed Block 用于没有独立 UI 区域、或需要添加浮动/覆盖层元素的功能。Shoplazza 会在 HTML </head></body> 闭合标签前渲染并注入 App Embed Block。

Image

在 Schema 中通过 "target" 字段指定注入位置:

target 值注入位置
"body"</body> 标签前(最常用)
"head"</head> 标签前

注意:App Embed Block 安装后默认处于停用状态,商家需要在主题编辑器的 主题编辑 > 应用管理 中手动激活。

适合使用 App Embed Block 的场景:

  • 浮动按钮、聊天气泡等悬浮组件。

  • SEO meta 标签、数据分析、埋点追踪脚本。

  • 在所有页面上生效的全局功能。

示例:app_embed_block.liquid

以下是一个悬浮按钮 App Embed Block 的完整示例(blocks/app_embed_block.liquid)。推荐做法:CSS / JS 写在 assets/ 目录的独立文件中,通过 Liquid 过滤器引入,而不是把 <style> / <script> 内联到 Liquid 文件里——便于复用、CDN 缓存、避免重复加载(详见后文的 "资源引用" 章节)。

{{ 'floating_button.css' | asset_abs_url | stylesheet_tag }}
{{ 'floating_button.js' | asset_abs_url | script_tag }}

<div class="myapp-floating-button-wrapper">
<button
type="button"
class="myapp-floating-button"
style="
background-color: {{ block.settings.background_color }};
color: {{ block.settings.text_color }};
"
>
<span>{{ block.settings.button_label }}</span>
</button>
</div>

{% schema %}
{
"name": {
"en-US": "Floating Button",
"zh-CN": "悬浮按钮"
},
"icon": "https://assets.shoplazza.com/oss/operation/a425c6e10e32f87a1e7271c9ed9347d8.svg",
"target": "body",
"settings": [
{
"type": "text",
"id": "button_label",
"label": {
"en-US": "Button Label",
"zh-CN": "按钮标签"
},
"default": "Help"
},
{
"type": "color",
"id": "background_color",
"label": {
"en-US": "Background Color",
"zh-CN": "背景颜色"
},
"default": "#ff0000"
},
{
"type": "color",
"id": "text_color",
"label": {
"en-US": "Text Color",
"zh-CN": "文字颜色"
},
"default": "#ffffff"
},
{
"type": "text",
"id": "link_url",
"label": {
"en-US": "Click URL",
"zh-CN": "点击跳转链接"
},
"default": "https://www.shoplazza.dev"
}
]
}
{% endschema %}

关于 icon 字段:示例中的 assets.shoplazza.com 是 Shoplazza 内部 CDN 上的占位图标,实际发布时请替换为你自己上传的图标 URL

assets/floating_button.css

.myapp-floating-button-wrapper {
position: fixed;
bottom: 24px;
right: 24px;
z-index: 9999;
}

.myapp-floating-button {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 12px 16px;
border-radius: 999px;
font-size: 14px;
font-weight: 600;
text-decoration: none;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.25);
cursor: pointer;
transition:
transform 0.08s ease-out,
box-shadow 0.08s ease-out;
}

.myapp-floating-button:hover {
transform: translateY(-1px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
}

assets/floating_button.js

document.addEventListener('DOMContentLoaded', () => {
const btn = document.querySelector('.myapp-floating-button');
console.log('悬浮按钮已加载, button element:', btn);
if (!btn) return;

btn.addEventListener('click', event => {
console.log('悬浮按钮已点击');
// 跳转 URL 可通过 schema 的 link_url 设置项传入;这里硬编码仅为示意
window.open('https://www.shoplazza.dev', '_blank');
});
});

效果展示:

Image

代码说明:

  • "target": "body":指定为 App Embed Block,内容注入到 </body> 前。App Embed Block 必须在 Schema 中显式设置 target

  • "icon":在主题编辑器的应用嵌入列表中显示的图标,使用绝对 URL。

  • block.settings.button_label 等:读取商家在主题编辑器中配置的设置值。

  • 资源引入: CSS / JS 通过 asset_abs_url | stylesheet_tagasset_abs_url | script_tag 引入外部文件。如果确实需要在 Liquid 中内联 <style> / <script>,请把 JS 逻辑包裹在 IIFE 中避免全局变量污染——但推荐还是用外部文件,方便缓存与复用。

Snippets(代码片段)

snippets/ 目录用于存放可复用的 Liquid 代码片段,可在多个 Block 中引用,避免重复代码。

示例:snippets/rating_stars.liquid

{%- if rating < 0 -%}
{%- assign safe_rating = 0 -%}
{%- elsif rating > 5 -%}
{%- assign safe_rating = 5 -%}
{%- else -%}
{%- assign safe_rating = rating -%}
{%- endif -%}
{%- assign blank_stars = 5 | minus: safe_rating -%}
<span aria-label="{{ safe_rating }}/5 stars">
{{ 'i18n.ratings.star_label' | t }}:
{%- for i in (1..safe_rating) -%}

{%- endfor -%}
{%- for i in (1..blank_stars) -%}

{%- endfor -%}
</span>

if / elsifrating 限制在 0~5 之间(Shoplazza Liquid 不提供 at_least / at_most 这类 clamp filter,可用的 math filter 见 Math filters),防止评分为负数或大于 5 时渲染异常;外层 <span aria-label> 为屏幕阅读器提供可读文本。

在 Block 中引用该 Snippet:

{% render 'rating_stars', rating: avg_rating %}

或:

{% include 'rating_stars' %}

{% render %}{% include %} 的区别

{% render %}{% include %}
变量作用域独立作用域,不继承外部变量(需通过参数显式传入)共享外部变量作用域
参数传递通过 withfor 或具名参数传递直接访问外部所有变量
推荐场景需要明确隔离、可复用性强的片段需要访问上下文变量的片段

Schema 配置

每个 Block 的 Liquid 文件末尾都需要添加一个 {% schema %} ... {% endschema %} 块,用于定义区块的名称、类型和可配置的设置项。每个文件只能包含一个 {% schema %} 块。

顶级属性

属性类型是否必填说明
nameObject在主题编辑器中显示的区块名称。必须同时提供 en-USzh-CN 两种语言。建议不超过 25 个字符。
targetStringApp Embed Block 必填区块注入位置。App Embed Block 需设置为 "body""head";App Block 无需设置。
iconString区块在主题编辑器中显示的图标,使用图片绝对 URL。仅 App Embed Block 适用。
settingsArray提供给商家的自定义设置项列表,在主题编辑器中选中区块时显示。
presetsArray默认配置
tagString如果设置,则用指定 HTML 标签包裹区块输出;不设置时默认用 div 包裹。
classString添加到包裹标签的额外 CSS 类名。

name 的多语言格式

name 必须配置为包含 en-USzh-CN 的多语言对象:

{
"name": {
"en-US": "Product Rating",
"zh-CN": "商品评分"
}
}

settings 配置项

每个 setting 对象的结构:

{
"type": "color",
"id": "color",
"label": {
"en-US": "Star Color",
"zh-CN": "星星颜色"
},
"default": "#ff0000"
}
字段是否必填说明
type设置项的控件类型(见下表)
id设置项的唯一标识,在 Liquid 中通过 block.settings.<id> 访问
label在主题编辑器中显示的标签,必须同时提供 en-USzh-CN
default设置项的默认值

常用 type 类型:

type说明示例默认值
text单行文本输入框"默认文本"
textarea多行文本输入框"多行文本"
color颜色选择器"#ff0000"
select下拉选择框(需配合 options 字段)"option_value"
checkbox勾选框true
range滑动范围选择(需配合 minmaxstep 字段)50
image_picker图片选择器,让商家从后台上传或选择图片

在 Liquid 中访问设置值:

{{ block.settings.color }}
{{ block.settings.button_label }}
{{ block.settings.background_color }}

资源引用

方式一:{% use %} 标签(推荐,用于加载 CSS/JS)

{% use %} 是 Shoplazza 提供的 Liquid 标签,用于在 Block 中加载 assets/ 目录下的 CSS 或 JS 文件:

{% use "app_block.css" %}
{% use "app_block.js" %}

特点:

  • 如果同一文件在页面上被多个区块引用,只会加载一次,避免重复。

  • CSS 文件会自动在 <head> 中注入 <link> 标签。

  • JS 文件会自动以异步方式加载。

方式二:asset_abs_url 过滤器(用于引用图片等路径)

对于需要在 HTML 属性中动态引用资源路径的场景(如图片 src),使用 asset_abs_url 过滤器获取资源的绝对 URL:

<img src="{{ 'thumbs_up.svg' | asset_abs_url }}">

结合其他过滤器使用:

{{ 'app_embed_block.css' | asset_abs_url | stylesheet_tag }}
{{ 'app_embed_block.js' | asset_abs_url | script_tag }}

注意:在 Theme App Extension 中引用 assets/ 目录下的资源,必须使用 asset_abs_url,而不是主题开发中的 asset_urlshoplaza_asset_urlasset_abs_url 会根据扩展 ID 和文件哈希生成带唯一标识的路径,确保不同扩展间的同名文件不会冲突。

文件命名限制

通过 asset_abs_url 引用的资源文件(图片、CSS、JS 等),文件名不能包含连字符 -,可以使用下划线(_)代替,如 thumbs_up.svgapp_block.css。否则无法生成远程资源。

两种方式的适用场景:

使用场景推荐方式
在 Block 中加载 CSS/JS 文件{% use "app_block.css" %}
在 HTML 属性中引用图片或其他资源路径{{ 'thumbs_up.svg' | asset_abs_url }}
动态生成 <link><script> 标签{{ 'app_block.css' | asset_abs_url | stylesheet_tag }}

多语言(locales)

locales/ 目录存放店面文本的多语言翻译文件,文件命名格式为 {语言代码}.json(如 en-US.jsonzh-CN.jsonzh-TW.json)。平台支持 15 个地区(含台湾)和 14 个国家的语言文件。

文件格式

locales/en-US.json:

{
"ratings": {
"star_label": "Rating",
"recommendation_text": "Recommended Product!"
}
}

locales/zh-CN.json:

{
"ratings": {
"star_label": "评分",
"recommendation_text": "推荐产品!"
}
}

在 Liquid 中使用翻译

通过 t 过滤器引用翻译键,键名使用点号分隔的路径,并以 i18n. 作为命名空间前缀:

{{ 'i18n.ratings.star_label' | t }}
{{ 'i18n.ratings.recommendation_text' | t }}

平台会根据当前店铺语言自动加载对应语言文件中的翻译文本。

备注

商家无法在主题编辑器中编辑 Theme App Extension 的店面多语言文本,这些文本由开发者在 locales/ 文件中统一维护。