Accentuate Custom Fields Documentation

Introduction

Most of the examples below use the “product” scope. To use metafields for other object types, just replace “product” with your required scope for the template such as “collection”, “customer”, “page”, “shop” etc.

By default, all custom fields are defined using the namespace “accentuate”. You can override this on a field-by-field basis by specifying another namespace, which will then be used when storing custom field values. Please take care when choosing a namespace, so it doesn’t collide with other apps’ namespaces.

Custom fields for the “shop” object are global and therefore available throughout your Liquid templates. You can use shop custom fields to hold content relevant to your store irrespective of the context of the current visitor’s page. For example header/footer content and links, that you normally would code in a page or directly in your design’s layout file.

Field types

A note about empty values

As a general rule: If a value of a custom field is empty, its corresponding metafield does not exist. A test for that particular key will return false (or “nil” in Liquid terms), which gives us a nice clean syntax for checking if a given field (a “key” in metafield terms) has a value

{% if product.metafields.accentuate.title %}
  <h1>{{ product.metafields.accentuate.title }}</h1>
{% endif %}

Checkboxes

A checkbox normally has two states - checked or unchecked. In our case, it is a little different - the value of a checked checkbox is represented as a string value of “true”. An unchecked checkbox, however, does not contain “false” - it simply doesn’t exist. Accordingly, we can test for it being checked or not this way

{% if product.metafields.accentuate.backorder %}
  <p>{{ product.title }} can be backordered</p>
{% else %}
  <p>{{ product.title }} can NOT be backordered</p>
{% endif %}

Another example

 <input type="checkbox" {% if product.metafields.accentuate.backorder %} checked {% endif %}>

Numbers and Ranges

A custom field of type Number or Range is stored as a numeric value and can be subject to numeric tests and filters in Liquid

{% if product.metafields.accentuate.stock < 5 %} 
<p>We are low on stock, but we if we buy more, 
    we have {{ product.metafields.accentuate.stock | plus: 100 }}</p>
{% endif %}

Dates

A custom field of type Date can be subject to date filters in Liquid

{{ product.metafields.accentuate.publishdate | date: "%a, %b %d, %y" }}

Text and HTML text

The value of text based custom fields are represented as you may expect - as metafields with string values matching the value of their respective custom fields

<h3>{{ product.metafields.accentuate.subtitle }}</h3>

Again, you can test for an empty value via the absence of the metafield

{% if product.metafields.accentuate.subtitle %}
  <h3>{{ product.metafields.accentuate.subtitle }}</h3>
{% endif %}

Selections

A selection list, where you have opted for a single selection only, is represented as a metafield with its string value matching the selected value

<p>You have selected the value: {{ product.metafields.accentuate.selection }}</p>

Basically, the same thing applies for a selection list, where you have opted for multiple selections, but since we can have multiple value selected at any given time, each value is listed with the “pipe” symbol (|) as a separator token. You can use Liquid’s ‘split’ filter on the metafield to separate the values - like this:

{% assign selected_values = product.metafields.accentuate.selection | split: '|'  %}
{% for selected_value in selected_values %}
   <p>{{ selected_value }}</p>
{% endfor %}

Tags

Tags behave similar to selections (see above) with the only difference being that you define the values for every instance of your Shopify object as opposed to the selection lists’ predefined options. A tag field, where you have entered only a single value, is represented as a metafield with its string value matching your input

<p>You have entered the value: {{ product.metafields.accentuate.tags }}</p>

As with selections, if you have entered multiple values, each value is listed with the “pipe” symbol (|) as a separator token. You can use Liquid’s ‘split’ filter on the metafield to separate the values - like this:

{% assign entered_values = product.metafields.accentuate.tags | split: '|'  %}
{% for entered_value in entered_values %}
   <p>{{ entered_value }}</p>
{% endfor %}

Colors

A Color type gives you a convenient control to select a color and store the result as a string in hex RGB format such as #000000, #e9e9e9, #ffffff etc. Note that you can use Liquid color filters to change or extract properties from these color strings - more info here

<button style="background-color: {{ product.metafields.accentuate.my_color }}">Click</button>

Reference Types

A custom field defined as a reference type will contain the referenced Shopify object’s handle as its value. You can use this handle to obtain the actual Shopify object via a Liquid global object depending on the type (for more on this, see the links to the Liquid Cheat Sheet and Global Objects below)

{{ blogs[product.metafields.accentuate.related_blog].title }}

{{ articles[product.metafields.accentuate.related_article].title }}

{{ page[product.metafields.accentuate.related_page].title }}

{{ collections[product.metafields.accentuate.related_collection].title }}

{{ all_products[product.metafields.accentuate.related_product].title }}

{{ linklists[product.metafields.accentuate.related_linklist].links }}

Be aware, that Shopify imposes a restriction on how many calls to “all_products” you can make on any single Liquid page. Currently, this limit is set to 20 unique handles per page.

Using reference types, we can also get the metafields from the referenced objects using the handle. This is just as easy as getting the url or title as shown above.

{{ all_products[product.metafields.accentuate.related_product].metafields.accentuate.isbn }}

If you have opted for multiple selections for your reference type, each object’s handle is listed with the “pipe” symbol (|) as a separator token. You can use Liquid’s ‘split’ filter on the metafield to separate the handles - like this:

{% assign selected_handles = product.metafields.accentuate.selection | split: '|'  %}
{% for selected_handle in selected_handles %}
   <p><a href="{{ all_products[selected_handle].url }}">{{ all_products[selected_handle].title }}</a></p>
{% endfor %}

Images and Files

Images and files are automatically uploaded to a secure Google Cloud bucket and the corresponding URL is stored in the metafield, ready to use:

<img src="{{ product.metafields.accentuate.my_extra_image }}"/>

The URL in the metafield will - for file types where this is possible - contain the image dimensions as query parameters, specified as width x height e.g. “?800x600” . If the dimensions for the image are needed in Liquid, you can use Liquid’s ‘split’ filter on the metafield like this:

{% assign dimensions = product.metafields.accentuate.my_extra_image | split: '?' | last | split: 'x' %}
<p>Size: {{ dimensions.first }} x {{ dimensions.last }}</p>

Note Images and files are served to your visitors through a CDN (via domain cdn.accentuate.io). This optimizes delivery to your visitor’s browser significantly, but also caches files on so-called edge locations globally. When you update an image or a file but keep the filename unchanged, it may take some time before the file is updated in the CDN cache and the updated image or file is visible to all visitors. If an immediate update is required, just change the filename before uploading

Advanced image handling

Accentuate also supports advanced image handling such as resizing, cropping and rotating images as well some more exotic options such as flipping and applying of filters. This is achieved via an easy-to-use integration with Google’s Image API directly in Liquid:

<img src="//images.accentuate.io?options=w200&shop={{ shop.permanent_domain }}&image={{ product.metafields.accentuate.my_image }}"/>

The URL for images.accentuate.io takes three parameters - options, shop and image.

The parameter options is used to describe which effect you’d like to have performed, whereas shop and image are used to tell the integration which shop would like which image to have options applied. You should always use the Liquid drop as the value for shop.

The value for the above parameter options is just a simple example. A plethora of options are available and they can be combined to achieve the desired effect.

Examples (curated from this StackOverflow entry) :

Option Effect
s0 original size image (default if no options provided)
s (without a value) stretches image to fit dimensions
s640 generates image 640 pixels on largest dimension
w100 generates image 100 pixels wide
h100 generates image 100 pixels tall
c crops image to provided dimensions (combine with w or h option)
n same as c, but crops from the center
p smart square crop, attempts cropping to faces
pp alternate smart square crop, does not cut off faces
cc generates a circularly cropped image
ci square crop to smallest of: width, height, or specified =s parameter
nu no-upscaling. Disables resizing an image to larger than its original resolution.
fv flip vertically
fh flip horizontally
r90, r180, r270 rotates image 90, 180, or 270 degrees clockwise (examples, use any degree)
b10 add a 10px border to image
c0xAARRGGBB set border color, eg. =c0xffff0000 for red
l100 sets JPEG quality to 100% (1-100)
fSoften=1,100,0 where 100 can go from 0 to 100 to blur the image
fVignette=1,100,1.4,0,000000 where 100 controls the size of the gradient and 000000 is RRGGBB of the color of the border shadow
fInvert=1 inverts the image
fbw=1 makes the image black and white

To rotate an image 90 degrees clockwise with a max width of 300px, use:

<img src="//images.accentuate.io?options=r90-w300&shop={{ shop.permanent_domain }}&image={{ product.metafields.accentuate.my_image }}"/>

Or to circular crop an image with a width of 400px and make it black/white, use:

<img src="//images.accentuate.io?options=w400-cc-fbw=1&shop={{ shop.permanent_domain }}&image={{ product.metafields.accentuate.my_image }}"/>

When building responsive web pages, you can also leverage the options to build a srcset attribute:

<img src="{{ product.metafields.accentuate.my_image }}" 
srcset="//images.accentuate.io?options=w300&shop={{ shop.permanent_domain }}&image={{ product.metafields.accentuate.my_image }} 1x, 
//images.accentuate.io?options=w600&shop={{ shop.permanent_domain }}&image={{ product.metafields.accentuate.my_image }} 2x" />

Options can be combined by separating them with hyphens (be aware, options don’t always work well together).

Using namespaces

As an alternative to multiple value selection (or for types where this is not an option), you can define a set of custom fields having a distinct namespace. You can then loop the fields within that namespace to create e.g. a list of related products. Note, when you loop the fields in this manner, every field will be a two-dimensional array with the key as the first element and the value the second (and last) element

<h3>Related products</h3>
{% for field in product.metafields.related_products %}
   {% assign ref_handle = field.last %}
   <p><a href="{{ all_products[ref_handle].url }}">{{ all_products[ref_handle].title }}</a></p>
{% endfor %}

This example creates a gallery of images, where custom fields share a distinct namespace

<h3>Image Gallery</h3>
{% for field in product.metafields.my_image_gallery %}
  <img src="{{ field.last }}"/>
{% endfor %}

Listing all custom fields

If you are in an investigative mood, you can list all metafields and their associated values in one go. Go to your theme editor, create an alternate template for your object type (here: product) called “fields” (as an example) and paste the below code as content.

You can now view your custom fields’ values for a product by appending “?view=fields” to the url (or &view=fields, if the url already has a ? in it like variants will have)

Remember: empty values will not have an associated metafield and will not show in this list

<h3>List of custom fields for {{ product.title }}</h3>
<ul>
   {% for field in product.metafields.accentuate %}
   <li>{{ field.first }}: {{ field.last }}</li>
   {% endfor %}
</ul>

How to copy/paste field definitions

You can copy/paste field definitions individually or in bulk inside the same shop or between shops. For multiple shops, you can open two tabs in your browser and log in to the “from” and “to” shop respectively.

To copy an individual field, use the “Copy” and “Paste” buttons. When pasting, edit the properties for the pasted fields if needed and repeat the procedure for any additional fields.

To copy all fields for an object scope, hold down use the Command (⌘) key (on Windows, this is the Windows key) when clicking the “Copy” and “Paste” buttons. When pasting multiple fields, any existing fields with the same key will not be replaced.

How to use your custom field labels in Liquid

The labels used in the definitions of your custom fields are used for editing purposes only and are not carried through to the individual metafield values so you can use them directly via Liquid.

You can, however, use a filter on the output of the key name, remove any underscores (or replace with spaces) and optionally capitalize the text

<h3>List of custom fields for {{ product.title }}</h3>
<ul>
   {% for field in product.metafields.accentuate %}
   <li>{{ field.first | replace: '_', ' ' | capitalize }}: {{ field.last }}</li>
   {% endfor %}
</ul>

Using custom fields in order notifications

Custom fields are also available for orders. An order object in Shopify contains references to the ordering customer as well as the ordered products and variants.

Examples of Liquid drops to use in e.g. a notification template:

{{ order.customer.metafields.accentuate.nick_name }}

{% for line in line_items %}
    {{ line.product.metafields.accentuate.tech_description }}
    {{ line.variant.metafields.accentuate.washing_instructions }}
{% endfor %}

Allowing customers to edit custom fields

You can enable your customers to edit the information stored about them in customer custom fields.

Note

An example:

<form id="customer_metafields">  

   <!-- Mandatory id field -->
   <input type="hidden" name="customer[id]" value="{{ customer.id }}" />

   <!-- fields belonging to the customer object in Shopify -->
   <input type="text" name="customer[first_name]" value="{{ customer.first_name }}" placeholder="First name" />
   <input type="text" name="customer[last_name]" value="{{ customer.last_name }}" placeholder="Last name" />
   <input type="checkbox" name="customer[accepts_marketing]" {% if customer.accepts_marketing %} checked {% endif %}/> Can't wait, send me stuff

   <!-- Customer metafield examples -->
   <input type="text" name="metafield[accentuate.nick_name]" value="{{ customer.metafields.accentuate.nick_name }}" placeholder="Nickname" />
   <input type="text" name="metafield[accentuate.birthday]" value="{{ customer.metafields.accentuate.birthday }}" placeholder="Your birthday" />
   <input type="checkbox" name="metafield[accentuate.check]" {% if customer.metafields.accentuate.check %} checked {% endif %}/> Yes, send me a free gift on my birthday

   <!-- Metafield w/multiple values example -->
   <input type="checkbox" name="metafield[accentuate.multiselect][]" data-option-value="value-1" /> Select this to choose value 1
   <input type="checkbox" name="metafield[accentuate.multiselect][]" data-option-value="value-2" /> Select this to choose value 2

   <!-- File upload example -->
   <input type="file" name="metafield[accentuate.avatar]" accept="image/png, image/jpeg" />

   <input type="submit"/>
</form>

Then, in your theme.liquid file, near the </body> closing tag, be sure to include the Accentuate proxy script and one line of code to bind your form to the proxy:


{% if template contains 'customers/account' %}
  <script src="https://app.accentuate.io/dist/proxy.js"></script>>
  <script>
     Accentuate($("#customer_metafields"));
  </script>
{% endif %}

</body>

Adjust the above selector of the form - $(“#customer_metafields”) - to match your actual code.

The “Accentuate()” function takes two optional parameters:

The first optional parameter is a callback function where you can take action after updates have been submitted to Accentuate. This callback is served with a “data” object containing two properties, “status” and “message”, which you can use for inspecting whether the update succeeded or not.

A simple example, where the results are just logged to the browser’s console:

<script>
    Accentuate($("#customer_metafields"), function(data) { console.log(data.status, data.message); });
</script>

If your form contains file uploads (input type=”file”), the file uploads are handled separately from the rest of the form’s fields. You don’t need to worry about this but you will experience that the callback function (if defined) is called twice, once for any files and once for all other fields

The second optional parameter is a callback function where you can validate your form prior to submitting it to Accentuate’s handling. If you return false from the validation callback, the form will not be submitted.

Any other value than false will allow for form submission.

Example of a validation function that checks for a non-zero length of a field with id myfield:

<script>
    Accentuate($("#customer_metafields"), null, function() { if ($("myfield").val().length == 0) return false });
</script>

Please note:_

Exporting

It is possible to export your individual products, pages, orders, customers etc. together with the values for your defined custom fields. Values are exported in CSV format ready to open in your favorite text editor or spreadsheet program.

The first line (or “row” if you like) is a required header line with two fixed values “_id” and “_info” followed by one or more custom field names (with any user-defined namespace).

The actual value for an ID depends on the object type - skus are used for products and variants, email addresses for customers, order numbers for orders and finally handles for the remaining objects - pages, blogs, articles and collections.

The “_info” column is information associated with the instance’s ID - like the product title or the customer’s name. This is for information only and changing this value won’t have any effect on any later import.

Third column and onward contain the custom field value associated with the instance ID. All values are separated with semicolons ( ; ). If a value itself contains semicolons ( ; ) or double quotes ( “ ), the value will be surrounded with double quotes and any contained double quoted will be “escaped” as two double quotes, e.g. the value Hi “there” becomes “Hi ““there”””

As an example, exporting two products “sku-1” and “sku-2”:

_id;_info;custom_field_1;custom_field_2;custom_field_3
sku-1;This is product for sku-1;value-1;value-2;value-3
sku-2;This is product for sku-2;value-1;value-2;value-3

Exporting for selected objects only

Accentuate also allows for export of a subset of objects via the Shopify admin. From the relevant object list (such as product list, customer list etc.), perform a Search or Filter and then bulk select the objects for which you’d like to export the custom fields. Then select the “Actions” menu and click “Export Custom Fields”.

Importing CSV files

Importing custom field values rely on the exact same format as the export, so you may use an exported file directly as the source for import. When editing values for import, please take care to adhere to the format as described above - you are, however, free to use commas and semicolons as separators as you please.

Except for the required _id and _info columns, you may remove any columns as you please, but, if present, the header value must match a defined field name for the type.

Be sure to embed semicolons and double quotes as described above for the export.

If in doubt before import - get in touch.

Importing XLSX files

Accentuate also accepts import of native Excel (XLSX) files.

You can still use an exported CSV file as a starting point for building an import file in Excel. Just open it in Excel, choose “Save As …” and change the document type to “Excel Workbook” and change the file type to XLSX.

Columns A and B are reserved for the required _id and _info columns respectively, but for column C and onward, you may remove any columns as you please, but, if present, the header value must match a defined field name for the type.

You now have the luxury of keeping each custom field value in its own cell and don’t have to worry about double quotes and semicolons.

All data must exist in a single sheet. If in doubt before import - get in touch.

Important notes about import/export

Uninstalling Accentuate

If you choose to uninstall Accentuate after having used it, all of your custom field values, images and files will still be accessible on your store front (with the exception of images served via our advanced image handling) but you cannot edit them from within the Shopify admin.

Use of other metafield tools for custom fields created with Accentuate, including Shopify’s built-in editor for metafields, is strongly discouraged.

More about Shopify Metafields

More about Shopify Global Objects

Liquid Cheat Sheet