Dynamic Product Detail Pages. Part 1 – Page Editor

Scenario

Your Sitecore site needs to display product detail pages. Maybe it’s retail, maybe it’s e-commerece, maybe it’s a catalogue with (or without) online sample orders, maybe it’s an inventory listing with inquiry forms, maybe it’s something else. The detail pages may have same look and feel for all products, may vary per category or type, may have customizations or unique content for some products. The products data does not originate in Sitecore, it is not being managed there either, and the data set isn’t small. Pretty common set of requirements.

Last but not least, you want to be able to edit your product detail page(s) look and feel in Page Editor – you design to components, you build to components, you understand that your marketing/content team needs flexibility and a certain level of autonomy. You want to compose your product detail page out of a number of components each one focusing on a specific part of the product info or user interaction. The marketing/content team can then individually personalize and A/B test these building blocks as well as insert arbitrary content.

You may want to consider e-commerce solutions for Sitecore (e.g. Active Commerce) if your implementation is a full cycle online commerce or even if it’s half of that. This series of blog posts is about an interesting technique to do a very small part of what those products are capable of.

Options

First, we need product data accessible to your Sitecore site. There are various techniques that can get you there and the right way is always context-specific:

  • You can ingest your data as items
  • You can data provide your data and make Sitecore think it has it as items
  • You can build a data access layer to access your products data directly or via services
  • You can crawl your data into an index and use search API
  • You can use [your favorite integration technique]

What matters for this blog post is whether you create a page item for each product. If you do, making it Page Editor editable is “easy” – just treat it as any other page in your site and don’t forget that you can define presentation on the standard values and even open that special item in Page Editor. You can also use a combination of a custom link provider and item resolver to give your products nice SEO-friendly attributes-driven URLs. If you don’t (maybe your dataset is too large, maybe it changes too frequently, maybe your data just doesn’t fit the page model), you need to think outside the box.

Dynamic Page

We start by defining a route.

routes.MapRoute("ProductDetailPage", "products/{category}/{product}", new
{
    controller = "ProductDetailPage",
    action = "Display"
});

Then we build a controller:

public class ProductDetailPageController : DynamicPageController
{
    public ActionResult Display(string category, string product)
    {
        Assert.IsNotNullOrEmpty(series, "series");
        Assert.IsNotNullOrEmpty(product, "product");

        var product; // Use a service to find the product (more in Part 2)
        var page; // Find the template to use (see below and more in Part 2)

        return RenderDynamicPage(page, product);
    }

Then we create a special page item that will be used as a template for all product detail pages. If your product detail pages vary per category, for example, you can have more than one template. This is almost your regular content page except it won’t be navigated to directly. You may as well create it outside your site content hierarchy, somewhere where you store site shared content, for example. This page item can be edited in Page Editor like any other page. I will look into how to componentize it and how to expose product data to all components on that page in Part 2 of this series.

Then we think outside the box and implement the DynamicPageController (the code is simplified):

public abstract class DynamicPageController : Controller
{
    protected virtual ActionResult RenderDynamicPage<T>(Item page, T product)
    {
        // stage MVC page context to point to the "template" item
        var pageContext = new PageContext
        {
            RequestContext = Request.RequestContext,
            Item = page,
        };
        
        ContextService.Get().Push(pageContext);

        // make product data accessible to all components that need it (more in Part 2)
        this.ShareProductData(product);

        // same technique as used by SitecoreController to kick off rendering engine
        return View(pageContext.PageView);
    }
}

I used a generic syntax to allow myself some room in Part 2 of this series to look at product data as objects and product data as items. The rest should be self explanatory.

Coming Up

We have got a functional prototype of a dynamic product detail page. Without an actual page item to represent a product we defined a route and will have to use @Url.RouteUrl() to render links, can’t really use the LinkManager. The route is serviced by a controller that is capable of executing all proper rendering pipelines for a product detail template page. This is a good start but is only the beginning. We now need to:

  • Fetch the products data and support componentization of the template page (coming up in Part 2)
  • Ensure our dynamic product detail pages can host WFFM forms (coming up in Part 3)
  • Think about SEO, performance / caching, and marketing automation / analytics (coming up in Part 4)

Check back soon!

Pavel Veller

Add a Comment

Your email address will not be published. Required fields are marked *

Or request call back