Technical Insights: Azure, .NET, Dynamics 365 & EV Charging Architecture

Category: Sitecore

How to Generate Sitemap XML in Sitecore Using PowerShell

If you manage a multi-site Sitecore environment, you’ve probably encountered the need to create sitemap.xml files for search engines like Google and Bing. While you can build this with C# code or third-party modules, an easier, zero-deployment approach is to use the Sitecore PowerShell Extensions (SPE) module.

In this guide, you’ll learn how to generate a Sitemap XML for multiple websites directly from the Sitecore admin interface using PowerShell. This approach is ideal for teams that do not have access to deploy code to content delivery (CD) servers or for situations where the original source code is missing.

Why Generate Sitemap XML Using PowerShell

Using Sitecore PowerShell to generate sitemap files provides several advantages:

  • No code deployment required; everything runs in the Content Management (CM) environment.
  • Supports multiple sites within one instance (multi-tenant setup).
  • Full control over URL structure, output path, and file naming.
  • Quick and repeatable; can be run on-demand or scheduled.
  • Produces search engine-friendly XML that complies with sitemaps.org.

PrerequisitesBefore running the script, ensure the following:

  1. Sitecore PowerShell Extensions (SPE) is installed.
  2. You can access PowerShell ISE within the Sitecore admin area (/sitecore/shell/Applications/PowerShell/PowerShellIse).
  3. The IIS App Pool user has write permissions to the folder where the sitemap XML will be saved.

The PowerShell Script

Below is the complete script that generates a combined sitemap.xml for multiple sites in your Sitecore instance.

# =======================================
# Sitecore Unified Sitemap Generator
# Combines multiple sites into one sitemap.xml
# =======================================

# Define all site configurations
$sites = @(
    @{
        RootPath = "master:/sitecore/content/sample-website/Home"
        Domain   = "https://www.sample-website.com"
    },
    @{
        RootPath = "master:/sitecore/content/another-site/Home"
        Domain   = "https://www.another-site.com"
    }
)

# Output path for the combined sitemap
$outputPath = "D:\WebApplications\sitecore\sitemap_combined.xml"

# Configure LinkManager options
$linkOptions = New-Object Sitecore.Links.UrlOptions
$linkOptions.AlwaysIncludeServerUrl = $false
$linkOptions.AddAspxExtension = $false
$linkOptions.LanguageEmbedding = "Never"

Write-Host "Starting unified sitemap generation..."

# Initialize XML document
$sitemap = New-Object System.Xml.XmlDocument
$urlset = $sitemap.CreateElement("urlset")
$urlset.SetAttribute("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9")
$sitemap.AppendChild($urlset) | Out-Null

# Function to traverse and append items
function Add-ItemToSitemap($item, $domain) {
    if ($item -ne $null -and $item.TemplateName -ne "Folder" -and $item.Fields["__Renderings"]) {

        # Generate relative URL
        $relativeUrl = [Sitecore.Links.LinkManager]::GetItemUrl($item, $linkOptions)

        # Strip CM hostname if present
        if ($relativeUrl -match "https?://[^/]+(/.*)") {
            $relativeUrl = $Matches[1]
        }

        # Build full CD URL
        if ($relativeUrl.StartsWith("/")) {
            $fullUrl = "$domain$relativeUrl"
        } else {
            $fullUrl = "$domain/$relativeUrl"
        }

        # Build <url> element
        $urlElement = $sitemap.CreateElement("url")

        $loc = $sitemap.CreateElement("loc")
        $loc.InnerText = $fullUrl
        $urlElement.AppendChild($loc) | Out-Null

        $lastmod = $sitemap.CreateElement("lastmod")
        $lastmod.InnerText = $item.Statistics.Updated.ToString("yyyy-MM-dd")
        $urlElement.AppendChild($lastmod) | Out-Null

        $urlset.AppendChild($urlElement) | Out-Null
    }

    foreach ($child in $item.Children) {
        Add-ItemToSitemap $child $domain
    }
}

# Iterate over each site and add its URLs
foreach ($site in $sites) {
    Write-Host "`n--------------------------------------------"
    Write-Host "Processing site: $($site.Domain)"
    Write-Host "Root path: $($site.RootPath)"
    Write-Host "--------------------------------------------`n"

    $rootItem = Get-Item -Path $site.RootPath
    if ($null -eq $rootItem) {
        Write-Error "Root item not found: $($site.RootPath)"
        continue
    }

    Add-ItemToSitemap $rootItem $site.Domain
}

# Save combined sitemap
$sitemap.Save($outputPath)

Write-Host "`nUnified sitemap generated successfully."
Write-Host "Output path: $outputPath"

How the Script Works

1. Site Configuration

The $sites array defines multiple websites (root paths and their public domains). You can add as many entries as your Sitecore instance hosts.

$sites = @(
    @{ RootPath = "master:/sitecore/content/sample-website/Home"; Domain = "https://www.sample-website.com" }
)

2. LinkManager Options

The script configures Sitecore’s LinkManager to generate clean, relative URLs without .aspx extensions or CM hostnames.

3. Recursive Traversal

The function Add-ItemToSitemap recursively loops through all Sitecore items under each root path and includes items that have renderings (actual pages).

4. URL Normalization

The script ensures that all URLs point to the content delivery (CD) domain, not the internal CM hostname, even though the script is executed in the CM environment.

5. XML Output

All URLs from all configured sites are merged into a single XML structure under <urlset> and saved to the defined $outputPath.

Example Output

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://www.sample-website.com/about-us</loc>
    <lastmod>2025-11-06</lastmod>
  </url>
  <url>
    <loc>https://www.another-site.com/blog/latest-article</loc>
    <lastmod>2025-11-06</lastmod>
  </url>
</urlset>

This sitemap can be submitted directly to Google Search Console, Bing Webmaster Tools, or any search crawler for indexing.

Summary

This PowerShell-based sitemap generator provides a simple, flexible, and deployment-free solution for Sitecore developers and administrators. It can be easily adapted for:

  • Single or multi-site Sitecore instances
  • Multilingual site structures
  • Automated nightly tasks using Sitecore’s Task Scheduler

By using this approach, you can maintain full control over how search engines crawl your websites without requiring code changes or deployments.

Resolving the “Certificate Chain Was Issued by an Authority That Is Not Trusted” Error During Sitecore Installation on Windows 11

When installing Sitecore on Windows 11, you might encounter the following error:

A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 - The certificate chain was issued by an authority that is not trusted.)

This issue arises due to a recent security enforcement rolled out by Microsoft. Windows 11 now requires SQL Server connections to use encrypted connections by default. Some of the PowerShell scripts used during the Sitecore installation process are not configured to handle this change, resulting in the above error.

In this blog post, we’ll dive into the root cause of the issue and walk you through the steps to resolve it.


Understanding the Root Cause

The error is triggered because the PowerShell scripts used in the Sitecore installation attempt to connect to the SQL Server without explicitly trusting the server’s SSL certificate. With the new security enforcement, connections to the SQL Server default to encryption, but without a trusted certificate, the connection fails.

This is particularly relevant when using self-signed certificates or development environments where the SQL Server’s certificate authority is not inherently trusted.

How to Fix the Error

The solution is to explicitly configure the Sitecore installation scripts to trust the SQL Server’s certificate by setting the TrustServerCertificate variable to true. This needs to be done in two specific JSON files used during the installation process:

  1. sitecore-xp0.json
  2. xconnect-xp0.json

Steps to Resolve

  1. Locate the JSON Files:
    • Navigate to the folder where you extracted the Sitecore installation files.
    • Open the ConfigurationFiles directory (or equivalent, depending on your setup).
    • Find the sitecore-xp0.json and xconnect-xp0.json files.
  2. Modify the JSON Files:
    • Open sitecore-xp0.json in a text editor (e.g., Visual Studio Code or Notepad++).
    • Look for [variable('Sql.Credential')] in the JSON structure.
    • Add the following key-value pair:"TrustServerCertificate": true
    • Example:
"CreateShardApplicationDatabaseServerLoginInvokeSqlCmd": {
    "Description": "Create Collection Shard Database Server Login.",
    "Type": "InvokeSqlcmd",
    "Params": {
        "ServerInstance": "[parameter('SqlServer')]",
        "Credential": "[variable('Sql.Credential')]",
        "TrustServerCertificate": true,
        "InputFile": "[variable('Sharding.SqlCmd.Path.CreateShardApplicationDatabaseServerLogin')]",
        "Variable": [
            "[concat('UserName=',variable('SqlCollection.User'))]",
            "[concat('Password=',variable('SqlCollection.Password'))]"
        ]
    },
    "Skip": "[or(parameter('SkipDatabaseInstallation'),parameter('Update'))]"
},
"CreateShardManagerApplicationDatabaseUserInvokeSqlCmd": {
    "Description": "Create Collection Shard Manager Database User.",
    "Type": "InvokeSqlcmd",
    "Params": {
        "ServerInstance": "[parameter('SqlServer')]",
        "Credential": "[variable('Sql.Credential')]",
        "TrustServerCertificate": true,
        "Database": "[variable('Sql.Database.ShardMapManager')]",
        "InputFile": "[variable('Sharding.SqlCmd.Path.CreateShardManagerApplicationDatabaseUser')]",
        "Variable": [
            "[concat('UserName=',variable('SqlCollection.User'))]",
            "[concat('Password=',variable('SqlCollection.Password'))]"
        ]
    },
    "Skip": "[or(parameter('SkipDatabaseInstallation'),parameter('Update'))]"
}
  • Repeat the same modification for the xconnect-xp0.json file.
  • Save and Retry Installation:
    • Save both JSON files after making the changes.
  • Re-run the Sitecore installation PowerShell script.

    Additional Notes

    • Security Considerations: Setting TrustServerCertificate to true is a quick fix for development environments. However, for production environments, it’s recommended to install a certificate from a trusted Certificate Authority (CA) on the SQL Server to ensure secure and trusted communication.
    • Error Still Persists?: Double-check the JSON modifications and ensure the SQL Server is accessible from your machine. If issues persist, verify firewall settings and SQL Server configuration.

    Conclusion

    The “Certificate chain was issued by an authority that is not trusted” error during Sitecore installation is a direct result of Microsoft’s enhanced security measures in Windows 11. By updating the Sitecore configuration files to include the TrustServerCertificate setting, you can bypass this error and complete the installation successfully.

    For a smoother experience in production environments, consider implementing a properly signed SSL certificate for your SQL Server.

    If you’ve encountered similar issues or have additional tips, feel free to share them in the comments below!

    Powered by WordPress & Theme by Anders Norén