Custom site header and footer using a SharePoint-hosted add-in

In this post, I will show you how to create a custom site header and footer for SharePoint Online/Office 365 that will render on all pages using a SharePoint-hosted add-in. This could be used to post critical alerts or to specify the level of business impact of the content stored within a particular site (e.g., high, medium, or low).

This add-in will accomplish the following, all without a single line of server-side code:

Upon installation, deploy 3 JavaScript files to the Style Library of the host web

Register 3 user custom actions in the host web to ensure these JavaScript files are loaded on every page

Via an add-in part, provide a mechanism for users to enable/disable and set properties of the custom header and footer (e.g., message text, background/text color)

Store and retrieve configuration parameters for the site header and footer in the host web’s property bag

Rendering a custom header and footer

We might be tempted to edit the master page directly to add a header and a footer, but this is not considered a best practice (especially in SharePoint Online, where master page changes can be rolled out quite frequently). Instead, our add-in will make use of JavaScript techniques to insert <div> elements at the top and bottom of the page for our header and footer:

NOTE: The <div> IDs in SharePoint Online are never set in stone and could change at any time. If they do, you will need to update HeaderFooter.js to reference the new <div> IDs.

jQuery makes it easy to create our custom header and footer <div> elements and insert them in the appropriate location within the DOM with its .insertBefore() and .insertAfter() functions following this approach:

Huge shout-out to Randy Drisgill for his SharePoint 2013 Sticky Footer implementation. The “sticky” footer anchors the footer <div> to the bottom of the page (or the bottom of the browser window if the available screen real estate exceeds the amount of content on a given page). I only needed to make one change to Randy’s StickyFooter.js implementation, and that was to account for the height offset imposed by the addition of our customHeader <div>:

For anyone following the OfficeDev PnP, the concept of remote provisioning to allow add-ins to deploy files to the host web should be a familiar one. However, the PnP examples make use of the .NET Managed CSOM to do this, which is a perfectly valid technique but would require us to develop a provider-hosted add-in (allowing that code to run in Azure or some other web server). Since I wanted to create a SharePoint-hosted add-in, I had to find a way to accomplish this using only JavaScript. Thankfully, I found Chris O’Brien’s post with code showing how to provision files to the host web using JavaScript. You will see that my code is based heavily on the example he provides and provisions the following files from the add-in web to the host web:

The add-in also includes an add-in part (deployed to and rendered from the add-in web) that allows users to enable/disable the header/footer and set the text and colors:

When the add-in part loads, it uses JavaScript to query the property bag of the host web to see if these settings already exist and if so, prepopulates the values in the form. Once the user has made the necessary changes, clicking Set Values will save the changes back to the property bag (again, using JavaScript).

NOTE: The need for our add-in to read and write data to and from the host web property bag requires us to request the FullControl permission at the Web scope in our add-in manifest (AppManifest.xml):

SharePoint 2013 introduced the Minimal Download Strategy (MDS), which reduces page load time by sending only the differences when users navigate to a new page. While this is a wonderful benefit, it wreaks havoc with solutions that need to manipulate the DOM every time a new page is loaded. In other words, our header and footer may render perfectly on the home page when we first load it, but thanks to MDS when we navigate to the “Documents” library, only part of the page will actually be re-rendered. Our header and footer will not display properly (if at all) when only part of the page is re-rendered to support a new page request.

I encourage you to download it, try it out in your environment, and let me know if you run into any issues with it. My sincere thanks go out to Chris O’Brien, Randy Drisgill, and Wictor Wilen for giving me the building blocks needed to put this add-in together.