Collaborate, Innovate, Automate

New-SPOAlertInventoryList

This PnP PowerShell script creates the SharePoint Alert Inventory list used by Get-SPOAlertInventory to store the results of a tenant-wide classic Alerts scan. Run it once, on whichever site you want the results to live, before running the inventory scan — it is safe to re-run, since it only creates columns that don't already exist.

Purpose

Microsoft is retiring classic SharePoint Alerts in July 2026. Before that happens, every tenant needs an audit trail of who has alerts configured, on what, and what should happen to each one. This script builds the destination list for that audit:

Prerequisites

PowerShell Script

<#
.SYNOPSIS
    Creates the SharePoint Alert Inventory list on devintranet, with all
    columns needed to store results from Get-SPOAlertInventory.ps1 and to
    support the follow-up outreach workflow (review status, notes, action
    needed) ahead of the July 2026 SharePoint Alerts retirement.

.NOTES
    Requires: PnP.PowerShell 3.x

#>

[CmdletBinding()]
param(
    [Parameter(Mandatory = $false)]
    [string]$SiteUrl = "https://tenantName.sharepoint.com/sites/siteName",

    [Parameter(Mandatory = $false)]
    [string]$ClientId = "",

    [Parameter(Mandatory = $false)]
    [string]$ListName = "SPOAlertInventory",

    [Parameter(Mandatory = $false)]
    [string]$ListTitle = "SharePoint Alert Inventory"
)

Write-Host "Connecting to $SiteUrl ..." -ForegroundColor Cyan
Connect-PnPOnline -Url $SiteUrl -Interactive -ClientId $ClientId

# --- Create the list if it doesn't already exist ---
$existingList = Get-PnPList -Identity $ListName -ErrorAction SilentlyContinue

if ($existingList) {
    Write-Host "List '$ListName' already exists. Skipping creation, will only ensure columns exist." -ForegroundColor Yellow
}
else {
    Write-Host "Creating list '$ListName' ..." -ForegroundColor Cyan
    New-PnPList -Title $ListName -Template GenericList -OnQuickLaunch | Out-Null
}

# --- Rename the default Title column to something meaningful ---
Set-PnPField -List $ListName -Identity "Title" -Values @{Title = "Alert Title"} | Out-Null

# --- Helper to add a field only if it doesn't already exist ---
function Add-FieldIfMissing {
    param(
        [string]$ListName,
        [string]$InternalName,
        [string]$DisplayName,
        [string]$Type,
        [string[]]$Choices,
        [switch]$Required
    )

    $field = Get-PnPField -List $ListName -Identity $InternalName -ErrorAction SilentlyContinue
    if ($field) {
        Write-Host "  Field '$InternalName' already exists, skipping." -ForegroundColor DarkGray
        return
    }

    switch ($Type) {
        "Choice" {
            Add-PnPField -List $ListName -InternalName $InternalName -DisplayName $DisplayName `
                -Type Choice -Choices $Choices -Required:$Required | Out-Null
        }
        default {
            Add-PnPField -List $ListName -InternalName $InternalName -DisplayName $DisplayName `
                -Type $Type -Required:$Required | Out-Null
        }
    }
    Write-Host "  Added field '$DisplayName' ($Type)" -ForegroundColor Green
}

Write-Host "Adding columns to '$ListName' ..." -ForegroundColor Cyan

# --- Site identification ---
Add-FieldIfMissing -ListName $ListName -InternalName "SiteUrl"        -DisplayName "Site URL"          -Type URL
Add-FieldIfMissing -ListName $ListName -InternalName "SiteTitle"      -DisplayName "Site Title"        -Type Text

# --- Alert ownership ---
Add-FieldIfMissing -ListName $ListName -InternalName "CreatedFor"      -DisplayName "Created For"        -Type User
Add-FieldIfMissing -ListName $ListName -InternalName "CreatedForLogin" -DisplayName "Created For (Login)" -Type Text

# --- Alert configuration detail ---
Add-FieldIfMissing -ListName $ListName -InternalName "AlertListUrl" -DisplayName "List / Library URL" -Type URL
Add-FieldIfMissing -ListName $ListName -InternalName "EventType"    -DisplayName "Event Type"          -Type Text
Add-FieldIfMissing -ListName $ListName -InternalName "AlertFilter"  -DisplayName "Filter" -Type Choice -Choices @(
    "AnythingChanges",
    "SomeoneElseChangesAnItem",
    "SomeoneElseChangesItemCreatedByMe",
    "SomeoneElseChangesItemLastModifiedByMe"
)
Add-FieldIfMissing -ListName $ListName -InternalName "Frequency" -DisplayName "Frequency" -Type Choice -Choices @(
    "Immediate",
    "Daily",
    "Weekly"
)
Add-FieldIfMissing -ListName $ListName -InternalName "DeliveryChannel" -DisplayName "Delivery Channel" -Type Text
Add-FieldIfMissing -ListName $ListName -InternalName "AlertTime"       -DisplayName "Alert Time"       -Type DateTime

# --- Scan metadata ---
Add-FieldIfMissing -ListName $ListName -InternalName "ScanDate" -DisplayName "Scan Date" -Type DateTime -Required
Add-FieldIfMissing -ListName $ListName -InternalName "ScanStatus" -DisplayName "Scan Status" -Type Choice -Choices @(
    "OK",
    "ERROR",
    "CLEANUP_NEEDED"
)
Add-FieldIfMissing -ListName $ListName -InternalName "ScanStatusDetail" -DisplayName "Scan Status Detail" -Type Note

# --- Outreach / governance workflow ---
Add-FieldIfMissing -ListName $ListName -InternalName "Reviewed" -DisplayName "Reviewed" -Type Boolean
Add-FieldIfMissing -ListName $ListName -InternalName "ActionNeeded" -DisplayName "Action Needed" -Type Choice -Choices @(
    "Migrate to SharePoint Rule",
    "Migrate to Power Automate",
    "Keep monitoring (not yet reviewed)",
    "No longer needed, safe to ignore",
    "Creator unreachable / orphaned"
)
Add-FieldIfMissing -ListName $ListName -InternalName "ReviewNotes" -DisplayName "Review Notes" -Type Note

Write-Host "`nList setup complete: '$ListTitle' ($ListName) on $SiteUrl" -ForegroundColor Green
Write-Host "Remaining manual step: consider adding a default view showing ScanStatus, ActionNeeded and Reviewed for quick triage." -ForegroundColor Yellow

Usage Notes

Related