SharePoint Online: How to Apply Site Policy using PowerShell?

Requirement: Apply site policy in SharePoint Online using PowerShell.

How to Apply SharePoint Online Site Policy using PowerShell?

Site Policies are a great way to implement governance in SharePoint Online. Applying site policies can be done through the SharePoint Online web browser interface, however, using PowerShell can be more efficient and allow for automation in large-scale scenarios. In this guide, we will show you how to apply site policies in SharePoint Online using PowerShell.

Create a Site Policy in SharePoint Online

As of today, we can’t create a new site policy through PowerShell! However, we can save time by creating a site policy at the content type hub instead of creating one at each site collection. Here is how to create a site policy in the SharePoint Online content type hub:

  1. Log in to the content type hub of your tenant at https://<tenant>.sharepoint.com/sites/contentTypeHub
  2. Click on the Settings gear in the top-right corner >> Choose “Site Settings”.
  3. Click on the “Site Policies” link under the “Site Collection Administration” section.
  4. Create a new policy as per requirement. I’ve created a policy that makes the site collection to read-only by selecting “Do not close or delete site automatically” and checking the “The site collection will be read-only when it is closed”.
    sharepoint online create site policy powershell
  5. Once the site policy is created, You have to publish it to the site collections. From the Site Policies page of the content type hub, click on the “Manage publishing for this policy” link next to the site policy you just created.
  6. Choose the “Publish” or “Republish” option to push your site policy to all SharePoint Online site collections.

Once you publish, It takes some time for the policy to appear in site collections, and you may have to wait up to 24 hours. Once your site policy is published, you should see it on the target site collection’s “Site Policy” page.

Activate the “Site Policy” Feature, if it’s not activated already

The “Site Policy” Feature must be activated on the site collection level to apply the Policy. If it’s not activated already (In Group sites, It’s disabled by default!), follow these steps:

  1. Go to Settings >> Site Settings >> Click on the “Site collection features” link.
  2. Click on the “Active” button for Site Policy Feature.
    sharepoint online site policy feature

Apply Site Policy to the Site Collection

Applying a site policy using the web interface is quite simple. Go to Site Setting to apply the site policy and click on the “Site Closure and Deletion” link under Site Administration. Select the site policy you created and click the “OK” button. Come back to the “Site Closure and Deletion” page to click the “Close this site now” button to close a site collection. The selected site policy will be applied after a site collection is closed.

PowerShell to Apply Site Policy to Site Collection:

Alright, When you need to apply a site policy for a large number of sites, we can use PowerShell instead of web UI. Once the site policy is available in target sites, we can apply it to the site collection through PowerShell. Here is the CSOM PowerShell script to apply:

#Load SharePoint Online CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.Office.Client.Policy.dll"

#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/Marketing"
$PolicyName = "Set Site Read-Only"

#Setup Credentials to connect
$Cred = Get-Credential
     
#Setup the context
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$Ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.UserName,$Cred.Password)

#Get the Web
$Web = $Ctx.Web
$Ctx.Load($Web)
$Ctx.ExecuteQuery()

#Get Site Policies
$Policies = [Microsoft.SharePoint.Client.InformationPolicy.ProjectPolicy]::GetProjectPolicies($Ctx, $Web)
$Ctx.Load($Policies)
$Ctx.ExecuteQuery()

#Get the Policy to Apply 
$SitePolicy =  $Policies | Where -Property Name -eq $PolicyName
If($SitePolicy)
{
    #Apply the policy
    [Microsoft.SharePoint.Client.InformationPolicy.ProjectPolicy]::ApplyProjectPolicy($Ctx, $Web, $SitePolicy)
    $Web.Update()
    $Ctx.ExecuteQuery()
    
    #Close the Site
    [Microsoft.SharePoint.Client.InformationPolicy.ProjectPolicy]::CloseProject($Ctx,$Web)
    $Ctx.ExecuteQuery()

    Write-host "Site Policy has been Applied & Site Closed Successfully!" -f Green
}

To open the site again, use the following:

[Microsoft.SharePoint.Client.InformationPolicy.ProjectPolicy]::UnArchiveSite($ctx,$SiteURL)

PnP PowerShell to Apply Site Policy in SharePoint Online

Now, let’s use PnP PowerShell to activate the “Site Policy” feature at the site collection if it’s not activated already, and then apply the “Site Policy” to the given site collection.

#Apply Site Policy for a Site collection
Function Apply-PnPSitePolicy([String]$SiteUrl, [String]$PolicyName)
{
    #Connect to the Site 
    Connect-PnPOnline -Url $SiteUrl -Interactive

    #Check if "Site Policy" Feature is active
    $SitePolicyFeature = Get-PnPFeature -Identity "2fcd5f8a-26b7-4a6a-9755-918566dba90a" -Scope Site -Web $SiteUrl
    If($SitePolicyFeature.DefinitionId -eq $null)
    {
        #Activate "Site Policy" Feature for the site collection
        Enable-PnPFeature -Identity "2fcd5f8a-26b7-4a6a-9755-918566dba90a" -Scope Site
        Write-Host "Site Policy Feature is Activated at $($SiteUrl)" -ForegroundColor Green
    }
    
    #Get Policy to Activate
    $SitePolicyToActivate = Get-PnPSitePolicy -Name $PolicyName | Select-Object -Property Name
    If ($SitePolicyToActivate)
    {
        #Apply Site Policy
        Set-PnPSitePolicy -Name $PolicyName

        #Close the site
        Set-PnPSiteClosure -State Closed

        Write-Host "Site Policy Applied to $($SiteUrl)" -ForegroundColor Green
    }
    Else
    {
        write-Host "Site Policy '$($PolicyName)' not found in Site $($SiteUrl)" -ForegroundColor Yellow
    }
}

#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/Purchase"
$PolicyName= "Set Site Read-Only"

#Call the function to apply site policy
Apply-PnPSitePolicy -SiteUrl $SiteURL -PolicyName $PolicyName

If you just activated the “Site Policy” feature, policies created in the content type hub won’t immediately show at site collections! You may have to wait up to 24 hours.

Salaudeen Rajack

Salaudeen Rajack - Information Technology Expert with Two-decades of hands-on experience, specializing in SharePoint, PowerShell, Microsoft 365, and related products. He has held various positions including SharePoint Architect, Administrator, Developer and consultant, has helped many organizations to implement and optimize SharePoint solutions. Known for his deep technical expertise, He's passionate about sharing the knowledge and insights to help others, through the real-world articles!

10 thoughts on “SharePoint Online: How to Apply Site Policy using PowerShell?

  • Hi Salaudeen,

    Many thanks for sharing this, it helped a great deal!
    While testing the script on my end, I thought whether it would be possible to apply the policy to more than one site at the time (.csv file with site URLs or a list on SharePoint)? That way, it can be done in bulk for 10 or 20 sites at the time, which would save a lot of time and even automate things.

    Looking forward to the response!

    Reply
  • Hi Salaudeen! thanks for all you do for the SharePoint community! this web rocks!
    My question is if is there a possibility to change the content for the email message when the site Collection will be deleted. the instructions are not suitable for SharePoint 2019 because there is not “site settings” in the settings gear.
    Thanks in advance!
    /Michel

    Reply
  • FYI it is working when you first do
    “Add-PnPContentTypesFromContentTypeHub -ContentTypes “[GUID]” -Site $SiteURL”

    before calling the Get-PnPSitePolicy !

    Reply
  • not working, Get-PnPSitePolicy do not return a value. In UI you can see the policy…..

    Reply
  • Hi – I created a site policy and published it but when I run [Microsoft.SharePoint.Client.InformationPolicy.ProjectPolicy]::GetProjectPolicies it doesnt return the full list of project policies. It is a newly created site policy but I’ve waited over 24 hours but still dont see the site policy returned from the GetProjectPolicies method. I do see the project policy in the UI though.

    Reply
  • Yes, an equivalent version for onPrem would be really helpful, we need it for SharePoint 2019. I can see that pnp PS module exists for onPrem too but can’t find similar cmdlets in the same. Even if you can enunciate the equivalent cmdlets to be used for the onprem PnP version it would help drastically.

    Reply
  • Hi Salaudeen ,

    The Script is working now and it apply the site policy successfully on the site but , it just fail on the line [ $Ctx.ExecuteQuery() ]

    #Apply the policy
    [Microsoft.SharePoint.Client.InformationPolicy.ProjectPolicy]::ApplyProjectPolicy($Ctx, $Web, $SitePolicy)
    $Web.Update()
    $Ctx.ExecuteQuery() — [ This line return PowerShell error as follows ]

    —————————————————————————————————————————————————————–
    Exception calling “ExecuteQuery” with “0” argument(s): “Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))”
    At line:37 char:5
    + $Ctx.ExecuteQuery()
    + ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ServerUnauthorizedAccessException

    Site Policy has been Applied & Site Closed Successfully!

    ————————————————————————————————————————————————————–

    Note -The Site policy get applied but it throw an error as mentioned above , i would appreciate any help on this.
    I am running the script with global admin account.

    Reply
  • Hi .. the script is not working in my case, the line doesn’t return the result [ $Web = $Ctx.Web ]

    sometime the error in PS – An error occurred while enumerating through a collection: The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested..

    please help

    Reply
  • Hi – Do you have a script for the same for On-Prem as well?

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *