“Filter” your commerce navigation

Within Episerver Commerce you can have a lot of rules for displaying a product to a visitor, e.g. if it’s available for the current market. So it can happen that when you click on a main category or subcategory link there are no products displayed.

To prevent this, as it can be quite annoying for a visitor, I came up with a “trick” to not display the categories when there are no products for the visitor.

These are the steps:

Index the route segments of the main and sub categories for a product using an extension method

public static List MainCategoryRouteSegments(this ProductContent product)
{
	List categorieList = new List();
	IEnumerable categories = product.GetCategories();

	foreach (ContentReference categorySubNode in categories)
	{
		IEnumerable mainCategories = ContentLoader.Value.GetAncestors(contentLink: categorySubNode)
			.OfType();

		categorieList.AddRange(mainCategories.Select(c => c.RouteSegment).ToList());
	}

	return categorieList.Distinct().ToList();
}

public static List SubCategoryRouteSegments(this ProductContent product)
{
	ReadOnlyCollection categories = product.GetCategories().ToContent();
	return categories.Select(c => c.RouteSegment).Distinct().ToList();
}

Query for all products with facets which gives you the route segments of the categories that actually contain products that the visitor can see.

public static List GetMainSegmentsForQuery(this ITypeSearch query) where T : ProductContent
{
	query = query
		.TermsFacetFor(x => x.MainCategoryRouteSegments(), facet => facet.Size = 25)
		.Take(0)
		.StaticallyCacheFor(new TimeSpan(0, 1, 0, 0));

	IContentResult results = query.GetContentResult(3600);

	List segments = results.TermsFacetFor(x => x.MainCategoryRouteSegments()).Terms
		.Where(tc => tc.Count > 0).Select(tc => tc.Term).ToList();

	return segments;
}

public static List GetSubSegmentsForQuery(this ITypeSearch query) where T : ProductContent
{
	query = query
		.TermsFacetFor(x => x.SubCategoryRouteSegments(), facet => facet.Size = 25)
		.Take(0)
		.StaticallyCacheFor(new TimeSpan(0, 1, 0, 0));

	IContentResult results = query.GetContentResult(3600);

	List segments = results.TermsFacetFor(x => x.SubCategoryRouteSegments()).Terms
		.Where(tc => tc.Count > 0).Select(tc => tc.Term).ToList();

	return segments;
}

When you have those you can filter out the menu items that have no products underneath.

You could argue to just use “Episerver Search & Navigation” to get main navigation items, but I prefer not to because you might end up with no navigation if there is a hiccup in the service.

The full code sample is in a Gist

Leave a comment