The Is Anchor category setting and category product positions do not play well when combined together. You might think that marrying two simple category settings would result in a simple solution, but think twice before you do so or you might get a headache of Magento proportion! In this post we will attempt to demystify how Is Anchor works and how you can best make use of it.
How does category positioning work?
You probably know that sorting a category by the default "Best Value" criteria uses the Position field of the products in the category to determine its position in the category listing. This is a whole number value which can be set per product in a category to sort the products in ascending numeric order. Setting a higher position value for a product will move it closer to the bottom of the category list, after all products with the default position of 0.
What does Is Anchor actually do?
The Is Anchor display setting for categories allows a category to "inherit" and display all products from its child categories. When Is Anchor is set to "Yes", products assigned to child categories will be combined and displayed in the parent category along with any products directly assigned to it. This means you can use Is Anchor at upper level categories to avoid having to explicitly assign products all the way along a branch of the category tree. Instead, simply assign products to their lowest level (most specific) category and they will then be displayed automatically in parent categories.
This setting is also typically associated with layered navigation, since by default it needs to be set to "Yes" before layered navigation will appear on the frontend for a given category.
Combining Is Anchor and category positions
What is not well documented is the interaction between these two settings in a multi-level category tree. How are products sorted according to their assigned position values in an "anchor" category when there are products in both the parent (anchor) and child categories? Will products directly assigned to the parent category and with a position value set override position values for the same product set at lower categories? What if a product is assigned to two child categories with different position values?
To illustrate what happens, consider the following category tree from our own Magento store:
The categories contain the following products with the corresponding position values:
|Category||Category Level||Category Position||Product||Position|
|Payments / Shipping||2||1||Australia||100|
|Payments / Shipping > Payments||3||1||ANZ eGate||200|
|Payments / Shipping > Shipping||3||2||IFS SmartFreight Shipping||50|
If the sort direction is ascending, we might assume that the products in the "Payments / Shipping" category would be displayed starting with position 50 first, followed by the product with position 100, and then finally the product with the highest position value (200).
Instead, what we actually end up with is:
It turns out that products from a child category are given a position in the parent category based on a weighting applied to their position value from the child category. The exact formula used by Magento is:
(category position + 1) * (category level + 1) * 10,000 + product position in category
This means that products in categories higher up in the category tree will have a much greater weighting than the products in their parent category. So if the products are sorted in ascending position order, products from the parent category would be displayed at the top even if their position values are larger than the position values of products in the child categories.
Furthermore, if a product is in both the parent and child categories, then the smaller of the two calculated position values will be used. This could be confusing if you have a few products which are in multiple categories and they don't appear to be ordered relative to the other products from the same category.
If we apply Magento's position formula to the example above, you can see that the products have different position values than you might have originally expected:
|Product||Original Position in Child||Computed Position in Parent||Displayed Position|
|IFS SmartFreight Shipping||50||120,050||3rd|
Magento's anchor category functionality is extremely useful for managing large catalogs since it avoids repeated category assignment, but you need to keep in mind how it affects the position values of products in case you intend to make use of position sorting. If your primary concern is ensuring that you have precise control over the position of products in categories, then it may be impractical to use Is Anchor and it would probably better to turn it off. However, since layered navigation is normally desirable, it then becomes necessary to modify code so that layered navigation is still shown. Without modification, Magento's core position sort functionality is a tradeoff between explicit control and being able to use layered navigation.