Add Bazaarvoice hierarchical category export
Map hierarchical categories in your Bazaarvoice export in Productsup.
By default, the Bazaarvoice export sends a flat category list, where each product points to a single category and nothing describes how those categories relate to each other. If your catalog has a category tree, you can map a set of additional attributes in Dataflow so that the export sends the full hierarchy to Bazaarvoice. This page covers only those additional attributes. For the rest of the setup, including the destination configuration, see Add Bazaarvoice export.
Flat and hierarchical categories
In a flat export, Bazaarvoice receives your categories as unrelated entries:
<Categories>
<Category><ExternalId>galaxy-s</ExternalId><Name>Galaxy S</Name></Category>
<Category><ExternalId>iphone</ExternalId><Name>iPhone</Name></Category>
</Categories>A hierarchical export adds a ParentExternalId element to each category, so that Bazaarvoice receives a tree:
<Categories>
<Category><ExternalId>electronics</ExternalId><Name>Electronics</Name></Category>
<Category><ExternalId>phones</ExternalId><ParentExternalId>electronics</ParentExternalId><Name>Phones</Name></Category>
<Category><ExternalId>galaxy-s</ExternalId><ParentExternalId>phones</ParentExternalId><Name>Galaxy S</Name></Category>
</Categories>A category tree lets Bazaarvoice show breadcrumbs on review pages, roll up reviews from a subcategory to its parent, and build category-level review pages and widgets.
The products themselves do not change. Each product still points to one category through the CategoryExternalId attribute.
Bazaarvoice requires parent categories to appear before their subcategories in the feed. The platform orders the category section for you, so the order of the records in your feed does not matter.
Attributes to map
Keep every attribute you already map, and add one group of attributes for each level of your category tree. Replace {N} with the level number, starting at 1 for the top level of the tree:
| Attribute | Required | Bazaarvoice XML element |
|---|---|---|
| CategoryLevel{N}Id | Yes | ExternalId |
| CategoryLevel{N}Name | Recommended | Name |
| CategoryLevel{N}Url | No | CategoryPageUrl |
| CategoryLevel{N}ImageUrl | No | ImageUrl |
| CategoryLevel{N}ParentId | Yes from level 2 onward | ParentExternalId |
There is no CategoryLevel1ParentId attribute, because level 1 is the top of the tree.
The platform reads the levels in order, starting at level 1 and continuing for as long as it finds the next level, up to a maximum of 10 levels. A gap in the numbering stops the platform from reading the remaining levels.
The destination has no setting for hierarchical categories. The platform recognizes these attributes by name and uses them on the next site run.
How the platform maps the attributes
The numbered attributes hold the ancestors of a category. The CategoryExternalId attribute holds the category that the product itself belongs to.
Read a category path as a breadcrumb trail. Everything before the last element of the path goes into the numbered attributes, and the last element stays in the CategoryExternalId attribute you already map:
Electronics > Phones > Samsung > Galaxy S
-------- numbered levels 1-3 -------- - leaf -
CategoryExternalIdThe CategoryName, CategoryPageUrl, and CategoryImageUrl attributes continue to describe the category in CategoryExternalId.
The platform uses the CategoryParentExternalId attribute only on records that leave all numbered attributes empty. When a record fills the numbered attributes, the deepest level you populate becomes the parent of the category in CategoryExternalId.
The platform writes all category IDs in lower case, in the ExternalId, ParentExternalId, and CategoryExternalId elements alike, so your product references continue to resolve.
Mapping examples
The following examples abbreviate the attribute names to keep the tables readable. For example, L1Id stands for CategoryLevel1Id, and L2ParentId stands for CategoryLevel2ParentId. Use the full attribute names in Dataflow.
Map a three-level category tree
| CategoryExternalId | CategoryName | L1Id | L1Name | L2Id | L2Name | L2ParentId |
|---|---|---|---|---|---|---|
GALAXY-S | Galaxy S | ELECTRONICS | Electronics | PHONES | Phones | ELECTRONICS |
IPHONE | iPhone | ELECTRONICS | Electronics | PHONES | Phones | ELECTRONICS |
COFFEE | Coffee Makers | HOME | Home | KITCHEN | Kitchen | HOME |
Both phone records repeat the same ancestry, which is expected. The platform still writes each category only once:
<Categories>
<Category><ExternalId>electronics</ExternalId><Name>Electronics</Name></Category>
<Category><ExternalId>home</ExternalId><Name>Home</Name></Category>
<Category><ExternalId>kitchen</ExternalId><ParentExternalId>home</ParentExternalId><Name>Kitchen</Name></Category>
<Category><ExternalId>phones</ExternalId><ParentExternalId>electronics</ParentExternalId><Name>Phones</Name></Category>
<Category><ExternalId>coffee</ExternalId><ParentExternalId>kitchen</ParentExternalId><Name>Coffee Makers</Name></Category>
<Category><ExternalId>galaxy-s</ExternalId><ParentExternalId>phones</ParentExternalId><Name>Galaxy S</Name></Category>
<Category><ExternalId>iphone</ExternalId><ParentExternalId>phones</ParentExternalId><Name>iPhone</Name></Category>
</Categories>The platform groups the categories by level instead of following the order of your records, which is what keeps every parent ahead of its subcategories.
Map products at different depths
Products do not need to sit at the same depth in the tree. Populate only the levels that each record needs and leave the remaining levels empty:
| Product | CategoryExternalId | L1Id | L2Id | L2ParentId | L3Id | L3ParentId |
|---|---|---|---|---|---|---|
| Galaxy S25 | GALAXY-S | ELECTRONICS | PHONES | ELECTRONICS | SAMSUNG | PHONES |
| Xiaomi 14 | XIAOMI | ELECTRONICS | PHONES | ELECTRONICS | ||
| USB cable | CABLES | ELECTRONICS |
This mapping places galaxy-s under samsung, xiaomi under phones, and cables directly under electronics.
Map a product to a category that is also a parent
A product can belong to a category in the middle of the tree. Map that category to CategoryExternalId and its ancestors to the numbered attributes:
| Product | CategoryExternalId | L1Id | L2Id | L2Name | L2ParentId |
|---|---|---|---|---|---|
| Galaxy S25 | GALAXY-S | ELECTRONICS | PHONES | Phones | ELECTRONICS |
| Phone gift card | PHONES | ELECTRONICS |
The platform declares phones once, in its position under electronics, and both products resolve to it. Its name and URL come from the CategoryLevel2Name and CategoryLevel2Url attributes. For a category that is both a parent and a product's own category, populate the numbered attributes rather than only the CategoryName and CategoryPageUrl attributes.
Combine flat and hierarchical categories
You do not need to convert your whole feed at once. When a record leaves all numbered attributes empty, that record stays flat, and both shapes can appear in the same feed:
| Product | CategoryExternalId | CategoryParentExternalId | L1Id | L2Id | L2ParentId |
|---|---|---|---|---|---|
| Galaxy S25 | GALAXY-S | ELECTRONICS | PHONES | ELECTRONICS | |
| Extended warranty | SERVICES | ||||
| Damage insurance | INSURANCE | SERVICES |
This mapping gives galaxy-s its tree, makes services a category without a parent, and places insurance under services through the CategoryParentExternalId attribute.
On a record that populates the numbered attributes, the platform ignores the CategoryParentExternalId attribute and uses the deepest populated level instead. Use one or the other on each record, not both.
Add hierarchical categories to an existing flat mapping
If your Dataflow already produces a flat category mapping such as the following:
| CategoryExternalId | CategoryName | CategoryPageUrl |
|---|---|---|
GALAXY-S | Galaxy S | https://shop.example.com/c/galaxy-s |
Keep all of these attributes as they are and map the ancestors alongside them:
| CategoryExternalId | CategoryName | CategoryPageUrl | L1Id | L1Name | L2Id | L2Name | L2ParentId |
|---|---|---|---|---|---|---|---|
GALAXY-S | Galaxy S | https://shop.example.com/c/galaxy-s | ELECTRONICS | Electronics | PHONES | Phones | ELECTRONICS |
No existing attribute changes its meaning, and no product reference breaks.
Check your mapping
After a site run, the run log names the category source and the number of categories the platform added:
INFO: Category source: CategoryExternalId leaves + numbered ancestors (CategoryLevel1Id..CategoryLevel3Id)
INFO: Categories added: 17 | took: 0.01sIf the log still reports flat (CategoryExternalId), the CategoryLevel1Id attribute does not reach the export. Check the attribute name and its mapping in Dataflow.
The platform can also report the following warnings. Neither warning stops the site run:
| Warning | Meaning |
|---|---|
… parent id(s) are referenced but never declared … | A CategoryLevel{N}ParentId attribute points to an ID that no record declares, usually because of a gap in the category path or a typo |
… set CategoryParentExternalId to something other than their deepest CategoryLevel*Id … | A record populates both parent attributes, and the platform used the numbered level |
Common mapping mistakes
| Mistake | Result |
|---|---|
| Skipping a level, such as populating level 1 and level 3 but leaving level 2 empty | The platform never declares the parent of the level 3 category, which produces a warning and causes Bazaarvoice to reject the category |
| Mapping CategoryLevel{N}ParentId to a value other than the CategoryLevel{N-1}Id of the same record | The tree reaches Bazaarvoice with the wrong shape |
| Repeating the value of CategoryExternalId as the deepest numbered level under a different ID | The tree gains one redundant level |
| Using the same ID at two levels | The platform declares the category once, at the shallower level, with the name of that level |
| Using different names for the same ID across records | The platform uses the name from the first record it reads |
If you map the Category file URL field in the destination, the external category file replaces the category section of the feed entirely, and the platform ignores these attributes. See Add Bazaarvoice export for more information.
How is this guide?