So I’ll start by saying how bowled over I am by the engagement I’ve had after posting a tweet sharing that I had programmatically updated the new footer. For this, thank you, this kind of engagement and praise is why I love the community and contributing to it.
I want to share some numbers with you, which was one of the main reasons for pursuing this task.
- My customer had 180 sites where the footer needed configuring.
- Settings, change the look, select footer (three clicks)
- Enable footer, browser and select a logo and then upload it, enable displaying the footer name and then add the footer name text, apply settings and close settings (eight clicks)
- Edit links (one click), create a new link, add text, add a URL, save the link, then (four clicks) and then repeat for three other links (twelve further clicks). Then save the navigation (one clicks). Eighteen clicks for footer links.
- That is a total of 29 clicks per site — a total of 4,860 clicks for all these sites.
Almost five thousand clicks is a lot of mouse work and this number doesn’t even factor in browsing to each site nor typing each of the values and URLs, which leaves a lot of room for errors too!
To emphasise just why I wanted to achieve this programmatically. Colleagues started to perform this manually while I did some R&D. During this time a collection of sites were updated. However, even with signed-off designs, change request and final confirmation, the customer still changed their mind hence why I like to code and work lean. This kind of change is not uncommon. However, for any organisation that centrally manages sites, has a flattened modern information architecture (IA) or a Hubified intranet with many sites where a standard and consistent footer might be wanted, not being able to manage the footer through PowerShell or other means is a problem. Even managing variations of a standard footer is likely to be an issue for if there is no way to handle it programmatically.
The intranet team within a large government department I have been working closely with over the last two years are responsible for close to 200 sites. Performing tasks against these sites and making changes to them efficiently using PowerShell or other means is essential. Finally, we should not forget that trends, standards and regulations change over time. One such example is that regulations for internet and intranet sites within the government might require that certain information must be readily available from the footer, which would lead to a need for wide-spread changes. Even with their carefully designed flat site structure as part of their information architecture (IA) which leverages Hub sites this change is still site-by-site as the footer configuration is not inherited from a Hub site and therefore set independently.
Exploring how the Footer works
So with all this in mind, I started to explore how this could be achieved using PowerShell. The options and tools are limited and restricted given the environment. I felt that if this could be through the UI, then there must have been an API I could play with to achieve the same result. Off I went in my lab using Fiddler, SharePoint Online Client Browser, Edge Insider developer tools, Postman and VS Code. Troubleshooting and reverse engineering things is a childhood pastime. I found many other exciting easter eggs during this exercise that I hope to share too, but it was like there was a bounty on resolving the footer configuration.
Colleagues in my team were also looking for a solution to similar problems for their customers. A colleague quickly followed up about some undocumented verbs he found in the site design schema (see Site design JSON schema on Microsoft Docs). This news also confirms what I learned from some PG colleagues. Sadly, the footer only has site design support right now.
What I discovered through Edge tools that each change to the footer through the editing footer links or from the change the look pane invoked an API post to “/_API/SaveMenuState”. This post had a JSON payload with the configuration of the footer and also included any footer links. Win!
Initial approach and exploration
I took off with examples of this JSON payload that I obtained from Developer Tools after applying several different footer configurations. I started exploring how the API worked using Postman (this is an excellent tool by the way). To use Postman, I had to create an SP app to get an auth token from AAD so I could use Postman with SPO APIs. I gave the app full tenant access so I could explore things better. Getting started with Postman was a great lesson and one I want to share in a separate post, but Postman is now a vital tool for me when working with SharePoint Online. Once I had played with the API, I set out to achieve the same behaviour in PowerShell.
I set out with the intent to share my work as I know this was going to be of interest to lots of others. I decided to create multiple functions, so each part of the footer can be configured separately. I also built this with a view of contributing and sharing it as part of the SharePoint PnP module. The code is functional and not perfect. Let me walk you through it and share the entire thing at the end too.
the script uses the
the output information (
$DebugPreference = "Continue"
Enable/Disable SPO Footer – These two functions were created to quickly enabled and disable the footer with a simple function call.
Get/Set SPO Footer (Logo and Text) – It is useful to be able to get the configuration of both the footer text and the footer logo. These functions can be helpful to validate the configuration, for example. These both exist in the JSON as nodes with consistent GUID for their “title” and similar they both have a “key” that identifies them. To simplify the functions I created an overarching function to run them all.
Get/Add/Remove Navigation Links – This needs further work but it could leverage the existing Get/Add/Remove-PnpNavigationNode cmdlets. For my customer, I hardcoded the URLs in the JSON payload on line 417 but I provided a sample of how this looks on lines 408-415.
- Enable/Disable-Footer – Enables and disables the footer
- Get/Set-SPOFooter – Get the configuration of the footer
- Get/Set-SPOFooterText – Set the footer text
- Get/Set-SPOFooterLogo – Set the footer logo
- Set-SPOFooterLinks – Create footer links
Here is the script with all the functions and some examples. I’m going to reach out to Vesa and the PnP team to see about getting this included somehow. But, for now, enjoy. If you have any issues or comments, please let me know!
Quirks to be aware of
During my testing, I noticed a number of quirks I had to work around or that I want to share and make you aware of.
- When using Postman between sessions, you must refresh your auth token to continue accessing SPO.
- No value is available when reviewing $site.FooterEnabled using the Get-PnPSite cmdlet so you cannot check to see if the footer is enabled or not.
- When getting the footer, I noticed there seem to be several different states for how the footer configuration which might impact the GET functions however I have tried to mitigate this risk.
- Enabled with no configuration
- Enabled, but the JSON appears similar to when it is it disabled
- Enabled with configuration and or links.
- I noticed some sites had the footer enabled after the footer feature was released, while others it was disabled, this was why I built the function to check how the configuration of the footer.
I hope you find this post helpful. Your engagement and feedback are what drive me to write posts like this, so please keep it up!