For an internal project at Sitecore, we wanted to make it as easy as possible for users to create a SXA site using modules. For example, if they wanted pages and page designs for blog posts, they would select the “Blog” module.

I discovered that having a truly automated module is more difficult than it seems. Fortunately, I was able to address many of these issues through Powershell scripts. In this post, I will walk you through creating an example Blog module. I assume basic knowledge of Sitecore Experience Accelerator (SXA) and SXA modules.

First, I created templates for a Blog Landing Page and Blog Page. These would be mapped to corresponding Page Designs. The Page Design for Blog Landing Page contains a Search Results rendering, and the Blog Page a Page Content rendering. The rendering variants and partial designs for these lived within a Global shared site, whereas the page designs were on the local site.

If all the partial designs live in the Global site, this presents a unique challenge for the Search Results rendering. How do we define the search scope? We can’t use the location query to restrict the search to a specific parent item’s children, as in a branch that path doesn’t exist yet. Fortunately, there is another query to address this: “sxa:UnderCurrentPage”. This will ensure the search is restricted to the children on the item the Search Results rendering lives on. We can also specify a template to restrict the search- in this case, the Blog Page. This can all go on a search scope under the Global site instead of locally. Now no need to add it to a branch on our module.

We also had another issue- we wanted the user to be able to easily edit the Header and Footer. That meant they couldn’t live on the Global site. More on how I solved that problem later.

To initially create the module for Blog, I navigated to /sitecore/system/Settings/Feature and inserted a Module. Under system areas, I only checked off Settings and Branches.

I found the Branch for my new module under /sitecore/templates/Branches. Here I inserted two items: Blog Pages and Blog Page Designs. Blog Pages held the pages that would go under the Home item. Blog Page Designs contained Page Designs.

Here, we see another problem: there is nothing under Partial Designs, because this Page Design does not live under a site. To address this, I had to view the raw value for Partial Designs. I copied in the Partial Design GUIDs from the Global Partial Designs for Blog.

We are left with two problems: 1) How to insert the header and footer and 2) How to map the page designs to the Page Designs item. The second may seem like an easy post-step for the user. However, this quickly becomes a hindrance the more Page Designs you create.

In a separate module, I built out the header and footer partials. For every module, I then added a Powershell script to add this header and footer to all the page designs.

Import-Function Get-SiteItem

$SiteItem = Get-SiteItem $Site

$header = Get-Item -Path “master://$($SiteItem.Paths.Path)/Presentation/Partial Designs/Header”

$metadata = Get-Item -Path “master://$($SiteItem.Paths.Path)/Presentation/Partial Designs/Metadata”

$footer = Get-Item -Path “master://$($SiteItem.Paths.Path)/Presentation/Partial Designs/Footer”

$pageDesigns = Get-Item -Path “master://$($SiteItem.Paths.Path)/Presentation/Page Designs”

$items = $pageDesigns.Children

foreach ($item in $items) {

        $item.Locking.Unlock()

        $item.Editing.BeginEdit()

        if(!$item.Fields[‘PartialDesigns’].Value.Contains($header.ID)) {

                  $item.Fields[‘PartialDesigns’].Value =  “$($item.Fields[‘PartialDesigns’].Value)|$($header.ID)|$($metadata.ID)|$($footer.ID)”

     }

        $item.Editing.EndEdit()

}

Mapping the page designs took another Powershell script, which required slight variations to each module. I added this as a “Post Setup Step”.

Import-Function Get-SiteItem

$SiteItem = Get-SiteItem $Site

$value = “”

$blogPageID = “{9E655297-B109-4673-ACB8-D661C9007736}”

$blogLandingPageID = “{066C976E-5E05-46DB-BC09-AC8008B5C776}”

$blogPageDesign = Get-Item -Path “master://$($SiteItem.Paths.Path)/Presentation/Page Designs/Blog Page”

$blogPageDesignID = [System.Web.HttpUtility]::UrlEncode($blogPageDesign.ID)

$blogLandingPageDesign = Get-Item -Path “master://$($SiteItem.Paths.Path)/Presentation/Page Designs/Blog Landing Page”

$blogLandingPageDesignID = [System.Web.HttpUtility]::UrlEncode($blogLandingPageDesign.ID)

$value = “$value&$blogPageID=$blogPageDesignID”

$value = “$value&$blogLandingPageID=$blogLandingPageDesignID”

#get Page Designs Item

$pageDesigns = Get-Item -Path “master://$($SiteItem.Paths.Path)/Presentation/Page Designs”

#set templates to design mapping

$pageDesigns.Locking.Unlock()

$pageDesigns.Editing.BeginEdit()

$pageDesigns.Fields[‘TemplatesMapping’].Value = $pageDesigns.Fields[‘TemplatesMapping’].Value + [System.Web.HttpUtility]::UrlEncode($value)

$pageDesigns.Editing.EndEdit()

With these steps, you should now have a module that on site creation, instantaneously sets up everything needed for a site to have a Blog Landing Page with Blog Pages.

Shout out to Mark Van Alst in Technical Marketing and Alan Plocieniak on the SXA team for steering me in the right direction!

How to Build a SXA Module for a Search Listing Feature

Leave a Reply

Your email address will not be published.