Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
NOTE: This describes schema version 1.7.
A product has codes, texts and pictures. The texts and pictures can be defined for multiple languages. For each product a set of complement products can also be defined.
Note that all used languageCodes must be registered on the account used to upload the information to Mediablob. Please check your account details with your Shoppa representative if you are unsure.
Lets build a product from scratch and see how different requiements evolve its xml definition.
Lets say our customerId is 1143 and we have a product with only some basic information:
brand: Orrefors
name: Champagneglas
sku: 65467-14
ean code: 123456789012
This corresponding xml format is:
A product must always have at least one text
section. Brand and name are required for new products. In the example above the product is described in the Swedish language.
We extend the product with additional sales arguments and a unit for prices:
short sales argument: Exklusivt tvåpack. En perfekt bröllopspresent.
long sales argument: Efva Attling är en juveldesigner som har använt sin rika erfarenhet och expertis för att skapa glaskonst. Hennes tredje glas är ett maskulint martiniglas med en silverring.
unit: st
The xml for describing the product now becomes:
To protect content against xml formatting constraints, the &
character is xml encoded. This follows the xml specification and must be used for any content.
We decide to support English too. The xml gets extended with an additional <text />
section. We also start the product with a generic language text xx
with generic text for all languages unless overridden.
Even without actual such texts, we recommend always including a row for xx to prevent duplicate products in the future.
Finally, we add pictures to the swedish brand and productName fields. English users do not get to see any pictures for now.
As you can see, the pictures are referenced by a hashCode. What hashCode to use will be described in detail in the Pictures section.
Pictures require a countryCode
. This is a legacy construct and is easily created by lowercasing the last two characters of the languageCode.
The hashCode returned from the picture uploader is based on md5, but formatted as a guid. The difference is big or little endianess. If you prefer to reference the picture by its md5 code, you can use the md5
attribute instead:
Instead of referencing an image by hashCode or md5, you can provide a public uri from where Mediablob can download the picture for you. Mediablob will only use the same uri once, so you must ensure the uri is unique for each picture. Avoid using this scheme unless you are using a picture database that ensure unique uri's per picture.
In the sample above, Mediblob would keep using the original downloaded picture even if the content of the uri changes.
This describes StoreInfo schema version 1.6.
While most product information is static over time, prices are not. Stores have different prices for the same product and prices change at different times. This information is stored in pricelists which is one kind of StoreInformation package
.
In contrast to products and campaigns, pricelists are not automatically inherited along the customer tree. A store uses the pricelist named STANDARD
from its own node by default, but a named pricelist from a parent node can be explicitly selected instead.
Pricelists are described by package
s with a name and a start date, but no stop date. If no name is provided, the default name STANDARD
is assumed. If you also provide a package id, you can later use this to refer to that package instead of using name + start date.
Mediablob primarily identifies packages by id
+ countryCode
. If id
is not provided, the package is identified by name
+ countryCode
. We recommend using the id
for identification when possible. This behaviour is different from previous versions of the api and should be considered when updating existing integrations.
Prices are changed by sending a new package with the same name for a later date.
Lets build a pricelist from scratch and see how it evolves with different requirements.
Lets say store S123 wants to sell our sample product for 205 SEK. The price is valid from September 21st, 2008. The corresponding xml format for creating a standard pricelist is:
Some stores may use a mutual pricelist. In this case HQ wants to publish a named pricelist the stores can subscribe to. We create the same pricelist above as a named pricelist. We use an id
from the HQ ERP system for future tracking and updates. Here is the xml we need:
Now we want to add two other products to the named pricelist. The xml for this is:
After this, the pricelist contains three priced products.
We finally decide to restructure our pricelist system and want to delete a pricelist completely. We do this by setting the delete
attribute but omitting the startDate
. The xml for this is simply:
In addition to deleting a complete pricelist you also have the option to remove a selection of products from the existing pricelist. Instead of defining the delete
attribute in the package
tag, it will be set in the product
tag. The xml for this is simply:
List of all available schema versions for each XML type.
Future price changes requires the use of StoreInfo schema version 1.6 or higher and is only supported by Shoppa versions 2.25 or higher.
Assume we have the following base price list to begin with. It has a start date of 2020-01-01
From 2020-01-15 we want to increase the price of product 111111
to 59.95 SEK. We also want to lower the price of 222222
to 19.95 and 444444
to 69.95 two weeks later.
Here we have to refer to the same package ID as the base price list if the changes are to be combined with the base price list at desired change date. Each package startdate in the XML defines when the changes will apply.
We have therefore created one package with startdate 2020-01-15 and one with startdate 2020-02-01 for the respective price changes.
The price of the product 333333
remains the same at each change date.
If we want to reduce a price during a short period of time, for e.g. under a two month time. Afterwards we are to set the old price back again. We can not set a stopdate for the reduced price, instead we have to send the higher price on new.
The product will now be on a reduced priced during the two months between 2020-02-01 and 2020-03-31. At 2020-04-01 th eproduct will return to its original price.
It is possible to remove a previously uploaded package in case it was incorrect. This will remove all price changes that were set to occur at the specific date.
We delete the price changes above for 2020-02-01 with this xml:
The price change at 2020-01-15 will still be in effect.
To remove individual products from future price changes, use the delete
attribute on the product element, like so:
We have now deleted the change for product 444444.
The change for product 222222
at 2020-02-01 will still remain.
Here we will send in a few price changes for the product 111111
over a period of time. We will have price changes at each package startdate.
To remove all future price changes for product 111111
we have to delete the product from each future price change package with the same startdate defined as when the change were to occur.
The XML will look like this:
Assuming we don't know when all the price changes for a product occurs, we can delete all prices for a product by sending in the product with an empty price value. The startdate of the package will determine from which date the prices are deleted.
All future price changes and the current price for product 111111
are now deleted, starting 2020-01-15.
Here we have a price change for 2020-02-01. After a while it is decided that the product should have another price from the same startdate. Correcting the price change is accomplished by setting the new price for the same startdate.
At 2020-02-01 the product will now have a price of 24.95 instead of the original 19.95.
Some time passes and we have made multiple changes to our pricelists at different times. For some reason we may have the need to replace all prices in a pricelist with new prices. Some products may no longer be relevant for example. We do this by setting the fullPackage
attribute like this:
Now there will no longer be a price for product 333333
or 444444
starting from 2020-04-15.
Sometimes you need to delete existing products or parts of a product, or you want to make sure any existing information is removed and not merged with the new information. Below we describe the different approaches you can use to solve this.
You delete a product field by simply assigning it as an empty field.
Lets say we want to delete the infoshort field we added in Adding a new text field. We can do that by sending the following xml:
Note however that in case this product was overloaded from another customer node, the original text will now be visible again. If you actually want the field to be empty, regardless of what has been defined at a higher level, you need to write an empty space to the field, like this:
The space inside the field content is mandatory here. If the field is empty the original content will be visible again.
To remove an entire language from our example product, we add a <text/>
section with the attribute delete="true"
:
There is no reason to add text fields to a deleted <text />
section since the import will simply ignore them.
If you want to replace all texts for a specific language and make sure there are no legacy fields left behind, you need to write a delete-section followed by the new <text />
section:
Make sure the delete comes first, or your newly added texts will be deleted too!
Sometimes you want to delete an entire product, with all texts, codes and picture references. This is done with the following xml:
As before, if the product is owned by another customer, the product will still be visible with its original content.
For every product we can assign a list of complement products. The complements are displayed in Shoppa when the base product is displayed and can be automatically assigned to templates to easily build multi-product signs.
Note: Just because product A assigns product B as a complement does not mean the opposite is true. You must explicitly assign all relationships you want to use.
Lets assign a complement product to our sample product:
You can of course assign complement products at the same time you create your product or modify other properties of it. The only requirement is that the complement product already exists in Mediablob.
If you send a <complementProducts />
list as above, the new complements will be merged with any existing complements and make the list of complements longer. If you instead want to replace the existing complements with a new list, you need to set replace="true"
:
The above xml effectively deletes complement 65468-3
, since it is no longer part of the list.
If you want to delete all existing complements for a product, you set delete="true"
on the <complementProducts />
section:
Note that deleting the complements list does not delete the product itself.
The Shoppa application can accept sign orders from external applications for printing. The sign order is an XML file which follows a predefined XML schema. The external application or PDA places the XML file in a predefined “hot folder” and Shoppa imports the file from this folder. The sign order can include one or many products. Each defined product can have text fields like name, brand, description, price and so on. The sign order has an auto print option. If this option is activated Shoppa will put all products on a predefined template and automatically send them for printing. When the auto print option is disabled Shoppa will show the products in a list for further action by user.
A few things are needed in order to use the local integration functionality:
The correct Add Ons for your enterprise and store level accounts. If you don't already have these, contact your Shoppa representative.
The location of the hot folder needs to be specified in the Shoppa configuration file, see below.
One or more display groups need to be created, preferably on an enterprise level account.
The location of the hot folder needs to be specified in Shoppas configuration file (shoppa2.exe.config). The relevant section is this:
If this setting does not already exist, add it in the <Shoppa.PL.Windows.Properties.Settings>
section. If the folder does not already exist, the Shoppa client will create it on startup.
In order to send a signorder file to Shoppa, simply place it in the hotfolder, either by hand for testing purposes, or use another appliction.
The folder will contain three or four subfolders, depending on the version of the Shoppa client.
In Shoppa 2.25 and newer, finished files will be moved to the archive folder after three days. Older versions do not do this, and the archive
folder is not created.
If a something goes wrong when processing a signorder file it will be moved to the error
folder, along with a .txt file containing an error message. A timestamp will be appended to the name of the signorder and the corresponding error file will have the same name, except for being a .txt file rather than an .xml file.
When a signorder is successfully processed it is moved to the finished folder. A timestamp will be appended to the name of the file.
There are several use cases for the signorder functionality. These are a few examples.
An application running on a handheld device can read the DisplayGroups.xml file if the hot folder is placed on a shared network drive and dynamically generate a list of available print options. The user can scan barcodes to select products and choose which template to use while out and about in the store. The application can generate a signorder and place it in the hot folder, and the selected signs will be printed through a computer running Shoppa. The user can then collect a stack of printed signs from the printer and start putting them up.
An application running on the same workstation as the Shoppa client can generate a list of products to print based on whatever business logic is available to it. The application can place a file in the hot folder and the user can access the list in Shoppa and create the required signs.
When you want to extend a product with additional information you simply send the product information you have with an existing product identifier.
The extended information can be anything; an additional language, an extra product code or picture references.
You can also reference the product by its ean code instead, by replacing the first line with <product id="123456789012" idType="EAN13">
. As you see, any code can be used as long as it is unique to the product.
Continuing on the section Extending product information, English could have been added to the existing product by sending only this xml:
As you see, adding a field or an entire extra language is essentially the same. Just reference the product by its identifier and add the missing information.
As stated initially, all products at a top customer node are available to all children. This means there is usually no need to add products at a store level. Instead the products are added to the HQ node or any branch-nodes in between HQ and the stores used for segmentation of information.
In some instances a store or branch-node needs to replace a certain part of a product. This is achieved by sending the same kind of update mentioned above, but for another customerId. Customer id´s are defined in the SOAP metadata and described in detain in a later chapter.
This describes .
Product groups is used for creating a hierarchy of products. It makes it easier for the users to do the search by brand or by product type. Much like pricelists, product groups are not inherited along the customer tree automatically, only stores that subscribe to the the product groups can see them.
Managing the product group subscriptions cannot currently be done through the API, it needs to be done through Mediablob.
Subscribing to product groups is all or nothing, the store either has access to the full set of product groups, or none at all.
Use the function call UploadProductGroupsXml to upload your product group xml.
The product groups are a hierarchy where each group can contain a number of subgroups, which in turn can have their own subgroups, etc. Each group must have its own unique ID. Shoppa places no particular restrictions on these ID:s, so we recommend that you mirror existing ID:s in whichever system you are using. Each group must also contain at least one text element, specifiying the name of the group. The group names can be specified by language, so that different users can have different group names, but bear in mind that the group structure and its contents will be the same.
The full definition of the product groups is done in two parts: first the structure is defined as per above, and then the products are assigned to their groups using the groups ID. Note that a product can belong to multiple groups.
The group structure cannot be edited. If a change is required you need to send the entire structure again. Note that products can still be added to groups without having to resend the entire structure.
Campaigns describe temporary prices used at one or more stores for a specific time period. Campaigns are usually used to show customers the original price and how much they save during the campaign. For this reason, campaigns are layered on top of the stores pricelist when used by Shoppa.
Like pricelists, campaigns are described in a StoreInformation package
. Campaigns are always created with a start- and a stopdate and they always need a name that can be used in Shoppa Client to select it.
As with pricelists, campaigns can be identified with name
, startDate
and countryCode
, but for simplicity we recommend using a reliable id
instead.
A campaign can not be converted to a pricelist and vice versa. If you create the wrong kind of package you need to delete the package and create a new one from scratch.
Lets make a 50% off campaign for our sample glass 65467-14
from October 1st - 4th. The xml for this is:
We decide to postpone our campaign one day and extend it to a full week. If we simply set a new startDate we would update product prices at that date rather than of changing the startdate of the entire campaign. Moving the campaign thus requires us to use the attribute newStartDate
:
What campaigns to run in an organization may be known a long time at HQ, but it may be sensitive to tell the stores too early and risk informing customers and competitors. By setting the visibleStartDate
attribute you decide how long beforehand the stores see the campaign. All users at HQ still see the campaign in their clients and can validate its content.
Similarly, some stores may want access to campaigns after they formally end, to run them a little longer and get rid of excess stock. To keep the campaign visible in Shoppa Client after the campaign ends you set the visibleStopDate
attribute.
A product can have complement products assigned to it specifically in a campaign. You can also assign campaign information to the complement products as you are assigning them. Note that values cannot be set with the value
attribute, they have to be contained by the field
element.
You should also add the attribute complementBehaviour
to the product element. This takes one of three values and determines the way complement products are added and/or removed. The accepted values are replace
, delete
and merge
. They do the following:
Replace: Removes all existing complement products and replaces them with the new ones. This is the default option.
Delete: Removes all existing complement products. Any new complement products will be ignored.
Merge: Adds the new complement products to the set of existing ones.
If a campaign should be removed completely, that can be achieved by setting the delete
attribute in the package
tag. We refer to the campaign by defining the corresponding id
, startDate
, and stopDate
. The xml for this is simply:
If we instead only want to remove a selection of products from the campaign, we set the delete
attribute in the product
tag. The xml for this is simply:
Local prices in combination with central prices requires the use of Shoppa version 2.25 or higher.
Pricelists on a store level overrides central prices only if the store is subscribed to the central pricelist, both pricelists have the same package ID, and the local pricelist does not have the name "STANDARD"
All future price change functionality is applicable for local overridden pricelists as well as central pricelists.
Locally overridden prices for a product will always trumf any centrally price changes for the same product.
Here we have a central pricelist stored on a HQ level.
In one of the stores we have different prices for the products with ID 222222
and 333333
. We will therefore only send the price changes to the local pricelist.
Store1 will now have the local prices in addition to central prices that are not overridden. The other stores will receive all the prices from the Central Pricelist.
If a local price stops being active and we want the central price to be used again, it can be accomplished by deleting the local price from its pricelist.
Here we have deleted the product with ID 222222
from the local pricelist. Store1 will now receive a price for the product from the Central Pricelist. Other local price overrides will still remain.
The Schemas folder contains a file called DisplayGroups.xml that describes the available .
This describes SignOrder schema version 1.1.
A signorder file can reference a number of products, which display groups that should be used to print them, and how many copies should be printed. Additionally you can specify values for the product fields (e.g. price, text1, etc.). Note that these values will not override existing product fields, but will only populate empty fields. The exception to this is the price field, which will override existing prices.
Other notes:
To specify values for code fields (Code1, EAN13, etc.) you need to use the <code>
element, rather than the <field>
element.
To get multiple products onto one template they need to be grouped in a products
element. Which display group to use should then be specified for the products
element, and not the individual product
elements. In this case the product
elements need to have the productIndex
attribute, in order to specify which product index to use in the template(s).
The usageDate
attribute can be used to get prices from future dates. If omitted, todays date will be used.
If the autoPrint
attribute is false, there is no need to specify display groups.
Display groups are managed through the Shoppa client. Each display group can reference multiple layouts and formats of multiple templates, and also a different number of copies for each. The most common use case is one copy of one format/layout/template.
The file DisplayGroups.xml is located in the sub folder Schemas in the hot folder. It is automatically generated by the Shoppa client, and contains information about the available display groups. It could look something like this:
Each group has a name, an Id and at least one member, groups without members are omitted from the file. Each member references a template, a layout, a format and a number of copies.
If the received XML-messages are malformed, or something goes wrong during processing of the message, an error message will be returned by our integration service. This document covers the most common error messages. Unexpected faults might produce unknown exceptions which are not covered by this document.
Error messages are reported in one of two ways: as XML or as plain strings. Problems with file contents are generally reported as XML, while other problems, such as authentication and connectivity issues are reported as strings. Error messages are contained in the <UploadProductXmlResult>
-tag.
Example of XML-reported error; trying to add a product that does not exist to a campaign:
Example of string-reported error; wrong password was used:
The picture at the specified URL could not be retrieved. The reason is stated in the error text. Here are some example error texts:
The picture at '*' could not be retrieved. Reason: The remote server returned an error: (404) Not Found.
The picture at '*' could not be retrieved. Reason: Invalid URI: The format of the URI could not be determined.
The picture at '*' could not be retrieved. Reason: Byte array for GUID must be exactly 16 bytes long.
The picture at '*' could not be retrieved. Reason: Unable to read data from the transport connection: The connection was closed.
The picture at '*' could not be retrieved. Reason: Exception has been thrown by the target of an invocation.
The picture at '*' could not be retrieved. Reason: Lost connection to MySQL server during query
The picture at '*' could not be retrieved. Reason: Lost connection to backend server.
The picture at '*' could not be retrieved. Reason: Content-Disposition and Content-Type is missing and no file extension found in URI.
Recommended actions:
The remote server returned an error: (404) Not Found.: Verify that the URL is working and is reachable by our service.
Lost connection to MySQL server during query: Our service is not responding properly. Wait a few minutes and try again.
Lost connection to backend server.: Our service is not responding properly. Wait a few minutes and try again.
Content-Disposition and Content-Type is missing and no file extension found in URI.: Add missing meta-data to images, or add extensions to the URL.
Example XML excerpt:
Error text: "The supplied picture hashcode (*) does not match any known Mediablob picture"
The hashcode doesn't match any picture in Mediablob.
Recommended action: Make sure the picture is uploaded before trying to assign it to a product.
Example XML excerpt:
Error text: "Product does not exist in Mediablob"
You're trying to include a non-existing product in a campaign or price list.
Recommended action: Make sure the product is created before adding it to campaigns/price lists.
Example XML excerpt:
Error text: "Product does not exist"
You’re trying to delete a product that does not exist, or add a product that does not exist to a product group.
Recommended actions:
Deleting a product: The product is already deleted, or never existed. If possible, revise your integration system to avoid deleting already deleted products.
Adding to product group: Make sure the product is created before adding it to product groups.
Example XML excerpt (campaign/price list):
Example XML excerpt (product group):
Error text: "Product is a duplicate"
The product appears twice in a campaign or price list.
Recommended action: If possible, revise your integration system to avoid sending the same product twice or more in the same context (same campaign, product import, etc.).
Example XML excerpt:
Error text: "Failed to Save the product"
The product could not be saved, probably because of something that happened serverside.
Recommended action: Wait a while and resend your data.
Example XML excerpt:
Error text: "Found 2 products"
When trying to add a product to a product group, two products with the same code were found.
Recommended action: Resolve the conflict, or use a different code to add the product to the product group.
Example XML excerpt:
Error text: "Product has duplicates in the Xml file. The first copy of the product is saved."
The same product appears multiple times in a product import. Only the first appearance of the product is used, the other ones are discarded.
Recommended action: If possible, revise your integration system to avoid sending the same product twice or more in the same context (same campaign, product import, etc.).
Example XML excerpt:
Error text: "The product already belongs to another supplier."
You are trying to modify, or superimpose a value on, a code on a product that does not belong to the customer node you are integrating to. E.g. a store cannot change a code on a product that is owned by their HQ.
Recommended action: If possible, revise your integration system to not attempt to modify codes on lower levels in the customer hierarchy than the product is created on.
Example XML excerpt:
Error text: Found existing product in database using the same product code: CodeType '*', Value '*'. Product codes must be unique.
You are trying to assign a code to a product, but the code is already used on another product in Mediablob.
Recommended action: If possible, revise your integration system to avoid this behaviour.
Example XML excerpt:
Error text: Found duplicate code: CodeType '*', Value '*'. Product codes must be unique.
You are trying to assign the same code to multiple products within the same file.
Recommended action: If possible, revise your integration system to avoid this behaviour.
Example XML excerpt:
Error text: "User is not authenticated."
The authentication provided in the SOAP-object is not valid.
Recommended action: Verify that you are using the correct login information.
Error text: "Either uri or keyword MUST be set on a product picture."
There is a picture tag that lacks 'uri', 'hashCode' and 'md5' attributes. One of them must be present to successfully reference a picture.
Recommended action: If possible, revise your integration system to avoid this behaviour.
Error text: "Object reference not set to an instance of an object."
The imported XML does not contain any information.
Example of imported XML:
Recommended action: If possible, revise your integration system to avoid sending anything if there is no data to send.
Error text: "Failed to save picture '*'. The picture might be corrupt, try uploading the picture again or use another picture."
Something went wrong when uploading one or more pictures. Several instances can be present in the same response.
Recommended action: Try uploading the picture again.
Example:
Error text: "*. Line *, position *."
There is a syntax error in the imported XML. This is typically caused by unescaped special characters: '&', '<' and '>'. See the encoding section for more details.
Recommended action: Make sure you are encoding special characters correctly: once to get them into the import XML and then once again to get them into the SOAP-object.
Example:
Error text: "Guid *"
You have done too many revisions and the version number has gone out of bounds.
Recommended action: Contact Shoppa.
Example:
Error text: "Line: *, Position: * "*""
The imported XML does not match the XML-schema.
Recommended action: Adjust the generation of the XML content according to the given reason.
Example:
Error text: "Deadlock found when trying to get lock; try restarting transaction"
Something went wrong serverside.
Recommended action: Wait a while and resend your data.
Error text: "Connection must be opened."
Something went wrong serverside.
Recommended action: Wait a while and resend your data.
Error text: "Lost connection to MySQL server during query"
Something went wrong serverside.
Recommended action: Wait a while and resend your data.
Error text: "failed to create new session"
Something went wrong serverside.
Recommended action: Wait a while and resend your data.
Error text: "Exception has been thrown by the target of an invocation."
Something went wrong serverside.
Recommended action: Wait a while and resend your data.
Error text: "Lost connection to backend server."
Something went wrong serverside.
Recommended action: Wait a while and resend your data.
Error text: "An exception occured that could not be fully serialized: Exception has been thrown by the target of an invocation."
Something went wrong serverside.
Recommended action: Wait a while and resend your data.