Control SXA Page Designs via Query String by Derek Hunziker

I am once again compelled to write about customizing Sitecore Experience Accelerator (SXA). While the feature I’m about to show you can be quite useful, what’s more interesting to me, is the way that the developers of SXA have anticipated customization and built almost every piece of it to be extensible. So with that in mind, let’s dive right in!

With SXA, you can easily adjust the look & feel of a web page by setting it’s “Page Design”. A page design is essentially a collection of partial designs which represent the reusable parts of your website. For example, you may have one “Main” Page Design that includes everything, such as a logo, navigation, header, footer, social links, etc., and you may also have a “Minimal” Page Design with just your company logo and a simplified footer. Switching between the Page Designs is as simple as selecting which one you want. This is done on the page item, like so:

“Set it and forget it”

“Set it and forget it”

Yet, with the Page Design being set within a field on the page item, we’re limited in terms of Personalization or dynamically altering the page design at runtime. Wouldn’t it be cool to change the page design on-the-fly, say, via query string? This would allow us, for example, to serve up a single page to different audiences with a completely different look & feel:

design.png

My colleague Filip Traikov and I set out to investigate whether something like this this would be possible in SXA. What we found was very encouraging. As it turns out, the Page Design is set within SXA’s “IPresentationContext”, and like many other parts of SXA, the default implementation is registered in Sitecore’s Dependency Injection configuration section. We can therefore patch in our own implementation rather cleanly:

<configuration>
  <sitecore>
    <services>
      <register serviceType="Sitecore.XA.Foundation.Presentation.IPresentationContext, Sitecore.XA.Foundation.Presentation" implementationType="Sitecore.XA.Foundation.Presentation.PresentationContext, Sitecore.XA.Foundation.Presentation" lifetime="Singleton">
        <patch:attribute name="implementationType">Example.Foundation.SitecoreExtensions.Presentation.PresentationContext, Example.Foundation.SitecoreExtensions</patch:attribute>
      </register>
    </services>
  </sitecore>
</configuration>

Next came the implementation itself, which was handled by Filip. It was as simple as inheriting the default SXA PresentationContext and overriding a single method:


public class QueryStringBasedPresentationContext : PresentationContext
{
  protected override Item DoGetPageDesignItem(Item item, Item pageDesignsItem)
  {
    string pageDesignQueryParam = Sitecore.Context.HttpContext.Request.QueryString.Get("design");

    if (!string.IsNullOrWhiteSpace(pageDesignQueryParam))
    {
      Item selectedPageDesign = pageDesignsItem
        ?.Children
        ?.SingleOrDefault(c => c.Name.Equals(pageDesignQueryParam, StringComparison.OrdinalIgnoreCase));

      if (selectedPageDesign != null)
      {
        return selectedPageDesign;
      }
    }

    return base.DoGetPageDesignItem(item, pageDesignsItem);
  }
}

What I find most interesting about this code is the careful attention to detail by the SXA team. If you look closely at the DoGetPageDesignItem() method, you’ll notice that it takes two parameters:

  • item = The Context/Page Item you’re rendering, and…

  • pageDesignsItem = The site relative folder containing all of your page designs, typically located at: /sitecore/content/Tenant/YourSite/Presentation/Page Designs

This second parameter shows me that the SXA team was really thinking ahead as to how this method would be extended. By passing in the root item of the Page Designs collection, the SXA developers have saved us from having to produce a site-relative query ourselves, letting us focus on what matters most - business logic!

Happy extending!