Import your products into SCAYLE
Introduction and preparation
- Product Data Management
- Tech
Robert Merten
VP Tech
SCAYLE provides you a very flexible product schema and entity level structure.
It allows you to model your product schema in a way that it matches your product portfolio you're planning to sell via SCAYLE.
Products are the central data structure for category listings and product detail pages.
Information about products is stored as Attribute Groups. Product data can be configured and customized at different entity levels. The system differentiates between three entity levels: master, product, and variant.
The user can specify which product information correlates to which entity level. Prices are determined by the variant because that is the specific entity to be sold.
Be aware that Product is the Entity Level that is responded on Product Listing pages such as Category Page, Search Result Page and Product Detail Page.
Variant is the Entity Level that you use to put a specific Product Variant in a Basket or use it for a Transaction.
You define your Product Schema by using Attribute Groups on Master, Product & Variant level.
An Attribute Group is a collection of different attributes (or attribute values). For example, the Attribute Group color could contain attribute values; black, blue, and green. We use this information to define a product and its characteristics. All the information a customer may need to know about a product should be stored in an Attribute Group in SCAYLE. For example, if you want to share a product’s cleaning instructions, list the details as an attribute.
There are two types of Attribute Group available in SCAYLE:
Both types can be translated. This is relevant if you’re working with multiple shop countries and languages.
Simple Attribute Groups can be used for different products, but it is also possible to add several values of a simple attribute group to one product with multi-select.
Advanced Attribute Groups are most often free text fields that are connected to a specific product.
Every Attribute Group is valid for only one entity type, which is determined by the level
.
The supported levels are:
The Attribute Group type describes attribute values. The supported values are:
"red"
["red", "blue"]
{"de_DE": "Rot", "en_GB": "red"}
[{"de_DE": "Rot", "en_GB": "red"}, {"de_DE": "Blau", "en_GB": "blue"}]
{"width": 90, "height": 180, "unit": "cm"}
[{"width": 90, "height": 180, "unit": "cm""}, {"width": 100, "height": 200, "unit": "cm"}]
When an Attribute Group is defined as shared ("isShared": true
), entities share attribute values instead of having their own values. In this case, if the value is changed or a new translation is added or removed for the attribute, all entities sharing the same attribute value will be affected.
Shared attributes' translations are fully replaced with those provided in the payload.
In entity related update methods translations of locked attributes are ignored. To update such translations, the query parameter ignoreAttributeLocks=true
is necessary.
It is not possible to share attributes of the advanced
and advancedList
types.
For attribute values with a string length longer than 255 characters, you have to create an advanced Attribute Group.
This can be done by passing "isShared": false
and the respective Attribute Group type, for example localizedString
if you want to have a translatable attribute.
See the example below for creating such an attribute group:
{
"name": "description",
"frontendName": {
"en_US": "Description"
},
"type": "localizedString",
"isShared": false,
"level": "product"
}
Attributes of advanced
and advancedList
types are used to store compound arbitrary values. These values are described by the attribute group structure. For example, if you want to save product dimensions {"width": 90, "height": 180, "unit": "cm"}
, you need the following structure:
{
"width": {
"type": "integer"
},
"height": {
"type": "integer"
},
"unit": {
"type": "attributeGroup",
"attributeGroupName": "unit"
}
}
The attribute group structure supports various data types:
attributeGroupName
to be specified, e.g., {"type": "attributeGroup", "attributeGroupName": "unit"}
attributeGroupName
and attributeName
to be specified, e.g., {"type": "attributeGroup", "attributeGroupName": "unit", "attributeName": "cm"}
When creating an Attribute Group within the SCAYLE Panel, you can choose between Simple
and Advanced
attribute structures.
If Advanced
is selected and Component
has only one field, then Admin API considers this attribute group to be of the following type:
simple
- if the attribute group is not translatable and the field is a single-selectsimpleList
- if the attribute group is not translatable and the field is a multi-selectlocalizedString
- if the attribute group is translatable and the field is a single-selectlocalizedStringList
- if the attribute group is translatable and the field is a multi-selectAdmin API does not support nested or multiple group sets in the advanced group structure.
Most shops offer a variety of products, so it's helpful to categorize these products. In SCAYLE, we use master categories, which could include divisions such as trousers, T-shirts, dresses, etc. Based on the master categories, you can define different product types (related to purchase categories in the tenant systems.) For example, differentiating between clothing products and furniture products. Every product requires a master category in SCAYLE, and you must input this information to create a product. Within each master category, you can define mandatory attribute groups for corresponding products.
Keep in mind the differences between master categories and shop categories. Master categories are only relevant for product structure in the SCAYLE backend.
You can set up master categories manually or by importing them in the SCAYLE Panel. We recommend manual setup because you’ll only need to complete this step once. Details can be found here.
Now that you have an overview of our product structure, you’ll need to decide what kinds of attribute groups and master categories you’ll need for your project.
We've put together this guide to help you with your decisions.
Question/situation | Answer |
---|---|
What information about a product should be shown in the shop front end? | All product-related information should be listed in an attribute group in SCAYLE. |
Do you have products in the same style but differing in dimensions like color, pattern, or print? | If yes, you should assign all the products of the same style to the same master. |
Is there information that always remains the same about a product, besides color or size? | This information should be defined in an attribute group on the master level. |
Is there information that differs between color options? | If yes, this information should only be related to the specific color and defined in an attribute group on the product level. |
Is there specific information for a product size that is relevant for the customer? | If yes, this information should be defined in an attribute group on the variant level. |
Is there any product-related information that is requested for third-party tools or reporting that has to be handled in SCAYLE? | You should also include this information within SCAYLE attribute groups. |
How do you structure your products in your purchase tool? | You can usually use your purchase structure to create the same master categories. |
Do you plan on selling different product types? | For example, furniture and fashion products should be handled with different master categories. |
Should you list product information in an advanced or simple attribute group? | To decide which type of attribute group to use, consider if the information is reusable. Only free text descriptions or product-specific information (like EANs) should be advanced attribute groups. All product information can usually be listed in simple attribute groups. Please try to mostly use simple attribute groups to reduce database complexity. |
In SCAYLE, we distinguish between different attribute group types, in particular simple attributes with clearly defined single values, and advanced attributes with compound-structured values.
The method is used to create an attribute group.
let response = await adminApi.apis.AttributeGroups.createAttributeGroup({}, {requestBody: newAttributeGroup});
let createdAttributeGroup = response.body;
let newAttributeGroup = {
"name": "material",
"frontendName": {
"de_DE": "Material",
"en_GB": "Material"
},
"group": "characteristics",
"type": "simple",
"isShared": true,
"level": "product"
};
let response = await adminApi.apis.AttributeGroups.createAttributeGroup({}, {requestBody: newAttributeGroup});
let createdAttributeGroup = response.body;
let newAttributeGroup = {
"name": "material_composition_textile",
"frontendName": {
"de_DE": "Materialzusammensetzung",
"en_GB": "Material Composition"
},
"type": "advancedList",
"isShared": false,
"level": "product",
"structure": {
"group": {
"type": "attributeGroup",
"attributeGroupName": "overmaterial"
},
"components": {
"type": "array",
"items": {
"fraction": {
"type": "integer"
},
"unit": {
"type": "attribute",
"attributeGroupName": "unit",
"attributeName": "%"
},
"material": {
"type": "attributeGroup",
"attributeGroupName": "material"
}
}
}
},
"shopCountries": [
{
"shopKey": "ms",
"countryCode": "DE"
}
],
"isOverridablePerShop": true
};
let response = await adminApi.apis.AttributeGroups.createAttributeGroup({}, {requestBody: newAttributeGroup});
let createdAttributeGroup = response.body;
Please note that deletion of an attribute group is only possible if the following conditions below are fulfilled:
Additionally, please be aware that when an attribute group is deleted, all associated entities will also be removed.
This method can be used to delete an existing attribute group.
adminApi.apis.AttributeGroups.deleteAttributeGroup({attributeGroupName: attributeGroupName});
adminApi.apis.AttributeGroups.deleteAttributeGroup({attributeGroupName: "material_composition_textile"});
Since attribute groups have many dependencies, there are some restrictions on when and how you can update them. Only an attribute group, which does not have any attributes can be updated. It is also not possible to change an attribute group level.
This method can be used to update/replace an existing attribute group.
Parameter | Details |
---|---|
id | Integer READ-ONLY The ID of the attribute group created by SCAYLE. |
name | String A name that uniquely identifies an attribute group. |
frontendName | String The localized attribute group name. It must include at least the default language that is configured in SCAYLE. |
type | String An attribute group type. |
isShared | Boolean Specifies whether an attribute value is shared among multiple entities or if each entity has its own unique value. It's important to note that attributes of advanced types cannot be shared, so 'isShared' must always be set to false in such cases. |
level | String Defines the attribute group level, specifying the type of entity it is applicable to. |
structure | Array A structure, which describes advanced attribute values. Mandatory for the advanced type. |
shopCountries | AttributeGroupShopCountry A list of shop countries the attribute group is valid for. The attribute group is valid for all shop countries if the field is omitted. |
isOverridablePerShop | Boolean Defines if shop-specific attribute values are allowed for the given attribute group. |
isDifferentiating | Boolean If an attribute group is differentiating, then every entity must have a unique attribute value. This configuration is not applicable to the advanced type, neither to attribute groups marked as isShared=false. |
let response = await adminApi.apis.AttributeGroups.updateAttributeGroup({attributeGroupName: attributeGroupName}, {requestBody: attributeGroup});
let updatedAttributeGroup = response.body;
let attributeGroup = {
"name": "simple_material_composition_textile",
"frontendName": {
"de_DE": "Materialzusammensetzung",
"en_GB": "Material Composition"
},
"group": "textile",
"type": "simple",
"isShared": true,
"level": "product"
};
let response = await adminApi.apis.AttributeGroups.updateAttributeGroup({attributeGroupName: "material_composition_textile"}, {requestBody: attributeGroup});
let updatedAttributeGroup = response.body;
This method can be used to update/replace the frontend name for an existing attribute group.
This operation replaces existing translations, e.g. all translations of the given attribute group not provided in the payload will be deleted.
await adminApi.apis.AttributeGroups.updateFrontendName({attributeGroupName: attributeGroupName}, {requestBody: attributeGroupFrontendName});
let attributeGroupFrontendName = {
"de": "Materialzusammensetzung",
"en": "Material Composition"
};
await adminApi.apis.AttributeGroups.updateFrontendName({attributeGroupName: "material_composition_textile"}, {requestBody: attributeGroupFrontendName});
You have the option to request attribute groups, both simple and advanced, by their names.
This method can be used to get an existing attribute group by its name.
let response = await adminApi.apis.AttributeGroups.getAttributeGroup({attributeGroupName: attributeGroupName});
let attributeGroup = response.body;
let response = await adminApi.apis.AttributeGroups.getAttributeGroup({attributeGroupName: "simple_material_composition_textile"});
let attributeGroup = response.body;
When retrieving multiple attribute groups, you can paginate results and apply other parameters to narrow down your query.
This method can be used to get a collection of attribute groups. It is possible to refine the search by applying filters in the options.
let response = await adminApi.apis.AttributeGroups.getAttributeGroups();
let attributeGroups = response.body.entities;
Attribute group collection read can be used with optional parameters - called options:
Parameter | Details |
---|---|
limit |
Maximum number of items in the result. (default: |
filters[id] |
Comma-separated list of attribute group IDs that should be used for filtering. |
filters[minId] |
Minimum ID of attribute groups, which should be returned. |
filters[maxId] |
Maximum ID of attribute groups, which should be returned. |
filters[level] |
Filter attribute groups by level. |
filters[type] |
Filter attribute groups by type. |
let response = await adminApi.apis.AttributeGroups.getAttributeGroups({"filters[type]": "simple"});
let attributeGroups = response.body.entities;
let response = await adminApi.apis.AttributeGroups.getAttributeGroups({"filters[level]": "product"});
let attributeGroups = response.body.entities;
When retrieving multiple attributes, you can paginate results to limit your query.
This method can be used to get a collection of shared attributes given for an attribute group.
let response = await adminApi.apis.AttributeGroups.getAttributes({attributeGroupName: attributeGroupName});
let attributes = response.body.entities;
Parameter | Details |
---|---|
limit | Integer Maximum number of items in the result. (default: |
let response = await adminApi.apis.AttributeGroups.getAttributes({attributeGroupName: "material_composition_textile"}, {limit: 50});
let attributes = response.body.entities;
For basic setup, we need to add the following attribute groups:
Attribute group name | Product Level | Structure | Attribute (values) |
---|---|---|---|
brand | Master | simple | adidas, nike |
color | Product | simple | black, green, blue |
size | Variant | simple | S,M,L,XL |
description | Product | advanced | product-specific value |
This endpoint can be used to create an unattached attribute for an attribute group.
The attribute can be created only if:
If Attribute Group is multiselect
, only one option can be created per request.
const response = await client.apis.AttributeGroups.createAttribute({attributeGroupName: attributeGroupName}, {requestBody: newAttribute});
const attribute = response.body;
const attribute = {value: "XL"};
const response = await client.apis.AttributeGroups.createAttribute({attributeGroupName: "size"}, {requestBody: attribute});
const createdAttribute = response.body;
const attribute = {value: {
"de_DE" => "grün",
"en_GB" => "green",
}};
const response = await client.apis.AttributeGroups.createAttribute({attributeGroupName: "color"}, {requestBody: attribute});
const createdAttribute = response.body;
This endpoint can be used to update an attribute for an attribute group.
The attribute can be updated only if:
If Attribute Group is multiselect
, only one option can be updated per request.
For a localized attribute, the translation for the default locale should be uses as {attributeValue}
parameter.
const response = await client.apis.AttributeGroups.updateAttribute({attributeGroupName: attributeGroupName, attributeValue: attributeValue}, {requestBody: newAttribute});
const attribute = response.body;
const attribute = {value: "L"};
const response = await client.apis.AttributeGroups.updateAttribute({attributeGroupName: "size", attributeValue: "XL"}, {requestBody: attribute});
const updatedAttribute = response.body;
const attribute = {value: {
"de_DE" => "gelb",
"en_GB" => "yellow",
}};
const response = await client.apis.AttributeGroups.updateAttribute({attributeGroupName: "color", attributeValue: "grün"}, {requestBody: attribute});
const updatedAttribute = response.body;
This endpoint can be used to delete an attribute from an attribute group.
The attribute can be deleted only if:
If Attribute Group is multiselect
, only one option can be deleted per request.
For a localized attribute, the translation for the default locale should be uses as {attributeValue}
parameter.
await client.apis.AttributeGroups.deleteAttribute({attributeGroupName: attributeGroupName, attributeValue: attributeValue});
await client.apis.AttributeGroups.deleteAttribute({attributeGroupName: "size", attributeValue: "XL"});
Updating the product state will trigger the state evaluation. When the desired state is live
, the product might end up in the problem
state.
Not all state transitions are allowed!
Parameter | Details |
---|---|
state | String The state of the product determined by the state evaluation process. The only possible values to request are |
merchantReferenceKeys | String[] A list of merchant reference keys the merchant product belongs to. |
merchantProductStatesREAD-ONLY | MerchantProductState[] A list of merchant keys to which the merchant product belongs to and the state of the merchant product. |
let response = await adminApi.apis.Products.updateProductState({productIdentifier: productIdentifier}, {requestBody: productState});
let productState = response.body;
Update or create the time when products go live for the first time in a shop country.
let response = await adminApi.apis.Products.updateProductsFirstLiveAt({}, {requestBody: productsFirstLiveAt});
let productsFirstLiveAt = response.body;
Use Storefront API to:
All product data is based on a predefined master data structure that is initially created and configured.
Once all product data has been transferred to the system, you can start with the master data configuration. The best way to do this is to get an overview in the Settings area.
On the left side, you can see the different data structure levels:
Composite products are generally considered to be the same as normal products. The difference is that composite products are not real products, but, as the name suggests, they are composed of several other products. Simple examples are a bikini top and a bikini pant or a jersey with a flocking (e.g. name and number) on the back. Here again the same product hierarchy applies, consisting of masters, products and variants.
If you want to read more about masters, products and variants, please refer to the corresponding pages, starting with Product Data Management - Products - Overview.
The data model being used to represent (composite) products in SCAYLE contains entities with multiple levels of abstractions.
Import your products into SCAYLE
Robert Merten
VP Tech