Using Metrics to Justify Your SharePoint Investment

There is no dearth of opinion on this topic, whether it be from Microsoft or any of the many, many vendors out there who want to help you justify, plan, design, implement, or support (or paint, or count, or whatever) your SharePoint installation.  So, I thought it would be absolutely critical for me to toss my ideas into the mix.

Ever since my Knowledge Management consulting days way back in the mid-1990s’, clients that I have worked with have struggled with how to justify their investment in SharePoint or any other collaboration platform.  SharePoint isn’t really software that supports operational processes, after all, though it certainly can at some levels.  SharePoint is more about enhancing productivity or accelerating creativity or driving revenue.  These have always been difficult things to measure or predict.

When it comes to how to think about SharePoint (or any other similar technology) metrics, I think of a spectrum.  (The PowerPoint guy in me wants to draw a slide for this, but I’m going to stick to words.)

At the left of the spectrum are things that I think of as "care and feeding".  These are the typical things that an IT department watches with a Web application: uptime, page hits, unique users, clicks, etc.  To me, you just have to do this stuff right.  If you don’t you’re not good at your job, are you?  The application needs to work well.  (Luckily, our friends at Microsoft have invested quite a bit to make sure this is the case.)

Next is the category of cost reduction.  Teams being more efficient, global communication being more effective, and reduced reliance on email (and therefore reduced capacity requirements) fall into this category.  This is nice stuff, but it still is just paring back on money that would have otherwise been spent.

Improved consistency starts to cross the line between cost-cutting and revenue generation.  If you can enable a sales team to get a better proposal to a potential client faster, you’ve got a bit of both.  If an R&D team can benefit from previous research that has worked rather than starting from scratch, they may generate a better product, faster.  Training costs may decrease so that you can hire better people.  This category starts with little things like consistent document templates and best practice examples, through project templates, and repeatable processes.

At the far right of the spectrum is serendipity.  These are the things that wouldn’t have happened if the SharePoint platform hadn’t been there: a new $3M product idea, the hiring of a perfect resource into a position that has been impossible to fill, the close of a huge sale because someone in the organization you’d never heard of had the right slant, etc.  If these things happened because of some connection that was made due to SharePoint, then you can take some of the credit for it.  Make sure that you get explicit agreement from the parties involved that SharePoint made it happen and their willingness to tell the story for you.  This is the stuff that management really wants to hear about, but it has to be real.  Don’t try to take credit for something because it was stored on a disk drive that you bought.

A few more ways to think of this (aligned to the same spectrum):

  • Quantitative —–> Qualitative
  • Traditional —–> "Out of the box"
  • Defensive —–> Offensive (by this I mean that the numeric metrics tend to prove that you’re doing your job right; the qualitatives tend to prove that you are making a difference)
  • Frequent —–> Rare
  • Incremental —–> Huge
  • Hard —–> Soft (don’t be afraid to claim credit for fuzzy gains, but be prepared to back them up — or better yet, to have others back it up for you)
  • Leading —–> Lagging
Technorati tags: , ,

Rolling Up Calendars in SharePoint

The idea of rolling up calendars across multiple SharePoint sites comes up very frequently in conversations with clients.  We’ve always tried to think of a nice, elegant way to make it work, but haven’t ever really come up with the “right” answer.  I saw a post on SharePointPedia today that looks to be that “right” answer.

In the post, Corro’ll Driskell outlines such a nice solution, I wish I’d thought of it.  You can read his post for clear step-by-step instructions (with illustrations), but basically he shows how to take advantage of the Data View Web Part’s (DVWP’s) capability to link data sources.  This is simple, and looks like it will work for calendars and any other consistently formed lists.

There are only a few questions or issues that I have about this:

  • How many different data sources can be linked in this way?  My guess is that there is some upper limit, but it may be large enough not to be of concern.
  • One needs to know exactly where the data sources are.  i.e., This doesn’t work if you want to roll up all of the calendars in a Site Collection, but you don’t know how many there are or where they will be.
  • With calendars, you will need to be satisfied with a list view (as opposed to a calendar grid view).  DVWPs give you great flexibility on display, however.  For instance, you might color code the items in the list based on which calendar they come from.

None of these questions or issues is a reason not to use this method, but they may have an impact on its usefulness for you.

SharePoint Content Types and Templates

One of the most powerful features of SharePoint 2007 (MOSS), in my opinion, seems to be one that doesn’t get a lot of attention in the blogosphere: Content Types.  From a Knowledge Management or Content Management perspective, Content Types are a huge benefit.

Not only do Content Types allow you to define metadata (columns) that uniquely make up the Content Type, but you can also attach a template to each Content Type.  This allows you to provide the user the appropriate skeletal form or document whenever they click on New/[Content Type Name] in a library.  (If they already have the template instantiated, then they would use the Upload button instead.)

This means that you will want folks to change their work behavior slightly.  Whenever they create a new document, you will want them to go to the library and start with the blank template, because it may have changed since the last time they used it.  (I think that most people dig around on their hard drive and find the last one that they created and start there, which is a sloppy habit and leads to divergence from any standards that you are trying to put in place.)

The other thing that you will want to do for this approach to be successful is to make sure that you have Best Practice examples that have been instantiated from the templates easily available for the user.  These examples can (and should) change over time, as new instances are seen as improvements on the old Best Practices.  For something like a Network Access Request Form, the Best Practice isn’t going to change often, but for richer Content Types like Proposals they will.

A big part of the power behind Content Types is the capability for them in have parents from which they inherit metadata.  For instance, for an Intranet build out, you might create a base document Content Type called Intranet Base Document, and have all of the other document-based Content Types inherit from it.  That way you can manage columns that apply to all document Content Types in the parent.  Careful design and architecture of your Content Types up front will ensure that the foundation you lay will be of the greatest use going forward.  (You can’t change Content Type parentage after you’ve built them.)

If you haven’t looked at what Content Types in MOSS can do for you, it’s time to do so!

Faceted Search for SharePoint 2007 (MOSS)

I had seen the post on the Microsoft SharePoint Products and Technologies Team Blog the other day about faceted search, but for some reason, it didn’t make an impression.  Today, Scott Jamison posted about it, so I took another look.  (I’ve worked with Scott, and I pay attention when he touts something.)

This is really a cool option to enhance what SharePoint Search can do for you.  The most immediate use I thought of was for a company directory or facebook that is much more interactive than basic Search.  (I’ve posted a few other times about ways to build up this capability, but none of my ideas worked this well.)  Check out the WSS Demo site for an interactive demo.

A few other ideas from the Microsoft SharePoint Products and Technologies Team Blog post:

  • Music catalog: songs have attributes such as artist, title, length, genre, date.
  • Company white pages: directory of people with names, department, role, region.
  • Recipes: cuisine, main ingredients, cooking style, holiday.
  • Travel site: articles have authors, dates, places, prices.
  • Regulatory documents: product and part codes, machine types, expiration dates.
  • Image collection: artist, date, style, type of image, major colors, theme.

A new release is planned in a week or so, with these new features:

  • Multi-thread processing. 1st thread runs for up to 500 facets synchronously, while the 2nd thread is running asynchronously against up to ~30,000 facets.
  • Client side refresh (not AJAX) that updates only facets web part without page refresh.
  • Web part connections to pass Facet settings to the bread crumbs.

Extended facet schema now supports:

  • Facet icons — default icon per facet name complimented by an icon per facet value .
  • Friendly names for facet values.
  • Exclusions — allow exclude facet when values match pattern.
  • Built-in wildcard match, especially useful for exclusions.
  • Improved search syntax, added supports for sentences and quoted phrases.

Pre-Populating SharePoint List Item Values Using Query String Variables

A client of ours was having trouble getting this idea to work based on a post he found on the Microsoft SharePoint Designer Team Blog.  I took a look and got it to work nicely in a test situation.  This is a nice trick, as it can help to pre-populate metadata that your users might otherwise need to provide.

Here’s how I got it to work:

  • I created a Custom List on a MOSS site with no customizations
  • I added the script below into the page, just below the line:       <asp:Content ContentPlaceHolderId=”PlaceHolderMain” runat=”server”>
  • Now, when I hit the New button on the list, I get alerts that the JavaScript is parsing out the Query String variables, as expected
  • I altered the default URL to look something like: http://<<servername>>/Lists/<<List Name>>/NewForm.aspx?Title=XXX
  • The Title is pre-populated with the Query String value that I provide, like ‘XXX’ above

The original post above shows how to make this work for a lookup column, and the code can be extended to work with any column type.  (It would be a nice exercise to make the code work regardless of the column type, but I’ll leave that as an exercise for the reader.)

I’ve left in the alerts that I used to test things so that you can see how it flows.

<script type="text/javascript">

_spBodyOnLoadFunctionNames.push("fillDefaultValues");

function fillDefaultValues() {
  var qs = location.search.substring(1, location.search.length);
  var args = qs.split("&");
  var vals = new Object();

  for (var i=0; i < args.length; i++) {
    var nameVal = args[i].split("=");
    var temp = unescape(nameVal[1]).split('+');

    nameVal[1] = temp.join(' ');
    vals[nameVal[0]] = nameVal[1];
    alert('fillDefaultValues: vals[nameVal[0]]=' + vals[nameVal[0]] + ' nameVal[0]=' + nameVal[0] );
  } 
  setValueFromQueryString(nameVal[0], vals[nameVal[0]]);
}

function setValueFromQueryString(fieldName, value) {
  alert('setValueFromQueryString: fieldName=' + fieldName + ' value=' + value);
  if (value == undefined) return;
  var theField = getTagFromIdentifierAndTitle("input","TextField",fieldName);
  if (theField != null) theField.value = value;
}

function getTagFromIdentifierAndTitle(tagName, identifier, title) {
  alert('getTagFromIdentifierAndTitle: tagName=' + tagName + ' identifier=' + identifier + ' title=' + title);
  var len = identifier.length;
  var tags = document.getElementsByTagName(tagName);

  for (var i=0; i < tags.length; i++) {
    var tempString = tags[i].id;
    if (tags[i].title == title && (identifier == "" || tempString.indexOf(identifier) == tempString.length - len)) {
                alert('getTagFromIdentifierAndTitle: tags[i].id=' + tags[i].id + ' tags[i].title=' + tags[i].title + ' tags[i]=' + tags[i]);
      return tags[i];
    }
  }
  return null;
}
</script>

NOTE: This approach will NOT work in SharePoint 2003 because the column input fields on the page are generated differently.  Rather than just using the basic <INPUT> tag to construct the input fields (as MOSS does), each column is displayed by using JavaScript, like the example below (do a View Source on your page to see this in your environment):

<TR>
  <TH nowrap valign=top class="ms-formlabel"><nobr>Year</nobr></TH>
  <TD class="ms-formbody" style="padding-left:5px">
    <SCRIPT>
      fld = new TextField(frm,"Year","Year","2008");
      fld.cchMaxLength = "255";
      fld.cchDisplaySize = "";
      fld.IMEMode="";
      fld.BuildUI();
    </SCRIPT>
    &nbsp;
<SPAN class="ms-formdescription"></SPAN>
  </TD>
</TR>

This is done internally in the ListFormWebPart, so short of writing a custom Web Part with a new BuildUI function, I just don’t see a way to make this approach work.  Too bad, as, while it isn’t very elegant, it works well!

Yet another good argument to move to MOSS.