Использование переменных Liquid в Shopify Flow

Переменные Liquid — это определенные в Liquid заполнители, которые заменяются значениями из GraphQL Admin API при запуске рабочего процесса. Переменные могут описывать атрибуты клиентов, заказов и товаров, участвующих в ваших рабочих процессах, например номер заказа, цену заказа или имя клиента. Переменные можно использовать в условиях для управления логикой рабочего процесса или для вывода данных из действия.

Добавление переменных в рабочие процессы с помощью Liquid

Вы можете добавлять переменные с помощью Liquid в любое текстовое поле со ссылкой «Добавить переменную». Нажмите на ссылку «Добавить переменную» под соответствующим полем, а затем выберите переменную из списка.

Изображение панели конфигурации действия «Отправить внутреннее электронное письмо» с выделенной опцией «Добавить переменную» под полем «Тема».

Переменные в списке «Добавить переменную» отфильтрованы, поэтому вы можете использовать только те переменные, которые возвращаются на предыдущих шагах, например триггерами. Например, триггер «Заказ создан» предоставляет ресурсы заказа и магазина из Admin API, которые можно вставить в качестве переменных. После того как вы выберете переменную из списка, она будет добавлена в текстовое поле в виде правильно отформатированного кода Liquid.

Вы также можете писать код Liquid прямо в текстовом поле. Например, с помощью переменной {{ order.name }} можно отобразить строку заказа из панели администратора Shopify, например order-123.

Поскольку Flow использует Admin API для извлечения данных для Liquid, в синтаксисе переменных используется верблюжий регистр (camel case). В переменных, записанных в верблюжьем регистре, первое слово начинается со строчной буквы, а все последующие — с заглавной, например firstName или canMarkAsPaid. Например, чтобы получить доступ к дате создания товара, введите {{ product.createdAt }}. Если вы используете синтаксис Liquid в теме Shopify, где верблюжий регистр не используется, необходимо будет ввести {{ product.created_at }}.

Условные теги и теги итераций Liquid

Теги Liquid можно использовать с переменными для выполнения следующих функций:

  • Составление условных операторов, например для определения, превышает ли общая сумма заказа 100 $.
  • Перебор списка объектов, например для вывода данных по каждой позиции в заказе.

Для составления этих операторов и перебора объектов можно использовать теги Liquid.

Например, следующий код Liquid отображает номер заказа, если его общая сумма превышает 100 $:

{% if order.totalPriceSet.shopMoney.amount > 100 %}
  Order number: {{ order.name }}
{% endif %}

Вы также можете использовать цикл for для перебора списка объектов, например позиций в заказе. Например, следующий код Liquid отображает название каждой позиции в заказе:

{% for li in order.lineItems %}
  {{ li.title }}
{% endfor %}

Flow поддерживает следующие условные теги (теги управления потоком) Liquid:

Flow также поддерживает следующие теги итераций Liquid:

Применение фильтров к переменным

С помощью фильтров можно преобразовывать данные переменных в Liquid. Flow поддерживает все фильтры Liquid с открытым исходным кодом.

Например, следующий код Liquid удаляет префикс из названия заказа и выводит оставшуюся часть: {{ order.name | remove: "Order-" }}

Особенности использования переменных Liquid в фильтрах

Перед преобразованием переменных с помощью фильтров ознакомьтесь со следующими особенностями:

  • Flow не поддерживает точечную нотацию, доступную для некоторых фильтров. Например, Flow поддерживает {{ order.lineItems | size }}, но не {{ order.lineItems.size }}.
  • Flow не поддерживает точечную нотацию для метаполей. Например, вы не можете использовать {{ order.metafields.custom.hold_note }}. Вместо этого необходимо выполнить перебор метаполей, как показано в примерах.
  • Flow не поддерживает использование индексов для доступа к элементам списка. Например, вы не можете использовать {{ order.lineItems[0].title }}. Вместо этого необходимо выполнить перебор позиций, как показано в примерах.

Фильтры дат

В дополнение к стандартным фильтрам Liquid, Flow предоставляет фильтры дат для получения даты относительно другой даты, чтобы поддерживать триггер «Запланированное время» и функции «Получить данные». Эти фильтры — date_minus и date_plus. Например:

  • Чтобы вернуть дату на один день в будущем: {{ "now" | date_plus: "1 day" }}
  • Чтобы вернуть дату на один день в прошлом: {{ "now" | date_minus: "1 day" }}

Эти фильтры принимают second, minute, day, week, month и year в качестве единиц длительности как в единственном (например, second), так и во множественном числе (например, seconds). Вы также можете указать следующие типы настраиваемых единиц:

  • Целое число, представляющее количество секунд: {{ "now" | date_minus: 3600 }}, где 3600 эквивалентно 1 часу.
  • Строка длительности в формате ISO 8601: {{ "now" | date_minus: "P1Y2D" }}, где P1Y2D означает 1 год и 2 дня.

Криптографические фильтры

Shopify Flow предоставляет криптографические фильтры для хеширования и создания кодов аутентификации сообщений на основе хеша (HMAC). Эти фильтры полезны для создания уникальных идентификаторов, контрольных сумм или интеграции со сторонними системами, которым требуются определённые форматы хеша.

Фильтры хеширования

Shopify Flow поддерживает следующие типы фильтров хеширования:

  • blake3 — создаёт хеш BLAKE3 (рекомендуется для общего использования).
  • sha256 — создаёт хеш SHA-256.
  • sha1 — создаёт хеш SHA-1.
  • md5 — создаёт хеш MD5.

Для общего хеширования и новых реализаций следует использовать blake3, так как этот алгоритм обеспечивает более высокую производительность и безопасность по сравнению со старыми. Однако sha256, sha1 и md5 доступны для обеспечения совместимости со сторонними системами.

Пример использования: {{ "hello world" | blake3 }} возвращает хеш BLAKE3 для «hello world».

Фильтры HMAC

Чтобы создать HMAC с секретным ключом, используйте один из следующих поддерживаемых фильтров:

Пример использования:

  • Базовый вариант: {{ "message" | hmac_sha256: "secret_key" }}
  • С использованием секретов (рекомендуется): {{ "message" | hmac_sha256: secrets.api_key }}

Примеры использования переменных с Liquid в Shopify Flow

Чтобы лучше понять, как использовать переменные Liquid, рассмотрите следующие примеры:

Вывод URL-адресов для ресурсов

Вам нужно вывести URL для клиента, заказа и товара, которые задействованы в рабочем процессе.

# Output the base Admin URL for your store
https://admin.shopify.com/store/{{ shop.myShopifyDomain | replace: ".myshopify.com", "" }}

# Assign the base Admin url to a variable named base_url:
{%- capture base_url -%}https://admin.shopify.com/store/{{ shop.myShopifyDomain | replace: ".myshopify.com", "" }}{%- endcapture -%}

# Customer from a Customer trigger:
{{ base_url }}/customers/{{ customer.legacyResourceId }}

# Customer without the base_url:
https://admin.shopify.com/store/{{ shop.myShopifyDomain | replace: ".myshopify.com", "" }}/customers/{{ customer.legacyResourceId }}

# Customer from an Order trigger:
{{ base_url }}/customers/{{ order.customer.legacyResourceId }}

# Order:
{{ base_url }}/orders/{{ order.legacyResourceId }}

# Product:
{{ base_url }}/products/{{ product.legacyResourceId }}

# Product Variant:
{{ base_url }}/products/{{ product.legacyResourceId }}/variants/{{ productVariant.legacyResourceId }}

# Example showing a clickable link in HTML, making use of the URL:
<a href="{{ base_url }}/products/{{ product.legacyResourceId }}">{{ product.title }}</a>

Преобразование списка тегов в метаполе

Вы хотите преобразовать набор тегов в метаполе, представляющее собой список однострочных текстовых полей. Вы создаёте рабочий процесс с помощью триггера «Товар добавлен в магазин» и используете действие «Обновить метаполе товара». В разделе «Значение» действия «Обновить метаполе товара» вы добавляете следующий код Liquid. В этом примере предполагается, что вам нужно задать значения только один раз при создании товара и что у товара есть два соответствующих тега: color:red и color:orange.

Пример кода Liquid для заполнения списка однострочного текстового поля.
Входные данныеВыходные данные
{% capture mf_value %}
{%- for tags_item in product.tags -%}
  {%- if tags_item contains "color:" -%}
    "{{- tags_item | remove_first: "color:" | strip -}}",
  {%- endif -%}
{%- endfor -%}
{% endcapture -%}
[{{mf_value | remove_last: ","}}]
      
["red","orange"]

Создание динамического сообщения электронной почты для заказа

Вы хотите создать рабочий процесс для отправки электронного письма сотруднику, когда клиент тратит на заказ более 500 $. Вы создаёте рабочий процесс с помощью триггера «Заказ создан», задаёте условие, которое выполняется, если общая сумма заказа превышает 500 $, и используете действие «Отправить внутреннее электронное письмо». В разделе «Сообщение» этого действия вы используете следующие переменные.

Пример использования переменных для предоставления данных о клиенте.
Входные данныеВыходные данные
Please send a personal thank you note to {{ order.customer.firstName }} {{ order.customer.lastName }}({{ order.customer.email }}) for placing an order for $ {{ order.totalPriceSet.shopMoney.amount }}.
Отправьте личное благодарственное письмо Jeanne Dupont (jeanne@example.com) за размещение заказа на сумму 763,42 $.

Создание динамического сообщения электронной почты для товара, запас которого заканчивается

Вы решили, что вам нужно информировать сотрудника, когда товарные запасы заканчиваются и необходимо заказать ещё. Вы создаёте рабочий процесс, который начинается с триггера «Количество товаров изменено», и задаёте условие, которое выполняется, если предыдущее количество товаров меньше или равно 10. В разделе «Сообщение» действия «Отправить внутреннее электронное письмо» вы используете следующие переменные.

Пример использования переменных для предоставления сведений о товаре.
Входные данныеВыходные данные
Please reorder {{ product.title }}. Email owner@store.com to verify that they've received the purchase order.
Перезакажите товар «High Waist Leggings — Black». Отправьте электронное письмо на адрес owner@example.com, чтобы убедиться, что они получили заказ на поставку.

Создание динамического сообщения электронной почты для уведомления персонала о мошенническом заказе

Вы хотите отменять заказы с высоким уровнем риска, но предпочитаете, чтобы ваш персонал отменял их вручную. Вы создаёте рабочий процесс, который начинается с триггера «Заказ создан», и задаёте условие, которое выполняется, если уровень риска заказа равен «высокому». В разделе «Сообщение» действия «Отправить внутреннее электронное письмо» вы используете следующие переменные.

Пример использования переменных для предоставления информации о мошенническом заказе.
Входные данныеВыходные данные
Our Shopify store has received an order with a high risk of fraud. We would like to cancel this order right away, before it is sent to production:
{{ order.name }} {{ order.billingAddress.lastName }}, {{ order.billingAddress.firstName }} {{ order.email }}
Please confirm the new order status. Thanks!
Наш магазин Shopify получил заказ с высоким риском мошенничества. Мы хотели бы отменить этот заказ прямо сейчас, до его отправки в производство:

#1001
Dupont, Jeanne
jeanne@example.com

Пожалуйста, подтвердите новый статус заказа. Спасибо!

Вывод позиций заказа с помощью цикла for

При получении заказа может быть полезно отправить сообщение, содержащее заказанные товары. Это можно сделать с помощью цикла for, который многократно выполняет блок кода. Текстовые поля, поддерживающие переменные, также поддерживают циклы for и объект forloop.

Например, вы хотите создать рабочий процесс, который будет возвращать список всех артикулов и их количества в заказе. В разделе «Сообщение» действия «Отправить внутреннее электронное письмо» используйте следующие переменные.

Пример использования цикла for для предоставления информации о заказе.
Входные данныеВыходные данные
Order summary:
{% for a in order.lineItems %}
  {{a.sku}} ( {{a.quantity}} )
{% endfor %}
Сводка по заказу:
8987097979 (50)
8877778887 (3)
888998898B (1)

Вывод позиций заказа с дополнительной информацией с помощью цикла for

Вы можете добавить в электронное письмо больше информации, например название товара, артикулы, цену за единицу и информацию о доставке для клиента. Для этого в разделе «Сообщение» действия «Отправить внутреннее электронное письмо» используйте следующие переменные.

Пример использования цикла for для предоставления более подробной информации о заказе.
Входные данныеВыходные данные
Order summary:
{% for a in order.lineItems %}
  Product: {{a.title}}
  SKU: {{a.sku}}
  Price (per unit): ${{a.originalUnitPriceSet.shopMoney.amount}}
  Quantity: {{a.quantity}}
{% endfor %}
Сводка по заказу:
Товар: Леггинсы с высокой талией — черные
SKU: 8987097979
Цена (за единицу): 8,49 $
Количество: 5
Товар: Спортивные носки — синие
SKU: 888998898B
Цена (за единицу): 5,61 $
Количество: 2

Вывод определенных позиций путем объединения цикла for и оператора if

Допустим, вам нужно отслеживать проданные товары, поставляемые определенным продавцом. В разделе «Сообщение» действия «Отправить внутреннее электронное письмо» используйте следующие переменные и включите оператор if в свой цикл for.

Пример использования цикла for и оператора if для предоставления информации о заказе от определенных продавцов.
Входные данныеВыходные данные
Acme product sold:
{% for x in order.lineItems %}
  {% if x.vendor == 'acme-vendor' %}
    Product name: {{x.title}}
    SKU: {{x.sku}}
  {% endif %}
{% endfor %}
Продан товар Acme:
Название товара: Леггинсы с высокой талией — черные
SKU: 8987097979

Сложные объекты данных в Shopify Flow

Flow позволяет получать доступ практически к любым данным, которые есть в GraphQL Admin API. К ним относятся сложные объекты данных, например списки и объекты. Однако существуют некоторые ограничения на то, что можно делать с этими объектами. В этом разделе описаны эти ограничения и приведены примеры работы с ними.

Вместо прямого вызова списков и объектов следует перебирать их в цикле и включать только нужные вам поля.

Например, вместо прямого вызова {{ order.lineItems }} используйте следующий формат для вызова определенных полей. Эти примеры включают все поля, которые были бы вызваны при прямом обращении к списку или объекту. Скопируйте и вставьте те поля, которые вам нужны.

Текст
{% for li in order.lineItems %}
    {% comment %}li.contract - omitted{% endcomment %}

{% for ca in li.customAttributes %}
    {{ ca.key }}
    {{ ca.value }}
{% endfor %}

{% for da in li.discountAllocations %}
    {{ da.allocatedAmountSet.presentmentMoney.amount }}
    {{ da.allocatedAmountSet.presentmentMoney.currencyCode }}
    {{ da.allocatedAmountSet.shopMoney.amount }}
    {{ da.allocatedAmountSet.shopMoney.currencyCode }}
{% endfor %}

{{ li.discountedTotalSet.presentmentMoney.amount }}
{{ li.discountedTotalSet.presentmentMoney.currencyCode }}
{{ li.discountedTotalSet.shopMoney.amount }}
{{ li.discountedTotalSet.shopMoney.currencyCode }}

{{ li.discountedUnitPriceSet.presentmentMoney.amount }}
{{ li.discountedUnitPriceSet.presentmentMoney.currencyCode }}
{{ li.discountedUnitPriceSet.shopMoney.amount }}
{{ li.discountedUnitPriceSet.shopMoney.currencyCode }}

{% comment %}li.duties - omitted {% endcomment %}

{{ li.fulfillableQuantity }}

{{ li.fulfillmentService.callbackUrl }}
{{ li.fulfillmentService.fulfillmentOrdersOptIn }}
{{ li.fulfillmentService.handle }}
{{ li.fulfillmentService.id }}
{{ li.fulfillmentService.inventoryManagement }}
{% comment %}rest of location omitted{% endcomment %}
{{ li.fulfillmentService.location.name }}
{{ li.fulfillmentService.productBased }}
{{ li.fulfillmentService.serviceName }}
{% for sm in li.fulfillmentService.shippingMethods %}
    {{ sm.code }}
    {{ sm.label }}
{% endfor %}
{{ li.fulfillmentService.type }}

{{ li.fulfillmentStatus }}
{{ li.id }}

{{ li.image.altText }}
{{ li.image.height }}
{{ li.image.id }}
{% comment %}li.image.metafield omitted{% endcomment %}
{% comment %}li.image.privateMetafield omitted{% endcomment %}
{{ li.image.width }}

{{ li.merchantEditable }}
{{ li.name }}
{{ li.nonFulfillableQuantity }}

{{ li.originalTotalSet.presentmentMoney.amount }}
{{ li.originalTotalSet.presentmentMoney.currencyCode }}
{{ li.originalTotalSet.shopMoney.amount }}
{{ li.originalTotalSet.shopMoney.currencyCode }}

{{ li.originalUnitPriceSet.presentmentMoney.amount }}
{{ li.originalUnitPriceSet.presentmentMoney.currencyCode }}
{{ li.originalUnitPriceSet.shopMoney.amount }}
{{ li.originalUnitPriceSet.shopMoney.currencyCode }}

{% comment %}rest of product omitted{% endcomment %}
{{ li.product.title }}

{{ li.quantity }}
{{ li.refundableQuantity }}
{{ li.requiresShipping }}
{{ li.restockable }}

{{ li.sellingPlan.name }}

{{ li.sku }}

{% for tl in li.taxLines %}
    {{ tl.priceSet.presentmentMoney.amount | json }}
    {{ tl.priceSet.presentmentMoney.currencyCode | json }}
    {{ tl.priceSet.shopMoney.amount | json }}
    {{ tl.priceSet.shopMoney.currencyCode | json }}
    {{ tl.rate | json }}
    {{ tl.ratePercentage | json }}
    {{ tl.title | json }}
{% endfor %}

{{ li.taxable }}
{{ li.title }}

{{ li.totalDiscountSet.presentmentMoney.amount }}
{{ li.totalDiscountSet.presentmentMoney.currencyCode }}
{{ li.totalDiscountSet.shopMoney.amount }}
{{ li.totalDiscountSet.shopMoney.currencyCode }}

{{ li.unfulfilledDiscountedTotalSet.presentmentMoney.amount }}
{{ li.unfulfilledDiscountedTotalSet.presentmentMoney.currencyCode }}
{{ li.unfulfilledDiscountedTotalSet.shopMoney.amount }}
{{ li.unfulfilledDiscountedTotalSet.shopMoney.currencyCode }}

{{ li.unfulfilledOriginalTotalSet.presentmentMoney.amount }}
{{ li.unfulfilledOriginalTotalSet.presentmentMoney.currencyCode }}
{{ li.unfulfilledOriginalTotalSet.shopMoney.amount }}
{{ li.unfulfilledOriginalTotalSet.shopMoney.currencyCode }}

{{ li.unfulfilledQuantity }}

{% comment %}rest of variant omitted{% endcomment %}
{{ li.variant.title }}

{{ li.variantTitle }}
{{ li.vendor }}

{% endfor %}

json
{
    "lineItems": [
        {% for li in order.lineItems %}
            {% if forloop.first != true %},{% endif %}
        {
            "contract": {
                {% comment %}rest of contract omitted{% endcomment %}
                "id": {{ li.contract.id | json }}
            },
            "customAttributes": [
                {% for ca in li.customAttributes %}
                    {% if forloop.first != true %},{% endif %}
                    {
                        "key":{{ ca.key | json }},
                        "value":{{ ca.value | json }}
                    }
                {% endfor %}
            ],
&#x22;discountAllocations&#x22;: [
            {% for da in li.discountAllocations %}
                {% if forloop.first != true %},{% endif %}
                &#x22;allocatedAmountSet&#x22;: {
                    &#x22;presentmentMoney&#x22; : {
                        &#x22;amount&#x22;: {{ da.allocatedAmountSet.presentmentMoney.amount | json }},
                        &#x22;currencyCode&#x22;: {{ da.allocatedAmountSet.presentmentMoney.currencyCode | json }}
                    },
                    &#x22;shopMoney&#x22;: {
                        &#x22;amount&#x22;: {{ da.allocatedAmountSet.shopMoney.amount | json }},
                        &#x22;currencyCode&#x22;: {{ da.allocatedAmountSet.shopMoney.currencyCode | json }}
                    }
                }
            {% endfor %}
        ],

        &#x22;discountedTotalSet&#x22;: {
            &#x22;presentmentMoney&#x22; : {
                &#x22;amount&#x22;: {{ li.discountedTotalSet.presentmentMoney.amount | json }},
                &#x22;currencyCode&#x22;: {{ li.discountedTotalSet.presentmentMoney.currencyCode | json }}
            },
            &#x22;shopMoney&#x22;: {
                &#x22;amount&#x22;: {{ li.discountedTotalSet.shopMoney.amount | json }},
                &#x22;currencyCode&#x22;: {{ li.discountedTotalSet.shopMoney.currencyCode | json }}
            }
        },

        &#x22;discountedUnitPriceSet&#x22;: {
            &#x22;presentmentMoney&#x22; : {
                &#x22;amount&#x22;: {{ li.discountedUnitPriceSet.presentmentMoney.amount | json }},
                &#x22;currencyCode&#x22;: {{ li.discountedUnitPriceSet.presentmentMoney.currencyCode | json }}
            },
            &#x22;shopMoney&#x22;: {
                &#x22;amount&#x22;: {{ li.discountedUnitPriceSet.shopMoney.amount | json }},
                &#x22;currencyCode&#x22;: {{ li.discountedUnitPriceSet.shopMoney.currencyCode | json }}
            }
        },
        &#x22;duties&#x22;: [
            {% for duty li.duties %}
            {% if forloop.first != true %},{% endif %}
            {
                {% comment %}rest of duties omitted{% endcomment %}
                &#x22;id&#x22;: {{ duty.id | json }}
            }
            {% endfor %}
        ],
        &#x22;fulfillableQuantity&#x22;: {{ li.fulfillableQuantity | json }},

        &#x22;fulfillmentService&#x22;: {
            &#x22;callbackUrl&#x22;:{{ li.fulfillmentService.callbackUrl | json }},
            &#x22;fulfillmentOrdersOptIn&#x22;: {{ li.fulfillmentService.fulfillmentOrdersOptIn | json }},
            &#x22;handle&#x22;: {{ li.fulfillmentService.handle | json }},
            &#x22;id&#x22;: {{ li.fulfillmentService.id | json }},
            &#x22;inventoryManagement&#x22;: {{ li.fulfillmentService.inventoryManagement | json }},
            {% comment %}fulfillmentService.inventoryManagement - omitted {% endcomment %}
            &#x22;productBased&#x22;: {{ li.fulfillmentService.productBased | json }},
            &#x22;serviceName&#x22;: {{ li.fulfillmentService.serviceName | json }},
            &#x22;shippingMethods&#x22;: [
                {% for sm in li.fulfillmentService.shippingMethods %}
                    {% if forloop.first != true %},{% endif %}
                    {
                        &#x22;code&#x22;: {{ sm.code | json }},
                        &#x22;label&#x22;: {{ sm.label | json }}
                    }
                {% endfor %}
            ],
            &#x22;type&#x22;: {{ li.fulfillmentService.type | json }}

        },
        &#x22;fulfillmentStatus&#x22;: {{ li.fulfillmentStatus | json }},
        &#x22;id&#x22;: {{ li.id | json }},
        &#x22;image&#x22;: {
            &#x22;altText&#x22;: {{ li.image.altText | json }},
            &#x22;height&#x22;: {{ li.image.height | json }},
            &#x22;id&#x22;: {{ li.image.id | json }},
            {% comment %}li.image.metafield omitted{% endcomment %}
            {% comment %}li.image.privateMetafield omitted{% endcomment %}
            &#x22;width&#x22;:{{ li.image.width | json }}
        },
        &#x22;merchantEditable&#x22;: {{ li.merchantEditable | json }},
        &#x22;name&#x22;: {{ li.name | json }},
        &#x22;nonFulfillableQuantity&#x22;: {{ li.nonFulfillableQuantity | json }},

        &#x22;originalTotalSet&#x22;: {
            &#x22;presentmentMoney&#x22; : {
                &#x22;amount&#x22;: {{ li.originalTotalSet.presentmentMoney.amount | json }},
                &#x22;currencyCode&#x22;: {{ li.originalTotalSet.presentmentMoney.currencyCode | json }}
            },
            &#x22;shopMoney&#x22;: {
                &#x22;amount&#x22;: {{ li.originalTotalSet.shopMoney.amount | json }},
                &#x22;currencyCode&#x22;: {{ li.originalTotalSet.shopMoney.currencyCode | json }}
            }
        },

        &#x22;originalUnitPriceSet&#x22;: {
            &#x22;presentmentMoney&#x22; : {
                &#x22;amount&#x22;: {{ li.originalUnitPriceSet.presentmentMoney.amount | json }},
                &#x22;currencyCode&#x22;: {{ li.originalUnitPriceSet.presentmentMoney.currencyCode | json }}
            },
            &#x22;shopMoney&#x22;: {
                &#x22;amount&#x22;: {{ li.originalUnitPriceSet.shopMoney.amount | json }},
                &#x22;currencyCode&#x22;: {{ li.originalUnitPriceSet.shopMoney.currencyCode | json }}
            }
        },

        &#x22;product&#x22;: {
            {% comment %}rest of Product omitted{% endcomment %}
            &#x22;title&#x22;: {{ li.product.title | json }}
        },

        &#x22;quantity&#x22;: {{ li.quantity | json }},
        &#x22;refundableQuantity&#x22;: {{ li.refundableQuantity | json }},
        &#x22;requiresShipping&#x22;: {{ li.requiresShipping | json }},
        &#x22;restockable&#x22;: {{ li.restockable | json }},

        &#x22;sellingPlan&#x22;: {
            &#x22;name&#x22;: {{ li.sellingPlan.name | json }}
        },

        &#x22;sku&#x22;: {{ li.sku | json }},

        &#x22;taxLines&#x22;: [
            {% for tl in li.taxLines %}
                {% if forloop.first != true %},{% endif %}
                {
                    &#x22;priceSet&#x22;: {
                        &#x22;presentmentMoney&#x22; : {
                            &#x22;amount&#x22;: {{ tl.priceSet.presentmentMoney.amount | json }},
                            &#x22;currencyCode&#x22;: {{ tl.priceSet.presentmentMoney.currencyCode | json }}
                        },
                        &#x22;shopMoney&#x22;: {
                            &#x22;amount&#x22;: {{ tl.priceSet.shopMoney.amount | json }},
                            &#x22;currencyCode&#x22;: {{ tl.priceSet.shopMoney.currencyCode | json }}
                        }
                    },
                    &#x22;rate&#x22;: {{ tl.rate | json }},
                    &#x22;ratePercentage&#x22;: {{ tl.ratePercentage | json }},
                    &#x22;title&#x22;: {{ tl.title | json }}
                }
            {% endfor %}
        ],
        &#x22;taxable&#x22;:{{ li.taxable | json }},
        &#x22;title&#x22;:{{ li.title | json }},

        &#x22;totalDiscountSet&#x22;: {
            &#x22;presentmentMoney&#x22; : {
                &#x22;amount&#x22;: {{ li.totalDiscountSet.presentmentMoney.amount | json }},
                &#x22;currencyCode&#x22;: {{ li.totalDiscountSet.presentmentMoney.currencyCode | json }}
            },
            &#x22;shopMoney&#x22;: {
                &#x22;amount&#x22;: {{ li.totalDiscountSet.shopMoney.amount | json }},
                &#x22;currencyCode&#x22;: {{ li.totalDiscountSet.shopMoney.currencyCode | json }}
            }
        },

        &#x22;unfulfilledDiscountedTotalSet&#x22;: {
            &#x22;presentmentMoney&#x22; : {
                &#x22;amount&#x22;: {{ li.unfulfilledDiscountedTotalSet.presentmentMoney.amount | json }},
                &#x22;currencyCode&#x22;: {{ li.unfulfilledDiscountedTotalSet.presentmentMoney.currencyCode | json }}
            },
            &#x22;shopMoney&#x22;: {
                &#x22;amount&#x22;: {{ li.unfulfilledDiscountedTotalSet.shopMoney.amount | json }},
                &#x22;currencyCode&#x22;: {{ li.unfulfilledDiscountedTotalSet.shopMoney.currencyCode | json }}
            }
        },

        &#x22;unfulfilledOriginalTotalSet&#x22;: {
            &#x22;presentmentMoney&#x22; : {
                &#x22;amount&#x22;: {{ li.unfulfilledOriginalTotalSet.presentmentMoney.amount | json }},
                &#x22;currencyCode&#x22;: {{ li.unfulfilledOriginalTotalSet.presentmentMoney.currencyCode | json }}
            },
            &#x22;shopMoney&#x22;: {
                &#x22;amount&#x22;: {{ li.unfulfilledOriginalTotalSet.shopMoney.amount | json }},
                &#x22;currencyCode&#x22;: {{ li.unfulfilledOriginalTotalSet.shopMoney.currencyCode | json }}
            }
        },

        &#x22;unfulfilledQuantity&#x22;: {{ li.unfulfilledQuantity | json }},

        &#x22;variant&#x22;: {
            {% comment %}rest of variant omitted {% endcomment %}
            &#x22;title&#x22;: {{ li.variant.title | json }}
        },

        &#x22;variantTitle&#x22;: {{ li.variantTitle | json }},
        &#x22;vendor&#x22;: {{ li.vendor | json }}
    }
{% endfor %}
]

}