Expressions
Overview
Expressions present a powerful tool to derive values from product data. It is useful to create SEO optimized titles and descriptions, as well as derive arbitrary attributes like tax-included prices, tax, shipping, etc.
Expressions compose of tokens (variables that represents context data that is being pulled into the feed like variant price, options, etc), constants (texts, numbers), operators (math operators, string concatenation), function (text case manipulation, date calculation, etc.) and self expressive keywords like "if", "then", "else".
Some examples where expressions can be used:
- A custom field representing tax that equal to 21% of product price.
- A "Shipping and included" price that equal product price added with a shipping fee for a marketplace that take only shipping and tax included prices.
- A condition to include or exclude variant from feed based on its metafield and/or other data
Following screenshot is showing a condition that match when one of following conditions are met
- quantity > 10
- price between 10 and 20
- has a product metafield with namespace "my_fields" and key "always_include" which has value "yes"
Editing expression
Editing expression is made easier with some help of the expression editor
To hide complexity, an expression can be in read-only mode, showing a general description of the expression underneath. Click on 'Edit' button to reveal the expression and edit it.
A token can be added by typing the single quote ('), supported tokens will be listed in a contextual dropdown and one needs to be selected from the list to be added into the expression box. Added tokens have a greyed background and can be changed by clicking on it.
Depending on context, typing the double quote (") may display a list of applicable constants in a dropdown. Added constants will have a greyed background, but with a green color instead of orange like the tokens.
A good example is editing the Google product category. The list includes thousands of categories, so the dropdown is helpful to select the right category.
Examples
String concatenation
Regular expression match
Regular expression is really powerful (and complicated) way to check for patterns in string values. Examples include:
- If Product description include one of the following words: "shirt", "jean", "child" or "women":
- 'Product description' ~= "(shirt|jean|child|women)"
- If Product tile starts with "Men" or "Boy". This does not include titles that have the word men somewhere else in the sentence
- 'Product title' ~= "(^men|^boy)" will match "Men's wear" and "Boy's jeans" but not "T-shirt for men"
"Looking-up" expression
Following screenshot is showing an expression derive a tax-included price value from the value of product type.
- If the product is clothing then the price should include a 10% rise for tax
- if it's is kitchen ware or household then the tax included is 20%
- otherwise the price stay the same
Sometime you may need to specify shipping cost for product according to its price and/or weight
Following is an expression for
- If price > 100 shipping is free
- if 50 < price < 100 shipping is 10% of price
- if price < 50 then shipping is 5
"List returning" expression
Some attributes expect a list of values will have this icon next to their names, , including the product details, product highlights, additional images and promotion ID. Expressions for these attributes should return one of the following forms:
1/ An array in the form of ("value1","value2","value3")
2/ A metafield that contains a list of values. For example additional images could be provided by a metafield that returns a list of files.
3/ (deprecated) A string, which then be processed as below:
- for product details and product highlights, the string will be split into lines and the list of lines will then be used as the list of values. If the content (highlights, details) needs to be in multi-line, use an array as option 1 above.
- for additional images and promotion ID, the string will be split by commas (,)
Option 3 also includes support of text metafields (single line and multi line), whose values will be processed accordingly.
Product detail entries
Product details is a special list which include entries, each composed of section name (optional), attribute name (optional) and attribute value seperated by colons.
- Section name (optional):Attribute name (optional):Attribute value
If there is only one element, it would be used as the Attribute value. Attribute name will take the default value of "Detail 1", "Detail 2", etc. For more meaningful attribute names, add them in before the value and separate them with colons
- Display:4k
- Vendor:Samsung
If the value has to include colons itself, wrap it in quotes
- General:Display:"color: green"
Multiple details can be added each on a line. Multiple details would help enrich your product data for better performance. Use a multi-line metafield to store multiple details.
"Money returning" expression
Some attributes expect money amount with currency. For example cost of good sold. The expression should return BOTH the amount and the currency, e.g "12USD" or "3 GBP".
"Measurement returning" expression
These attributes expect a value and a unit. For example unit pricing measure and unit pricing base measure. The expression should return BOTH the value and the unit, e.g. "1.3kg" or "12 floz".
"Boolean" expression
These attributes accept yes/no values. The expression should be either a logic expression, or an expression that return "yes" or "no".
Example of a logic expression
Price > 10 or Quantity < 3
The same logic expression re-written to return "yes"/"no"
if Price > 0 or Quantity < 3 then "yes" else "no"
Metafields and metaobjects
Metafields play important role in storing custom data for Shopify products and variants. Use of metafields in expression allow endless customization for feed attributes. Metaobjects is a special type of metafields that can store structured data. Each metaobject is referenced as a metafield, and composes of fields. Fields can be simple data (text) or even another metaobject, allowing the structure to be nested.
A metafield are often identified with its namespace and key, joining with a dot (.). Example: mm-google-shopping.age_group refers to metafield namespace mm-google-shopping and key age_group.
Metafields are presented in expression as tokens, composed of namespace, key and some metadata that allow the app to properly retrieve the value of the metafield.
Metafields can be added into expressions using several ways:
- "De-factor" metafields including the Google Shopping metafields. For example mm-google-shopping.age_group. The Google Shopping metafields are supported by Shopify import/export utility to add product with Google Shopping attributes. "De-factor" metafields are listed in the contextual menu in the expression editor, and can be access by typing in the editor
- Custom metafield can be added with the metafield form, which can be open from the expression editor by typing in the text 'metafield. Do note that the single quote is the "magic" search trigger for all the tokens in expression
Supported metafield owner types include Product and Variant, which can be selected in the metafield form. Metafield can be of type text, image, image list, JSON or a metaobject. Metaobjects can be nested as many level as needed
Metafield translation
By default the translatable metafields will be translated into the selected feed language. In the metafield form, check the "Untranslated" to skip translation, which might be desired for metafields that store enumerated fields like [age_group], [gender]. The drop down list of "de-factor" metafields also support "Untranslated" versions of corresponding metafields.
Reference
There are 2 basic types of consts: numbers and strings. Numbers may be floating point or integers. Strings should always be double-quoted. Types get automatically converted when possible, for example:
"1" + 2 == "12"
"12" - 1 == 11
"12" * 1 == 12
Values | Description |
---|---|
43, -1.234 | Numbers |
"hello" | String |
" \" \\ " | Escaping of double-quotes and blackslash in string |
BEWARE!
Strings must be double-quoted! Single quotes are for tokens.
Numeric arithmetic | Description |
---|---|
x + y | Add |
x - y | Subtract |
x * y | Multiply |
x / y | Divide |
x ^ y | Power |
x mod y | Modulo |
BEWARE! Modulo always returns a positive number: -1 mod 3 == 2
.
Comparisons | Description |
---|---|
x == y | Equals |
x != y | Does not equal |
x < y | Less than |
x <= y | Less than or equal to |
x > y | Greater than |
x >= y | Greater than or equal to |
x == y <= z | Chained relation, equivalent to (x == y and y <= z) |
x ~= y | Regular expression match |
x in (a, b, c) | Equivalent to (x == a or x == b or x == c) |
x not in (a, b, c) | Equivalent to (x != a and x != b and x != c) |
Boolean logic | Description |
---|---|
x or y | Boolean or |
x and y | Boolean and |
not x | Boolean not |
if x then y else z | If boolean x is true, return value y, else return z |
( x ) | Explicit operator precedence |
Objects and arrays | Description |
---|---|
(a, b, c) | Array |
a in b | Array a is a subset of array b |
x of y | Property x of object y |
Functions | Description |
---|---|
abs(x) | Absolute value |
ceil(x) | Round floating point up |
empty(x) | True if x is undefined , null , an empty array or an empty string, or an invalid number (result of division by zero, for example) |
exists(x) | True unless x is undefined or null |
floor(x) | Round floating point down |
log(x) | Natural logarithm |
log2(x) | Logarithm base two |
log10(x) | Logarithm base ten |
max(a, b, c...) | Max value (variable length of args) |
min(a, b, c...) | Min value (variable length of args) |
round(x) | Round floating point |
sqrt(x) | Square root |
replace(x, searchRegex, replaceWith, fallback) | Look for all regular expression matches by searchRegex in x , and replace with replaceWith . The optional fallback if presented will be returned if no matches is found. |
default(x, fallback1, fallback2, ..., fallbackN) | Look from left to right and return the first non-empty value found. This function is helpful to cascade fallback values for optional expression (non-existing metafield, etc.). |
toFixed(x, decimalPlaces) | Converts a number to a string, rounding the number a specified number of decimal. |
date(dateValue, deviation, deviationType) | Modify input date by deviation amount of time. deviationType could be "second", "minute", "hour", "day", "week", "month", "year".To get a date 3 months from now date('{now}', 3, "month") Same time last week date('{now}', -1, "week") |
substring(stringValue, start, end?, granularity?) | Return a sub string of the stringValue which starts at index start and ends up to (but not including) index end . First character is at index 0. If granularity is set to "word" or "sentence" then indexes are counted in words or sentences accordingly, instead of characters. |
case(stringValue, caseType) | Modify the case of stringValue . caseType takes one of the following values- "low": uncapitalize whole text - "up": capitalize whole text - "sentence": uncapitalize whole text and capitalize the first character - "title": uncapitalize whole text and capitalize the first character of each words |
capture(stringValue, captureRegex, defaultValue, matchPos=1, capturePos=1, flags="gsi") | Capture part of the stringValue using captureRegex . This is useful in cases like:- Extracting colors from product title. The colors are known in advanced (e.g the list of colors is known). Falling back to "white" if no color is found: capture( Product title , "\\b(red|green|blue)\\b","white")- Extracting colors from product title. The color is the last word in product title: capture( Product title , "\\b(\\w+)$")- Extracting the first line from Product HTML description capture( Product description HTML , "(.*?)(<br>|$)") Advanced parameters and advanced usage In edge cases, captureRegex can find multiple matches in the stringValue , and captureRegex can also contain multiple capturing groups, advanced parameters can be used to get to the desired result.matchPos : the index of the match to use, starting from 1. If negative then the match is counting backward from the last match. Value of -1 would means the last match, value of -2 means the match before the last match, and so on. The value is default to 1.capturePos : the index of the capturing group to use, starting from 1. Default to 1. This is useful in cases when more than 1 capturing groups is needed.flags : The regular expression flags. Default to "gsi" which treats stringValue as a "single line" where dot (.) would match newlines as well as any other characters. In cases where newlines detection is important for the search then the flags should be changed to "multiline" mode, e.g. "gm". Do note that "g" flag is always on and cannot be turned off. |
strlen(stringValue) | Return the length of stringValue |
split(stringValue, boundary) | Split the stringValue by boundary and return the array of substrings. boundary could take the following values
|
filter(array, regex, inverted?, limit?, property?) | From array , return only the items that match ( or does not match if inverted is true ) regular expression regex . Use the optional limit parameter to limit number of return items. If property is presented, then the items are regarded as objects and the match is test against the item's property |
slice(source, start?, end?) | Return a portion of the source (a string or an array) selected from start to end (end not included) where start and end represent the index of (characters or items) in that source. start Optional Zero-based index at which to start extraction, converted to an integer. Negative index counts back from the end of the source — if start < 0, start + source.length is used. If start < -source.length or start is omitted, 0 is used. If start >= source.length, nothing is extracted. end Optional Zero-based index at which to end extraction, converted to an integer. slice() extracts up to but not including end. Negative index counts back from the end of the source — if end < 0, end + source.length is used. If end < -source.length, 0 is used. If end >= source.length or end is omitted, source.length is used, causing all elements until the end to be extracted. If end is positioned before or at start after normalization, nothing is extracted. |
datediff(fromDate, toDate) | Return the number of days between fromDate and toDate . If toDate is before fromDate the result is negative. |
dateformat(dateValue, format, timezone, locale) | Return the formatted date string in the given format. The result varies by timezone and locale option. Example: |
striptags(withTags, xmlMode) | Strip tags from withTags and return plain text. If xmlMode is set to true XML tags are stripped out, otherwise only strip out HTML tags. |
join(stringArray, separator?) | Join the items of stringArray into a string, separated by separator (default to comma "," if not presented). |
object(serializeEmptyValue?, key1, value1, key2, value2, ...) | Returning an "object" structure that is mapped into complex xml structure.
|