Customize the Header

Previously, we have talked about how you can Customize Your Homepage. This time around I want to talk about something that is of similar ubiquity: the header.

Located ever vigilantly at the top of the page, the header comprises:

  • The site logo
  • The navigation menu
  • The minicart
  • Links to log in / register or, if the shopper is logged in, a user summary
  • Site search

You can find the files for this module in Modules > suitecommerce > Header.

For the purposes of this article, I'm going to talk about some of the customizations that you can do to the site logo and navigation menu.

SC.Configuration.js

Before I get to specifics, however, I want to talk about a very important file, not only in this module but also your site. Located in Modules > suitecommerce > SCA is SC.Configuration.js. This is a configuration file that contains a number of vital settings that dictate how some modules behave. As you look through the JavaScript files for the header, you'll frequently see it as a dependency. It is one of four frontend configuration files that is included in SCA; as it is the global one, it applies throughout the site and not one particular application (i.e., Shopping, My Account and Checkout).

You can read more about it and the other configuration files in our documentation.

Before You Start

Remember, as always, we strongly recommend creating overrides for any template changes you make rather simply editing the source files.

Also note that we're going to be creating a special extension (like an override) of the configuration file, that is different because of its nature. We'll come to that in due time.

Change Your Logo

This bit isn't too complicated. The site logo displays throughout the site as a permanent reminder of your site's brand. Furthermore, it has become a common standard in web design that the logo always provides a link back to the homepage.

The site logo is controlled by Header.Logo.View.js and header_logo.tpl. Most commonly you simply either need to change the image file of the logo itself, or the location of the file. By default we store the logo in img/SCA_Logo.png. So you can simply swap that out with your site's logo if you wish.

Alternatively, you can upload your site logo, to its own location and/or filename, and modify the path. The path is stored in SC.Configuration.js as the logoUrl property. Change it here rather than hardcoding it into your template or view.

If you're unfamiliar with how to work with static images, see article on it.

One final note: notice that for our default design we keep the logo quite small. When choosing a logo, remember to keep its dimensions inline with your site's design so that it looks good at all responsive views.

Navigation Menu

Depending on the size of your site / product catalog, you may not want a navigation with a lot of links in it. For example, luxury brand sites with a limited range typically prefer to keep links to a minimum so that they have a simplistic look. Other sites, perhaps clothing retailers that cater for all genders, ages, styles, etc., will have a very detailed menu so that shoppers can drill drown to their product lines very quickly. Before starting you should consider what links you want to offer customers.

The navigation can take two forms. One is shown to desktop users, or, specifically, users with a viewport wider than the medium minimum amount ($screen-md-min), and the other to tablet and mobile users (i.e., when it is lower than this amount). I will talk about them individually in a moment, but first let's look at where the data comes from.

Navigation Data and Template

As you might have guessed by now, we store the data for the navigation in SC.Configuration.js. There are two properties you need to know:

  1. navigationDummyCategories — for the purposes of the demo site, we have included some JSON data which are effectively sub-categories, which appear in the header menus of each of the categories in the navigation.
  2. navigationData — this is where the main navigation data is stored. It is an array of objects, with each object determining a navigational item.

For simplicity, we have coded navigationDummyCategories this way so that sub-categories are quick and easy to generate. When creating your own navigation, you can remove this property and change the structure of the property that calls them.

So as you can see, navigationData is the main data. Each top-level object becomes a main navigational item; if the object contains a category property then those objects become navigational sub-items.

The properties for each of the items are passed to header_menu.tpl. Handlebars loops through the categories in the template file, iterating each category item and then each level of categories below it. While we include three levels by default, you could go further but this may not provide good user experience.

Extend SC.Configuration.js

So you should have an idea about the items you want to include in your menu. As always, we never modify the source files so we need to create a separate file for our modifications. For configuration files, this requires us to extend the file. It functions in a similar way to overrides but rather than overriding a whole module or file, it allows us to override specific values in the file (and add our own).

So, to start, create a directory in your folder that you use for your site's customizations. You can call it what you like, but for me I'm going to call it CustomConfigurations. Then I'm going to create an entry point file like I normally would under the JavaScript directory. Do the same and it should look like the following:

  • Modules

    • CustomConfigurations@1.0.0

      • JavaScript

        • CustomConfigurations.js

Within this file, I'm going to set up the file like I normally would by including my dependencies and a mountToApp function. I know my navigation data, so I'm going to put the following into the file:

define(
  'CustomConfigurations'
, [
    'SC.Configuration'
  ]
  , function (
      Configuration
  )
{
  'use strict';

  return  {

    mountToApp: function (application) {

      Configuration.navigationData = [
      {
        text: _('Home').translate()
      , href: '/'
      , 'class': 'header-menu-home-anchor'
      , data: {
          touchpoint: 'home'
        , hashtag: '#/'
        }
      },
      {
        text: _('Shop').translate()
      , href: '/search'
      , 'class': 'header-menu-shop-anchor'
      , data: {
          touchpoint: 'home'
        , hashtag: '#/search'
        }
      },
      {
        text: _('Men').translate()
      , href: '/search'
      , 'class': 'header-menu-men-anchor'
      , categories: [
        {
          text: _('Shirts Under $30').translate()
        , href: '/search'
        , 'class': 'header-menu-level3-anchor'
        , data: {
            touchpoint: 'home'
          , hashtag: '#/pricelevel5/0to30?keywords=shirt'
          }
        }]
      },
      {
        text: _('Women').translate()
      , href: '/search'
      , 'class': 'header-menu-women-anchor'
      , categories: [
        {
          text: _('10% Off Dresses').translate()
        , href: '/search'
        , 'class': 'header-menu-level3-anchor'
        , data: {
            touchpoint: 'home'
          , hashtag: '#search?keywords=dress&promocode=tenoff'
          }
        }]
      },
      {
        text: _('Outdoor Wear').translate()
      , href: '/search'
      , 'class': 'header-menu-outdoor-anchor'
      , categories: [
        {
          text: _('Red Jackets').translate()
        , href: '/search'
        , 'class': 'header-menu-level3-anchor'
        , data: {
            touchpoint: 'home'
          , hashtag: '#/custitem31/red?keywords=jacket'
          }
        }]
      }]
    }
  };
});

So the mountToApp method loads the custom module into the application and in doing so adds all of the custom properties that we've added. In this case, we have added our overrides for the navigation data. Note that we've prefixed Configuration before the declaration as that is the name we gave the configuration file we're overriding (and listed as dependency). At this point, you could also add in any other overrides or, indeed, any extra properties that you want to add to your configuration.

After saving the file you'll need to create an ns.package.json file in the root of the module folder. In it, put the following:

{
  "gulp": {
    "javascript": [
      "JavaScript/*.js"
    ]
  }
}

After saving that, update the distro.json file to include the new module:

  1. First, add the name of the module to the list of modules in the modules object (e.g., "efficiencies/CustomConfigurations": "1.0.0").
  2. Then add the module to the dependencies array of the applications we're going to use it in. As this is a global change, we'll need to add it to all of them. Thus, in turn, search for "shopping.js", "myaccount.js" and "checkout.js" and add it to each dependencies array.

Save the file as well. Just before we test this, we need to add in some styling.

Style the Menu Items

So you should have created an override for the Header module. In it you'll need to find the styling for the menu items. For maximum flexibility, you'll notice in the data and the template that we have added in support for custom classes for each item (we gave them the classes of header-menu-women-anchor and header-menu-outdoor-anchor, for example). However, we added support in the Sass so that you can use a standard class for these items if you want. If you do a search in the Sass for .header-menu-home-anchor you'll find the styling I'm talking about. Add the new selectors so it looks something like the following:

.header-menu-home-anchor,
.header-menu-shop-anchor,
.header-menu-men-anchor,
.header-menu-women-anchor,
.header-menu-outdoor-anchor{
    @extend .header-menu-level1-anchor;
    color:$sc-color-secondary;
}

Now we're ready to test. Save all the files and start (or restart) your local server and visit your local site. It should look something like the following:

Customization Ideas

I've given you the basics of what you can do with the navigation menu and its data, but there are some other ideas that you could do with your site.

URL Parameters

You'll notice in the sample data I provided above that I've included some interesting values for the hashtag property. Let me just give you an idea about the sort of thing you can include:

  1. #/pricelevel5/0to30?keywords=shirt — my site is configured to use the pricelevel5 field to sort by price. By including that in the URL, followed by a value (e.g., "0to30"), I'm able to filter results by price, namely products $30 or cheaper. If you tack on a keyword search, like "shirt", you're able to effectively return shirts cheaper than $30.
  2. #search?keywords=dress&promocode=tenoff — similarly, this is a keyword search. However, you may not know that you can apply promotion codes via the promocode URL parameter. In this case, I've set up a promotion that applies a 10% discount to orders. When the user clicks the link they are taken to a keyword search for "dress" and a promotion is automatically applied to their cart.
  3. #/custitem31/red?keywords=jacket — this returns jackets that are red. It's quite simple, but for sites that sell apparel you could, for example, configure a link for 'black dresses'.

Think about your fieldsets and think about what you could expose to your customers as searches.

Add Custom Properties

I talked a bit about the class property, and how you could just remove it from the data and the template. You could simplify the whole thing and hardcode the class like all the other classes in the template.

But remember that the data structure we've provided is only necessary because of the template we've provided. You can very easily add your own data to the JSON and then use this data in your template.

One idea I had is that you could add in imagery. You need to be careful with images that you include in your navigation menu (because it needs to work at all resolutions) but you could set up your data with an image property and then add in a check to show an image in your template if it exists. It could be as simple as doing the following:

{{#if image}}<img src="{{image}}">{{/if}}

Again, if you're unfamiliar with how to work with static images then refer to the article on it.

My final bit of advice, though, is not to make it too complicated. Remember that we used Handlebars for templating, which is meant to be logicless. The more complicated and conditional you make the data, the harder it'll be to make it a reality (and harder it will be to maintain).

Hardcode the Menu

All of this is set up to use a dynamic, iterative approach to generating the menu. If you wanted to, you could discard the entire notion of navigation data and using #each loops in your template.

We don't recommend against this approach, but keep in mind that while it gives you maximum control of the template it will increase the amount of time you will spend maintaining the navigation menu.

If you do decide to hardcode your navigation, note the impact it has on the navigation menu used for mobile and tablet devices (called the header sidebar), which uses separate code.

Header Sidebar

The header sidebar is what is shown on the mobile and tablet views. It's what replaces the header menu and is hidden until the user taps the icon that looks like a burger.

It's part of the same Header module and uses the same Header.View.js view as the main navigation menu but has other files that it depends on:

  • jQuery.sidebarMenu.js — a custom jQuery plugin that handles the animation of the sidebar.
  • header_sidebar.tpl — a template file that resembles and operates similarly to header_menu.tpl.
  • _header-sidebar.scss — a Sass file that contains the template's styling.

The advice for customizing this is similar to that of the main navigation code. As you'll see in the template, it works by iterating through the categories in the navigation data and generating sub-menus for each item.

The good thing about this separation but similarity is that it enables you to customize one as much as you want, while the other is untouched. You can have separate behavior and design for each, or work to bring the two together.

The only thing I would say is keep in mind that this area of functionality is meant to be simple and easy-to-use and not to over-complicate it. You may find, in fact, that after putting in your navigation data that you do not need to make any customizations to the sidebar, other than, say, superficial changes with Sass.

Summary

The Header module includes a number of items of functionality and in this article we looked specifically at the functionality used for navigation around the site.

You can customize them to suit your site's design and navigational needs. By default, the items in the menu are generated dynamically using JSON data in the global configuration file, SC.Configuration.js and to make modifications to this data we looked at how you can create an extension to this, which in some ways operates like an override. Once you have that data, you can then plug that into the template which iterates through it, generating each of the items.

We then looked at other ways you can customize this data by, for example, adding custom properties and modifying the templates to use that data, and interesting URL parameters that you can include to kick off searches.

Finally, we looked at the sidebar that is used by mobile and tablet users. Logically, it functions similarly to the main navigation menu in that it uses the same data and a similar looking template, but it does require an additional jQuery plugin that we have provided.

Further Reading