Deploying a Modern Page Template with a Banner Image
The use case
A client wasn’t super-enthused about the grey abstract banner images provided by default on all new SharePoint pages and wanted to provide a different default company-approved banner image on their pages.
The solution overview
We decided to create a custom site design for the client. When creating a new site, site owners would choose the new site design from the list of available site designs. The site designs, apart from applying the company’s theme, would also run a site script to provision a PnP provisioning template that would add a page template to the site with the banner image predefined. New pages could then be created from that page template and have the company-approved banner image in place.
Because all sites would be sharing the default banner image, it also made sense to set up an organization-wide shared asset library where the banner image would live.
Now – creating a site design and site script to run a PnP provisioning template is a whole different post, so I won’t cover it here (plus, you can check out Microsoft’s doc with all the step-by-steps to use a site design for PnP provisioning). But what you’ll see below are the steps to set up the organization asset library, create and export a page template, and provision the page template to your site.
- You will need PnP-PowerShell installed. Take a look at PnP-PowerShell on Github and make sure you have the latest version of the SharePoint Online cmdlets. Check out my post on getting started with PnP-PowerShell if you’re just starting out.
- You will also need the latest version of the SharePoint Online Management Shell and tenant-level admin rights.
- While not necessary for this tutorial, if you’re going to be running site scripts and provisioning PnP, you’ll also need Power Automate and access to Azure Functions and Azure Queue storage. *See my notes at the end of this post.
Here we go!
First, let’s keep track of the variables you’ll want to have on hand.
# You'll need tenant level rights $adminSiteUrl = "" # https://yourtenant-admin.sharepoint.com # This is the site where you'll deploy the page template $site = "" # https://yourtenant.sharepoint.com/sites/yourSite (where to deploy the page template) # This is the site that will hold all the shared assets for your organization $imageAssetLibraryRootUrl = "" # https://yourtenant.sharepoint.com/sites/assetSite/ # This is the folder that holds the shared images $imageAssetLibraryFolderUrl = "" # https://yourtenant.sharepoint.com/sites/assetSite/assetLibrary/assetFolder # While you're at it, why not store your credentials? $Credentials = Get-Credential
Next, you’ll want to set up the organization-wide shared asset library, if you haven’t already.
# Connect to the tenant Connect-SPOService -Url $adminSiteUrl -Credential $Credentials # Make your site folder into an organization-wide asset library for images Add-SPOOrgAssetsLibrary -LibraryURL $imageAssetLibraryFolderUrl -OrgAssetType ImageDocumentLibrary
What that does is to add a new tab to the image panel for ‘Your organization.” Users can now add images that are within that folder from any other site on your tenant.
Now, you’ll want to add the banner image to your asset folder. The fast way is probably just to drag and drop it into the asset folder. But if you’re going to be working with multiple environments (such as a dev site, a QA site, and uat site), why not make that a provisioning template, too? Notice that in the code below, you want to update the Folder attribute with the folder path to your organization-wide asset library, relative to the asset site itself.
<?xml version="1.0"?> <pnp:Provisioning xmlns:pnp="http://schemas.dev.office.com/PnP/2020/02/ProvisioningSchema"> <pnp:Preferences Generator="OfficeDevPnP.Core, Version=3.21.2005.0, Culture=neutral, PublicKeyToken=5e633289e95c321a" /> <pnp:Templates ID="CONTAINER-TEMPLATE-PAGE-TEMPLATE-BANNER"> <pnp:ProvisioningTemplate ID="TEMPLATE-PAGE-TEMPLATE-BANNER" Version="1" BaseSiteTemplate="SITEPAGEPUBLISHING#0" Scope="RootSite"> <pnp:Files> <!-- Update the Folder with the library name/folder path on the image asset site --> <!-- For example, if your image asset library is at https://yourtenant.sharepoint.com/sites/orgassets/shared/images, Folder="shared/images" --> <pnp:Directory Src="images" Folder="assetLibrary/assetFolder" Overwrite="true" Recursive="true" Level="Published" /> </pnp:Files> </pnp:ProvisioningTemplate> </pnp:Templates> </pnp:Provisioning>
After updating your XML file, you can go back to PowerShell to run the commands to connect to the organization-wide asset site and run the provisioning template to upload your banner image to that site.
# Upload your banner image to the library Connect-PnPOnline $imageAssetLibraryRootUrl -Credentials $Credentials Apply-PnPProvisioningTemplate -Path .\banner.xml
Now that you have your banner image, you’re ready to create your page template! If you want a quick way to get started, you can start with our page-template.xml file structure, which contains the banner image and three sections (1 column, 2 column, 1 column).
<?xml version="1.0"?> <pnp:Provisioning xmlns:pnp="http://schemas.dev.office.com/PnP/2020/02/ProvisioningSchema"> <pnp:Preferences Generator="OfficeDevPnP.Core, Version=3.21.2005.0, Culture=neutral, PublicKeyToken=5e633289e95c321a" /> <pnp:Templates ID="CONTAINER-TEMPLATE-PAGE-TEMPLATE-WITH-BANNER"> <pnp:ProvisioningTemplate ID="TEMPLATE-PAGE-TEMPLATE-WITH-BANNER" Version="1" BaseSiteTemplate="SITEPAGEPUBLISHING#0" Scope="RootSite"> <pnp:ClientSidePages> <!-- start clientsidepage for page template --> ><!-- modify the Title and PageName and modify the Thumbnail to point to your asset site library file--> <pnp:ClientSidePage PromoteAsTemplate="true" Title="Page template with org banner" PageName="Templates/Page-template-with-org-banner.aspx" ThumbnailUrl="/sites/YourAssetSite/OrgAssets/Images/banner.png" PromoteAsNewsArticle="false" Overwrite="true" > <!-- modify the image URL to point to your asset site library file --> <pnp:Header ServerRelativeImageUrl="/sites/YourAssetSite/OrgAssets/Images/banner.png" Type="Custom" LayoutType="FullWidthImage" TextAlignment="Center" ShowTopicHeader="false" ShowPublishDate="false" TopicHeader="" AlternativeText="" /> <!-- update the rest of your layout and content --> <pnp:Sections> <pnp:Section Order="1" Type="OneColumn" /> <pnp:Section Order="2" Type="TwoColumn" /> <pnp:Section Order="3" Type="OneColumn" /> </pnp:Sections> </pnp:ClientSidePage> <!-- end clientsidepage --> </pnp:ClientSidePages> </pnp:ProvisioningTemplate> </pnp:Templates> </pnp:Provisioning>
Note that you should modify the Thumbnail and the ServerRelativeImageUrl attributes to point to your asset site library file (lines 9 and 11)! And maybe you want to change the Title and PageName (template file name) also (line 9).
If you want a more complex page layout, maybe with some web parts initially set up in columns and sections, then pull open SharePoint and create a page of your own. Point to your organization-wide asset library’s banner image for the page banner, and add sections and columns and web parts to your heart’s content. (The page can be saved in draft mode and doesn’t have to be published.) This screenshot below shows a more complex page layout, created in SharePoint Online:
When you’re done, run these commands in PowerShell to export the site pages from your site:
# Connect to the site ($site = whatever site you created the page on) Connect-PnPOnline $site -Credentials $Credentials # Export the provisioning template: Update the "your-location" path to a folder on your computer Get-PnPProvisioningTemplate -Out "C:\your-location\export.xml" -IncludeAllClientSidePages -PersistBrandingFiles -Handlers PageContents
Open your exported XML file, and look for the ClientSidePage section that was generated by your specific page layout. You’ll want to essentially copy and paste all of that into the page-template.xml file, to replace what we have there.
Some things to note, which are pointed out in the screenshot above:
- For pnp:ClientSidePage, PromoteAsTemplate needs to be set to “true” to make it a page template
- The Title is what your page template will be called
- The PageName is the file name of your page template
- The pnp:Header’s ServerRelativeImageUrl needs to point to your banner image in your organization-wide assets folder
When your page-template.xml file is good to go, all you need to do is to connect to the site you want to deploy the page template to and apply the provisioning template! And if you’re planning to build a site script, site design, and function app, then the page-template.xml file is what you would use for your provisioning template file.
# Connect to the site if you haven't yet Connect-PnPOnline $site -Credentials $Credentials # Apply the provisioning template Apply-PnPProvisioningTemplate -Path .\page-template.xml
Go to your site, click “New” on the home page to add a page, and you’ll see your custom page template available from the new page panel. If you select it, you’ll see the preview on the right with your custom banner image! To use it, click the Create page button in the bottom right.
We hit up a few topics today in this post:
- Using PowerShell to make an organization-wide asset library for your tenant
- Provisioning an image file to a site
- Exporting modern pages into a PnP provisioning template with the -IncludeAllClientSidePages switch
- Provisioning a modern page template with a PnP provisioning template
- And of course, including a custom banner image in the modern page template
As always, you can find code samples at Github!
What cool things are you doing with PnP provisioning and modern SharePoint? Drop us a note below!
*Note: I’m not a licensing expert, so I asked our team what they knew about what licenses and subscriptions would be required:
A Power Automate flow, triggered by a site design, that adds a message to an Azure storage queue does not require any additional Power Platform licenses if you already have a P1 license. The creator of the flow is the one who needs the license. Alternatively, you can use an Azure Logic App instead of a Power Automate flow, which is set up almost identically. This is what we at PixelMill usually do since flows are tied to the creator — and it’s nice to have everything in one place in Azure, besides the site designs and scripts which live in SharePoint.
On the Azure side, you will need an Azure subscription for the storage queue and azure function (and logic app, if you go that route). Our experience is that a few dollars a month covers the consumption of tenants that create thousands of sites with site designs per month, but you should use the Azure pricing calculator to check your specific setup and use cases.
Are you looking to customize your SharePoint intranet, but need some assistance? A PixelMill SharePoint expert would love to chat with you today!