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"

17 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
    Replies
    1. Hi Nitesh,

      Applying background color is not working for me. Others are working like a charm. Could you please help me to apply background color.

      Delete
  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
    2. Hi, Is there a way to put a message in the banner and do a auto redirection to the new migrated site in 10 or 20 seconds

      Delete
  8. Will this work on SharePoint 2010 sites that you are migrating to SharePoint online?

    ReplyDelete
  9. Is there a way we can add/remove banner onto multiple site collection utilizing the above script.
    Either we pick up site collections URL from single variable or sharepoint list etc.
    I have tried to use below approach, but it throws an error "Add-CustomAction : Cannot process argument transformation on parameter 'Site'. Cannot convert the "System.Object[]" value of type "System.Object[]" to type "Microsoft.SharePoint.SPSite"."

    $Site= @(
    "https://contoso./sites/Test"
    "https://contoso.com/sites/Test2"
    )

    ReplyDelete
  10. Hello guys, is anyone able to guide towards solution to above query November 17, 2020 at 6:09 PM.

    ReplyDelete
  11. Hello Guys, After putting up a notification message, I want the site to redirected automatically to newly migrated site in 10 secs. Can someone help me on the same.

    ReplyDelete

Please Login and comment to get your questions answered!

Powered by Blogger.