Smarter XM Cloud: Rendering insights for PO, CE and more

Hero image

Let’s be honest here: projects tend to get messy pretty fast. When you’re running multiple sites on the same codebase, keeping track of which renderings are used where can be a real challenge, especially since they all live on the same shared platform. Staying on top of documentation requires serious endurance. And let's face it, most developers aren’t exactly thrilled about writing documentation. Luckily, with tools like AI, this task is becoming much easier :)

To leverage AI effectively, you first need solid data. That’s why I created a PowerShell script that scans your master database, identifies all your sites, pulls all the renderings per site (from both final and shared layouts), and produces a clean JSON report. No gimmicks, just straightforward, useful information — exactly what AI needs to transform the data into a clear and organised table.

Before diving into the technical details, here’s why this matters — whether you’re a Product Owner, Content Editor, or Developer.

Why should it matter to you?

Product Owners: You want to be in control. Having a clear overview of which components run where makes it easier to estimate the risk when changing a component and to make smarter decisions around releases.

Content Editors: This info might not affect your day-to-day work directly, but it can be useful during testing to understand which parts of a site might be impacted by changes.

Developers: You want a comprehensive overview so you can accurately evaluate the risk of your changes and know exactly where and how to test them.

This script puts that map in your hands.

What the Powershell script does

Here’s how it works in a nutshell:

  1. Switches to the master database — because that’s where all your layout and rendering info lives
  2. Recursively searches under /sitecore/content for all your site roots, skipping irrelevant system folders
  3. For each site, it grabs every page and pulls all renderings assigned to the default device, from both shared layout* and final layout**
  4. Collects all unique rendering IDs, then looks up their names so you get something readable
  5. Outputs everything as clean, nicely formatted JSON — easy to consume, share, or feed into AI tools for further analysis.
  6. Save the output into a JSON file for further use
* Shared Layout: This is the baseline presentation details for an item and is common across all language versions and item versions. It defines the default renderings and structure for the page.
** Final Layout: This represents the effective presentation for a specific language version and item version after applying any changes such as personalisation, testing, or version-specific overrides on top of the shared layout. So it can vary between languages and versions.

Powershell script:
# ——————————————————————————————
# 1a) Switch to the master DB
Set-Location master:

# 1b) Define Dutch language object (adjust language code if needed)
$language = [Sitecore.Globalization.Language]::Parse("nl-NL")

# ——————————————————————————————
# 2) Recursive finder for “site roots”, skipping “Experience platform websites”
function Get-SiteRoots {
    param([Parameter(Mandatory=$true)][Sitecore.Data.Items.Item]$Parent)
    if($Parent.TemplateName -eq 'Branch') {
        return
    }

    # Cache children once
    $children = $Parent.GetChildren()

    # If any child has a __Renderings field with a value, this is a site root
    if ($children | Where-Object { $_.Fields['__Renderings'] -and $_.Fields['__Renderings'].Value }) {
        # Output this item and stop recursion here
        Write-Output $Parent
        return
    }

    # Otherwise, recurse into children
    foreach ($child in $children) {
        Get-SiteRoots -Parent $child
    }
}

# ——————————————————————————————
# 3) Discover all site roots under /sitecore/content
$rootContent = Get-Item "master:/sitecore/content"
$siteRoots = @(Get-SiteRoots -Parent $rootContent) | Sort-Object -Property Name

# ——————————————————————————————
# 4) Prepare device & master DB API
$device   = Get-LayoutDevice -Default
$masterDb = [Sitecore.Configuration.Factory]::GetDatabase("master")

# ——————————————————————————————
# 5) For each site root, collect unique rendering names
$results = @()

foreach ($siteRoot in $siteRoots) {
    $uids = New-Object System.Collections.Generic.HashSet[string]
    $pages = ,$siteRoot + $siteRoot.Axes.GetDescendants()

    foreach ($page in $pages) {
        # Get Dutch language version of the page
        $dutchPage = $page.Database.GetItem($page.ID, $language)
        
        $renderings = @(Get-Rendering -Item $dutchPage -Device $device) + @(Get-Rendering -Item $dutchPage -Device $device -FinalLayout)
        foreach ($r in $renderings) {
            if ($r.ItemID) {
                $uids.Add($r.ItemID.ToString()) | Out-Null
            }
        }
    }

    $names = $uids | ForEach-Object {
        $item = $masterDb.GetItem([Sitecore.Data.ID]::Parse($_))
        if ($item) { $item.Name }
    } | Sort-Object -Property Name

    $results += [PSCustomObject]@{
        SiteRoot   = $siteRoot.Name
        Renderings = $names
    }
}

# ——————————————————————————————
# 6) Emit perfectly formatted JSON via parse→serialize trick
$results |
  ConvertTo-Json -Depth 5 |      # serialize
  ConvertFrom-Json        |      # parse back into objects
  ConvertTo-Json -Depth 5 |      # re-serialize with proper indentation
  Out-Host                       # push to the console

How to leverage AI

In order to create a good overview you could write a program yourself, but that's not needed anymore. You could use AI for this task, it doesn't really matter which client you use. In my case I used the 4.1-mini LLM to process the JSON to a readable table.

Here's the prompt that I used:
I have a JSON file containing an array of objects. Each object has a SiteRoot string and a Renderings list of objects. Each rendering object includes a RenderingItemName.

I want to transform this JSON into an Excel sheet structured as a matrix:
  • Rows: unique SiteRoot values
  • Columns: unique RenderingItemName values
  • Cell values: a checkmark (✓) if the SiteRoot uses that rendering, else empty
Please create a Python script that:
  1. Reads the JSON file
  2. Extracts all unique SiteRoot and RenderingItemName pairs
  3. Builds the presence matrix as described
  4. Saves the matrix as an Excel file named SiteRoot_Renderings_Matrix.xlsx
  5. Provides the path to the saved Excel file so I can download it
Ignore any null or empty Renderings. Strip whitespace from rendering names.
Return the final Excel file path.

The output will look something like this:

AI - Excel sites vs rendering output

If you combine this with your architecture, you will have a pretty good documentation of your platform.

Happy codin'!