-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathcopy-prefixed-tags-to-metafields.json
29 lines (29 loc) · 11 KB
/
copy-prefixed-tags-to-metafields.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"docs": "Use this task to copy prefixed tags to metafields, useful for Online Store 2.0 filtering. When run manually, it will scan for all of the object type you have configured in the task, and add/update the configured metafield on each with the resulting *tag value* when the tag prefix is matched.\n\nThis task supports the `customer`, `order`, and `product` Shopify object types, and the following [Shopify metafield types](https://shopify.dev/apps/metafields/definitions/types): `boolean`, `date`, `date_time`, `number_decimal`, `number_integer`, and `single_line_text_field`. The tag prefix should include any existing demarcation (e.g. spaces, dashes, colons) from the tag value.\n\n__By example:__\n- *Object type:* \"product\"\n- *Metafield type:* \"date\"\n- *Tag prefix:* \"Release Date: \"\n- *Product tag:* \"Release Date: 2022-04-01\"\n- *Tag value:* \"2022-04-01\"\n\n__Important Notes:__\n- This task does not sync tags to metafields on an ongoing basis, nor does it delete existing metafields when there are no qualifying tags for a product.\n- If there are multiple qualifying tags on an object, then there is no guarantee on which one the task might utilize, but it will only be one of them in any case.\n- When using *date* and *date_time* metafield types, the tag value __must__ be in ISO-8601 format (*YYYY-MM-DD* and *YYYY-MM-DDTHH:MM::SS* respectively).\n- For the *boolean* metafield type, the tag values can be any of the following: *true*, *false*, *yes*, *no*, *1*, or *0*. The resulting metafield value will be either \"true\" or \"false\".",
"halt_action_run_sequence_on_error": false,
"name": "Copy prefixed tags to metafields",
"online_store_javascript": null,
"options": {
"shopify_object_type__required": null,
"metafield_namespace__required": null,
"metafield_key__required": null,
"metafield_type__required": null,
"tag_prefix__required": null
},
"order_status_javascript": null,
"perform_action_runs_in_sequence": false,
"preview_event_definitions": [],
"script": "{% assign object_type = options.shopify_object_type__required | strip %}\n{% assign metafield_namespace = options.metafield_namespace__required | strip %}\n{% assign metafield_key = options.metafield_key__required | strip %}\n{% assign metafield_type = options.metafield_type__required | strip %}\n{% assign tag_prefix = options.tag_prefix__required %}\n\n{% assign allowed_object_types = \"customer,order,product\" | split: \",\" %}\n{% assign allowed_metafield_types = 'boolean,date,date_time,number_decimal,number_integer,single_line_text_field' | split: \",\" %}\n\n{% unless allowed_object_types contains object_type %}\n {% error %}\n {{ allowed_object_types | join: \", \" | prepend: \"Object type must be one of: \" | json }}\n {% enderror %}\n{% endunless %}\n\n{% assign object_type_plural = object_type | append: \"s\" %}\n\n{% unless allowed_metafield_types contains metafield_type %}\n {% error %}\n {{ allowed_metafield_types | join: \", \" | prepend: \"Metafield type must be one of: \" | json }}\n {% enderror %}\n{% endunless %}\n\n{% assign objects = array %}\n\n{% if event.topic == \"mechanic/user/trigger\" %}\n {% assign cursor = nil %}\n\n {% for n in (0..1000) %}\n {% capture query %}\n query {\n {{ object_type_plural }}(\n first: 250\n after: {{ cursor | json }}\n reverse: true\n ) {\n pageInfo {\n hasNextPage\n endCursor\n }\n nodes {\n id\n tags\n metafield(\n namespace: {{ metafield_namespace | json }}\n key: {{ metafield_key | json }}\n ) {\n type\n value\n }\n }\n }\n }\n {% endcapture %}\n\n {% assign result = query | shopify %}\n\n {% if event.preview %}\n {% capture result_json %}\n {\n \"data\": {\n {{ object_type_plural | json }}: {\n \"nodes\": [\n {\n \"id\": \"gid://shopify/{{ object_type | capitalize }}/1234567890\",\n \"tags\": {{ tag_prefix | append: \"1\" | json }}\n }\n ]\n }\n }\n }\n {% endcapture %}\n\n {% assign result = result_json | parse_json %}\n {% endif %}\n\n {% assign objects = objects | concat: result.data[object_type_plural].nodes %}\n\n {% if result.data[object_type_plural].pageInfo.hasNextPage %}\n {% assign cursor = result.data[object_type_plural].pageInfo.endCursor %}\n {% else %}\n {% break %}\n {% endif %}\n {% endfor %}\n\n {% assign metafields = array %}\n\n {% for object in objects %}\n {% for object_tag in object.tags %}\n {% if object_tag contains tag_prefix %}\n {% assign object_tag_value = object_tag | remove: tag_prefix %}\n {% assign object_tag_verify = object_tag_value | prepend: tag_prefix %}\n\n {% if object_tag_value == blank or object_tag_verify != object_tag %}\n {% log\n message: \"Tag prefix found without a value or not located at the front of the tag; skipping.\",\n object: object,\n tag: object_tag,\n tag_prefix: tag_prefix\n %}\n {% continue %}\n {% endif %}\n\n {% comment %}\n -- validation for various metafield types\n {% endcomment %}\n\n {% case metafield_type %}\n {% when \"boolean\" %}\n {% assign lowercased_object_tag_value = object_tag_value | downcase %}\n\n {% if lowercased_object_tag_value == \"true\"\n or lowercased_object_tag_value == \"yes\"\n or lowercased_object_tag_value == \"1\"\n %}\n {% assign object_tag_value = \"true\" %}\n\n {% elsif lowercased_object_tag_value == \"false\"\n or lowercased_object_tag_value == \"no\"\n or lowercased_object_tag_value == \"0\"\n %}\n {% assign object_tag_value = \"false\" %}\n\n {% else %}\n {% log\n message: \"Non-boolean tag value found; it must be one of: 'true', 'false', 'yes', 'no', '1', or '0'; skipping.\",\n tag: object_tag,\n tag_prefix: tag_prefix,\n tag_value: object_tag_value,\n object: object\n %}\n {% continue %}\n {% endif %}\n\n {% when \"date\" %}\n {% if event.preview %}\n {% assign object_tag_value = \"2020-01-01\" %}\n {% endif %}\n\n {% assign object_tag_value_check\n = object_tag_value\n | parse_date: \"%Y-%m-%d\"\n | date: \"%Y-%m-%d\"\n %}\n\n {% if object_tag_value_check != object_tag_value %}\n {% log\n message: \"Tag value must be a valid date in ISO-8601 format with delimiters: 'YYYY-MM-DD'; skipping.\",\n tag: object_tag,\n tag_prefix: tag_prefix,\n tag_value: object_tag_value,\n object: object\n %}\n {% continue %}\n {% endif %}\n\n {% when \"date_time\" %}\n {% if event.preview %}\n {% assign object_tag_value = \"2020-01-01T12:00:00\" %}\n {% endif %}\n\n {% assign object_tag_value_check\n = object_tag_value\n | parse_date: \"%Y-%m-%dT%H:%M:%S\"\n | date: \"%Y-%m-%dT%H:%M:%S\"\n %}\n\n {% if object_tag_value_check != object_tag_value %}\n {% log\n message: \"Tag value must be a valid datetime in ISO-8601 format with delimiters: 'YYYY-MM-DDTHH:MM::SS'; skipping.\",\n tag: object_tag,\n tag_prefix: tag_prefix,\n tag_value: object_tag_value,\n object: object\n %}\n {% continue %}\n {% endif %}\n\n {% when \"number_decimal\" %}\n {% comment %}\n -- use regex to make sure value is an integer or decimal, then convert to float for saving in metafield\n {% endcomment %}\n\n {% assign object_tag_value_check\n = object_tag_value\n | match: \"^(\\d+\\.?\\d*|\\.\\d+)$\"\n | append: \"\"\n %}\n\n {% if object_tag_value_check != object_tag_value %}\n {% log\n message: \"Tag value must be a decimal; skipping.\",\n tag: object_tag,\n tag_prefix: tag_prefix,\n tag_value: object_tag_value,\n object: object\n %}\n {% continue %}\n {% endif %}\n\n {% assign object_tag_value\n = object_tag_value\n | times: 1.0\n | append: \"\"\n %}\n\n {% when \"number_integer\" %}\n {% assign object_tag_value_check\n = object_tag_value\n | times: 1\n | round: 0\n | append: \"\"\n %}\n\n {% if object_tag_value_check != object_tag_value %}\n {% log\n message: \"Tag value must be an integer; skipping.\",\n tag: object_tag,\n tag_prefix: tag_prefix,\n tag_value: object_tag_value,\n object: object\n %}\n {% continue %}\n {% endif %}\n {% endcase %}\n\n {% if object.metafield.value != object_tag_value %}\n {% capture metafield %}\n {\n ownerId: {{ object.id | json }}\n namespace: {{ metafield_namespace | json }}\n key: {{ metafield_key | json }}\n type: {{ metafield_type | json }}\n value: {{ object_tag_value | json }}\n }\n\n {% endcapture %}\n\n {% assign metafields = metafields | push: metafield %}\n {% endif %}\n\n {% break %}\n {% endif %}\n {% endfor %}\n {% endfor %}\n\n {% assign groups_of_metafields = metafields | in_groups_of: 25, fill_with: false %}\n\n {% for group_of_metafields in groups_of_metafields %}\n {% action \"shopify\" %}\n mutation {\n metafieldsSet(\n metafields: [\n {{ group_of_metafields | join: newline }}\n ]\n ) {\n metafields {\n id\n namespace\n key\n type\n value\n owner {\n ... on {{ object_type | capitalize }} {\n id\n tags\n }\n }\n }\n userErrors {\n code\n field\n message\n }\n }\n }\n {% endaction %}\n {% endfor %}\n{% endif %}",
"subscriptions": [
"mechanic/user/trigger"
],
"subscriptions_template": "mechanic/user/trigger",
"tags": [
"Customers",
"Metafields",
"Online Store 2.0",
"Orders",
"Products",
"Tag"
]
}