# 使用 Liquid 模板

Liquid 模板通过实现复杂的逻辑，极大地扩展了 Pushwoosh 的个性化功能，这是对常规[动态内容](/zh/developer/guides/personalization/dynamic-content/)用法的补充。

Pushwoosh 中的消息个性化基于 [Tags (用户数据)](/zh/developer/guides/audience-and-segmentation/tags/)。Pushwoosh 提供了多种[默认 Tags](/zh/developer/guides/audience-and-segmentation/tags/#default-tags) 和[自定义 Tags](/zh/developer/guides/audience-and-segmentation/tags/#custom-tags)。使用它们，您可以指定用户的名字、城市、购买历史等，以发送更个性化的消息，例如：`Hi {First_name}, thanks for ordering {item}`。

Liquid 模板为动态内容增加了更多逻辑。例如，如果用户的订阅标签包含 "free"，您可以向他们发送一条消息：“获取您的 10% 折扣。”

根据用户的 ID、行为和偏好修改消息内容，是提高相关性并从营销活动中获得更佳效果的最有效方法。

## 语法

基于 [Shopify 的 Liquid](https://shopify.github.io/liquid/) 的内容模板使用 [**tags** (标签)](/zh/developer/guides/personalization/liquid-templates/#tags)、[**objects** (对象)](/zh/developer/guides/personalization/liquid-templates/#objects) 和 [**filters** (过滤器)](/zh/developer/guides/personalization/liquid-templates/#filters) 的组合来加载动态内容。内容模板允许您从模板内部访问某些变量并输出其数据，而无需了解数据本身的任何信息。

<Aside type="note">
要了解有关语法的更多信息，请参阅 [Liquid 文档](https://shopify.github.io/liquid/basics/introduction/)。
</Aside>

### 对象

`objects` (对象) 定义了将向用户显示的内容。`objects` 应包含在双花括号中：`{{ }}`

例如，在个性化消息时，在其正文中发送 `{{Name}}` 以将用户名添加到消息内容中。用户的姓名 (Name 标签值) 将替换用户将看到的消息中的 Liquid 对象。

<Tabs>
  <TabItem label="输入">

```

Hi {{Name}}! We're glad you're back!

```

  </TabItem>

  <TabItem label="输出">
    Hi Anna! We're glad you're back!
  </TabItem>
</Tabs>


### 标签

`tags` (标签) 为模板创建逻辑和控制流。花括号百分号分隔符 `{%` 和 `%}` 及其包围的文本在模板呈现时不会产生任何可见输出。这使您可以分配变量并创建条件或循环，而无需向用户显示任何 Liquid 逻辑。

例如，使用 `if` 标签，您可以根据用户设备上设置的语言来改变消息的语言：

<Tabs>
  <TabItem label="输入">

```liquid
{% if Language == 'fr' %}
Salut!
{% else %}
Hello!
{% endif %}
````

  </TabItem>

  <TabItem label="输出 (fr)">
    Salut!
  </TabItem>

  <TabItem label="输出 (es)">
    Hello!
  </TabItem>
</Tabs>

### 标签运算符

<table data-header-hidden><thead><tr><th width="189.5" align="center">运算符</th><th>描述</th></tr></thead><tbody><tr><td align="center"><code>==</code></td><td>等于</td></tr><tr><td align="center"><code>!=</code></td><td>不等于</td></tr><tr><td align="center"><code>></code></td><td>大于</td></tr><tr><td align="center"><code>&#x3C;</code></td><td>小于</td></tr><tr><td align="center"><code>>=</code></td><td>大于或等于</td></tr><tr><td align="center"><code>&#x3C;=</code></td><td>小于或等于</td></tr><tr><td align="center"><code>or</code></td><td>逻辑或</td></tr><tr><td align="center"><code>and</code></td><td>逻辑与</td></tr><tr><td align="center"><code>contains</code></td><td>检查字符串或字符串数组中是否存在子字符串</td></tr></tbody></table>

<Aside type="note">
在具有多个 `and` 或 `or` 运算符的标签中，运算符的检查顺序是_从右到左_。您不能使用括号更改操作顺序——括号在 Liquid 中是无效字符，会导致您的标签无法工作。
</Aside>

### 过滤器

`filters` (过滤器) 修改 Liquid 对象或变量的输出。它们在双花括号 `{{ }}` 和变量赋值中使用，并由管道字符 `|` 分隔。一个输出上可以使用多个过滤器，并从左到右应用。


<Tabs>
<TabItem label="输入">

```

{{ Name | capitalize | prepend:"Hello " }}

```

</TabItem>

<TabItem label="输出">

Hello Anna

</TabItem>
</Tabs>

## 在通过 API 发送的消息中使用 Liquid 模板

在您的 [`createMessage`](/zh/developer/api-reference/messages-api/#createmessage) 请求中使用 Liquid 语法来实现 Liquid 模板。模板可用于 `createMessage` 请求的 "content" 参数，以及任何其他支持动态内容的参数，特别是特定于平台的 "title"、"subtitle" 和 "image" 参数。

通过使用内容模板，您可以在 API 请求中指定数据（传递 "template_bindings" 参数），或者从存储在用户设备上的 Tag 值中获取数据（不使用 "template_bindings" 参数）。这样，您就能够构建包含极其相关内容的用户级推送营销活动。

<Aside type="note">
请注意，与动态内容不同，模板中的变量应按如下方式包含在双花括号中：`{{myVariable}}`。
</Aside>

要使用名称中包含空格的 Tags 定义模板逻辑，请使用以下技巧：

**示例**

```
{% capture my_tag %}{{My Tag}}{% endcapture %}
{% if my_tag == 'value' %}
Content to send in this case
{% else %}
Content to send otherwise
{% endif %}
```
## Liquid 模板用例

在这里，您会发现几个 Liquid 模板派上用场的用例。

### 多语言推送

Liquid 模板可以明确指定用户应以何种语言接收您的推送消息。请看 API 请求的简单示例以及根据请求中使用的模板绑定收到的消息。


<Tabs>
<TabItem label="Liquid 输入">

```

{% if Language == 'es' %}
¡Hola!
{% else %}
Hello!
{% endif %}

````

</TabItem>

<TabItem label="API 请求">

```javascript
{
  "request": {
    "application": "XXXXX-XXXXX", // Pushwoosh app code
    "auth": "yxoPUlw.....IyEX4H", // API access token from Pushwoosh Control Panel
    "notifications" : [ // push message parameters
      {
       "content": "{% raw %}
{% if language == 'es' %}¡Hola!{% else %}hello!{% endif %}
{% endraw %}",
        "template_bindings": { // optional. When no template_bindings are passed in a request, Tag values from the device are used.
         "language" : "es"
        }
      }
    ]
  }
}
````

</TabItem>

<TabItem label="输出">

**语言为 'es'**：
¡Hola!

**语言为 'en'**：
Hello!

</TabItem>
</Tabs>


### 订阅升级提示

根据客户当前的计划，鼓励他们升级订阅。

<Tabs>
  <TabItem label="Liquid 输入">

```

{% if Subscription == 'Basic' %}
    Upgrade to Silver for getting more product features and 24/7 support.
{% elsif Subscription == 'Silver' %}
    Upgrade to Gold for priority support and advanced features.
{% else %}
    Please contact your manager to renew your subscription.
{% endif %}

````

</TabItem>

<TabItem label="API 请求">

```json
{
  "request": {
    "application": "XXXXX-XXXXX", // Pushwoosh app code
    "auth": "yxoPUlw.....IyEX4H", // API access token from Pushwoosh Control Panel
    "notifications" : [ // push message parameters
      {
       "content": "{% raw %}
{% if Subscription == 'Basic' %}Upgrade to Silver for getting more product features and 24/7 support.{% elsif Subscription == 'Silver' %}Upgrade to Gold for priority support and advanced features.{% else %}Please contact your manager to renew your subscription. {% endif %}
{% endraw %}",
        "template_bindings": { // optional. When no template_bindings are passed in a request, Tag values from the device are used.
         "language" : "es"
        }
      }
    ]
  }
}
````

  </TabItem>

  <TabItem label="输出">

**对于使用基础订阅计划的用户：**
升级到白银版以获得更多产品功能和 24/7 支持。

**对于使用白银订阅计划的用户：**
升级到黄金版以获得优先支持和高级功能。

**对于使用其他计划的用户：**
请联系您的客户经理续订您的订阅。

  </TabItem>
</Tabs>


### 列表标签

内容模板对于处理列表类型的标签非常有用。

#### 变量大小

一种可能的用例是根据标签包含的值的数量来提供不同的内容。例如，您可以为具有不同行为的客户提供不同的折扣。假设客户的愿望清单中有一些商品——根据他们打算购买的产品数量，用最合适的折扣鼓励他们购买！


<Tabs>
<TabItem label="Liquid 输入">

```

{% if WishList.size >= 3 %}
Get 20% off your next purchase!
{% elsif WishList.size == 2 %}
Get a 10% discount on your next purchase!
{% else %}
Hey, take a look at new outwears!
{% endif %}

````

</TabItem>

<TabItem label="API 请求">

```javascript
{
  "request": {
    "application": "XXXXX-XXXXX", // Pushwoosh app code
    "auth": "yxoPUlw.....IyEX4H", // API access token from Pushwoosh Control Panel
    "notifications" : [ // push message parameters
      {
       "content": "{% raw %}
{% if WishList.size >= 3 %}Get 20% off your next purchase!{% elsif WishList.size == 2 %}Get a 10% discount on your next purchase!{% else %}Hey, take a look at new outwears!{% endif %}
{% endraw %}",
        "template_bindings": {
         "WishList" : ["Skinny Low Ankle Jeans", "Linen Trenchcoat", "High Waisted Denim Skirt", "Strappy Tiered Maxi Dress"]
        }
      }
    ]
  }
}
````

</TabItem>

<TabItem label="WishList 大小 ≥ 3">

<img src="/personalization-liquid-templates-1.webp" alt="心愿单大小大于等于3的邮件预览" width="200"/>

</TabItem>

<TabItem label="WishList 大小 = 2">

<img src="/personalization-liquid-templates-2.webp" alt="心愿单大小等于2的邮件预览" width="200"/>

</TabItem>
</Tabs>

#### 变量包含

您可能需要处理的另一个情况是处理列表标签值，并根据标签包含的值来提供最相关的内容。

<Tabs>
<TabItem label="Liquid 输入">

```

{% if WishList contains 'Skinny Low Ankle Jeans' %}
Get 20% off products in your wishlist!
{% else %}
Hey, take a look at the brand new Skinny Low Ankle Jeans!
{% endif %}

````

</TabItem>

<TabItem label="API 请求">

```javascript
{
  "request": {
    "application": "C90C0-0E786",
    "auth": "yxoPUlw.....IyEX4H", // API access token from Pushwoosh Control Panel
    "notifications" : [ // push message parameters
      {
       "content": "{% raw %}
{% if WishList contains 'Skinny Low Ankle Jeans' %}Get 20% off your next purchase!{% else %}Hey, take a look at the brand new Skinny Low Ankle Jeans!{% endif %}
{% endraw %}",
        "template_bindings": {
         "WishList" : ["Skinny Low Ankle Jeans", "Linen Trenchcoat", "High Waisted Denim Skirt", "Strappy Tiered Maxi Dress"]
        }
      }
    ]
  }
}
````

</TabItem>

<TabItem label="变量包含数据">

<img src="/personalization-liquid-templates-3.webp" alt="包含数据的个性化模板" width="200"/>

</TabItem>

<TabItem label="变量不包含数据">

<img src="/personalization-liquid-templates-4.webp" alt="数据缺失时的备用视图" width="200"/>

</TabItem>
</Tabs>


### 复数

通过使用内容模板，您可以根据用户的行为调整消息内容。例如，如果列表标签包含多个值，您可以修改消息文本以包含复数词。


<Tabs>
<TabItem label="Liquid 输入">

```
    Get 20% off item
{% if WishList.size > 1 %}
    s in your WishList!
{% else %}
    in your Wishlist!
{% endif %}

````

</TabItem>

<TabItem label="API 请求">

```javascript
{
  "request": {
    "application": "C90C0-0E786",
    "auth": "yxoPUlw.....IyEX4H", // API access token from Pushwoosh Control Panel
    "notifications" : [ // push message parameters
      {
       "content": "Get 20% off item{% raw %}
{% if WishList.size > 1 %}s in your WishList!{% else %} in your Wishlist!{% endif %}
{% endraw %}",
        "template_bindings": { // optional. When no template_bindings are passed in a request, Tag values from the device are used.
         "WishList" : ["Skinny Low Ankle Jeans", "Linen Trenchcoat", "High Waisted Denim Skirt", "Strappy Tiered Maxi Dress"]
        }
      }
    ]
  }
}
````

</TabItem>

<TabItem label="复数">

<img src="/personalization-liquid-templates-5.webp" alt="复数形式模板示例" width="200"/>

</TabItem>

<TabItem label="单数">

<img src="/personalization-liquid-templates-6.webp" alt="单数形式模板示例" width="200"/>

</TabItem>
</Tabs>

### 时区

时区模板根据指定的时区转换日期和时间。

<Tabs>
<TabItem label="Liquid 输入">
```
{{ MyDate | timezone: MyTimezone | date: \"%Y-%m-%d %H:%M\" }}
```
</TabItem>

<TabItem label="API 请求">
```javascript title="示例"
{
  "request" : {
    "auth" : "3H9bk8w3.....Acge2RbupTB", // API access token from Pushwoosh Control Panel
    "application" : "XXXXX-XXXXX", // Pushwoosh app code
    "notifications" : [ // push message parameters
      {
        "content": "Current Date: {{ MyDate | timezone: MyTimezone | date: \"%Y-%m-%d %H:%M\" }}",
        "template_bindings": { // optional. When no template_bindings are passed in a request, Tag values from the device are used.
         "MyDate" : "2019-07-23 15:00",
         "MyTimezone" : "Asia/Dubai"
        }
      }
    ]
  }
}
```
</TabItem>
<TabItem label="输出"> <img src="/personalization-liquid-templates-7.webp" alt="推送通知中的个性化日期输出" width="200"/>
</TabItem>
</Tabs>


## Connected content

Connected content 是 Liquid 模板中的一项功能，允许您直接在电子邮件或推送通知消息中动态检索和使用来自外部源（例如 Web 服务）的数据。此功能通过从指定 URL 获取 JSON 数据并将其保存到可在内容中使用的变量中，从而实现实时个性化。

#### 主要用例

- **产品推荐**：显示为每个用户量身定制的个性化产品列表。

- **促销代码**：插入由后端服务生成的唯一促销代码。

#### 前提条件

* 要使用 Connected Content，您必须拥有自己的后端服务，该服务根据 **User ID、HWID 或自定义标签** 生成并提供所需的数据（例如，促销代码、产品推荐）。然后，Pushwoosh 在发送消息之前获取这些数据。

### 分步实施指南


#### 第 1 步：设置后端服务

后端服务应：

* 接受包含用户特定参数（例如 `userId`）的请求。Connected Content 支持 `UserID`、`HWID` 或您在项目中设置的任何自定义标签。
* 返回包含所需数据的 JSON 响应。然后，这些内容可以动态插入到消息中。

<Aside type="note" title="工作原理">

后端服务充当数据提供者，通过用户特定信息响应 HTTP 请求。

1. Pushwoosh 向您的后端发送请求，将用户特定标识符作为查询参数传递。
2. 您的后端处理请求并检索所需数据。
3. 您的后端返回一个 JSON 响应。
4. 在发送消息之前，Pushwoosh 从后端服务获取 JSON 响应，并动态地在消息内容中使用返回的值（例如 `code`）。

**响应示例**

```
{ "code": "SPECIALOFFERFORUSER12345" }
```
</Aside>



#### 第 2 步：在 Pushwoosh 中创建带有 Connected content 的预设

1. 在 [Push](/zh/product/content/push-presets/) 或 [Email 内容编辑器](/zh/product/content/email-content/drag-and-drop-email-editor/)中，将 Connected Content 语法插入到消息字段中。

**示例**

```
{% connected_content http://your-backend-url.com?userId={{ ${userid} }} :save result %}
```
**语法分解**
|  |  |
| ----- | ----- |
| `connected_content` | 从指定的后端 URL 获取 JSON 数据。 |
|    `http://your-backend-url.com` | 以 JSON 格式返回所需数据的后端端点。 |
| `userId={{ ${userid} }}` | 将用户 ID 传递给后端的动态查询参数。 |
| `:save result` | 将获取的 JSON 响应存储在 result 变量中，以便在 Liquid 模板中使用。 |

![插入 Connected Content 语法](/connectedcontent.webp)

**身份验证（可选）**

如果您的后端服务需要身份验证，您可以在 Connected Content 请求中包含 API 密钥或令牌，以确保安全访问。

```
{% connected_content http://your-backend-url.com?userId={{ ${userid} }}&auth=YOUR_API_KEY :save result %}
```

您还可以使用可选的 `:headers` 参数（一个包含标头名称和值的 JSON 对象）将身份验证（或任何其他）数据作为 HTTP 标头发送。

```
{% connected_content http://your-backend-url.com?userId={{ ${userid} }} :headers {"Authorization": "Bearer YOUR_TOKEN", "X-Api-Key": "YOUR_API_KEY"} :save result %}
```
|  |  |
| ----- | ----- |
| `:headers {...}` | 随请求发送的 HTTP 标头的 JSON 对象，例如 `Authorization: Bearer <token>`。 |

<Aside type="caution" title="仅限静态值">
`${}` 个性化变量仅在 URL 内部有效。`:headers` 内部的值是静态的，不会被插值。
</Aside>

**在 Connected content 中使用标签**

要包含自定义标签，请将它们作为查询参数插入到 **Connected Content** 请求中 (`{{ tag_name }}`)。

```
{% connected_content http://your-backend-url.com?userId={{ ${userid} }}{{ Language }} :save result %}
```

2. 接下来，添加包含**检索到的数据**的消息文本，如下所示：

```

Hey, {{userid}}, grab your personal promo code - {{result.code}}
```

![添加带有检索数据的消息文本](/connectedcontent-1.webp)

3. 在最终确定消息内容并配置预设设置后，保存它以便在营销活动中重复使用。

<video src="/connectedcontent-2.webm" title="发送带有 connected content 的消息" autoplay loop muted playsinline />

#### 第 3 步：使用配置的预设发送消息

使用[一次性推送](/zh/product/messaging-channels/push-notifications/send-push-notifications/one-time-push/#how-to-send-a-push-notification-using-the-one-time-push-form)或[电子邮件表单](/zh/product/messaging-channels/emails/send-email/#how-to-send-a-one-time-email)或[客户旅程](/zh/product/customer-journey/pushwoosh-journey-overview/)发送带有此预设的消息。

<Aside type="caution" title="重要">
如果服务返回的状态不是 HTTP 200 OK，则不会发送电子邮件或推送通知。这确保了您的通信仅在成功检索到必要数据时才会发出。
</Aside>