[SharePoint 2010] Programmatically Add JavaScript, Meta Tags, and CSS Styles to the Header of Every Page

For SharePoint sites, particularly public-facing ones, there are times when adding JavaScript, Meta Tags, CSS Styles or other content to the page <head> section is more practical than modifying master pages. For instance, you could add the jQuery library to the head of every page. If adding tags to the page <head> section is the only customization being made side-wide, doing so programmatically instead of modifying and un-ghosting the default master pages will increase the performance of the site. (Un-ghosting a page means that SharePoint is no longer grabbing the master page from the local hard drive and is instead grabbing it from the Content Database. This adds another call to the database that isn’t necessary unless you have a fully branded master page).

To demonstrate how to accomplish this programmatically using the AdditionalPageHead Content Place Holder, we will make a SharePoint solution in Visual Studio 2010 that adds a custom JavaScript file and a custom CSS file. This solution could be further extended to dynamically add different content based on configurable settings, however for this demonstration we will keep it simple.

  1. Open Visual Studio 2010 on a computer running SharePoint 2010.
  2. Select File > New Project.
  3. Make sure .NET Framework 3.5 is selected.
  4. Under Visual C# > SharePoint >2010, select Empty SharePoint Project.
  5. Provide a name and location for the solution, for the demonstration we are using CustomPageHead.
  6. Provide the URL to the local SharePoint site used for debugging your solution, for the demonstration we are using http://win7 (the URL of my local SharePoint 2010 site).
  7. Select “Deploy as a farm solution.” Since we are going to be deploying a user control to the SharePoint 14 HIVE (the local hard drive) it must be a farm solution.
  8. Select Finish.
  9. Next we will add the custom CSS stylesheet and JavaScript file to the solution. For demonstration purposes, we will be creating them in Visual Studio, however you may add your own files.
    1. Right-click the solution name (CustomPageHead) in the Solution Explorer.
    2. Select Add > SharePoint “Layouts” Mapped Folder. This creates the Layouts folder with a sub-folder that has the same name as the Solution (CustomPageHead). It is important that custom assets (such as JS and CSS files) are placed in that sub-folder or another sub-folder with a unique name to prevent files from conflicting with built-in SharePoint files or other installed solutions.
    3. Right-click the CustomPageHead folder under Layouts.
    4. Select Add > New Item.
    5. Under Visual C# > Web, select JScript File.
    6. Provide the new JavaScript file with a name, for this demonstration we are using “custom.js”.
    7. Select Add.
    8. Right-click the CustomPageHead folder under Layouts.
    9. Select Add > New Item.
    10. Under Visual C# > Web, select Style Sheet.
    11. Provide the new CSS file with a name, for this demonstration we are using “custom.css”.
    12. Select Add.
    13. To ensure the solution is working when we test it, we will use the custom.css stylesheet to change the background color. In the custom.css file, replace its contents with:
      body
      {
      		background-color: #777777;
      }
      
    14. Close the custom.js and custom.css files if they are still open.
  10. Right click the solution name (CustomPageHead) in the Solution Explorer.
  11. Select Add > SharePoint Mapped Folder…
  12. Expand the TEMPLATE folder and select CONTROLTEMPLATES. The designated location for storing user controls in SharePoint is the CONTROLTEMPLATES folder. Unlike the Layouts folder, a sub-folder is not automatically created.
  13. Right-click the CONTROLTEMPLATES folder.
  14. Select Add > New Folder.
  15. Name the folder the same name used for the sub-folder in the Layouts folder (CustomPageHead).
  16. Right-click the CustomPageHead sub-folder of CONTROLTEMPLATES.
  17. Select Add > New Item.
  18. Under Visual C# > SharePoint > 2010, select User Control.
  19. Provide the User Control with a file name (CustomPageHead.ascx).
  20. Select Add.
  21. Expand the CustomPageHead.ascx file in the Solution Explorer.
  22. Double-click the CustomPageHead.ascx.cs file to open it.
  23. Add a reference to the Microsoft.SharePoint namespace.
    using Microsoft.SharePoint;
    
  24. In the Page_Load section, add the following to grab the URL of the current site:
    string SiteURL = SPContext.Current.Web.Url;
    
  25. On the next line, add the following to register the custom.js client script:
    this.Page.ClientScript.RegisterClientScriptBlock(
    	this.GetType(), "custom.js", SiteURL + "/_layouts/CustomPageHead/custom.js");
    
  26. For all other types of <head> section tags (i.e. style sheets and meta tags), put the content of the tag in an override of the OnInit function:
    protected override void OnInit(EventArgs e)
    {
    	Page.Init += delegate(object sender, EventArgs e_Init)
    	{
    		string SiteURL = SPContext.Current.Web.Url;
                    Page.Header.Controls.Add(new LiteralControl(
    			"<link rel="stylesheet" type="text/css" href=""
    			+ SiteURL + "/_layouts/CustomPageHead/custom.css" />"));
                    Page.Header.Controls.Add(new LiteralControl(
    			"<meta name="keywords" content="sharepoint,c-sharp" />"));
    	};
    	base.OnInit(e);
    }
    
  27. The complete CustomPageHead.ascx.cs file:
    using System;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using Microsoft.SharePoint;
    
    namespace CustomPageHead.CONTROLTEMPLATES.CustomPageHead
    {
        public partial class CustomPageHead : UserControl
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                string SiteURL = SPContext.Current.Web.Url;
                this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "custom.js", SiteURL + "/_layouts/CustomPageHead/custom.js");
            }
            protected override void OnInit(EventArgs e)
            {
                Page.Init += delegate(object sender, EventArgs e_Init)
                {
                    string SiteURL = SPContext.Current.Web.Url;
                    Page.Header.Controls.Add(new LiteralControl(
                        "<link rel="stylesheet" type="text/css" href=""
                        + SiteURL + "/_layouts/CustomPageHead/custom.css" />"));
                    Page.Header.Controls.Add(new LiteralControl(
                        "<meta name="keywords" content="sharepoint,c-sharp" />"));
                };
                base.OnInit(e);
            }
        }
    }
    
  28. Close any open documents.
  29. Right-click the solution name (CustomPageName) in the Solution Explorer.
  30. Select Add > New Item.
  31. Under Visual C# > SharePoint > 2010, select Empty Element.
  32. Give the Empty Element a name (CustomPageHead) and select Add.
  33. Replace the contents of the Elements.xml file with the following reference the the CustomPageHead User Control (this tells SharePoint to replace the AdditionalPageHead Content Place Holder with the CustomPageHead User Control):
    <?xml version="1.0" encoding="utf-8"?>
    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
      <Control Id="AdditionalPageHead"
               ControlSrc="~/_controltemplates/CustomPageHead/CustomPageHead.ascx" 
               Sequence="12"/>
    </Elements>
    
  34. When creating the Empty Element, a Feature file (Feature1.feature) was added automatically. Double-click the Feature1.feature file to open it.
  35. Give the feature a Title and a Description. These are both displayed on the Site Actions > Site Features page where the feature is activated and deactivated.
  36. Leave the Scope set to Web. A Web in SharePoint is the individual SharePoint site, whereas a Site is a SharePoint Site Collection.
  37. Now that the solution is complete, right-click the solution name (CustomPageHead) in the Solution Explorer.
  38. Select Deploy.
  39. The solution is now deploying to your test SharePoint site. The results of the deployment will be displayed in the Output window at the bottom of the screen.
  40. Once the deployment is complete, visit the test SharePoint site to verify it is working.

Now the solution can be packaged up and deployed to your other SharePoint farms and sites as necessary. This solution can be customized to add just about any tags to the <head> sections of each SharePoint page.

John Chapman

Hello, I'm John Chapman. I am a SharePoint Developer for Sitrion (formerly NewsGator) living in Denver, Colorado. I develop solutions using SharePoint and .NET, and I thrive on the challenge of writing code to overcome the impossible, annoying, or otherwise difficult obstacles.

More Posts - Website - Twitter - LinkedIn - Google Plus

  • enti

    Hello. Thank you for this article it’s perfect but I am very sorry but this doesn’t work for me.
    This code:

    this.Page.ClientScript.RegisterClientScriptBlock(
    this.GetType(), “custom.js”, SiteURL + “/_layouts/CustomPageHead/custom.js”);

    only add text without any element:

    http://intranet/_layouts/CustomPageHead/custom.css

    to every page. If I want to add link to JS file I must use something like you have used with css:

    Page.Header.Controls.Add(new LiteralControl(“”));

    Hmm….So my question is what for is good to have such code in the Page_Load method?

    Thank You

  • Ronen

    Hi John, can you expand on how this solution can be further extended to dynamically add different content based on configurable settings?

    Thanks

    • http://www.sharepointjohn.com John Chapman

      You could create an application settings page that saves the desired content to a site property (see http://www.codeproject.com/KB/sharepoint/SPFSitePorperty.aspx for examples on how to set custom site properties). This would let you set the options and customizations on a per site basis.

  • Alex C

    Very nice solution, Mr. Chapman. Thank you for the step-by-step guide.

  • Alex C

    By the way, is that your cat with lime skin on its head? Very cute!!

  • http://blog.vanmeeuwen-online.nl Rob v. M.

    Hi John,
    Thank you so much for this post. Exactly what I was looking for. Clear step-by-step quided. Thanks!

  • Pingback: [SharePoint 2010] JavaScript Errors in sp.ui.rte.js and sp.ui.rte.debug.js | John Chapman's SharePoint Blog