How to regenerate the sitemap media item in an XM Cloud (Sitecore Headless SXA) site without publishing

Image
Computer open with code showing on the screen

The Problem

During local development I was trying to view the /sitemap.xml from the rendering host but was receiving an empty response. I found the current sitemap XML in the Media Library (/sitecore/media library/Project/<project_name>/<project_name>/Sitemaps/<app_name>/sitemap) and it is empty. I have pages on my site, but they're not in this sitemap.xml file in the media library.

A few things to note:

  • We're on Sitecore 10.3 and JSS 21 (Sitecore License Details says Sitecore XMCloud 1.5.62 (rev. 0)).
  • I cannot yet publish to Experience Edge, so if the generation requires publishing (as mentioned in this article), that won't work for me.
  • I tried deleting the file, but it was not automatically regenerating.
  • When I hit the /sitemap.xml path on the CM, it generates and loads properly in the browser, but no media item is created.
  • I have configured the <site>/Settings/Site Grouping/<site_name> item to have a target host name and host name and set the scheme to https.

     

The Solution

Okay, so how do we get the sitemap regenerated so that it contains the current pages in my site? It's actually quite simple once you know how to do it:

You can regenerate it by changing and saving (and then changing back/saving again) either of the below fields on the site definition item (/sitecore/content/<tenant>/<site>/Settings/Site Grouping/<site_definition>):

  • Site name
  • Start item

     

For the curious

I discovered this by reviewing /sitecore/admin/showconfig.aspx and searching for "sitemap." I found the below handler under the item:saved event:

<handler type="Sitecore.XA.JSS.Foundation.SiteMetadata.EventHandlers.SitemapMediaHandler, Sitecore.XA.JSS.Foundation.SiteMetadata" method="OnItemSaved" patch:source="Sitecore.XA.JSS.Foundation.SiteMetadata.config"/>

Decompiling it, I found those two fields are inspected for changes and then a job is run to generate the media library item:

protected void OnItemSaved(object sender, EventArgs args)
{
    Assert.ArgumentNotNull(sender, "sender");
    Assert.ArgumentNotNull(args, "args");
    if (!JobsHelper.IsPublishing() && Event.ExtractParameter(args, 0) is Item item && item.InheritsFrom(Sitecore.XA.JSS.Foundation.Multisite.Templates.JSSSiteDefinition.ID) && Event.ExtractParameter(args, 1) is ItemChanges itemChanges && (itemChanges.FieldChanges.Contains(Sitecore.XA.Foundation.Multisite.Templates._BaseSiteDefinition.Fields.SiteName) || itemChanges.FieldChanges.Contains(Sitecore.XA.Foundation.Multisite.Templates._BaseSiteDefinition.Fields.StartItem)))
    {
        string change = itemChanges.FieldChanges[Sitecore.XA.Foundation.Multisite.Templates._BaseSiteDefinition.Fields.SiteName]?.Value ?? item[Sitecore.XA.Foundation.Multisite.Templates._BaseSiteDefinition.Fields.SiteName];
        SiteInfo siteInfo = SiteInfoResolver.Sites.FirstOrDefault((SiteInfo s) => s.Name.Equals(change.Trim(), StringComparison.OrdinalIgnoreCase));
        if (siteInfo != null)
        {
            JobManager.Start(new DefaultJobOptions("SitemapMediaHandler", "SXA", "scheduler", this, "InitSitemapMediaJob", new object[1] { siteInfo })
            {
                CustomData = item.Database
            });
        }
    }
}