custom ps report for content tokens
This one is a fairly specific use case but could be adapted into something more generic if required.
Currently have situation where "tokens" are use across content in the Sitecore setup. Those tokens are then stored as key value pairs in a separate Dictionary; both of which are fully controllable by editors.
Where tokens are found in content, there is a bespoke process built into the code base that will retrieve token values and replace them inline.
For example:
- A Hero module item has a Title property, the value is
Hello, our product has won the Dwaineo Award [$award-count-and-date] - A Dictionary entry exists, where the key is
$award-count-and-dateand the value is7 time since August 2025
The above is now widespread across the whole website and helps content editors update wordy items in a single place, across hundreds of pages at once.
Now the challenge, we need an audit; what data source items and pages refer to this tokens? There isn't a Sitecore link since the linking is done in code. In steps Sitecore PSE:
$dbs = @{
"master"="master"
"web"="web"
}
$tokens = @{
"Sitecore Token ($)" = "$"
"Config Token (#)" = "#"
"System Token (+)" = "+"
}
$languages = @{
"English (United Kingdom)"="en-GB"
"English (region)"="en"
}
$language = "en-GB"
$database = "master"
$rootForModal = "/sitecore/content/Home"
$root = Get-Item -Path "$($database):$rootForModal"
$tokenPrefix = "$"
$settings = @{
Title = "Token Finder"
ShowHint = $true
OkButtonName = "Proceed"
CancelButtonName = "Abort"
Description = "Find all of the selected token types in item properties and rendering datasources."
Parameters = @(
@{
Name="database"
Title="Database"
Tooltip="Select the database to scan."
Options=$dbs
Value="master"
},
@{
Name="language"
Title="Language"
Tooltip="Select the language to scan."
Value="en-GB"
Options=$languages
},
@{
Name="tokenPrefix"
Title="Token Type"
Tooltip="The token type to search for."
Value="$"
Options=$tokens
},
@{
Name="root"
Title="Choose the report root"
Tooltip="Choose the root item to scan, this runs recursively."
Root=$rootForModal
}
)
Icon = [regex]::Replace($PSScript.Appearance.Icon, "Office", "OfficeWhite", [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
}
$result = Read-Variable @settings
if($result -ne "ok") {
Exit
}
# Check if root path has been changed from default
if($root.Paths.Path -eq $rootForModal) {
$confirmResult = Show-Confirm -Title "The root path has not been changed from $rootForModal - are you sure you want to proceed?"
if($confirmResult -ne "yes") {
Exit
}
}
# Use the selected database from the dialog
$rootItem = Get-Item -Path "$($database):" -ID $root.ID -Version latest -Language $language
$descendants = $rootItem.Axes.GetDescendants() |
ForEach-Object {
$_.Versions.GetLatestVersion()
}
$items = @($rootItem.Versions.GetLatestVersion()) + $descendants
Write-Host @($root).ItemPath
# Function to extract tokens from a string
function Get-TokensFromString {
param(
[string]$Text,
[string]$Prefix
)
$tokens = @()
if(![string]::IsNullOrEmpty($Text)) {
# Match all instances of [PREFIX...] pattern
# Escape special regex characters in the prefix
$escapedPrefix = [regex]::Escape($Prefix)
$pattern = "\[$escapedPrefix[^\]]*\]"
$tokensMatched = [regex]::Matches($Text, $pattern)
foreach($match in $tokensMatched) {
$tokens += $match.Value
}
}
return $tokens
}
# Function to scan item properties for tokens
function Get-TokensFromItem {
param(
[Sitecore.Data.Items.Item]$Item,
[string]$Prefix
)
$foundTokens = @()
# Iterate through all fields
$Item.Fields.ReadAll()
foreach($field in $Item.Fields) {
if($field -and !$field.Name.StartsWith("_")) {
$tt = $Item[$field.Name]
$tokens = Get-TokensFromString -Text $Item[$field.Name] -Prefix $Prefix
foreach($token in $tokens) {
$foundTokens += [PSCustomObject]@{
FieldName = $field.Name
Token = $token
}
}
}
}
return $foundTokens
}
$reportItems = [System.Collections.ArrayList]@()
Write-Host "Scanning $($items.Count) items..."
foreach($item in $items) {
# Step 1: Check item properties for tokens
$itemTokens = Get-TokensFromItem -Item $item -Prefix $tokenPrefix
foreach($tokenInfo in $itemTokens) {
$reportItem = [PSCustomObject]@{
"Icon" = $item.Appearance.Icon
"ItemPath" = $item.Paths.Path
"SourceType" = "Item Field"
"FieldName" = $tokenInfo.FieldName
"OriginalItemPath" = $item.Paths.Path
"Token" = $tokenInfo.Token
}
$reportItems.Add($reportItem) > $null
}
# Step 2: Check Final Renderings and their DataSources
$renderings = Get-Rendering -Item $item -FinalLayout
Write-Host "Scanning $($renderings.Count) renderings"
foreach($rendering in $renderings) {
if($rendering -and ![string]::IsNullOrEmpty($rendering.Datasource)) {
$datasource = $null
# Try to get the datasource item
if([Sitecore.Data.ID]::IsID($rendering.Datasource)) {
$datasource = Get-Item -Path "$($database):" -ID $rendering.Datasource -Version latest -Language $language
} elseif($rendering.Datasource.StartsWith("/")) {
$datasource = Get-Item -Path "$($database):$($rendering.Datasource)" -Version latest -Language $language
}
if($datasource) {
# Scan datasource properties for tokens
$dsTokens = Get-TokensFromItem -Item $datasource -Prefix $tokenPrefix
foreach($tokenInfo in $dsTokens) {
$reportItem = [PSCustomObject]@{
"Icon" = $datasource.Appearance.Icon
"ItemPath" = $datasource.Paths.Path
"SourceType" = "Datasource Field"
"FieldName" = $tokenInfo.FieldName
"OriginalItemPath" = $item.Paths.Path
"Token" = $tokenInfo.Token
}
$reportItems.Add($reportItem) > $null
}
}
}
}
}
if($reportItems.Count -eq 0) {
Show-Alert "No tokens in the format [$tokenPrefix...] were found."
} else {
$reportItems = $reportItems | Sort-Object ItemPath, FieldName, Token -Unique
$reportProps = @{
Title = "Token Finder Report"
InfoTitle = "Tokens Found in Items and Datasources"
InfoDescription = "This report shows all instances of tokens in the format [$tokenPrefix...] found in item fields and rendering datasource fields."
PageSize = 50
}
$reportItems | Show-ListView @reportProps -Property @{Label="Icon"; Expression={$_.Icon}},
@{Label="Token"; Expression={$_.Token}},
@{Label="Item Path"; Expression={$_.ItemPath}},
@{Label="Source Type"; Expression={$_.SourceType}},
@{Label="Field Name"; Expression={$_.FieldName}},
@{Label="Original Item"; Expression={$_.OriginalItemPath}}
}
Close-Window