Add a Notification Message in Top Banner of the SharePoint Site using PowerShell

Requirement: Add a message to top banner area of a SharePoint site collection


PowerShell to Add Site Notification Message in SharePoint:
After the migration from SharePoint 2013 to SharePoint 2016, we wanted to add a message at the top banner of a migrated site.
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

Function Add-CustomAction
{
    param 
    (
        [parameter(Mandatory=$true, ParameterSetName='Site')]
        [Microsoft.SharePoint.SPSite]$Site,
        
        [parameter(Mandatory=$true, ParameterSetName='Web')]
        [Microsoft.SharePoint.SPWeb]$Web,
        
        [parameter(Mandatory=$true, ParameterSetName='Site')]
        [parameter(Mandatory=$true, ParameterSetName='Web')]
        [string]$Message,
        
        [parameter(Mandatory=$true, ParameterSetName='Site')]
        [parameter(Mandatory=$true, ParameterSetName='Web')]
        [string]$ActionName,
        
        [parameter(Mandatory=$false, ParameterSetName='Web')]
        [switch]$IncludeSubWebs,

        [parameter(Mandatory=$true, ParameterSetName='Site')]
        [parameter(Mandatory=$true, ParameterSetName='Web')]
        [string][ValidateSet("Red", "Yellow", "Green", "Blue")]$BackGroundColor
    )

    begin
    {
        # To avoid quote conflicts
        $Message = $Message.Replace( "`"", "'")

        $startingSequence = 1100
        $JavaScript = @"

            function Execute_$($ActionName)_MessageBar_$($PSCmdlet.ParameterSetName)()
            {
                var st = document.getElementById('$ActionName');
                if(st != null)
                {
                    st.style.display = '';
                    return;
                }

                st = document.createElement("div");
                st.id = "$($ActionName)_MessageBar_$($PSCmdlet.ParameterSetName)";
                st.innerHTML = "<div class='ms-status-$($BackGroundColor.ToLower())' style='padding: 12px 14px 6px; border: 1px solid; font-family: \"Segoe UI\", Tahoma, sans-serif; font-size: 13px; min-height: 24px;'>$Message</div>";

                document.body.insertBefore(st, document.body.childNodes[0]);
            }

            // don't show on modal dialog windows
            if(!window.location.search.match("[?&]IsDlg=1"))
            {
                Execute_$($ActionName)_MessageBar_$($PSCmdlet.ParameterSetName)();
            } 
"@
    }
    process
    {
        $customAction = $null
        
        if( $PSCmdlet.ParameterSetName -eq "Site" )
        {
            Remove-CustomAction -Site $site -ActionName $ActionName | Out-Null
            $customAction = $Site.UserCustomActions.Add()
        }
        else
        {
            Remove-CustomAction -Web $Web -ActionName $ActionName | Out-Null
            $customAction = $Web.UserCustomActions.Add()
        }

        $customAction.Location    = "ScriptLink"
        $customAction.Sequence    = $startingSequence
        $customAction.Title       = $ActionName
        $customAction.ScriptBlock = $JavaScript
        $customAction.Update()

        if( $IncludeSubWebs )
        {
            foreach($w in $Web.Webs)
            {
                Add-CustomAction -Web $w -Message $Message -ActionName $ActionName -IncludeSubWebs -BackGroundColor $BackGroundColor
            }
        }
    }
    end
    {
    }
}

Function Remove-CustomAction
{
    param 
    (
        [parameter(Mandatory=$true, ParameterSetName='Site')]
        [Microsoft.SharePoint.SPSite]$Site,
        
        [parameter(Mandatory=$true, ParameterSetName='Web')]
        [Microsoft.SharePoint.SPWeb]$Web,
        
        [parameter(Mandatory=$true, ParameterSetName='Site')]
        [parameter(Mandatory=$true, ParameterSetName='Web')]
        [string]$ActionName
    )

    begin
    {
        $existingActions = @()
    }
    process
    {
        if( $PSCmdlet.ParameterSetName -eq "Site" )
        {
            $Site.UserCustomActions | ? { $_.Title -eq $ActionName } | % { $existingActions += $_ }
            $existingActions | % { $Site.UserCustomActions.Item($_.Id).Delete() }
        }
        else
        {
            $Web.UserCustomActions | ? { $_.Title -eq $ActionName } | % { $existingActions += $_ }
            $existingActions
            $existingActions | % { $Web.UserCustomActions.Item($_.Id).Delete() }
        }
    }
    end
    {
    }
}

$Site = Get-SPSite -Identity "https://intranet.crescent.com/"
Add-CustomAction -Site $site -Message "This site has been migrated to SharePoint 2016. Please don't change anything here!" -ActionName "SiteMovedBanner" -BackGroundColor Red
To Set a notification at web level, use:
$web = Get-SPWeb -Identity "https://intranet.crescent.com/sites/marketing/us"
Add-CustomAction -Web $web -Message "This site has been migrated to SharePoint 2016. Please don't change anything here!" -ActionName "WebMovedBanner" -BackGroundColor Yellow -IncludeSubWebs
To Remove the Custom action, use:
Remove-CustomAction  -Site $site -ActionName "SiteMovedBanner"

11 comments:

  1. Great thanks :) Omg you've already solved all possible problems with administering,- i'm reading you for more than 4 years and still finding something useful))
    Please keep safe your website and its domain for the future admins generation)
    Tnanks a lot again!

    ReplyDelete
  2. Thanks for sharing this post; as stated in the comment above, it's a great post. The only question I have as for my usage experience is how to stop multiple instances of the banner getting added to the top for each page visited.

    ReplyDelete
    Replies
    1. I'm having the same issue with multiple instances of the banner getting added?

      Delete
    2. The only workaround I was able to came up with to answer the question I posted above was to perform the following addition to the code.

      1. Insert a variable declaration before line 39: [ var firstTimeFlag = "Yes" ]
      2. Enclose line 50 inside a If Statement: [ if(firstTimeFlag == "Yes") { document.body.insertBefore(st, document.body.childNodes[0]); } ]
      3. Finally, Insert a line to reset the value of flag before line 58: [ firstTimeFlag = "No" ]

      This modification is not necessary if you're able to get the code to function as is, but in the situation you ran into the issue I was confronted with; then try this modification.

      Delete
  3. I have the problem of duplicate banners as well. MyITGuy's workaround didn't work for me, it didn't work at all. Anybody come up with a way to avoid this? Refreshing the page (F5) gets rid of the extra banner, but I'd like to know how to avoid it in the first place.

    ReplyDelete
    Replies
    1. Try turning off the Minimal Download Strategy Feature. Works great for me.

      Stowe

      Delete
  4. HI All,
    First off this solution is really - really cool way to go.

    I found a very easy solution for the repeating banner problem. Go to Manage Site Features and DEACTIVATE the Minimal Download Strategy Feature.

    Works like a charm for me!

    Stowe

    ReplyDelete
  5. Thanks a ton, this solution works like a charm. I made a little modification around background color used Hex code instead, but awesome!!!!!

    ReplyDelete
  6. Thanks for the solution, It works in SP 2016. But it is not working in SP online, I tried CSOM with powershell code runs properly but it is not add the banner but i can able add ribbon controls. Please anyone suggest solution for this

    ReplyDelete
  7. How would you add an HREF link in the banner?

    ReplyDelete
    Replies
    1. Put it in the Add-CustomAction line:
      Add-CustomAction -Web $web -Message "This site is scheduled to be decommissioned after July 20th. If you need access to this site after that date, please [a href='PUT URL HERE'] read [/a] the following instructions to submit a change request to claim ownership of this site.[BR][BR]For any general questions, please reach out to [a href='EMAIL ADDRESS'] [email protected] [/a]" -ActionName "WebMovedBanner" -BackGroundColor Red -ForeGroundColor White -IncludeSubWebs

      This example is for the web level banner, but it's the same for a site level banner. NOTE: I had to use [] instead of <> to get the reply to show the code. There was probably a better way to do that, but HTML isn't one of my strong points.

      Delete

Please Login and comment to get your questions answered!

Powered by Blogger.