March 21, 2025

SharePoint Site Provisioning: A Guide to Site Scripts & Site Designs with PowerShell

Introduction: Site Scripts and Site Designs

Automating site provisioning in contemporary SharePoint Online environments is essential for ensuring consistency, upholding governance, and enhancing collaboration within an organization. Site Scripts and Site Designs are key tools that facilitate this process, helping to standardize site creation and maintain organizational standards.


What is Site Design?

Site Design is a predefined set of actions that allows users to create new sites with a Modern UI in SharePoint Online (Office 365). It helps SharePoint consultants enhance consistency across multiple site collections within the same tenant. For example, with SharePoint Site Design, users can create new lists and libraries, define the site and list columns, establish content types, set themes, and choose a site logo, among other features.

Site Design is often associated with templates, but it is important to understand that it is not the same as a traditional template tied to a specific site. Many users mistakenly believe that changes made in Site Design will automatically apply to their existing sites. However, this is not how SharePoint Site Design functions. To implement the modifications from Site Design on existing sites, you must actively apply the Site Design to those sites.

SharePoint consultants have the option to choose Site Design when creating a new site through the user interface. Additionally, Site Designs can be applied to existing sites using various methods such as REST, CSOM, or PowerShell scripts. Essentially, Site Designs consist of a collection of scripts that operate in the background during the selection of a design for the creation of a new site. This functionality streamlines the process of site setup and ensures consistency across different SharePoint sites.

What are Site Scripts?

Site Scripts are JSON files that outline a specific sequence of actions to be executed when a Site Design is applied to an existing site or when a new site is created. These scripts can be run multiple times on the same site. They have a non-destructive nature, meaning they will only add missing elements to SharePoint sites.

As of now, you can add the below actions to your Site Script:
  1. Create a new list or library (or alter the default one created with the site).
  2. Create the site columns, and content types, and configure other list settings.
  3. Set site branding properties such as navigation layout, header layout, and header background.
  4. Apply a theme and also Set a site logo.
  5. Triggering a Microsoft Flow.
  6. Include principals (users and groups) in SharePoint roles.

NOTE: For constructing a JSON schema and its valid verbs, you can check the following resources.

Why Use Site Scripts and Site Designs?

  1. Standardization & Consistency
    • Ensures all sites follow the same structure, branding, and compliance requirements.
    • Reduces manual errors by applying predefined settings.
  2. Automation & Efficiency
    • Eliminates repetitive tasks such as manually creating lists, libraries, columns, or permissions.
    • Reduces setup time for new SharePoint sites.
  3. Customization without Custom Code
    • Site Scripts enable customization using JSON, eliminating the need for complex development efforts.
    • It can be enhanced using PnP PowerShellPower Automate, and various other SharePoint automation tools.
  4. Easy Updates & Scalability
    • Site Designs can be updated centrally and re-applied to existing sites.
    • Ideal for large organizations managing multiple SharePoint sites.

Creating a New Site Design and Site Script

Let us develop a new site script and design to enhance our understanding and generate additional ideas regarding the site script and design.

Create a JSON file named "Site-Script.json" and include the following code within it. The code defines five actions: 
  1. The first two actions create site columns.
  2. The third action creates a new content type in the site, named "User," and adds the two previously created site columns to this content type.
  3. The fourth action creates a new list in the SharePoint site, named "User Information," utilizing the newly created content type.
  4. The fifth action creates a new document library in the SharePoint site, named "User Documents", utilizing the created content type.

{
  "$schema": "https://developer.microsoft.com/json-schemas/sp/site-design.json#",
  "actions": [
    {
      "verb": "createSiteColumn", //verb to create SiteColumn
      "fieldType": "Text", //column type you want to create
      "displayName": "First Name", //Column Display Name
      "internalName": "FirstName",//Column Internal Name
      "isRequired": false, 
      "id": "2d738560-6a73-4d1b-854e-8b195f9021eb", //Unique gui-id for your site column you can genrate it manuualy.
      "group": "Test Site Columns" //give group name to identify
    },
    {
      "verb": "createSiteColumn",
      "fieldType": "DateTime",
      "displayName": "Date of Birthday",
      "internalName": "DateOfBirthday",
      "isRequired": false,
      "id": "da840479-d27e-490d-8624-cd1144ee07cc",
      "group": "Test Site Columns"
    },
    {
      "verb": "createContentType", //verb to create content type in site
      "name": "User", //ContentType Name
      "id": "0x0101009D1CB255DA76424F860D91F20E6C411800B609FEFDEFAA484299C6DE254182E666", //Unique content typeID
      "description": "User content type containing personal information",
      "parentId": "0x0101009D1CB255DA76424F860D91F20E6C4118", //Parent content type id
      "hidden": false,
      "subactions": [
        // you can add your site columns as many as you can..
        {
          "verb": "addSiteColumn",
          "internalName": "FirstName"
        },
        {
          "verb": "addSiteColumn",
          "internalName": "DateOfBirthday"
        }
      ]
    },
    {
      "verb": "createList", //Verb for Create a List
      "listType": "GenericList", //List type you want to create Ex:GenericList(CustomList),Document Library,Task List etc...
      "title": "User Information", //Title of your list
      "description": "List to store user personal information.", //Desciption of your list
      "templateType": 100, //Gave templtype for custom list it's 100, for document library it's 101
      "contentTypesEnabled": true, 
      "subactions": [
        {
          "verb": "addContentType",
          "name": "User"
        }
      ]
    },
    {
      //Creates a new Document Library
      "verb": "createList",
      "listType": "DocumentLibrary", //List type Document Library 
      "title": "User Documents", 
      "description": "Library for storing user-related documents.",
      "templateType": 101,
      "contentTypesEnabled": true,
      "subactions": [
        {
          "verb": "addContentType",
          "name": "User"
        }
      ]
    }
  ],
  "version": 1
}
If you want to create a list directly with its columns, you need to add the below JSON schema structure in the site script to accomplish this.

{
  "verb": "createList",
  "listType": "GenericList",
  "title": "User Information",
  "description": "List to store user personal information.",
  "templateType": 100,
  "subactions": [
    {
      "verb": "addField",
      "fieldType": "Text",
      "displayName": "First Name",
      "internalName": "FirstName",
      "isRequired": false
    },
    {
      "verb": "addField",
      "fieldType": "DateTime",
      "displayName": "Date of Birthday",
      "internalName": "DateOfBirthday",
      "isRequired": false
    }
  ]
}

How we can add Taxonomy Fields (Managed Metadata Fields) as Site Columns in Site-Script

In SharePoint, taxonomy fields, also known as managed metadata fields, are used to connect content types and lists with the Term Store. When creating site scripts, you can incorporate taxonomy fields as site columns and attach them to content types. Below is an example of how to construct the JSON schema to create a taxonomy field as a site column and add it to a content type using SharePoint site scripts.

First, you need to create a hidden site column associated with your actual taxonomy field. This column is already created with your managed property when you registered your managed property in the term store. Enter the below JSON schema to add the site column and change the value as per your managed property.

These fields are essential for backend processing, calculations, or metadata purposes but should remain hidden from end-users, especially when utilized for taxonomy management.

{
  "verb": "createSiteColumnXml",
  "schemaXml": "<Field ID=\"{"Unique Field GUID of your Managed Property"}\" Type=\"Note\" Name=\"DegreeTaxnomyField\" StaticName=\"DegreeTaxnomyField\" Group=\"Test Site Columns\" DisplayName=\"DegreeTaxnomyField\" ShowInViewForms=\"FALSE\" Required=\"FALSE\" Hidden=\"TRUE\" CanToggleHidden=\"TRUE\" />"
}
NOTE: Ensure that the Hidden attribute is set to true, and the Field ID matches exactly as it was created in the term store.

As mentioned before, these fields are hidden from the end-user and cannot be seen in the term store anywhere. To find the term's unique field ID, you can acquire it using the below PnP commands.

$adminSite = "https://<<Your-TenantName>>-admin.sharepoint.com"

Connect-PnPOnline -Url $adminSite -UseWebLogin

$TermField = Get-PnPField -Identity "<<Your Term-Name>>"
$fieldID = $TermField.TextField

write-Host "Field Id: $fieldID"
These commands return the Term's Field ID like: "Field Id: 6b9b1fd5-474c-4f08-820c-f1fc4352c1ba"

Now we create the Taxonomy Field Site Column, which we can add as site columns in our content type or anywhere else we choose to use it.
  • To create a taxonomy field as a site column in a site script, you need to define the field’s properties such as the Term Store, Term Set, and whether the field allows multiple selections.
  • Below is an example of creating a TaxonomyFieldType (managed metadata field) as a site column:
{
    "$schema": "https://developer.microsoft.com/json-schemas/sp/site-design.json#",
    "actions": [
        {
            "verb": "createSiteColumnXml",
            "schemaXml": "<Field ID=\"{Random unique Field-ID}\" Type=\"TaxonomyFieldType\" Name=\"Degree\" SourceID=\"http://schemas.microsoft.com/sharepoint/v3\" StaticName=\"Degree\" DisplayName=\"Degree\" Group=\"Test Site Columns\" ShowField=\"Term1033\" Required=\"FALSE\" EnforceUniqueValues=\"FALSE\" Mult=\"TRUE\"> \
      <Default></Default> \
      <Customization> \
          <ArrayOfProperty> \
              <Property> \
                  <Name>SspId</Name> \
                  <Value><<Your TaxonomyStoreSSPID>></Value> \
              </Property> \
              <Property> \
                  <Name>GroupId</Name> \
                  <Value><<Your TermStoreGroupID>></Value> \
              </Property> \
              <Property> \
                  <Name>TermSetId</Name> \
                  <Value><<DegreeTermSetID>></Value> \
              </Property> \
              <Property> \
                  <Name>TextField</Name> \
                  <Value>{<<Your Taxonomy Field ID>>  // same as per the Your Hidden column's FieldID
            }</Value>      
              </Property> \
              <Property> \
                  <Name>AnchorId</Name> \
                  <Value>00000000-0000-0000-0000-000000000000</Value> \
              </Property> \
              <Property> \
                  <Name>IsPathRendered</Name> \
                  <Value>false</Value> \
              </Property> \
              <Property> \
                  <Name>IsKeyword</Name> \
                  <Value>false</Value> \
              </Property> \
              <Property> \
                  <Name>Open</Name> \
                  <Value>false</Value> \
              </Property> \
          </ArrayOfProperty> \
      </Customization> \
  </Field>"
        }
    ]
}
Explanation of the JSON Schema:
  • Type: TaxonomyFieldType – Defines that this field will be used as a managed metadata field.
  • SourceID: Points to the SharePoint schema.
  • ShowField: Defines the language to be used to show the term (e.g., Term1033 for English).
  • Required: If the field is mandatory (FALSE means optional).
  • Mult: Allows multiple terms to be selected from the Term Set (TRUE).
  • Customization: Contains additional configuration for the taxonomy field, such as:
  • SspId: The ID for the taxonomy store.
  • GroupId: The ID of the Term Set group.
  • TermSetId: The ID of the Term Set from the Term Store.
  • TextField: The GUID of the field that will render the term text.
  • IsPathRendered: Whether to show the term path (hierarchy).
  • AnchorId: A default value (usually 00000000-0000-0000-0000-000000000000 for root terms).
  • IsKeyword: Defines whether the term is a keyword.
  • Open: Specifies whether the term set is open.
This is how we can create our site script with desired Content Types, Ste Columns, Predefined List Configurations, Document Libraries, and much more.

Now, we'll deploy our JSON Schema as a site script for our SharePoint tenant. Please refer to the PnP commands below for more information.

$adminSite = "https://<<Your-TenantName>>-admin.sharepoint.com" #Your Sharepoint admin site URL
$siteScriptFile ="c:\scripts\site-script.json" #File path of JSON file.

Connect-PnPOnline -Url $adminSite -UseWebLogin

$content = [IO.File]::ReadAllText($siteScriptFile)

$SPSiteScript = Add-PnPSiteScript -Content $content -Title "Test Site-Script"

$SiteScriptId = $SPSiteScript.Id

Write-Host "Site-Script ID: $SiteScriptId"
NOTE: Please save the Script ID that we used to create the Site Design.

Now, We create a new site design from the newly created site script. Please refer to the PnP commands below to create the site design.

$adminSite = "https://<<Your-TenantName>>-admin.sharepoint.com" #Your Sharepoint admin site URL

Connect-PnPOnline -Url $adminSite -UseWebLogin

$SiteDesignDetails = Add-PnPSiteDesign -Title $SiteDesignTitle -SiteScriptIds $SPSiteScript.Id -Description $SiteDesignTitle -WebTemplate TeamSite

Write-Host "Site Design is deployed successfully the GUID is:$($SiteDesignDetails.Id)"
NOTE: Please save the Site Design ID that we can use anywhere else.

After creating the site design, we can apply it to any site within our tenant. To do this, we need to run the following command.

$adminSite = "https://<<Your-TenantName>>-admin.sharepoint.com" #Your Sharepoint admin site URL

Connect-PnPOnline -Url $adminSite -UseWebLogin

# Run this Command If Your Site-Script has 30 Or less than 30 Actions
Invoke-PnPSiteDesign -Identity "<<Site-DesigneeID>>" -WebUrl "<<Site url>>"

# Run this Command If Your Site-Script has More than 30 actions
Add-PnPSiteDesignTask -SiteDesignId "<<Site-DesigneeID>>" -WebUrl "<<Site url>>"
NOTE: Execute the command based on the number of actions defined in your site script.

Summary 

This blog post discusses how Site Scripts and Site Designs in SharePoint Online simplify the site provisioning process by automating the creation of lists, libraries, content types, and branding. These tools help maintain consistency and governance across sites. 

 

Site Designs specify the configurations for a site, while Site Scripts—created using JSON—execute specific actions. These actions can include adding site columns, applying themes, and integrating Power Automate. By using these tools, organizations can reduce manual effort, enforce standardization, and achieve customization without the need for complex coding.


If you have any questions you can reach out our SharePoint Consulting team here.

No comments:

Post a Comment