Looping through all subsites in SharePoint Online

SharePoint Online requires use of the Client Object model when modifying the site via PowerShell due to there being no backend server exposed in Office 365. Users with previous experience of using JavaScript Client Object model will find this a familiar method.

In the example below, the Powershell iterates through all subsites (and subsites of subsites) in a site collection or root site. This could be used for disabling a web scoped feature or automating site modification.

First of all, the variables are initiated including the path to the relevant DLLs.

#connection variables and reference DLL
$username = "user@onmicrosoft.com"
$password = "Password123"
$SiteCollectionUrl = "https://tonyishere.sharepoint.com"
Add-Type -Path "c:\Microsoft.SharePoint.Client.dll"

A new object for the client context requires creating, this can be done in a reusable function as shown below.

# Generate ClientContext function so we can reuse
function GetClientContext($SiteCollectionUrl, $username, $password) {
     $securePassword = ConvertTo-SecureString $password -AsPlainText -Force
     $context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteCollectionUrl) 
     $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword) 
     $context.Credentials = $credentials
     return $context
}

The following function has a nested call to call itself, this enables it to iterate through subsites of subsites. Without the nested function call, it would only cover a single subsite depth. The function writes the url of the site to the screen but this could be replaced with more complex functionality such as enabling a feature or creating a list item.

# function to loop through subsites
function catchsubsites ($subsiteurl){
	$clientContext = GetClientContext $subsiteurl $username $password
	$rootWeb = $clientContext.Web
	$childWebs = $rootWeb.Webs
	$clientContext.Load($rootWeb)
	$clientContext.Load($childWebs)
	$clientContext.ExecuteQuery()
	#do something on top level site
	write-host $rootWeb.url -ForegroundColor Yellow
	foreach ($childWeb in $childWebs)
	{
		#do something for each subsite
		write-host $childWeb.url -ForegroundColor Yellow
		#see if there are any subsites beneath this and loop all of them too
		catchsubsites $childWeb.url
	}
}

Finally the function is called to kick off the whole process of looping through the site.

#Finally run the function to get it all started!
catchsubsites $SiteCollectionUrl

This example could be refined so that it doesn’t authenticate at every request but it does show how simple it can be to create the complex PowerShell scripts that we are all used to using on SharePoint on-premises in the cloud version of Microsoft’s Office 365 SharePoint Online.

Update: Code updated 01/10/2016, fixed variable in loop and added section to run code for parent site

6 thoughts on “Looping through all subsites in SharePoint Online

  1. Sarwa

    It is working fine but the catchsubsites multiple times rather than the perfect result .. Example

    Site 1 — Site Coll
    SubSite1
    ChildSite1

    but the output is coming as
    SubSite1
    ChildSite1

    SubSite1
    ChildSite1

    SubSite1
    ChildSite1

    Reply
    1. Tony Phillips Post author

      Hi Sarwa,

      Thank you for your comment.

      The code will dig straight into the child webs so you should get the subsites listed first. The code will list all the subsites that exist in the site collection. If you need them listed in a particular order you could put them into an array and sort them (as this method will always retrieve the subsites first).

      This code was designed to loop through each site and do a job (e.g. such as activate a feature) rather than show the list of the sites in a particular order.

      I did notice a mistake in the code which i will update now (should have been $childWebs rather than $subWebs in the loop).

      Reply
  2. Pingback: Set Offline Client Availability To No to Hide Sync for Sites via PowerShell in SharePoint Online | Drew Madelung

  3. samolpp

    can i get the same result with the help of ECMA script or JSOM or SPServices,
    i am stuck at the main parent site’s context!
    am unable to get the context of subsites when i tried to loop through the subsites.

    Reply
    1. Tony Phillips Post author

      Yes, you should be able to get the same results using JSOM or REST. It would be pretty intensive to do this look client-side if you had lots of subsites though. I would recommend looking at the REST API to do this through JavaScript.

      Reply
      1. Tony Phillips Post author

        Something like this would return subsites and you would have to re-loop this for each subsite to get the whole structure:
        /_api/web/webinfos?$select=ServerRelativeUrl,Title

        Reply

Leave a Reply

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