The SharePoint Social vs. Yammer Battle – Do We Care?

I’m driven to write this post after reading one by  over the weekend called Gartner: Yammer or SharePoint? The choice is still unclear.

The choice indeed may still seem unclear, but I think that the statement addresses the wrong questions.

In my opinion (I’m the only one here – you talkin’ to me?), we should stop talking about the “social” thing as a thing. Christian Buckley (@buckleyplanet) beat me to the punch in his comment on the post:

Part of the problem here is that we are still dealing with a serious learning curve on what social is, exactly, and how it fits into an organization’s culture and business needs. Microsoft needs to both education and evangelize a vision+roadmap that has not yet been articulated. That’s a tough row to hoe.

Rather than saying we should use SharePoint or Yammer for “social”, we should instead be talking about the specific things that we want people in a given population to be doing (or at least capable of doing – getting them to do it is a different challenge).

Once we understand what that might look like – and the goals will vary greatly by organization – we can start to make intelligent decisions about the right technologies for that particular case. Saying we need “social” means basically nothing. Or anything. Or something in between.

The slide that James showed from the Gartner webinar which prompted *his* post (and no, I did not see the webinar) starts to get at that set of questions, but I would say that it is still from the reverse angle. It’s useful, but it isn’t the point.

workloads-yammer-vs-sp-from-gartner

This sort of tool-driven analysis almost always leads to disappointment in my experience. It’s an easy way out for those who don’t want to do the harder work of understanding what the organization actually needs – and maybe even wants – by saying that this tool or that tool is the better one without clearly understanding the underlying problems in the first place.

Technologies can only support the kind of things that people are lumping under the social sobriquet to a certain degree. The concept of being social covers many things, but note that none of them mention SharePoint or Yammer:

so·cial [soh-shuhl] adjective (from Dictionary.com)
1. pertaining to, devoted to, or characterized by friendly companionship or relations: a social club.
2. seeking or enjoying the companionship of others; friendly; sociable; gregarious.
3. of, pertaining to, connected with, or suited to polite or fashionable society: a social event.
4. living or disposed to live in companionship with others or in a community, rather than in isolation: People are social beings.
5. of or pertaining to human society, especially as a body divided into classes according to status: social rank

I’ve already stopped saying “social” as much as I can – which isn’t easy – opting instead to push people to tell me what they want to accomplish. It makes most of them uncomfortable (or they say “You know, *social*), but in the long run these artificial packaging exercises are the wrong way to go.

Decide what you want to do, then decide which tool is the best match to solve that set of problems.

SPTechCon Social Demo

[important]

Mark Miller (@EUSP) and I did a webinar on Friday, March 15, 2013 at  to show the demo again and take questions about how we built it. If you’d like to look at the demo yourself, check out the publicly available page on NothingButSharePoint.com. The video is embedded below.

[/important]

It’s not every day that I get to create something in SharePoint with a Magic button.

Magic Button

I few weeks ago, Mark Miller pinged me asking if I’d be interested in helping him with a demo for his keynote at SPTechCon. When Mark asks, I tend to ask “how high” simply because it’s usually something fun. Sometimes, it’s even useful.

The basic idea was to show a social dashboard in SharePoint without letting on that we were using SharePoint. As you might imagine, none of this went along as linearly as I’m going to describe it. We tried various different things, added and removed columns, and widgets, etc. What I’ll describe is the end result.

First, I knew I wanted to use jQuery, jQueryUI, and SPServices, so I took a copy of default.aspx in a basic Team Site and added the following references. (Yes, I prefer the old Web Part Page over the Wiki pages. It’s much easier to work with. The Wiki pages tend to vomit markup all over what I do.)

<link href="Scripts/social_home_page.css" rel="stylesheet" type="text/css" />
<!-- Reference the jQueryUI theme's stylesheet on the Google CDN. Here we're using the "Start" theme -->
<link href="/ajax/libs/jqueryui/1.10.0/themes/start/jquery-ui.css" rel="stylesheet" type="text/css" />
<!-- Reference jQuery on the Google CDN -->
<script type="text/javascript" src="/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<!-- Reference jQueryUI on the Google CDN -- >
<script type="text/javascript" src="/ajax/libs/jqueryui/1.10.0/jquery-ui.min.js"></script>
<!-- Reference SPServices on cdnjs (Cloudflare) -->
<script type="text/javascript" src="/ajax/libs/jquery.SPServices/0.7.2/jquery.SPServices-0.7.2.min.js"></script>
<!--<script type="text/javascript" src="http://cdn.dev.skype.com/uri/skype-uri.js"></script>-->
<script type="text/javascript" src="Scripts/social_home_page.js"></script>

Next, I altered the markup for the page in SharePoint Designer. This was a demo, so there was zero concern about repeatability, of course. It’s nice to have that sort of freedom once in a while. By default, the page has a table with two columns set to 70% (left) and 30% (right) width. I simply changed that markup to have four columns, each with 25% width. In each of the two new table columns, I added a Web Part Zone. I wanted to drop as much of the social stuff as I could into the page using Content Editor Web Parts so that I could explain it more easily, like in this blog post. In edit mode, the page looked something like this: 3-11-2013 09-52-09 Next I added some CSS to the social_home_page.css file:

#s4-ribbonrow {
  display:none;
}
.s4-titlerowhidetitle {
  display:none;
}
#s4-leftpanel {
  display:none;
}
#MSO_ContentTable {
  margin-left:0;
}
#MSO_ContentTable table td {
  padding:3px;
}

This simple CSS removed all of the chrome we normally see on the page. In other words, we’ve removed the SharePoint from SharePoint to a large degree. The ribbon, title area, and Quick Launch are all totally hidden. (No screen shot for this – you wouldn’t see anything!) At this point, I had a page that looked like a big white nothing in the browser. Time to add the fun stuff. In Twitter, you can create widgets that display tweets from Twitter much like you can create different streams in HootSuite or TweetDeck. You can find this capability in Settings: 3-11-2013 09-58-00 I created three different widgets:

  • search stream for “EUSP”
  • search stream for “SPTechCon”, and
  • search stream for “SharePoint”

There are a few settings which give you basic control over the look and feel. If we were implementing this “for real”, it would probably make sense to make calls against the Twitter API and get the raw data so that we would have full control over the markup and visuals.3-11-2013 10-05-29 When you create the widget, you get a little snippet of markup and script which you can embed in a Web page. Those snippets are very simple. Here’s what the snippet for EUSP looks like:

<a class="twitter-timeline" href="https://twitter.com/search?q=EUSP" data-widget-id="306449761781817344"></a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

I put each snippet into a TXT file so that I could reference them in CEWPs. For the EUSP stream, I have a TXT file called twitter_search_eusp.txt in a Document library, and I just point to that file in the CEWP’s Content Link. This gets the three Twitter streams into the page:

3-11-2013 10-25-53

We also wanted to show something from Yammer, since it plays so importantly into Microsoft’s social story. While there are Yammer Web Parts available, I decided to go the widget route here as well. If you look under Apps in the Yammer Web interface, you’ll find Yammer Embed, which eventually takes you to the Yammer Embed page. There, you’ll find a PDF document that explains how to embed a Yammer feed. (Note to the Yammer folks: This isn’t a very clear process. Opportunity for improvement.)

Here’s what I ended up with for the SPYam feed. Note that I created my own id for the container so that it would fit into my page logic easily.

<script data-app-id="hyB2pTvrL36Y50py8EWj6A" src="https://assets.yammer.com/platform/yam.js"></script>
<script>
yam.connect.embedFeed({
  container: '#yammer-spyam-embedded-feed',
  network: 'spyam' // update with your own
});
</script>
<div id="yammer-spyam-embedded-feed"></div>

For some reason, the Yammer authentication mechanism simply won’t work in my page in Internet Explorer 9, so I switched to Firefox at this point, where I had no problems. (Another place for improvement, Yammer folks. However, it may well be that my IE9 is just sick.)

3-11-2013 10-43-14

Now we have all four streams we want in the page, at least in Firefox, for me.

I had seen some Twitter traffic about Dan McPherson’s lastest entries in the SharePoint Games under the Leap moniker. There are two offerings right now: LeapBackup and LeapMessages. Mark and I thought it would be cool if we could use LeapMessages to send a text message with the contents of a Tweet. I can imagine several use cases for this. Perhaps you work at Burger King, your Twitter account is hacked, and you need to notify the execs…

LeapMessages is really simple to implement. You just sign up on the Leap site, give the site URL and your Office365 credentials (it only works on Office365 right now), and Leap creates a list in your site called LeapMessages. If you add an item to that list, the LeapMessages engine grabs it (it polls every 30 seconds) and sends it out as a text from their gateway. Easy-peasy.

To implement this, I pulled a demo cheat. Since it takes a little time to load up the three Twitter streams and the Yammer stream, I set it up so that when I hovered over the Magic button (see below for more info on the button), this script would run, adding an SMS link at the bottom of each tweet in the three streams. I just had to wait until the three Twitter streams were loaded before I did the hover trick.

$("div.showSharePoint").hover(function () {

  if (!loadedSMS) {

    loadedSMS = true;

    $("iframe[id^='twitter-widget-']").contents().find("ul.tweet-actions").prepend("<ul><li><a class="SMS-send">SMS</a></li></ul>");
    $("iframe[id^='twitter-widget-']").contents().find(".SMS-send").click(function (e) {

      e.preventDefault();
      var thisTweet = $(this).closest("div.footer").closest("li");
      var thisTweetText = thisTweet.find("div.e-entry-content").text().trim();
      var thisTweetFullName = thisTweet.find("div.header span.full-name").text().trim();
      var thisTweetNickName = thisTweet.find("div.header span.p-nickname").text().trim();
      messageText.val("Interesting tweet from " + thisTweetFullName + " (" + thisTweetNickName + ") " + thisTweetText);
      countChars();

      $("#dialog").dialog("open");

    });
  }

}, function () {
  // Nothing to do
});

I added this markup at the bottom of the page for the dialog that would pop up when I clicked the SMS links.

<div id="dialog" title="Send SMS Message">
  <p class="validateTips">All fields are required.</p>
  <head>
    <meta name="WebPartPageExpansion" content="full" />
  </head>
  <form>
    <fieldset>
    <label for="phoneNumber">Phone Number</label>+1
    <input type="text" name="phoneNumber" id="phoneNumber"
    class="text ui-widget-content ui-corner-all" />
    <br />
    <label for="messageText">Message</label>
    <textarea rows="5" cols="40" name="messageText"
    id="messageText" value=""
    class="text ui-widget-content ui-corner-all"></textarea>
    <div id="charCount"></div></fieldset>
  </form>
</div>

When I clicked the SMS link, this script drove the dialog and wrote the entered data into the LeapMessages list using SPServices.

dialogDiv.dialog({
  autoOpen : false,
  height : 300,
  width : 500,
  modal : true,
  buttons : {
    "Send Message" : function () {
      var bValid = true;
      allFields.removeClass("ui-state-error");
      bValid = bValid && checkLength(phoneNumber, "Phone number", 10);
      bValid = bValid && checkRegexp(phoneNumber, /^([0-9])+$/i, "Phone number can only contain digits.");
      // From jquery.validate.js (by joern), contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
      if (bValid) {
        // Send the SMS message
        $().SPServices({
          operation : "UpdateListItems",
          async : false,
          batchCmd : "New",
          listName : "LeapMessages",
          valuepairs : [
            ["ReceiverMobileNumber", "+1" + phoneNumber.val()],
            ["Message", encodeXml(messageText.val())]
          ],
          completefunc : function (xData, Status) {}
        });
        $(this).dialog("close");
      }
    },
    Cancel : function () {
      $(this).dialog("close");
    }
  },
  close : function () {
    allFields.val("").removeClass("ui-state-error");
  }
});

There are a few helper functions referenced above, and here they are:

var loadedSMS = false;

var dialogDiv = $("#dialog");
var phoneNumber = $("#phoneNumber"),
messageText = $("#messageText"),
allFields = $([]).add(phoneNumber).add(messageText),
tips = $(".validateTips");

function checkLength(o, n, num) {
  if (o.val().length > num || o.val().length < num) {
    o.addClass("ui-state-error");
    updateTips(n + " must be  " + num + " digits.");
    return false;
  } else {
    return true;
  }
}

function checkRegexp(o, regexp, n) {
  if (!(regexp.test(o.val()))) {
    o.addClass("ui-state-error");
    updateTips(n);
    return false;
  } else {
    return true;
  }
}

function updateTips(t) {
  tips.text(t).addClass("ui-state-highlight");
  setTimeout(function () {
    tips.removeClass("ui-state-highlight", 1500);
  }, 500);
}

function countChars() {
  var messageLen = messageText.val().length;
  var errorClass = messageLen > 160 ? "class='ui-state-error'" : "";
  $("#charCount").html("You have used <span " + errorClass + " >" + messageLen + "</span> of 160 characters");
}
messageText.keyup(function () {
  countChars();
});

I decided to add one last piece of functionality. I couldn’t figure out how frequent the Twitter polling was, but when there was a new tweet in any any of the streams, I wanted to highlight it. To do this, I added this bit of script. It ran every three seconds to see if anything new had shown up, and if it had, it highlighted the counter at the top of each Twitter stream.

// Show tweet counters
setInterval("countTweets()", 3000);

function countTweets() {
  $("iframe[id^='twitter-widget-']").each(function () {
    var tweetCount = $(this).contents().find("li.tweet").length;
    var thisCounter = $(this).prev(".tweet-counter");
    if (thisCounter.length === 1) {
      var currCount = thisCounter.html();
      if (tweetCount != currCount) {
        thisCounter.addClass("ui-state-highlight");
        setTimeout(function () {
          thisCounter.removeClass("ui-state-highlight", 1500);
        }, 10000);
      }

      thisCounter.html(tweetCount);
    } else {
      $(this).before("<div class="tweet-counter">" + tweetCount + "</div>");
    }
  });
}

The Magic button is just a div. Yes, I violated best practices by making it a div instead of a real button. Don’t try this at home.

<div class="showSharePoint">Magic</div>

The Magic button contains the reveal. When I clicked on it, this script ran, unveiling the fact that the page was, in fact, a SharePoint page. There were very few oohs or aaahs that I could hear, which was a little disappointing, but hey, maybe I pushed it too fast or something.

// Set up the Magic button
$("div.showSharePoint").click(function () {

  var thisValue = $(this).text();

  if (thisValue == "Magic") {
    $("#RibbonContainer").hide();
    $("#s4-ribbonrow").slideDown(5000);
    $("#RibbonContainer").slideDown(5000, function () {
      $(this).fadeIn(1000)
    });
    $(".s4-titlerowhidetitle").fadeIn(5000);
    $("#s4-leftpanel").fadeIn(5000);
    $("#MSO_ContentTable").animate({
      "margin-left" : "150px"
    }, 5000, function () {
      // animation complete
    });
    $(this).text("No Magic");
  } else {
    $("#RibbonContainer").slideUp(5000, function () {
      $(this).fadeOut(1000)
    });
    $("#s4-ribbonrow").slideUp(5000);
    $(".s4-titlerowhidetitle").slideUp(5000);
    $("#s4-leftpanel").hide();
    $("#MSO_ContentTable").animate({
      "margin-left" : "0px"
    }, 5000, function () {
      // animation complete
    });
    $(this).text("Magic");

  }

});

So there you have it. I’m sure I’ve left some bits and bobs out of this in trying to make it consumable here, but I think I’ve gotten most of the important parts. All in good fun, and hopefully it got the message across that SharePoint doesn’t have to look like SharePoint and that we can do useful social stuff in SharePoint in many cool ways.

I’ve thought of a few neat things we could do with this, like storing the snippets in a SharePoint list and letting the user select which ones they want to see in their version of the page, dragging and dropping the streams into the order they like, and saving their settings for when they return. The possibilities with this stuff are really endless, depending on what you want to accomplish.

Have fun!

3-11-2013 11-47-29

Do You Use Yammer at Work? And Why Not SharePoint?

There was a question a while back on the Microsoft MVPs LinkedIn group (YAFSN! – see below) wondering “Do you use Yammer at work?”

I’m still trying to figure out how much I want to use Yammer. As when Google+ came out, I’m trying it. I pretty much abandoned G+, and Yammer may well go the same way for most things.

I got into Yammer via an invitation into SPYam from Bjørn Furuknap with my USPJA email address. Now I’m trapped into that identity for SPYam (the network for SharePoint discussions that Joel Oleson set up – ping me if you’d like an invitation) but have to use my work email address to access the SharePoint MVP network into which Microsoft has seemingly decided to move all communications. That tying of one’s identity to a single email domain (it seems you can’t combine domains into one über identity) is my biggest beef with the Yammer platform. I’m sure they will work that out, though. (Yammer probably could have done it in a few weeks. Now that it’s a Microsoft product, maybe in Yammer 2016, and you’ll only need to add a three server farm to enable it.)

I read a constant stream of complaints about other aspects of how Yammer works in – natch – Yammer. Sure, there are some true annoyances (no Shift-Enter in post entry, no parity between clients, Adobe Air!) but I could give you a litany of similar annoyances for every single YAFSN. User interfaces seem to always have annoyances. The important thing is how fast the people who develop the platform can react to consistent complaints and improve.

Everyone seems to think we need YAFSN (Yet Another Fantastic Social Network), but each new one that comes along simply fragments the landscape further. Who has the time to check dozens of these damn things? Social in the workplace must be a performance improvement, not a detriment. (I’d argue we should hold our personal social network use to the same standard. LOL catz!) if I have to check four or five social networks constantly in order to be well-informed, that drags down my efficiency.

I’ll keep using Yammer for the MVP stuff because I don’t have any choice, of course. Gotta get all those “secrets” somehow. It really makes me wonder, though, why we don’t use SharePoint to talk about SharePoint. It seems that in the vast majority of cases, SharePointilists prefer to use a different technology to communicate about SharePoint. That, to me, raises a far more important question: “Do you use SharePoint at work?”

Oh, I almost forgot to answer the original question. As a solo practitioner, there’s only me at work, so I don’t really need Yammer. I already have excellent tools in place to enable the voices in my head to converse.