Wednesday, November 25, 2015

Creating a Search Based Employee Blog Rollup in SharePoint 2013

Posted in SharePoint, Technical By Kyle Wright @ 1/28/2014

I recently got a request from a client that had a lot of employee engagement around blogging and they wanted to bring that front and center on their intranet home page. We were already rolling up an executive blog to the front page using the Content Query Web Part styled with some custom XSLT. They wanted it styled to look exactly the same, but using the CQWP again was out of the question since these employee blogs were coming from the user My Sites. The CQWP can’t roll content from other site collections, so we will use the new Search display templates in SharePoint 2013 to accomplish this goal of rolling all blog posts from across their environment. 

If you don’t care about all this, you can download these files and try them out for yourself at the bottom of this post. 

First, let’s talk about the structure of display templates. I’m not going to go into a huge amount of detail, that has already been covered on a great blog on Technet. There are two main files that control your display template and this example will update both of those. Essentially, there is a wrapper called Control_SearchResults.html that contains the global formatting and elements for all search results, and lots of files to style individual items. These files are all located in the Master Page gallery > Display Templates > Search folder. I recommend not modifying any of the original files, instead open one of the existing files and save as a new file. I typically do all of this work in SharePoint Designer. 

The first thing to do is create a new wrapper file, so I saved Control_SearchResults.hml as a new file called Control_SearchResultsBlogSummary.html. (Creative, right?) Never edit the JavaScript files for your templates, SharePoint creates and maintains those as you edit your HTML file. I didn’t do too much to modify this template with the exception of taking almost all of it out. This is a very basic display and I don’t need much in the way of formatting or detailed info, I just need the title, employee image, and a summary of the post. So, this is what I ended up for the control template:

<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"> 
<title>Blog Summary Result</title>
<!--[if gte mso 9]><xml>
<mso:TemplateHidden msdt:dt="string">0</mso:TemplateHidden>
<mso:MasterPageDescription msdt:dt="string">Displays the Search Results control.</mso:MasterPageDescription>
<mso:ContentTypeId msdt:dt="string">0x0101002039C03B61C64EC4A04F5361F385106601</mso:ContentTypeId>
<mso:TargetControlType msdt:dt="string">;#SearchResults;#</mso:TargetControlType>
<mso:HtmlDesignAssociated msdt:dt="string">1</mso:HtmlDesignAssociated>
<mso:HtmlDesignConversionSucceeded msdt:dt="string">True</mso:HtmlDesignConversionSucceeded>
<mso:HtmlDesignStatusAndPreview msdt:dt="string"> Templates/Search/Control_SearchResults_BlogSummary.html, Conversion successful.</mso:HtmlDesignStatusAndPreview>
<mso:CrawlerXSLFile msdt:dt="string"></mso:CrawlerXSLFile>
<mso:HtmlDesignPreviewUrl msdt:dt="string"></mso:HtmlDesignPreviewUrl>
    <div id="Control_SearchResults">
        <div class="ms-srch-result" id="Result" name="Control" style="margin-top:1px; width:280px;">
                <div id="Groups" class="ms-srch-result-groups">
                    ctx.ListDataJSONGroupsKey = "ResultTables"; 
                    _#= ctx.RenderGroups(ctx) =#_


That dropped the file from over 300 lines down to about 35, so it is much easier to read. The only real thing I added to this file was the styling on the ms-srch-result div. It would have been just as easy to put in my custom CSS file, but for demo purposes, I left it inline. This file calls the template that you configure in your search results web part using the _#= ctx.RenderGroups(ctx) =#_ line, so you can modify this file as needed. 

Next, I modified the Item_Discussion.html file to get my display template formatted for my blog roll. I started with that template because it already had most of what I needed in a format that looked pretty close to what I was after. 

Again, I mostly stripped out what I didn’t need, but this time I did add some content back in. We needed to have the employee’s picture next to the post to make it a bit more interesting on the page. I’m sure there are better ways to do this using all the search tools, but I banged my head against it for a while and went the easy way. I’ll add in some of the code that is actually new for this file, and you can find the full files available for download below.

if (!$isEmptyString(ctx.CurrentItem.AuthorOWSUSER))
author = Srch.U.getDisplayNameFromAuthorField(ctx.CurrentItem.AuthorOWSUSER);
var userPersonaId = id + "_peopleUserPersona";
var authorUsername = Srch.U.getUsernameFromAuthorField(ctx.CurrentItem.AuthorOWSUSER);
var authorPicUrl = "" + authorUsername.split("\\")[1] + "_MThumb.jpg";
authorPic = "<img src='" + authorPicUrl + "' style='width:70px;height:70px;float:left;margin:0 5px 5px 0;'>";

These lines get the current author from the search results, then just build a URL to the image library on the My Sites web application that stores the images. Since these are stored in a consistent manner based on username, this was the easiest way to go for me. Then, to add the output of that to our template, we just insert _#= authorPic =#_ into the HTML wherever you want the JavaScript variable to render.

<div>_#= authorPic =#_</div>
<div  id="_#= $htmlEncode(id + Srch.U.Ids.body) =#_">
        <div id="_#= $htmlEncode(id + Srch.U.Ids.title) =#_" class="ms-srch-item-title">
                <h3 class="ms-srch-ellipsis" style="padding-bottom:2px;">
                            <a clicktype="Result" id="_#= $htmlEncode(id + Srch.U.Ids.titleLink) =#_" href="_#= $urlHtmlEncode(ctx.CurrentItem.Path) =#_" style="font-size:15px;" title="_#= $htmlEncode(ctx.CurrentItem.Title) =#_" onfocus="_#= showHoverPanelCallback =#_">
                                _#= Srch.U.trimTitle(title, maxTitleLengthInChars, termsToUse) =#_

There are variables in the JavaScript in this page to control how long the blog title and text teaser are, so they are pretty easy to adjust. Once these files are saved and published, it is time to configure the search web part to use them. Just add a Search Results web part to your page, and edit the properties. Open the Query Builder and add ContentType:Post Title<>"Welcome to my blog!" -ContentClass=urn:content-class:SPSPeople as the Query text. This will prevent the default “Welcome to My Blog” posts that everyone gets when a blog is created from showing up on your page. 

Set the following options in the Display Templates section and click OK. If all goes according to plan, you should see a nicely formatted blog roll on your page. The options in the drop-down come directly from the <Title> element of your HTML files, so you can name them whatever you want. </p>


Feel free to download these files below. Just note that you will need to modify the URL to point to your My Site web application on line 79 of the Item_BlogSummary.html file.

Search Display Templates Download

For more information on C5 Insight or this blog entry, please Contact Us.


, , ,


Got something to say? Join the discussion ยป
    Posted by mike on 7/4/2014
    Nevermind, the string returned does not contain any slashes ("//") when retrieving the user name. There are two "|" characters. Once I get the email, I need to replace the . and the @ with _ for the picture URL to work.

    if (!$isEmptyString(ctx.CurrentItem.AuthorOWSUSER))
    author = Srch.U.getDisplayNameFromAuthorField(ctx.CurrentItem.AuthorOWSUSER);
    var userPersonaId = id + "_peopleUserPersona";
    var authorUsername = Srch.U.getUsernameFromAuthorField(ctx.CurrentItem.AuthorOWSUSER);
    var authorEmail = authorUsername.split("|")[2];
    var authorFormattedName = authorEmail.replace(/\./g,'_');
    var authorFormattedName = authorFormattedName.replace("@","_");
    var authorPicUrl = "" + authorFormattedName + "_MThumb.jpg";
    authorPic = "";
    Posted by mike on 7/4/2014
    Thanks for posting this, I've been looking for a solution like this for a few days now. But I can't seem to get the image to display properly next to the post.

    I'm getting this for my thumbnail image URL:

    I did not edit anything in the file besides the base url for this line:

    var authorPicUrl = "" + authorUsername.split("\\")[1] + "_MThumb.jpg";
    Posted by Charlie Price on 3/13/2014
    Kyle -

    that fixed the problem!

    Thanks a ton!

    No, our mysites don't have periods in them. That's why I was a little confused what was going on!
    Posted by Kyle Wright on 3/13/2014
    Interesting, I assume if you put in you will get a valid image? If that is the case, you could change authorUsername.split("\\")[1] to authorUsername.split("\\")[1].replace(".","_") and that should replace the period in your username with an underscore. I'm not sure why it didn't change that on its own though. If you go to your My Site, does it have the period in your username in the URL?
    Posted by Charlie Price on 3/13/2014
    Kyle -

    My images are not showing up. If I check the url being of the broken images I get the following:
    Posted by Kyle Wright on 3/13/2014
    Charlie, SharePoint automatically replaces periods in your username with underscores when it creates My Sites, etc because periods would mess up the URLs to your MySite. Are you displaying the username somewhere, or are your image links not working?
    Posted by Charlie on 3/13/2014
    One quick question on line 79 where the username is placed the script keeps altering my username for example Charlie.price gets rendered to Charlie_price

    Is there a way to have it keep the same format of my username?
    Posted by Vince on 3/4/2014
    The HTML is...

    %div id="_#= $htmlEncode(userPersonaId) =#_" class="ms-srch-hover-postPersona"%%/div%

    Replace the % with the appropriate markup...sorry don't know how to get it to display properly here
    Posted by TheKid on 3/4/2014
    FYI, this is the code needed to render the full user details with hover over details (changed AssignedTo to whatever field it is)...

    In your script...

    var id =;
    var userPersonaId = id + "_peopleUserPersona";
    var authorUsername = Srch.U.getUsernameFromAuthorField(ctx.CurrentItem.AssignedToOWSUSER);

    EnsureScriptFunc("searchui.js", "Srch.SSU", function()
    AddPostRenderCallback(ctx, function()
    Srch.SSU.renderPersona(authorUsername, userPersonaId);

    And then in the HTML...

    Hope this helps you or someone else.

    Posted by Aleksi N on 2/20/2014
    Thank you! The AuthorOWSUSER property was a life saver. I missed the getUsernameFromAuthorField in the post and opted for a regular expression to get the login name from the claims token. The regex I used to capture the login name is /#\.[w]\|.+\\(.+)$/ and could also be used to capture the domain name.

    Also I'm not sure if hardcoding the mysite url. There's a REST endpoint to get the profile picture url for a specific user that could be used to extract the base url (you'll need the domain name for this). Of course this would take the complexity of the display template to another level. The endpoint is /_api/SP.UserProfiles.PeopleManager/GetUserProfilePropertyFor(accountName=@v,propertyName='PictureURL')?@v='domain\loginname'

leave a reply

 [Quick Submit with Ctrl+Enter]

Remember my details
Notify me of followup comments via e-mail


About C5 Insight

We are a Microsoft Gold Certified partner focusing on SharePoint, Microsoft Dynamics CRM and  Learn more about us by visiting our website.

We Wrote the Bible on Microsoft SharePoint and Dynamics CRMBook-Microsoft Dynamics CRM 2011 and SharePoint 2010 Bible

Upcoming Events

Why Upgrade from SharePoint 2010?

12/08/15 @ 2:00 PM ET If your organization is considering a move to SharePoint 2013, then this webinar is for you. We know......

Comparing Salesforce and Dynamics CRM for Sales

12/15/15 @ 1:00 PM ET "Our CRM is so good that our sales team members WANT to use it," said no sales manager ever. Are yo... ...

Microsoft Social Engagement: Improving your Marketing LUCK

12/17/15 @ 1:00 PM ET Ready to get social? In this deminar (that's demo + webinar) session, we will take a look at the Mi... ...

Top Downloads

SharePoint 2013 Feedback Solution - collect feedback from users into a custom feedback list that captures their feedback and exactly where they were in SharePoint when they provided it.

Why CRM Fails - research into CRM failure, best practices, and how to recover from a failing project.

The 60 Second Collaboration Readiness Self-Evaluation - is your team really ready to collaborate?  If they're not, software isn't going to help.  Take the quick self-evaluation in each department to understand how well your culture collaborates.

Identify Your Support Gaps - collaboration and CRM projects often fall short when it comes to supporting users, because support for these projects is different from other projects.  



The information herein may be used solely at your own risk.  No warranty is made by the author or by C5 Insight, Inc.

The opinions expressed herein are those of the individual authors and do not necessarily represent C5 Insight, Inc in any way.

Copyright 2011-2013 by C5 Insight