Custom Attributes

Last updated

Custom Attributes#

Accounts, customers, displays, orders, products, variant, product medias and vouchers can all be expanded with additional information. Here's how you can do it!

The following structure is used in the configuration to define custom attributes on objects listed above. Attributes allow you to create arbitrary fields that will be available in the API and exports. There are different types of attributes.

The API-outputs defined below are using the Shop API, some differences might apply to other APIs, which will be defined in the corresponding API reference.

Important parts of client configuration have been moved to the Centra backend panel. Instead of writing to the config.php file, one can now edit relevant configuration sections with a JSON editor.

The process#

Go to System => Configuration.

If you can’t see it, it may be because:

  • You are not logged in as a full-access admin.
  • This is not a QA environment.
  1. Make config changes in a QA environment.
  2. Test the changes in the QA environment.
  3. Notify us that the config should be copied to production.

In the future, we plan to implement modifications to the process, transitioning it to full self-service. This means you'll be able to publish a configuration version in the QA environment and picking it up in production instances. Additionally, configurations will be version-controlled, and any alterations will be documented and accessible in the backend.

Before we deploy#

Just a heads-up, those config files are plain JSON, super easy to read, tweak, and stash away for safekeeping. It's a good call to always back up your current setup before diving into any big changes.

If you ever need a hand pushing the config to Production, Centra's staff has got your back. But first things first:

  • Export configuration in Prod, save file as backup,
  • Export new, tested config from QA,
  • (Centra) Import the new config to Production

Mapped and Dynamic attributes#

Mapped attributes#

The normal attribute on a product or variant is one which is mapped to an attribute object which can contain meta-data. There is a reason for this, for example: if you have a specific Color-attribute that contains the name, hex-code and image of the color. You do not want to upload these values every time, so an attribute is then created, which you then link to the products that should have the color. Think of mapped attributes as const values that you can later choose from.

The structure looks something like this:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { "desc": "Showroom Color Swatch", "group": "variation", "readonly": "true", "elements": { "desc": { "desc": "Color", "type": "textarea" }, "image": { "desc": "Image", "type": "image", "size": "60x60" } } }

You can then create a new Showroom Color Swatch-attribute under CATALOG / ATTRIBUTES:

When this attribute is saved, this attribute option will be listed under the Showroom Color Swatch-title in the variant-section of the product:

In the API, the values will come out like this:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { "countryOfOriginName": "", "sh_swatch": { "color": { "type": "image", "url": "https://.../client/dynamic/attributes/image_9471.jpg", "width": "60", "height": "60", "mimeType": "image/jpeg" }, "color_text": "#8b0000" }, "markets": { "...": "..." } }

Dynamic attributes#

Dynamic attributes are in comparison to mapped attributes not linked to any pre existing attribute, but do have specific data for the specific products. This data needs to be set for each product instead of linking to an existing attribute. The difference between mapped and dynamic is that dynamic uses "readonly": false for the attribute.

It used to be that if you had "readonly": false on the attribute, only the element with the text key would be visible in the API. This meant that if you needed multiple elements you needed multiple attributes as well. To keep with the previous behavior, this is still the case for single-element attributes. For dynamic attributes with multiple elements, every element will now be returned in the API as [attribute-name]-[element-name].

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 30 31 32 33 34 35 { "desc": "Promotion", "group": "product", "readonly": false, "elements": { "sale": { "desc": "Limited Edition", "type": "boolean", "options": [ [ "0", "No" ], [ "1", "Yes" ] ] }, "preorder": { "desc": "Promotion", "type": "boolean", "options": [ [ "0", "No" ], [ "1", "Yes" ] ] } } }

These will show up on the product directly with a Yes / No-option:

And in the API, it will show up like this:

1 2 3 4 5 ... "limited_edition_bool": "1", "promo_sale": "1", "promo_preorder": "1", ...

Please note that when the option you've selected is 0/false the property will not show up in the API at all.

Attribute groups#

The group on the attribute specifies where the attribute should be placed. The following groups exist today:

GroupDescription
productListed under General Attributes on all Products.
variationListed under each Variant on all Products.
displayListed on each product display
orderListed on each Order.
customerListed under each Customer.
accountListed under each Account (B2B).
sizechartListed under each size in a sizechart.
product_mediaListed under each image in AMS backend. Exposed in Checkout & Shop API. Assignable through Integration API.
voucherListed under each Voucher. Exposed in Checkout & Shop API. Assignable through Integration API.

Attribute element types#

Element-type is inside the elements-property for the attribute configuration:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 { "desc": "This is the attribute", "group": "product", "elements": { "Text": { "desc": "This is the element-typ", "type": "boolean", "options": [ [ "0", "No" ], [ "1", "Yes" ] ] } } }

The following element types exist today. Not all of them are supported for the Dynamic attributes (which are shown inline on each product/variant), so the support for the different options are listed below:

TypeLookSupportOptions
inputMapped/DynamicOne-line text field
textareaMapped/DynamicMulti-line text field
readonlyDynamicAllows a field without the ability to edit it. Used for showing IDs or things that should not be changed.
booleanDynamicOptions for the radio inputs (default is always 0): 'options' => [['0','No'],['1','Yes']]
selectMapped/DynamicDefault selected is always first option, so keep it as ['0','Select']
imageMappedSize of the image: 'size' => '600x400'. Allowed image formats: JPG, JPEG, PNG, GIF, SVG
fileMappedNo options available

Attributes with multi-select value

Selectable mapped attributes can be configured so that multiple values can be selected at once. This is achieved by adding parameter 'multi' => true to the attribute. For example, a multi-choice Label attribute can be configured like this:

1 2 3 4 5 6 7 8 9 10 11 12 13 { "desc": "Label", "group": "variation", "readonly": true, "multi": true, "elements": { "name": { "desc": "Label description", "type": "textarea" }, } }

In Centra, the attribute will look like this:

Its values will be returned as an object in API response:

1 2 3 4 "label": { "3": "Eco", "1": "Bio" },

API-output#

The API-output differs between Dynamic and Mapped attributes.

Mapped attributes will always have a parent element named as the attribute-key. This is how the elements look like from the mapped attributes:

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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 { "desc": "This is the attribute", "readonly": true, "group": "product", "elements": { "text": { "type": "Input", "desc": "Text" }, "textarea": { "type": "textarea", "desc": "Textarea" }, "boolean": { "desc": "Boolean", "type": "boolean", "options": [ [ "0", "No" ], [ "1", "Yes" ] ] }, "select": { "desc": "Select", "type": "select", "options": [ [ "0", "Select" ], [ "first", "First Option" ], [ "Second", "Second Option" ] ] }, "image": { "type": "image", "desc": "Image", "size": "600x400" }, "file": { "type": "file", "desc": "File" } } }

This is how the response from the API looks like:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { "attribute_field": { "text": "Text", "textarea": "Textarea", "boolean": "1", "select": "bb", "image": { "type": "image", "url": "https://.../client/dynamic/attributes/image1_4265_png.jpg", "width": "600", "height": "400", "mimeType": "image/jpeg" }, "file": { "type": "file", "url": "https://.../client/dynamic/attributes/6/image1.png" } } }

Dynamic attributes however, will be listed inline on the product inside the API.

Remember that only the element with the key text will be shown and only if the value is not 0/false.

1 2 3 4 5 6 7 8 9 10 11 12 { "desc": "This is the attribute", "group": "product", "readonly": false, "elements": { "text": { "desc": "Text", "type": "input" } } }

This is how it looks like in the API:

1 2 3 { "attribute_name": "This is the text" }

Media object attributes.

Configuration of an example dynamic attribute for product media of type caption:

1 2 3 4 5 6 7 8 9 10 11 { "desc": "Image caption", "group": "product_media", "readonly": false, "elements": { "value": { "desc": "Caption", "type": "input" } } }

Response from the Checkout API:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 { "mediaObjects": [ { "media": "1", "sources": { "standard": [ { "url": "http://localhost/client/dynamic/images/1_9adfeff6f2-red.jpg" } ] }, "attributes": { "caption_description": "Example caption" } } ] }

Response from the Shop API:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 { "media": [ { "type": "image", "sources": { "standard": { "url": "http://localhost/client/dynamic/images/1_9adfeff6f2-red.jpg", "width": 0, "height": 600, "mimeType": "image/jpeg" } }, "attributes": { "caption_description": "Example caption" } } ] }

The dynamic attribute element types supported are all returning simple strings, so they look the same as per above.

Examples#

We recommend using snake_case for all your custom attributes API names. Since Centra uses camelCase, and all the values are mixed up in the API responses, it's helpful to be able to immediately tell which attributes are custom, which also prevents the risk of accidentaly re-using already existing attribute name key.

Product care instructions#

A multi-line dynamic text field for entering additional information about the Product. Can also be set up on the Variant level (group => variation).

1 2 3 4 5 6 7 8 9 10 11 { "desc": "Product Care Instructions", "group": "product", "readonly": false, "elements": { "text": { "desc": "Product Care Instructions", "type": "textarea" } } }

This displays like this:

Product video#

Since products videos will be different on each product, we use a dynamic input field to store video URL

1 2 3 4 5 6 7 8 9 10 11 { "desc": "Product Video", "group": "product", "readonly": false, "elements": { "url": { "desc": "Product Video URL", "type": "input" } } }

This will look like this in the Product page:
ProductVideoURL

Dangerous goods#

Required for some products at customs. Might differ between product categories and shipping countries.

1 2 3 4 5 6 7 8 9 10 11 { "desc": "Dangerous goods", "group": "product", "readonly": false, "elements": { "value": { "desc": "Dangerous goods code", "type": "input" } } }

It renders as a simple input field in the UI:
DangerousGoods

Showroom swatch#

Remember, Variant-level attribute use group variation, not variant.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { "desc": "Showroom Color Swatch", "group": "variation", "elements": { "desc": { "desc": "Color", "type": "input" }, "hex": { "desc": "Hex", "type": "input" }, "image": { "desc": "Image", "type": "image", "size": "50x50" } } }

Swatch definitions need to be configured in Catalog -> Attributes:
ShowroomSwatch2

...and then selected on the Variant page:
ShowroomSwatch1

Promotion yes/no#

Booleans are normally dynamic, not pre-defined. Remember, default value(s) (index 0) will not be returned in the API.

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 30 31 32 33 34 35 { "desc": "Promotion", "group": "variation", "readonly": false, "elements": { "sale": { "desc": "Sale", "type": "boolean", "options": [ [ "0", "No" ], [ "1", "Yes" ] ] }, "preorder": { "desc": "Pre-order", "type": "boolean", "options": [ [ "0", "No" ], [ "1", "Yes" ] ] } } }

PromotionYesNo

Product gender#

The difference between this and Static attribute is that the select options cannot be adjusted/expanded without a code change.

Please notice, the keys are enums, not integers. Use ['0','Select'], not [0,'Select'].

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 { "desc": "Product gender", "group": "product", "readonly": false, "elements": { "value": { "desc": "Product gender", "type": "select", "options": [ [ "0", "Select" ], [ "fem", "Female" ], [ "male", "Male" ], [ "unisex", "Unisex" ] ] } } }

The select then looks like this in the UI:
ProductGender

Product material - multi-select#

For attributes which are pre-defined, multiple values can be made selectable at once.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 { "desc": "Product material(s)", "group": "product", "readonly": true, "multi": true, "elements": { "name": { "desc": "Material name", "type": "input" }, "description": { "desc": "Material description", "type": "textarea" } } }

Multi-select snippet looks like this in Centra:
ProductMaterialMulti

Product display additional text#

You can also define custom attributes on a display level:

1 2 3 4 5 6 7 8 9 10 11 { "desc": "Extra text", "group": "display", "readonly": false, "elements": { "name": { "desc": "Extra text", "type": "input" } } }

This renders like this:
ProductDisplayAttribute

Product media attribute#

You can add text-based attributes to product media - uploaded in AMS -> Catalog -> Product -> Variants. These media-level attributes are currently not translatable.

Let's take this example, where we would like to store the height (in cm) of the model posing in the picture:

1 2 3 4 5 6 7 8 9 10 11 { "desc": "Model Size (cm)", "group": "product_media", "readonly": false, "elements": { "value": { "desc": "Model size (cm)", "type": "input" } } }

This renders under each Image details, when you click the image in AMS backend, as:
ProductMediaAttribute

Image sizes#

There are some predefined image sizes, and you can add custom ones, just like before.

New config:

Custom relation types#

Learn how to configure custom display relations in our FE guide.

Relation types have been moved from the PRODUCT section to a separate entry.

New config:
Please note, that there are some predefined image sizes that you cannot delete. These are used by the system and are required to be present. You can edit them.

Custom attribute types#

Learn how to configure custom attributes.

Every attribute type definition is editable separately. The configuration structure remains the same.

New config:

You may notice that there is no Edit button on some attributes. These are not custom types, but belong to plugins. For example, if you have a Google Merchant or Facebook Feed plugin, you will see six attributes they define.

Modifying attributes

You can update and delete existing attribute definitions, and add new ones.

Attribute type names are restricted to letters, digits, underscore _ and minus sign -. You cannot change the type name, but you can clone an existing attribute into a new one. Just click on the Create attribute type button and pick an existing attribute type to duplicate, then edit this copy.

Custom sort order#

By default, we sort custom attributes alphabetically. If you want to change the order, you can use a Sort order field to the attribute definition. Please note that you can change it only on editable attributes. The lower the number, the higher the attribute will be in the list. Predefined attributes are always sorted last.

Remember that empty Sort order is not treated as 0. It is treated as null, and the attribute will be sorted alphabetically after attributes with numeric sort order.

Fields in the attribute definition is placed under the main configuration:

Configuration list before change:

Product variant before change:

Configuration list after change:

Product variant after change:

Broke something?#

Just let us know, and we will restore all configs to the state defined in the client’s repository. Only remember that the synchronization is uni-directional. In short, we can still deploy the config.php configuration to AMS backend configuration on demand, but that will overwrite any changes not present in the config file.