This article will give a simple example "or remember" on how you can use the Delegate controls to change Layout or simple add a global link in all SharePoint Sites without changing the Masterpages.
When i had 9 year old i was learning on how to make a newspaper article and teach me i should always answer the following questions:
Who?
Delegate Control already exist from older versions of SharePoint and can be very usefull when we want to create global Action that have impact in one or more SharePoint Sites.
There are a lot of articles talking on how we can use Delegate control "example" and don't wan't to repeat and make more "Social 2.0 noise...".
I already see a lot of article explaining on how easy is to Create/change global controls but you need to be carefull and think what are the consequence of this changes,
By default some of this delegates control already have features associated and if you want to change you will need to be carefull to don't deactivate or remove the OOB actions associated, for example if you change or add features in the delegate control "GlobalSiteLink3,GlobalSiteLink2"
If you access the Element file "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\FEATURES\SocialRibbonControl\SocialDelegateControl.xml" you can see this control already have actions associated and if you change or add new control you can broke the normal behavior of SharePoint Sites.
Content of "DelegateControl.xml":
<Control Id="GlobalSiteLink3" Sequence="100"
ControlClass="Microsoft.SharePoint.Portal.WebControls.SocialNotificationControl"
ControlAssembly="Microsoft.SharePoint.Portal, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<Control Id="GlobalSiteLink3-mini" Sequence="100"
ControlClass="Microsoft.SharePoint.Portal.WebControls.SocialNotificationMiniControl"
ControlAssembly="Microsoft.SharePoint.Portal, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<Control Id="GlobalSiteLink2" Sequence="100" ControlSrc="~/_controltemplates/socialdata.ascx" />
<Control Id="GlobalSiteLink2-mini" Sequence="100"
ControlClass="Microsoft.SharePoint.Portal.WebControls.SocialNavigationControl"
ControlAssembly="Microsoft.SharePoint.Portal, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
But for this article i want to make focus in the "AdditionalPageHead" control.
This control is somehow more special then others because one property "AllowMultipleControls".
This property give the ability to add multiple controls without Deactivating/overwrite existing OOB controls, giving more flexibility injecting ECMAScript and users/custom Controls.
Some Out of the Box Delegate Controls:
AdditionalPageHead - Delegate controlo allocated in top site - AllowMultipleControls
GlobalSiteLink0
GlobalSiteLink1
GlobalSiteLink2
SmallSearchInputBox
TopNavigationDataSource
PublishingConsole
QuickLaunchDataSource
What?
I want to create a global link in top left of Welcome Control to be accesible in all SharePoint Sites.
For this change was used the Internet explorer developer Tool to detect how the Welcome Control was added and inject some Javascript to make the change using firebug.
After the Script is created, make a litle test in the current SharePoint Page, edit the Page and add Form Web Part and inject the following Javascript:
Why?
I use Delegate Control to dont change Masterpages for all Sites...
Where?
To response this request Globaly was created a Visual Studio 2010 SharePoint Solution with Feature, since this solution need to be deployed globaly is used a Farm Solution.
We can define differents scopes where this Feature can be deployed "Farm, WebApplication, Site, Web", but if you install/activate with Scope "Farm" the Central Administration will also have the Support Link, i can recomend "Farm, WebApplication Scope" depending what you want to manage.
Create a User control where will have your code...
[Hive]CONTROLTEMPLATES\CustomHeader\CustomHeader.ascx
Content of CustomHeader.ascx "You can also include Server Side code to add multiple actions"

The "How?" is the process taken to response all other questions.
Support links:
Delegate Control
http://msdn.microsoft.com/en-us/library/ms463169.aspx
How to: Customize a Delegate Control
http://msdn.microsoft.com/en-us/library/ms470880.aspx
AllowMultipleControls
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.delegatecontrol.aspx
Replace SharePoint 2010 Search Box using Delegate Control
http://msmvps.com/blogs/sundar_narasiman/archive/2011/02/19/sharepoint-2010-delegate-control-to-replace-smallsearchinputbox.aspx
Using the Delegate Control
http://www.sharepointnutsandbolts.com/2007/06/using-delegate-control.html
Useful Delegate Controls in Windows SharePoint Services 3.0
http://www.wictorwilen.se/Post/Useful-Delegate-Controls-in-Windows-SharePoint-Services-30.aspx
PS: This script was only tested with Team Site Templates, you will need validate the other templates or change the script to have the same behavior.
---------------------------------------------------------------------------------------------------
Updated 05.03.2012
The code is updated ttrying to response all Templates
<script type="text/javascript">
ExecuteOrDelayUntilScriptLoaded(LoadLink, "sp.js");
function LoadLink() {
function getByClass (className, parent) {
parent || (parent=document);
var descendants=parent.getElementsByTagName('*'), i=-1, e, result=[];
while (e=descendants[++i]) {
((' '+(e['class']||e.className)+' ').indexOf(' '+className+' ') > -1) && result.push(e);
}
return result;
}
var myMenuContainer = getByClass ( 'ms-welcomeMenu' )[0].parentNode ;
var newSpan = document.createElement("span");
newSpan.innerHTML = '<a class="ms-menu-a" style="cursor:pointer;white-space:nowrap;" href="#" onclick="window.location=\'http://www.sharepointpt.org\';return false;"><span>SharePoint PT</span></a>';
newSpan.className = 'ms-SPLink ms-SpLinkButtonInActive ms-welcomeMenu';
myMenuContainer.insertBefore(newSpan, myMenuContainer.children[1]);
}
</script>
<noscript>
Your browser does not support JavaScript!
</noscript>
---------------------------------------------------------------------------------------------------
Code updated 08-05-2012 (improved efficiency in load)
typeof (ExecuteOrDelayUntilBodyLoaded) != "undefined" && ExecuteOrDelayUntilBodyLoaded(function () {
var welcomeMenuContainer, linkSpan;
//build link markup
linkSpan = document.createElement('span');
linkSpan.className = 'ms-SPLink ms-SpLinkButtonInActive ms-welcomeMenu';
linkSpan.innerHTML = '<a class="ms-menu-a" style="cursor:pointer; white-space:nowrap;" href="#" onclick="window.location=\'http://www.sharepointpt.org\'; return false;"><span>SharePoint PT</span></a>';
//inject link markup
welcomeMenuContainer = GetElementByClassName(window.document, 'ms-welcomeMenu').parentNode;
welcomeMenuContainer.insertBefore(linkSpan, welcomeMenuContainer.children[1]);
});
Thank you Marco Oechslin. :)
Link to Project.
Hope this help,
Kind regards
When i had 9 year old i was learning on how to make a newspaper article and teach me i should always answer the following questions:
- What?
- Who?
- Where?
- When?
- Why?
- How?
Who?
Delegate Control already exist from older versions of SharePoint and can be very usefull when we want to create global Action that have impact in one or more SharePoint Sites.
There are a lot of articles talking on how we can use Delegate control "example" and don't wan't to repeat and make more "Social 2.0 noise...".
I already see a lot of article explaining on how easy is to Create/change global controls but you need to be carefull and think what are the consequence of this changes,
By default some of this delegates control already have features associated and if you want to change you will need to be carefull to don't deactivate or remove the OOB actions associated, for example if you change or add features in the delegate control "GlobalSiteLink3,GlobalSiteLink2"
If you access the Element file "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\FEATURES\SocialRibbonControl\SocialDelegateControl.xml" you can see this control already have actions associated and if you change or add new control you can broke the normal behavior of SharePoint Sites.
Content of "DelegateControl.xml":
<Control Id="GlobalSiteLink3" Sequence="100"
ControlClass="Microsoft.SharePoint.Portal.WebControls.SocialNotificationControl"
ControlAssembly="Microsoft.SharePoint.Portal, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<Control Id="GlobalSiteLink3-mini" Sequence="100"
ControlClass="Microsoft.SharePoint.Portal.WebControls.SocialNotificationMiniControl"
ControlAssembly="Microsoft.SharePoint.Portal, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<Control Id="GlobalSiteLink2" Sequence="100" ControlSrc="~/_controltemplates/socialdata.ascx" />
<Control Id="GlobalSiteLink2-mini" Sequence="100"
ControlClass="Microsoft.SharePoint.Portal.WebControls.SocialNavigationControl"
ControlAssembly="Microsoft.SharePoint.Portal, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
But for this article i want to make focus in the "AdditionalPageHead" control.
This control is somehow more special then others because one property "AllowMultipleControls".
This property give the ability to add multiple controls without Deactivating/overwrite existing OOB controls, giving more flexibility injecting ECMAScript and users/custom Controls.
Some Out of the Box Delegate Controls:
What?
I want to create a global link in top left of Welcome Control to be accesible in all SharePoint Sites.
For this change was used the Internet explorer developer Tool to detect how the Welcome Control was added and inject some Javascript to make the change using firebug.
After the Script is created, make a litle test in the current SharePoint Page, edit the Page and add Form Web Part and inject the following Javascript:
<script type="text/javascript"> ExecuteOrDelayUntilScriptLoaded(LoadLink, "sp.js"); function LoadLink() { var myMenuContainer = document.getElementById('RibbonContainer-TabRowRight').children[2].children[0]; var newSpan = document.createElement("span"); newSpan.innerHTML = '<a class="ms-menu-a" style="cursor:pointer;white-space:nowrap;" href="#" onclick="window.location=\'http://www.sharepointpt.org\';return false;"><span>SharePoint PT</span></a>'; newSpan.className = 'ms-SPLink ms-SpLinkButtonInActive ms-welcomeMenu'; myMenuContainer.insertBefore(newSpan, myMenuContainer.children[1]); } </script>
When?
Load javascript after the page is loaded because the javascript needs to indentify the HTML ID "RibbonContainer-TabRowRight".
ExecuteOrDelayUntilScriptLoaded(LoadLink, "sp.js");
Why?
I use Delegate Control to dont change Masterpages for all Sites...
Where?
To response this request Globaly was created a Visual Studio 2010 SharePoint Solution with Feature, since this solution need to be deployed globaly is used a Farm Solution.
We can define differents scopes where this Feature can be deployed "Farm, WebApplication, Site, Web", but if you install/activate with Scope "Farm" the Central Administration will also have the Support Link, i can recomend "Farm, WebApplication Scope" depending what you want to manage.
Create a User control where will have your code...
[Hive]CONTROLTEMPLATES\CustomHeader\CustomHeader.ascx
Content of CustomHeader.ascx "You can also include Server Side code to add multiple actions"
<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %> <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="CustomHeader.ascx.cs" Inherits="CustomHeader.CONTROLTEMPLATES.CustomHeader.CustomHeader" %> <script type="text/javascript"> ExecuteOrDelayUntilScriptLoaded(LoadLink, "sp.js"); function LoadLink() { var myMenuContainer = document.getElementById('RibbonContainer-TabRowRight').children[2].children[0]; var newSpan = document.createElement("span"); newSpan.innerHTML = '<a class="ms-menu-a" style="cursor:pointer;white-space:nowrap;" href="#" onclick="window.location=\'https://www.sharepointpt.org\';return false;"><span>SharePoint PT</span></a>'; newSpan.className = 'ms-SPLink ms-SpLinkButtonInActive ms-welcomeMenu'; myMenuContainer.insertBefore(newSpan, myMenuContainer.children[1]); } </script>
Elements File
Reference to User control used to add custom control or inject Javascript.
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Control Id="AdditionalPageHead" Sequence="100" ControlSrc="~/_CONTROLTEMPLATES/CustomHeader/CustomHeader.ascx"></Control>
</Elements>
After deployed the Solution the link will be visible in top right of the SharePoint Site.

The "How?" is the process taken to response all other questions.
Support links:
Delegate Control
http://msdn.microsoft.com/en-us/library/ms463169.aspx
How to: Customize a Delegate Control
http://msdn.microsoft.com/en-us/library/ms470880.aspx
AllowMultipleControls
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.delegatecontrol.aspx
Replace SharePoint 2010 Search Box using Delegate Control
http://msmvps.com/blogs/sundar_narasiman/archive/2011/02/19/sharepoint-2010-delegate-control-to-replace-smallsearchinputbox.aspx
Using the Delegate Control
http://www.sharepointnutsandbolts.com/2007/06/using-delegate-control.html
Useful Delegate Controls in Windows SharePoint Services 3.0
http://www.wictorwilen.se/Post/Useful-Delegate-Controls-in-Windows-SharePoint-Services-30.aspx
PS: This script was only tested with Team Site Templates, you will need validate the other templates or change the script to have the same behavior.
---------------------------------------------------------------------------------------------------
Updated 05.03.2012
The code is updated ttrying to response all Templates
<script type="text/javascript">
ExecuteOrDelayUntilScriptLoaded(LoadLink, "sp.js");
function LoadLink() {
function getByClass (className, parent) {
parent || (parent=document);
var descendants=parent.getElementsByTagName('*'), i=-1, e, result=[];
while (e=descendants[++i]) {
((' '+(e['class']||e.className)+' ').indexOf(' '+className+' ') > -1) && result.push(e);
}
return result;
}
var myMenuContainer = getByClass ( 'ms-welcomeMenu' )[0].parentNode ;
var newSpan = document.createElement("span");
newSpan.innerHTML = '<a class="ms-menu-a" style="cursor:pointer;white-space:nowrap;" href="#" onclick="window.location=\'http://www.sharepointpt.org\';return false;"><span>SharePoint PT</span></a>';
newSpan.className = 'ms-SPLink ms-SpLinkButtonInActive ms-welcomeMenu';
myMenuContainer.insertBefore(newSpan, myMenuContainer.children[1]);
}
</script>
<noscript>
Your browser does not support JavaScript!
</noscript>
---------------------------------------------------------------------------------------------------
Code updated 08-05-2012 (improved efficiency in load)
typeof (ExecuteOrDelayUntilBodyLoaded) != "undefined" && ExecuteOrDelayUntilBodyLoaded(function () {
var welcomeMenuContainer, linkSpan;
//build link markup
linkSpan = document.createElement('span');
linkSpan.className = 'ms-SPLink ms-SpLinkButtonInActive ms-welcomeMenu';
linkSpan.innerHTML = '<a class="ms-menu-a" style="cursor:pointer; white-space:nowrap;" href="#" onclick="window.location=\'http://www.sharepointpt.org\'; return false;"><span>SharePoint PT</span></a>';
//inject link markup
welcomeMenuContainer = GetElementByClassName(window.document, 'ms-welcomeMenu').parentNode;
welcomeMenuContainer.insertBefore(linkSpan, welcomeMenuContainer.children[1]);
});
Thank you Marco Oechslin. :)
Link to Project.
Hope this help,
Kind regards