Wednesday, September 30, 2020

Sharing settings in a multisite SXA setup

Settings in a shared site - multisite Sitecore SXA

As you might know if you read my previous blogs, I'm working on a setup with an undefined number of (mini-)sites within a tenant that should share as much as possible in order to make the setup of a new site as simple and fast as possible. We already managed to share a lot: placeholder settings, 404 settings and of course the out of the box stuff like page and partial designs, rendering variants and so on.

We have a setup that matches the best practices with a shared site and a master site to clone from. 

This is the 5th part already in the blog series that results from that project, and this time we'll take a look at the Settings item in each SXA site. There are some candidates that we could share - the error handling section was taken care of in a previous post but I'll go over some other ones here.
Let's work bottom up..

Robots

It would be possible to share the robots settings which generates the robots.txt content for the site. There is a pipeline called getRobotsContent where we can plugin an extra processor if needed. This pipeline has ootb 3 processors.
The first one -GetContentFromSettings- will get the content from the Settings item of the current site. The second one is a backup and will fetch a physical robots.txt file if no content was provided (note that this could be useful in some cases to use this fallback functionality). The last one will add the sitemap information. 

We could insert our own version of the GetContentFromSettings in the 2nd spot where we get the contents from the shared site if we have no local content yet. That would be fairly easy to do.. but as you might notice it's all conditional here (could/would/...). Indeed, we actually decided not to do this.

We have a robots.txt file as fallback for the whole environment. Also, we want our shared (and master) site to stay closed for all robots - ok, they shouldn't be able to access them anyway but still...  So, all things considered we've put robots content in the master site that disallows all robots to make sure a new site does not gets opened until the site admin actually wants it to open. Still, it was interesting to see how the robots feature in SXA works.

Favicon

The favicon for your site can be managed in the Settings item of each site. You can select an item from the media library and it will be set as the favicon in that site by the Favicon rendering which is usually present in the metadata partial design.

Most of our sites will use the same favicon however. So we would like to share it - and there are a few ways of doing that. We could select the favicon in the master site and all newly created sites would use that favicon as they copy that value. It could be overwritten if needed so that is a valid option. It is an ootb option as well. The only disadvantage is that if the icon has to be changed (we usually do create a new item in that case so we don't have caching issues) we would need to change it on all sites.

Another option to explore was a fallback to the shared site where we could define the favicon just once. It appeared to be rather easy - this is the code we need:
public class FaviconRepository : Sitecore.XA.Feature.SiteMetadata.Repositories.Favicon.FaviconRepository, IFaviconRepository
{
  public override string GetFaviconHref(Item contextItem)
  {
    var icon = base.GetFaviconHref(contextItem);
    if (!string.IsNullOrEmpty(icon))
    {
      return icon;
    }

    var field = GetSharedSettingsItem(contextItem)?.Fields[Sitecore.XA.Feature.SiteMetadata.Templates._Favicon.Fields.Favicon];
    return field != null ? field.GetImageUrl() : string.Empty;
  }

  private static Item GetSharedSettingsItem(Item contextItem)
  {
    var shared = ServiceLocator.ServiceProvider.GetService<ISharedSitesContext>().GetSharedSitesWithoutCurrent(contextItem).FirstOrDefault();
    return shared != null ? ServiceLocator.ServiceProvider.GetService<IMultisiteContext>().GetSettingsItem(shared) : null;
  }
}
We override the FaviconRepository which is used in the Favicon rendering. The new GetFaviconHref function first calls the base version to check if anything was filled on the current site. If that is not the case we locate the Settings item for the (first - we know we have no more than one) shared site. On that Settings item we read the Favicon field and return the image url (or nothing). 

Registering this version in the dependency injection will make sure this is used and that's all there is to it. 


Conclusion

A smaller post this time.. but all small things will bring us to what we want (a site in 15 minutes). 

Don't worry though, as there will be a part 6 as well in which I'll cover locally overwriting some datasources set in the partial designs from the shared site. 

No comments:

Post a Comment