Newsfeed Insights

SharePoint Newsfeed Insights

Newsfeed InsightsOne of my clients who is using SharePoint 2013 Sitefeeds extensively in his new social intranet asked me to build ‘something’ to get some insights out of the Social feeds.
So I went and build a little demonstration just to get the following insights out of a SharePoint Site Newsfeed.

  • total number of posts
  • total number of replies
  • total number of likes

I wrote the following peace of JavaScript code to get to the JSON response of a Newsfeed. From there it is just a matter of digging through the structure of the data object.

<html>
  <head>
    <meta charset="utf-8">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js" />
    <script>
      var siteUrl = _spPageContextInfo.webAbsoluteUrl;
      var url = "/_api/social.feed/actor(item=@v)/feed(MaxThreadCount=10000)?@v='" + siteUrl + "/newsfeed.aspx'"

      $.ajax({
        url: url,
        method: "GET",
        headers: { "Accept": "application/json; odata=verbose" },
        dataType: 'json',
        success: function (data) {}, 
        error: function (data) {}
      });
    </script>
  </head>
  <body> 
  </body>
</html>

Here are a couple of examples on what to find were in the JSON Response

Total number of posts
data.d.SocialFeed.Threads.results.length

number of replies of a single post
data.d.SocialFeed.Threads.results[0].TotalReplyCount

number of likes of a single post
data.d.SocialFeed.Threads.results[0].RootPost.LikerInfo.TotalCount

number of likes of a single reply of a post
data.d.SocialFeed.Threads.results[0].Replies.results[0].LikerInfo.TotalCount

Here is the complete JavaScript code of my demo. You can use it in SharePoint WebParts, Add-Ins, Apps, or just put the js file in the Site Assets library and use it in a CEWP (Content Editor Web Part)

<html>
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"/ >
<script>
 var siteUrl = _spPageContextInfo.webAbsoluteUrl;
 var url = "/_api/social.feed/actor(item=@v)/feed(MaxThreadCount=10000)?@v='" + siteUrl + "/newsfeed.aspx'"
 $.ajax({
   url: url,
   method: "GET",
   headers: { "Accept": "application/json; odata=verbose" },
   dataType: 'json',
   success: function (data) {
     if (data.d.SocialFeed.Threads != null) {
       var results = data.d.SocialFeed.Threads.results;
       var numberOfPosts = 0, numberOfReplys = 0, numberOfLikes = 0;
       numberOfPosts = results.length;
       for(var i = 0; i < numberOfPosts; i++) {
         numberOfReplys = numberOfReplys + results[i].TotalReplyCount;
         numberOfLikes = numberOfLikes + results[i].RootPost.LikerInfo.TotalCount;	
         for(var j = 0; j < results[i].Replies.results.length; j++) {
           numberOfLikes = numberOfLikes + results[i].Replies.results[j].LikerInfo.TotalCount;	
         }					
       }

       document.querySelector("#socialThreadStats .sts-posts").innerHTML = numberOfPosts;
       document.querySelector("#socialThreadStats .sts-replys").innerHTML = numberOfReplys;
       document.querySelector("#socialThreadStats .sts-likes").innerHTML = numberOfLikes;
     }
 	else {
 	   document.getElementById("socialThreadStatsStatus").innerHTML = "No Newsfeed found in this web please check configuration"
 	}  
   }, 
   error: function (data) {}
 });
</script>
<style>
  #socialThreadStats {
    display: table;
    padding-top:20px;    
  }
  #socialThreadStats ul {
    display: table-row;
    height: 50px;
    vertical-align: bottom;
  }
  .sts-stat-header {
    display: table-cell;
    width: 120px;
    height: 50px;
    font-size: 16px;
    border-bottom: 2px solid lightgrey;
  }
  .sts-stat-value {
    display: table-cell;
    width: 106px;
    height: 50px;
    font-size: 36px;
    text-align: center;
    border-bottom: 2px solid lightgrey;
  }
</style>
</head>
<body>
  <h1>What´s happening</h1>
  <div id="socialThreadStats">
    <ul>
      <li class="sts-stat-header"><span class="sts-posts-Text">Posts: </span></li>
      <li class="sts-stat-value"><span class="sts-posts"></span></li>
    </ul>
    <ul>
      <li class="sts-stat-header"><span class="sts-replys-Text">Replies: </span></li>
      <li class="sts-stat-value"><span class="sts-replys"></span></li>
    </ul>
    <ul>
      <li class="sts-stat-header"><span class="sts-likes-Text">Likes: </span></li>
      <li class="sts-stat-value"><span class="sts-likes"></span></li>
    </ul>
  </div>
  <div id="socialThreadStatsStatus"></div>
  </body>
</html>

There is also a really good MSDN documentation on social feeds in SharePoint I want to share with you. https://msdn.microsoft.com/en-us/library/office/dn155789.aspx

UPDATE:

I updated the script to be able to get more than the default 20 threads.
You can use the ‘MaxThreadCount’ Property of the feed to get more threads. I set it in the example to feed(MaxThreadCount=10000) to get up to 10000 threads back. A thread is a post in the newsfeed. This does not count for Replies.

The IF-Blueprint IoT Plant Application – Part 1

Or „how to avoid the office plant apocalypse”

 

Plants have a hard life in our office. They are in a constant state of dying. To avoid the slow death, we decided to use the power of the cloud and IoT. We started to develop an IoT environment that measures the humidity of each plant and push the collected data into an Azure Database. From this cloud based data pool we have endless possibilities to process and analyze this data, e.g. send notifications via twitter when a plant is thirsty. In the upcoming series of blog posts I will describe the hardware- and software setup of our IoT environment (you can follow the plants on twitter @IFBplant). The whole setup is kind of a prototype and a playground to explore interesting technologies like Microsoft Azure Services, Netduino / Arduino, REST Services, Office Add-ins and Power BI.

IoT Environment Overview

To collect the humidity values, we placed on each plant an Arduino board. This board is equipped with a humidity sensor and an 868Mhz radio sender. This sensor is powered by a battery.
IoT Arduino Sensor
Another Arduion board acts as receiver. Via the serial bus we transfer the data to a Netduino board, this device is connected to our WLAN and pushes the sensor values with an REST service into an Azure hosted MSSQL Database.
IoT Arduino Netduino Sensors
The REST service and the public facing website was implemented as an ASP.NET MVC / WebAPI site which is also hosted in Azure. On the website, everyone can observer the sensor values without a login.
Azure Website
As a logged in user you can configure parameters like threshold values for a specific plant, setup some timer jobs for alarm notifications and define twitter messages. To manager the users access we used the Azure AD.
To export the sensor data from the Azure hosted database into Excel we used the new awesome Office Add-in technology.
Excel Office Add-in
For the number guys in our company we provide the senor values also in Power BI.
Power BI
The following picture gives you an overview of the IoT environment. As written before this is just a prototype with lots of potential improvements. In the upcoming blog posts I will explain the different aspects of the development process in detail.
IoT Environment Overview

Authenticate against an Azure Mobile Service app with ADAL.js

In one of my current projects I was trying to access a Azure Mobile Service from within a HTML Angular app. “Great!” I thought, let’s use ADAL.js and let the magic happen! So I installed ADAL.js, configured it and…..nothing, ADAL.js injects the Bearer token but I got a “401 unauthorize” from the Azure Mobile Service. After some research on the web I was able to get Azure Mobile Service authentication to work with an ADAL.js acquired authorization token.

The Setup

As mentioned above there are 2 “apps”, an HTML Angular app and an Azure Mobile Service app with a .NET backend. Both apps uses Azure Active Directory as the authentication backend, the following image shows this setup.

architecture

Azure Mobile Service app

We will start with the Azure Mobile Service app. Microsoft provides a detailed explanation on how to configure the windows azure active directory authentication for azure mobile service in this article.

After configuring the Azure Active Directory application for the Azure Mobile Service you only need to add the following configuration to the web.config of your Azure Mobile Service:

This options allows us to call the azure mobile service from the specified host (e.g. localhost). This option is only necessary if you like to call an Azure deployed Mobile Service app.

HTML app

After Creating the Azure Mobile Service AAD application we create a new AAD app for the HTML app with the following settings:

htmlapp_aad_1htmlapp_aad_2

Note: The APP-ID Url must not be a real URL, it’s more a unique identifier for your app. More Information about this here

After creating the Azure Active Directory app we can configure out HTML Angular app to use this AAD app with ADAL.js:

You can get the ClientID from the Azure Active Directory app:

htmlapp_aad_clientid

The redirectUri should also match the reply url you’ve configured in your Active Directory app:

htmlapp_aad_replyuri

For more information about how to use ADAL.js with Angular take a look at Vittorio Bertoccis blog post.

Another important step is to configure “oauth2AllowImplicitFlow” option in the AAD app Manifest. You can download this manifest from the “Configure” page of the AAD application:

manage_manifest

After downloading the manifest open it and set “oauth2AllowImplicitFlow” to “true”. This enables the OAuth client flow which is needed for client side (=javascript) authentication.

The last configuration we need to apply allows our HTML app to request access tokens for the Azure Mobile Service app. To do this we need to add the Azure Mobile Service app under “permissions to other applications” and delegate the “Access” permission:

access

Note: After clicking “Add application” you have to select “all Apps” to list all available apps.

Authenticate against Azure Mobile Service

Now that we have configured Azure AD for our HTML and Azure Mobile Service app we can extend the HTML app to authenticate against the Azure Mobile Service. To do this, we need to tell ADAL.js that we want to authenticate against this endpoint, so we need to add an endpoint configuration to out ADAL.js config:

The first part of the endpoint is the url of the endpoint, the second part is the APP-ID URI of the Azure Mobile Service AAD application. ADAL.js now injects into every call to the specified endpoint url a bearer token. Sadly Azure Mobile Service doesn’t use this token for authentication. Instead it uses its own token provided in a “X-ZUMO-AUTH” header. To get the token we can use the client-directed login operation . This allows us to get an Azure Mobile Service auth token for an already obtained AAD token. So we need to obtain an OAuth token for our Azure Mobile Service AAD app and present this token to Azure Mobile Service to get a valid Azure Mobile Service token. A little bit complicated but OK, let’s try this:

Summary

After this long post here are the key points:

  • Create a Azure Active Directory application for the Azure Mobile Service app and the HTML app
  • The HTML AAD app must have the set the “oauth2AllowImplicitFlow” option to “true” in the manifest
  • The HTML AAD app must have access to the Azure Mobile Service app (under “permissions to other applications)
  • The HTML App must have ADAL.js be configured with a endpoint for the Azure Mobile Service app
  • You have to use the client-directed login operation in your HTML app

If you find a more elegant solution for this problem or need further help, please let me know.