Marketplaces / Zalando Direct connection / Zalando Product Listings

Zalando Product Listings

The purpose of this page is to define the requirements for product content creation to Zalando on its multiple sites, taking in account specifics, ZFS and other

It seems for Zalando a “Product” is a full listing including all of its variants. For example - one Product will be a T-shirt with all its colours and sizes

Zalando opperate as a Catalogue. This means all sellers of a single product list their offers against a single record of this Product as description and information.

By definition this means we will have to go through several steps to ensure we are following the right Zalando process. This includes an initial checkup if products already exist on the Zalando Platform so we can move towards connecting to them and directly sending offers. Below can be seen information on the whole flow (which is following our standard understanding of the already mentioned steps as part of the abstraction)

Product structure is 3 tier on Zalando:

  • Product Model (Or the most Generic part of the common product combination like Title for example)
  • Product Config (Specific subsection of variations in the likes of Colour and Season that also include some additional attributes added to this section in the likes of Description)
  • Product Simples (The smallest section of the product. This is what holds the actual product identification: EAN. It also holds information for Size as well)

Each of the levels have their own unique Seller identifier. For us that will be the Product Account > Variation Group for the “Model” level, the Product > SKU for the “Simples” level and a new field or generated one for the “Config” level. We should supply the option for this to be provided by the end user if present (As a new field under Product Account Zalando) OR if not supplied at the point of Content creation generate one internal. We should use the Product Account > Variation Group _ the Variation Specific value followed by a “_config”. Example: “VG0001_Blue_config”. We should store the generated values in the mentioned fields in Product Account Zalando in case anything changes in said VS value. IF a product varies only by Size or doesn’t vary at all we still need to provide a Config ID. To do so we should first look in the Item Specifics field for a “color_code.primary” value and if there is one use it the same way as if the product varied by this colour. If there is no such field in the Item Specifics simply drop the Variation Specific value in which case we will end up with just “VG0001_config”

Check for Products existence

The whole idea of this process is to potentially reduce time to market & reduce system and manual load on Zalando’s side (it can reduce load on our data team as well). Because Zalando is a catalogue based MP with EANs as unique identifiers they can maintain a single product record in their system against which multiple sellers will provide their offers (same as Amazon). Basically you find the product you want and on it you have the prices of everybody that supply that instead of looking through hundreds of the same product. Additionally Zalando keep one product record for all of their channels and this product keeps all Taxonomy information as well as any translated localised information.

As in Hemi we keep multiple Product Accounts for different sites (this is the way we keep offer and stock, localisation, etc) first thing we want to do is check if the “pending” SKU doesn’t already have other products that are already listed on Zalando. Listed products are such that are on a productStatus = “Product Published” or “Product Created”. If we find any such instead of sending to the marketplace any checks or information we need to copy the information from the existing Product Account. The fields we need to copy are Product Account > ChannelItemID; ProductStatus AND Product Account Zalando > ModelID; ConfigID. If we successfully complete this we are to drop the List Update whole item to “completed” so we know there is no need to work with this product anymore via this flow.

If there is nothing for this SKU already listed on Zalando we are to follow the standard checking and mapping process for any new product, followed by a full creation if needed.

To achieve this we need to follow the bellow process

The check is a two step process. First we have to first check for the products actually existing on Zalando and if they do we need to map some unique IDs to that existing product. Only once we’ve done that we move directly to the offer as there is no need to send the content itself. This process looks like this:

  1. Check products: API Docs :https://developers.merchants.zalando.com/docs/checking-product-exists.html API Call: GET /products/identifiers/{ean} If the call is successful it should always return a response containing an “items” field. If product exists it will be returning the EAN as part of this object. If not it will be empty Example:

    {
      "items": [
        {
          "ean": "9780679762881"
        }
      ]
    }

    Note: Sandbox testing will ALWAYS return an EAN as existing

    Once we know that a product exists on Zalando we need to move to the second step of “connecting the existing product” which is also called “onboarding”

    We have two ways of initiating the next step - either build it in the same script that will just pick the product and directly try to connect to it or mark the product as existing (via setting a flag on item_account_zalando.existing = 1 {new field} to recognise this) so we can proceed with “onboarding” step below

    In case the product is NOT present on Zalando we should mark the item_account as “Product Not created” which should be the trigger after this for the content creation

    Selection requirements: revise_item = ‘pending' AND productStatus = ‘awaiting_creation’, ChannelItemID = '' AND item_account_zalando.existing = 0

    Update: IF successful SET item_account_zalando.existing = 1. IF unsuccessful SET productStatus = 'product_not_created’

  2. Onboarding existing products: API Docs: https://developers.merchants.zalando.com/docs/onboarding-existing-products.html API Call: PUT /merchants/{merchant_id}/products/identifiers/{ean} The call allows for mapping of the 3 already mentioned unique IDs (model, config, simples). Logic for the 3 unique IDs can be get from Create Products content. Its in the same page. Example:

    {
      "merchant_product_simple_id": "{YOUR_PROD_SIMPLE_ID}",
      "merchant_product_config_id": "{YOUR_PROD_CONFIG_ID}",
      "merchant_product_model_id": "{YOUR_PROD_MODEL_ID}"
    }

    If successful we should receive a 204 response. This is the point where we flag our product (productStatus = Product Created) so next steps can take place: update stock and price - which will mark the productStatus as Published and the listingStatus as Active when successful. We treat the product and MP as there is no ChannelItemId provided by Zalando as per our abstraction description for such cases (meaning we have to create a ChannelItemID in Hemisphere so it is not empty - please check the abstraction description and let me know if questions on what to be used)

    If we don’t succeed at connecting the product we should simply store the error with the right message so it can be resubmitted when possible

    Important: If for a variation group (a Zalando Product) we have a few Simple items (EANs) that exist but even one that doesn’t we will have to submit the whole product. This means that for every existing EAN we can set the correct statuses so those can actually proceed and be mapped for selling but the other left product/s will have to send the whole information as per the description below, including the options that already exist to Zalando for content creation

    Selection Requirements: (revise_item = ‘pending' AND item_account_zalando.existing = ‘1’ AND ChannelItemID = '') OR directly continue from step one (depending on the way of handling the calls)

    Update: IF successful SET productStatus = ‘Product Created’, ChannelItemID = (If its variation set here VariationGroup otherwise set SKU) IF unsuccessful SET revise_item = error, revise_item_error = {message from MP} OR 'We were unable to map the unique IDs to an existing product on Zalando. Please check and resubmit when ready’ (if any additional details please add as well if possible)

Create Products content

API Docs: https://developers.merchants.zalando.com/docs/onboarding-new-products.html

API Call: POST /merchants/{merchant_id}/product-submissions

Zalando’s product structure is fairly straight forward with the exception of a few key points. The way they operate is on “Outlines” which in effect is a Category and then for each category we have multiple attributes (or as they call them quite often “Types”). For each Category we are receiving back all attributes that this category services. This includes everything including Titles, Descriptions, Images, etc. Different outlines have different attributes AND those attributes can be on different levels. For example: ‘name’ (title) is on Model level together with ‘size_group’ (identifier of the type of size); ‘description’ is on Config level, meaning they allow every variant type to have different descriptions (which we don’t currently allow unless specifically broken down in separate variation groups), ‘media’ is also here (holding all images); Simple section holds the smallest part of attributes, predominantly focused on the EAN and Size value

The attribute structure allows for different type of attributes as well. Below is a brief outline, more for that in the taxonomy structure

  • Simple attributes - these are just a key-value pairing. In this section stay also the multivalued ones, as they can just hold one or more values but are still in the likes of a key-value. Values can be free text or enum as well
  • Type variants attributes - these attributes have what we call sub attributes. If you look at the example of ‘color_code.primary’ - the original attribute is actually ‘color_code' but it has a few different options. As an attribute it is and numeration type attribute and its enumeration values sit under ‘color_code’ but can be used for multiple different “Type variants” attributes. Depending on the Outline (category) we might have different section or selection of these to be mandatory and or optional. The end result is though that we post in the JSON a “simple” like attribute that refers to the specific attribute variant - key / value; {“color_code.primary”: “101”}
  • Complex attributes - There are also attributes that have sub attributes with their own values. This is separated in additional identifier called “type” within the requested attribute. As part of the taxonomy we will be polling these SubAttributes as separate attributes to take their own values. The cool thing is that then such a Complex attribute can be “simple” in nature or “type variant”… meaning we have to pass either the values for the attribute itself or for one of its type variants (please see material in the listing example below - material is the main, complex, attribute. It has different type variants one of which is upper_material_clothing. Material though, as a complex attribute, requires we pass both material_code and material_percentage. If we had another material type variant we would need to pass code and percentage as well for that one). This is the most complex it can get with attributes, no further going downs of a type variant having its own type variants or anything like this

Note: Size Group and Size Code are both complex attributes. I am separating them as they are quite specific and need their own info here too. Size Group is what controls what should be in Size Code. Choosing the right Size Group will guide for the allowed attributes for Size Code. Additionally both fields allow for types “size” and “length” where “size” is mandatory and “length” is optional. Based on the outline and needs of the product (let’s say jeans) there might be a need of both waist size and leg length. At this point the right “length” size group can be chosen as well the same way the “size” group is and added to the listing. If there is an option in Size Group for “length” it should then be provided to the Size Code as well

Example listing:

{
  "outline":"sandals",
  "product_model":{
    "merchant_product_model_id":"MODEL_ID_123",
    "product_model_attributes":{
      "name":"AIR FORCE SANDALS 1 '07 LV8 UTILITY",
      "brand_code":"ns1",
      "size_group":{
        "size":"4MU1000E2A"
      },
      "target_genders":[
        "target_gender_male",
        "target_gender_female"
      ],
      "target_age_groups":[
        "target_age_group_adult"
      ]
    },
    "product_configs":[
      {
        "merchant_product_config_id":"7b077fc4-fde3-47d4-8b25-97af8792",
        "product_config_attributes":{
          "color_code.primary":"001",
          "description":{
            "en":"Nice sandals",
            "de":"Gute Sandale",
            "ru":"???????? ???????"
          },
          "material.upper_material_clothing":[
            {
              "material_code":"li",
              "material_percentage":97.5
            },
            {
              "material_code":"el",
              "material_percentage":2.5
            }
          ],
          "media":[
            {
              "media_path":"https://hosting_of_your_choice/media/7b077fc4-fde3/pic-1.jpg",
              "media_sort_key":1
            },
            {
              "media_path":"https://hosting_of_your_choice/media/7b077fc4-fde4/pic-2.jpg",
              "media_sort_key":2
            }
          ],
          "season_code":"fs20",
          "supplier_color":"white"
        },
        "product_simples":[
          {
            "merchant_product_simple_id":"white-shoes-1105AA",
            "product_simple_attributes":{
              "ean":"9780679762881",
              "size_codes":{
                "size":"42"
              }
            }
          },
          {
            "merchant_product_simple_id":"white-shoes-2216BB",
            "product_simple_attributes":{
              "ean":"9780679763992",
              "size_codes":{
                "size":"44.5"
              }
            }
          }
        ]
      },
      {
        "merchant_product_config_id":"7b077fc4-fde3-47d4-8b25-97af8793",
        "product_config_attributes":{
          "color_code.primary":"608",
          "description":{
            "en":"Nice sandals",
            "de":"Gute Sandale",
            "ru":"Хорошие сандали"
          },
          "material.upper_material_clothing":[
            {
              "material_code":"li",
              "material_percentage":87.5
            },
            {
              "material_code":"el",
              "material_percentage":12.5
            }
          ],
          "media":[
            {
              "media_path":"https://hosting_of_your_choice/media/7b077fc4-fde3-47d4-8b25-97af8793/pic-1.jpg",
              "media_sort_key":1
            },
            {
              "media_path":"https://hosting_of_your_choice/media/7b077fc4-fde3-47d4-8b25-97af8793/pic-2.jpg",
              "media_sort_key":2
            }
          ],
          "season_code":"fs20",
          "supplier_color":"mint"
        },
        "product_simples":[
          {
            "merchant_product_simple_id":"mint-shoes-3326CC",
            "product_simple_attributes":{
              "ean":"9813752182012",
              "size_codes":{
                "size":"44.5"
              }
            }
          }
        ]
      }
    ]
  }
}

Mapping:

Zalando Field WAP Mapping WAP Notes
outline Product Account > Primary Category ID
product_model N/A
merchant_product_model_id Product Account > Variation Group In case we have a single product we should allow for the end user to control this value via a field in Product Account Zalando > Model ID. IF it is not filled in we should generate one as this is a mandatory unique value and store it against the product to use for a later purposes. A suggestion is to use either the Item > SKU followed by an underscore and “model_id”. this way it can be used as a “variation group” in the future as well if it becomes one
product_model_attributes N/A
name Item Account > Title This is one of the fields that will always be present the same way on all “outlines”
brand_code Item > Brand Expecting this will always be the same as well on all “outlines”. We should also be allowing for “Brand” key as well
size_group Item Account > Item Specific This is an IS as it defines the “type” of size we will be using. We should be looking for both SizeGroup.size/ SizeGroup.length attributes AND for only SizeGroup. If only SizeGroup is used we should default it to the “size” option
IF we have a variation specific for “size.length” and we don’t have a SizeGroup for this we want to block the whole listing where this is the case
target_genders Item Account > Item Specific
target_age_groups Item Account > Item Specific
product_configs
merchant_product_config_id Item Account Zalando > Config ID

OR Generated via Hemisphere | Generation suggestion: Please see above for the suggested method of Config ID generation | | | | product_config_attributes | | | N/A | | | | | | color_code.primary | | Item Account > Item Specific OR Item Account > Variation Specific | As it is not mandatory an item to vary by colour we should expect that this field can be a part of the IS as well. If we can mark it in our taxonomy as VS than great we can always expect it there. But in a general sense of speaking we can’t go through every category, every config attribute and mark it as IS or VS especially as it seems most of them can be used for VS as well. This means we should be ready for reading any of the Config attributes from both IS or VS fields and based on where they are expect a variation or not. | | | | | description | | Item Account > Description | Include Design template logic. HTML NOT ALLOWED | | | | | material.upper_material_clothing | | Item Account > Item Specific OR Item Account > Variation Specific | | | | | | media | | Item > Main Image + Item > More Picture URLs OR Item Account Zalando > Main Image + Item Account Zalando > Additional Images | Zalando images operate without a Listing lead image even if it is a multi variation product. Images are grouped around the Config sections - meaning every config (that is different than the “Size” variation) requires its own set of images. We are already doing the right groupings by Variation Group and we have the capability to group images based on the variation specifics. This is what we want to do here - omit the Listing Image and take as per our general standard the Main and More Pictures for a specific group (that is lead by different variations besides size) and map them to the Zalando fields Media is generally a complex attribute that has a URL and Order. For us the Main Image of a group is always 1 and then it should be followed by the determined More Picture URLs from the selected group. Image order should just come with the next available value (2, 3, 4, etc.) | | | | | season_code | | Item Account > Item Specific OR Item Account > Variation Specific | | | | | | supplier_color | | Item Account > Item Specific OR Item Account > Variation Specific | | | | | product_simples | | | | | | | | | merchant_product_simple_id | | Item > SKU | | | | | | product_simple_attributes | | N/A | | | | | | | ean | Item Account > Marketplace EAN ОR Item > EAN | | | | | | | size_codes | Item Account > Variation Specific | Even if a single product with only 1 size if “size_code” is a mandatory field for this category Size should be populated in VS field. We should also allow for “Size” key that maps to “size_code”. As per the description of “size_group” we can be expecting a size_code.size and a size_code.length. If we have only “size” it should always go to “size_code.size“ |

Upon successful submission of a feed Zalando will respond with 200 OK

Content creation should be picked only for products with productStatus = Product Not Created so we can ensure that the product check has done its job

UNKNOWN - At the moment there doesn’t seem to be a specific way of receiving a feed ID. The 200 OK simply means it has passed initial validation. From there on the product will go through more automated and manual validations before it gets published or not. The only way to track those seems to be through what is called Product Status Report (PSR) that doesn’t seem to be connected in any way to a specific feed but more looks like a general filter for products and their current status so we can just pull and map them all to continue with the Offer (simple Price & Stock updates as they are separate calls). Please read more on the PSR specific page

Select requirements: List / Update the whole item = ‘pending' AND productStatus = ‘product_not_created’ AND ChannelItemID = '’

Update: IF successful SET List / Update the whole item = 'sent' AND Product Status Date updated with the current time of processing (NOW()) IF unsuccessful SET revise_item = error, revise_item_error = {message from MP} OR ‘Product was not successfully created due to {server issue, validation issue, MP issue, unknown issue}’ (with all necessary details if possible)

Adding new Products to already created listing

This section will tackle the problem of adding new item_accounts to already existing listing

This might happen in cases we add new colours for example OR a single product is selling so well that we are transforming it to a variation with additional options. Or always it can be adding further variation options (adding Style to Colour for example)

In all of the above cases we have to pick all products for this variation and send them together almost as a new product to Zalando. We are to make the absolute same grouping as if a new variation is being sent but we need to be careful for the following specifics:

  1. ModelID - If the previously listed products within the newly formed variation (such that have ChannelItemID and productStauts = published) have the same ModelID AND the newly added options don’t have anything filled in for ModelD we are to use the value that is already set on the old product accounts for the whole variation. If there is a difference between modelIDs anywhere across the newly formed variation we are to set an error
  2. ConfigID - We need to add a check for the configID on the listed product accounts so we can see if they are Hemi generated or user input. If they are user input we are expecting to see configIDs on the newly added product accounts as well. If such are not present we should store an Error. If the configIDs are Hemi generated already we are to regenerate the ConfigIDs for the whole listing with all its variants again the same way we are doing when we are simply creating a new listing from scratch
  3. SimpleIDs - just to confirm that the same logic as already described should apply in this case as well
  4. revise_item - should be properly updated on all product accounts old or new with the correct communication status
Is this article helpful?
0 0 0