Luis Estefano
ServiceNow Employee
ServiceNow Employee

Service Portal is intended to give a great user experience to our employees or customers, allowing them to access their services on a quick and easy way.

 

But, what if we want to go one step forward and give them the best possible experience, we can align the portal with their corporative branding. In this way, the employees from different sub-companies, or the customers from different accounts could enjoy a better experience when accessing the Service Portal.

 

How we can accomplish MutiBranding Portal?

The idea is to create new StyleSheets per company/account we want to personalize the exprience for. Then, when accessing the Portal we check the logged in user company/account and load the StyleSheet if there is one for that particular company/account, and we keep the default styles if not.

 

 

 

SOLUTION


In the next example, we are personalising the experience for customers, so we are using the Account Number in order to distinguish the different StyleSheets, but it could be done also for employees/sub-companies. 

 

  1. Create StyleSheet with the Account Number as Name and set the personalised styles there. Do not attach the StyleSheet to the Portal theme, as it will be done dynamically based on the Account the logged in user is member of. 

    New StyleSheet: 
    • Name: ACCT0000001 (Account Number)
    • CSS: 
      body {
        /* Hack for prevent default styles to appear before the personalised ones */
        display: block; 
      }
      h2 a,
      a {	
         color: #ffa31a !important;
      }
      .navbar {
         background-color: #043559;
         border-bottom: .4rem solid #ffa31a !important;
      }
      .navbar .navbar-brand-logo {
         background-image: url('/Acme_logo_yellow.png');
         background-position: 10px 10px;
         background-repeat: no-repeat;
         background-size: 195px 50px;
         width:200px;
         height: 50px;
         margin: 0;
      }
      .navbar .navbar-brand-logo img {
         display: none !important;
      }
      .navbar a {
         color: #ffa31a !important;
         text-transform: uppercase !important;
         font-weight: bolder;
      }
      body main.body .cbe98a8d2cb20020000f8d856634c9c63 {
         background: rgb(2,0,36) !important;
         background: linear-gradient(180deg, rgba(2, 29, 49,1) 0%, rgba(4,53,89,1) 35%, rgba(0,212,255,1) 100%) !important;
      }
      main.body .homepage-quicklinks {
         background-color: #eeeeee;
      }
      main.body .homepage-quicklinks a h2 {
         color: #ffa31a;
      }
      .btn-primary {
         color: #043559;
         background-color: #00d4ff;
         border-color: #04a3c3;
      }
      .v94c300c7e777320075c2a117c2f6a9e7 .spw-announcements-root .details div.title div, .v94c300c7e777320075c2a117c2f6a9e7 .spw-announcements-root .details div.title a {
         color: #ffa31a;
      }
      .v1e699082d7001200a9addd173e24d4e3 .bs-callout-success {
          background-color: #ffe0b3 !important;
          border-color: #ffa31a !important;
      }​

      Note: it is a quick example in which we configure some basic colours for links, sections' backgrounds, and we change the corporative logo selecting one we previously uploaded to System Images.



  2. Create a client callable Script Include in which we define the function returning the Account number for the current user.

    New Script Include: 
    • Name: multiBrandingSP
    • API Name: global.multiBrandingSP
    • Client Callable: true
    • Application: Global
    • Accessible from: All application scopes
    • Active: true
    • Script: 

      var multiBrandingSP = Class.create();
      multiBrandingSP.prototype = Object.extendsObject(AbstractAjaxProcessor, {
      
          getStyleSheetFromAccount: function() {
              try {
      
                  var css_id = '';
                  var user_account_number = '';
      
                  // Get user account number
                  var userAccountGR = new GlideRecord('customer_account');
                  if (userAccountGR.get(gs.getUser().getCompanyID()))
                      user_account_number = userAccountGR.getValue('number');
      
                  // Get StyleSheet by name using the account number
                  var styleSheetGR = new GlideRecord('sp_css');
                  if (styleSheetGR.get('name', user_account_number))
                      css_id = styleSheetGR.getUniqueValue();
      
                  // Return StyleSheet sys_id
                  return css_id;
      
              } catch (e) {
                  gs.error('Error - ScriptInclude (multiBrandingSP): ' + e);
              }
          },
      
          type: 'multiBrandingSP'
      });


  3. Create a UI Script to load the StyleSheet if there is one for the user account. 

    New UI Script:
    • API name: serviceportal_overlay
    • UI Type: All
    • Application: Global
    • Active: true
    • Script: 

      loadMultiBrandingStyles();
      
      function loadMultiBrandingStyles() {
          // Call the Script Include in order to get the StyleSheet sys_id
          var ga = new GlideAjax('global.multiBrandingSP');
          ga.addParam('sysparm_name', 'getStyleSheetFromAccount');
          ga.getXML(uploadStyleSheet);
      }
      
      function uploadStyleSheet(response) {
      
          var answer = response.responseXML.documentElement.getAttribute("answer");
      
          // If any sys_id is returned, load the associated StyleSheet
          if (answer)
              jQuery('head').append('<link rel="stylesheet" type="text/css" href="/' + answer + '.spcssdbx?">');
      
          // Else allows the default styles to be displayed. 
          else
              jQuery('body').attr('style', 'display:block');
      }


  4. Attach the previous UI Script to the Service Portal theme

  5. Customise default StyleSheet for the theme in order to do not display content. It prevents the default styles to appear for an instant before we load the personalised styles. 

    If this is not needed, you can avoid the "else" code on the previous UI Script and also this 5th step. 

    Customise default StyleSheet: 
    • Name: sp-theme-la-jolla.css
    • CSS (add the following line): 
      body {display:none;}​

       

 

 

RESULT

Default Service Portal style when there is no StyleSheet defined for the logged in user account: 

 

LuisEstefano_0-1702838356091.png

 

 

 

Personalised Service Portal style when there is a StyleSheet defined for the logged in user account. In this example we changed the corporative logo, colours and backgrounds: 

LuisEstefano_1-1702838379553.png

 

 

 

ALTERNATIVE SOLUTION

Same solution could be achieved by different ways. Another one is to create a custom widget and embed it on the Portal Header, loading the desired StyleSheet if there is one associated with the user company/account. 

 

Widget Body HTML Template: 

 

 

<link href="/{{::data.css_id}}.spcssdbx?" rel="stylesheet" type="text/css" ng-if="data.css_id!=''" />

 

 

 

Widget Server Script: 

 

 

(function() {

    try {

        data.css_id = '';
        var user_account_number = '';

        var userAccountGR = new GlideRecord('customer_account');
        if (userAccountGR.get(gs.getUser().getCompanyID()))
            user_account_number = userAccountGR.getValue('number');

        var styleSheetGR = new GlideRecord('sp_css');
        if (styleSheetGR.get('name', user_account_number))
            data.css_id = styleSheetGR.getUniqueValue();


    } catch (e) {
        gs.error('Error - Widget (SN - Load Customer StyleSheet): ' + e);
    }

})();

 

 

 

Header Body HTML Template: 

 

 

<sp-widget widget="data.loadCustomerStyle"></sp-widget>

 

 

 

 

 

 

SOLUTION CONSIDERATIONS

The proposed solution has no contras or secondary effects as it does not require any update on ootb records, so there will not be any conflict raised when upgrading the platform. On the other hand, the alternative solution is updating the Portal Header and could require some effort on maintenance/upgrade, that is why it is not the best option. 

 

 

Hope it helps! 😉

 

Kind regards,

Luis Estéfano

Comments
sjadhav1
Tera Expert

Hello @Luis Estefano,

We have a similar requirement, we need to display different background image in the Employee Center(esc portal) based on the logged in user company. If the company field is empty, we need to display the default image which has been set in the container using the 'Instance in Page Editor'. We have tried the above given solution, but the image is not getting displayed.

Luis Estefano
ServiceNow Employee
ServiceNow Employee

Hi @sjadhav1,

 

the previous configuration has been designed for SP portal, not ESC. For ESC you need to do some adjustments on the CSS and adapt the styles to the ESC Theme. 

 

 

For example, we change the background gradient with the following lines:

body main.body .cbe98a8d2cb20020000f8d856634c9c63 {
   background: rgb(2,0,36) !important;
   background: linear-gradient(180deg, rgba(2, 29, 49,1) 0%, rgba(4,53,89,1) 35%, rgba(0,212,255,1) 100%) !important;
}

 

In the ESC Portal, the HTML elements are not the same and you need to adapt it. Something like this could do the trick:

body > div > section.page {
   background: rgb(2,0,36) !important;
   background: linear-gradient(180deg, rgba(2, 29, 49,1) 0%, rgba(4,53,89,1) 35%, rgba(0,212,255,1) 100%) !important;
}

 

 

The result on ESC would look like: 

LuisEstefano_0-1709282704170.png

 

Please, let me know if that helps! Thank you!

 

Kind regards,

Luis Estéfano

Smita9
Tera Contributor

Hello Luis,

Can we do multi-branding on Mobile agent?

Thanks!

alex2410
Tera Contributor

Hello @Luis Estefano ,

 

Could you please explain this step in more detail - 


Attach the previous UI Script to the Service Portal theme

 

Thank you!

Luis Estefano
ServiceNow Employee
ServiceNow Employee

Hi @Smita9,

 

For mobile theming, you have legacy and the Next Experience theming, depending on your current release and configuration. However, mobile theming is configured differently from Service Portals, so this approach doesn't apply to the Mobile App.

 

ServiceNow Documentation

 

I hope this clarifies things, and apologies for the delayed response!

 

 

Kind regards,

Luis Estéfano

Luis Estefano
ServiceNow Employee
ServiceNow Employee

Hello @alex2410

 

Sure, let me provide more details on those steps:

  1. Go to the Portal Record [sp_portal]
    "Service Portal -> Portals" from the main menu
  2. Access the associated Theme [sp_theme]
    "Theme" field on Portal record
  3. Navigate to the related lists and create a new JS Include [m2m_sp_theme_js_include]
    "JS Include" related list is at the bottom of the Theme form by default
  4. Add the UI Script to the JS Include, ensuring it is attached to the Portal Theme.

 

I hope this helps you get it working, do not hesitate to ask if it is not clear enough!

 

Kind regards,

Luis Estéfano

RichardK781
Tera Contributor

@Luis Estefano I am trying to apply same for portal-polaris-common-theme? any tips on how to go forward?

 

Luis Estefano
ServiceNow Employee
ServiceNow Employee

Hello @RichardK781 , 

The solution is the same; however, you'll need to adjust the CSS styles to match the specific theme you want to customize for each account. Anyone with basic CSS knowledge should be able to handle this, but feel free to reach out if you need assistance. I'll be happy to provide guidance or insights.

Kind regards,
Luis Estéfano

BrianMoore9
Tera Contributor

If you're dealing with multiple portals and unique branding for each, a solid approach is to use custom themes alongside appropriate widgets and CSS adjustments. I’ve found that setting up brand-specific UI scripts helps maintain consistency across different portals without breaking existing functionality. It might be useful to check if someone has shared additional insights on the kickstarter page, as these discussions often bring out clever workarounds.

Version history
Last update:
‎04-15-2024 02:52 AM
Updated by:
Contributors