An SSP sitemap is an arrangement of your site’s pages to help your visitors navigate within it. Most sites have a definite ‘home’ page, and probably have a page giving the author’s contact details, and then lots of other pages that can be grouped or subgrouped in various ways, usually forming some sort of hierarchy. A book-seller might use this hierarchy, for example:

SSP sitemaps are written in XML, so you’ll need some standard ‘boilerplating’ to begin with:

<?xml version="1.0" encoding="utf-8" ?>
<sitemap xmlns="http://standard-sitemap.org/2007/ns">

<!-- your items here -->

</sitemap>

Now add each of the items. Subitems can be placed inside their parent.

<?xml version="1.0" encoding="utf-8" ?>
<sitemap xmlns="http://standard-sitemap.org/2007/ns">

  <item name="Home" url="." />
  <item name="Catalogue" url="catalogue.html">
    <item name="Fiction">
      <item name="Authors" url="author-index.html" />
      <item name="Genres" url="genre-index.html" />
    </item>
    <item name="Non-fiction">
      <item name="Science" url="science-index.html" />
      <item name="Art" url="art-index.html" />
      <item name="Leisure" url="leisure-index.html" />
      <item name="Humanities" url="humanities-index.html" />
    </item>
  </item>
  <item name="Basket" url="your-basket.cgi" />
  <item name="Wishlist" url="your-wishlist.cgi" />
  <item name="Search" url="search.cgi" />
  <item name="Contact" url="contact.html" />
`
</sitemap>

Note that each item has a name, but most have a url attribute too. These are relative to the sitemap’s location. Some items don’t have a url, and are used just to group other items.

You can also give an item a verbose description:

<item name="Basket" url="your-basket.cgi"
   description="Check what you currently have in your basket." />

Roles

This is certainly one of the coolest features introduced by the Standard-Sitemap Protocol. The idea is to keep important items in the very same place, making them easier for the user to spot. You give an item a role with the role attribute:

<item name="Contact" url="contact.cgi"
   role="contact" />

The following roles are defined:

home
The home page — If no item has this role, the first item is used.
contact
A page for contact details
contentinfo
Central repository for all “background” information about the site, especially legal information like imprint, terms and conditions, privacy policy, etc.)
search
Site search mechanism
tree
Sitemap tree item — Formally, this is the default, so you probably won’t ever need to use it explicitly.

Items with roles contact and contentinfo are not displayed in the sidebar. To override this, you should use a tree attribute:

<item name="Contact us" role="contact" tree="include" />
include
Prevents the item from being hidden altogether.
exclude
Prevents the item from ever being shown.
user
The item will be hidden if it only has concealable roles, and the user prefers not to see such items. This is the default.
auto
The item will be hidden if it only has concealable roles, and the extension chooses to hide it.

Site search

If you’ve invested the time to put a search function on your site, you can make it appear in the sitemap too — not just as an item that takes the visitor to a search page, but as a search box that doesn’t appears as part of the browser. Here’s the code to use for a simple GET script:

<item role="search"
       url="search.php"
      data="q=%s" />

In our Firefox extension, this enables the user to type in a search term in a field at the top of the sidebar. Other implementations may choose to render it another way (e.g. a toolbar field), or not at all.

When you search for “buns”, the browser will take you to search.php?q=buns.

If your search function uses POST, not GET, it’s no problem:

<item role="search"
       url="search.php"
    method="post"
      data="q=%s" />

(Only application/x-www-form-urlencoded format is supported at the moment.)

Finally, if you don’t specify a search item, the sidebar will set up a Google site search instead.

Sequences and ordering

A list of child items may have some sort of order. A navigational sequence is expressed with relation="sequence":

<item name="Fanglebord construction" relation="sequence">
  <item name="Materials" />
  <item name="Components" />
  <item name="Surface treatment" />
  <item name="Assembly" />
  <item name="Finishing" />
</item>

This tells an implementation that it should provide a convenient way to move from one item to the next (or previous), regardless of which is the current page. The Firefox extension provides ‘previous’ and ‘next’ buttons on its toolbar for this.

If you have a very long list of items, they could take up too much space on the user’s display to show all at once. If they are already in some sort of lexical order, you might be tempted to divide them up into smaller groups, but how big should you make them? Instead, you can express the pre-existing ordering, and let the implementation choose the divisions:

<item name="Fruit" order="lexical">
  <item name="Apples" ... />
  <item name="Bananas" ... />
  <item name="Cherries" ... />
  <item name="Date" ... />
  <item name="Fig" ... />
  <item name="Gooseberry" ... />
  <item name="Lemon" ... />
  <item name="Olive" ... />
  <item name="Quince" ... />
  <item name="Watermelon" ... />
</item>

Now, an implementation could automatically choose the following divisions:

  • A…C
    • Apples
    • Bananas
    • Cherries
  • D…L
    • Date
    • Fig
    • Gooseberry
    • Lemon
  • O…W
    • Olive
    • Quince
    • Watermelon

Grouping

It’s possible to logically group some items without implying another subordinate level. In the following example, an implementation is permitted to show Apples, Bananas, etc, as children of Fruit.

<item name="Fruit">
  <item name="Edibility" ... />
  <item name="Cooking methods" ... />
  <item name="Classification" ... />
  <group name="Types">
    <item name="Apples" ... />
    <item name="Bananas" ... />
    <item name="Cherries" ... />
    <item name="Date" ... />
    <item name="Fig" ... />
    <item name="Gooseberry" ... />
    <item name="Lemon" ... />
    <item name="Olive" ... />
    <item name="Quince" ... />
    <item name="Watermelon" ... />
  </group>
</item>

A group need not have a name, and never has a url, but it can have a relation and an order.

Multiple languages

If you provide your site in multiple languages, you can express that in a single sitemap:

<item>
  <variant name="Home" lang="en" url="index.en.html" />
  <variant name="Accueil" lang="fr" url="index.fr.html" />
</item>

If you use Content Negotiation to serve the same page in different languages under a single URL, you can express that too:

<item url="index.html">
  <variant name="Home" lang="en" />
  <variant name="Accueil" lang="fr" />
</item>

(Of course, in that case, you could instead write multiple sitemaps, and have them content-negotiated too.)

Duplicate branches

Your sitemap doesn’t have to be a strict hierarchy. Subtrees can be repeated by reference:

<item name="Members">
  <item name="Steven" xml:id="steven">
    … Steven’s attributes …
  </item>
  … more members …
</item>

<item name="Admin">
  <external url="#thomas" />
  <external url="#steven" />
  … more admin …
</item>

Indeed, you can build up a tree entirely by reference, rather than enclosure. All you need is a place to define items that don’t automatically appear in the tree.

<sitemap>

  <external url="#home" />
  <external url="#contact" />
  … more top-level item references …


  <!-- anonymous item that will never be used itself -->
  <item tree="exclude">
    <item xml:id="home" name="Home"
         url="index.html" role="home" />
    <item xml:id="contact" name="Contact"
         url="contact.html" role="contact" />
    … more items in no particular hierarchy …
  </item>

</sitemap>

Conditional styling

Different visitors to a site will have different capabilities with respect to exploiting an SSP sitemap. One goal of this project is to avoid forcing authors, in the face that diversity, to choose between SSP’s out-of-band (OOB) navigation and whatever in-band navigation they have provided on their site. The in-band navigation takes up space in the page rendition, but is redundant to varying degrees if the sitemap is also on display or available on demand. If the author drops in-band navigation in favour of the sitemap, the visitor unable to use the sitemap can’t navigate; if the author drops the sitemap, the whole OOB-sitemap concept fails. There must be a way to deploy the sitemap such that the in-band navigation is disabled automatically only for those visitors able to see the sitemap.

It’s fairly easy to use CSS to hide parts of a page. The author should be able to wrap his in-band navigation in (say) a <div class="nav">…</div>, and be able to write:

.nav {
  display: none;
}

The techniques below allow rules to apply that property conditionally on whether the sitemap is displayed.

Sheet insertion

In earlier versions of the Firefox extension, we supported conditional CSS by allowing the author to put the additional styles in a separate stylesheet. Instead of referencing this from the page, which would apply it unconditionally, it was referenced from the sitemap file by the <style> element. The extension then took steps to insert it into the page when the sidebar was on display, and remove it again when the sidebar was hidden.

Because of various implementation problems, and some philosophical objections, we have dropped this technique for now, and favour another below.

Display levels

There are potentially many ways for a sitemap to be rendered. It might appear in the sidebar, or in a pop-up menu, or it might be aurally rendered. The author does not know which method a visitor is using, yet he might want to style according to method. We define several display levels, which the implementation can report it is using, and which the author can code against, ranging from 0 to 100:

0…9: unsupported
The browser is not sitemap-aware. There is no prospect of presenting a sitemap to the visitor. No implementations should ever report these values.
10…19: supported
The browser is sitemap-aware but has not detected a sitemap.
20…29: available
A sitemap is available, but the visitor must take some action to put it on display. An implementation that shows the sitemap in a sidebar should report this value while the sidebar is hidden.
30…39: transiently available
A sitemap is available, and the visitor must take some action to put it on (at least) temporary display. An implementation that presents the sitemap in something transient like a pop-up menu should use this range while the sitemap is hidden.
40…49: transient display
A sitemap is available, and the visitor is taking some action to put it on temporary display. It will disappear if the visitor’s attention is taken away. An implementation that presents the sitemap in something transient like a pop-up menu should use this range while the sitemap is on display.
Over 50: persistent display
The sitemap is on display in parallel with the page. It takes up ‘space’, and is available at a glance. It will not disappear even if the visitor’s attention is removed. This is what the sidebar declares when on display.

(Divisions over 50 are reserved for future refinement.)

Styling with classes

The author can arrange for a very small part of the page content to change according to the display level of the sitemap, by adding this directive to that sitemap:

<class-change
   xmlns:html="http://www.w3.org/1999/xhtml"
   elem="/html:html/html:body"
   attr="class" prefix="sitemap" />

This specifies that the <body> element’s class attribute should change to reflect changes in sitemap display level.

Given the directive above, the classes of <body> will contain exactly 100 values of the form sitemap-over-level or sitemap-under-level. If the level is 50, it will contain sitemap-over-0 to sitemap-over-49, and sitemap-under-51 to sitemap-under-100.

Now the author can disable his in-band navigation on the condition that the sitemap is at least ‘transiently available’ (30 or more) with:

body.sitemap-over-29 .nav {
  display: none;
}

If the sitemap is hidden again, the CSS doesn’t change, but the display level changes to (say) 25 ‘available’, and so the classes contain only sitemap-over-0 to sitemap-over-24 and sitemap-under-26 to sitemap-under-100. sitemap-over-29 is no longer present, so the CSS rule no longer applies, and the in-band navigation is revealed.

If the in-band navigation is quite small, the author might prefer to keep it on unless the display of the sitemap is stable, i.e. the level is 50+. In that case, his rule should instead depend on the class sitemap-over-49.

This technique has been in use since revision 442.


Having written a sitemap, you will need to deploy it.