Show Upcomming Birthdays Based on SharePoint 2013 User Profiles with Search (Office 365)
October 2, 2013 26 Comments
A lot of customers like to have some kind of anniversary webpart on their corporate intranet. In SharePoint 2013 and Office365 you can provide this functionality using the SharePoint User Profile and Search (and some Javascript).
In the SharePoint User Profile, users are able to provide their birthday by default. These values are automaticly crawled but you will not be able to apply filters using search. In this blog post I will describe the configuration steps for Office365.
> Go to the Site Settings -> Site Collection Administration -> Search Schema (you can also configure this in the SharePoint Admin level)
> Search for RefinableDate00, Edit the mapping (for SharePoint Onpremise, you are able to add a new one with type Date)
> Give it an alias like Birthday01
> Add “People:SPS-Birthday” as crawled field mapping
> Be sure you have some people filled in their birthday on their profile
> You are done, o365 will need to wait at most 1 week (yes, you are reading it right). Full crawls are now performed once a week, if you need it by tomorrow you can submit a support ticket to MS support, they will initiate a full crawl on request. Onpremise users just fire off a full crawl.
To test if your managed property is working you can perform a query to your search center.
https://tenantname.sharepoint.com/search/Pages/peopleresults.aspx?k=Birthday01>”01-01-2000″
Our prerequisities are met, and we are able to query for a birthday. So why should we need any code…
As you can see in the “test” query above, we are using the year 2000 to query, this is not just a coincidence. SharePoint stores the Date no Year fields using the year 2000, and SharePoint Online is not different on this one. Unfortunately this makes our Search Results webpart unusefull because you can only use keywords like today-5, yesterday, last week, last month and last year.
The javascript below will perform a restcall to the search service to retrieve the birthdays which are in range (30 days in this example).
(note: jquery is required)
<div id="resultsDiv"></div> <script type="text/javascript">// <![CDATA[ $(document).ready(function () { var e = ExecuteOrDelayUntilScriptLoaded(executeQuery(), "sp.js"); }); Date.prototype.AddDays=function(days) { this.setDate(this.getDate() + days); return this; } function executeQuery() { Results = { element: '', url: '', init: function (element) { Results.element = element; var birthday = 'Birthday01'; var space = '%20'; var colon = '%3A'; var quote = '%22'; var gt = '%3E'; var lt = '%3C'; var amp = '&'; // Get current date var currentTime = new Date(); var startMonth = currentTime.getMonth()+1; var day = currentTime.getDate(); // Get current date + 30 var endTime = new Date(); var endTime = currentTime.AddDays(30); var endMonth = endTime.getMonth()+1; var endDay = endTime.getDate(); var querytext = ""; // build query with the magic 2000 year if(startMonth!='12') { querytext += birthday + gt + quote + day + '-' + startMonth + '-' + '2000' + quote + space + 'AND' + space + birthday + lt + quote + endDay + '-' + endMonth + '-' + '2000' + quote; } else { querytext += birthday + gt + quote + day + '-' + startMonth + '-' + '2000' + quote + space + 'OR' + space + birthday + lt + quote + endDay + '-' + endMonth + '-' + '2000' + quote; } Results.url = _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?querytext=%27" + querytext + "%27&sourceid=%27B09A7990-05EA-4AF9-81EF-EDFAB16C4E31%27&selectproperties=%27Title,"+ birthday +",Path%27&sortlist=%27"+ birthday +":ascending%27"; }, load: function () { $.ajax( { url: Results.url, method: "GET", headers: { "accept": "application/json; odata=verbose", }, success: Results.onSuccess, error: Results.onError } ); }, onSuccess: function (data) { var results = data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results; var months = [ "januari", "februari", "maart", "april", "mei", "june", "juli", "augustus", "september", "oktober", "november", "december" ]; var html = "<div class='birthday'>"; for (var i = 0; i < results.length; i++) { var name = results[i].Cells.results[2].Value; var date = new Date(Date.parse(results[i].Cells.results[3].Value)); var link = results[i].Cells.results[4].Value html += "<span>"; html += "<a href='"+link+"'>" + name + "</a>"; html += " " html += date.getDate() + " "+ months[date.getMonth()]; html += " "; } if (results.length == 0) { html += "Er zijn geen verjaardagen (bekend)."; } html += "</div>"; Results.element.html(html); }, onError: function (err) { alert(JSON.stringify(err)); } } Results.init($('#resultsDiv')); Results.load(); } // ]]></script>
I have developed a asp.net MVC web application.
How i show a sharepoint page in my MVC web application.
View Page
This link is Working properly.But i want to show this link on inside IFrame.
I used to display this code for inside viewing.
in that time one error generated.
“Load denied by X-Frame-Options: http://win-spserver/_layouts/15/start.aspx#/SitePages/Home.aspx does not permit cross-origin framing.”
Please solve this issue.
is it possible or not ?
Hi Joran, Thanks for the article. I tried to develop your sample for sharepoint online, but when i try to map People:SPSBirthday property to a RefinableDate, i can’t see the People:SPSBirthday property on mapping screen. If you want , i can provide screenshot. Do you have an idea about this problem? Thanks for your help.
Regards.
i can’t see the People:SPSBirthday property on mapping screen to, can you fix that?
Search for: SPSBirthday. Then you will find it.
Same thing happened to me. The People:SPSBirthday shows up though once you have some user profiles with data in that field…..
Hi Berkay, the property should be named People:SPS-Birthday. Maybe you ‘ll have to fill one profile with a birthday at least.
Hi,
How could this be used to show upcoming anniversaries?
Thanks
Hi Joran, great article and worked perfectly. I have the same query as Karen, what would be the best way to show upcoming anniversaries based off the People:SPS-HireDate field.
Thanks
I’m able to execute the script, but I really miss the total age. Any ideas how to accomplish this?
And what about work anniversary – Have anyone worked out a solution for that as well?
Best regards
Benjamin
The default birthday field in sharepoint does not contain the birth year. So You Will need a custom field to accomplish this requirement. I don’t think you can get these results filtered using search. For the work anniversary this will workout pretty fine, because you can filter for a date minus 5 years, 10 years, etc.
Benjamin, in the example query there is a part which generate the “html” if want an age displayed, you need to create a javascritp variable which calaculates based on the date of today and the birthday date, then display this variable on a new line by updating the html code.
something like html += ” age: ” + yourvar;
where yourvar is calculated on the input
Hi Guys. I’m a noob, and I need this to work on our intranet. We are using SP 2013 Enterprise.
I have tried following the steps,. How and where do I use the script? Can I insert it inline, when I edit a page?
Hi, you can use the content editor webpart with a reference to a script file.
Hi, can you explain how to do this?
Hi Joran, i can put this in a sharepoint online app?
Yes you can, but you probably need to rewrite some code to perform cross domain scripting
Great article! Thanks
Your solution works like a charm, i just want to know if it is possible to display the profile image also, is this possible?
Here an update, so if someone can help me with the variables , this is really appreciated.
I managed to get the url , but now it is not yet dynamic.
The html code for the (in this case dutch) image path location is:
html +=”<img src='https://-my.sharepoint.com/User%20Photos/Profielafbeeldingen/__onmicrosoft_com_SThumb.jpg'>”;
However if you logon with your own domain, it will be ____SThumb.jpg
if i can retrieve the domain info and convert it to _, then i have found a way to add an image
Any suggestions?
hmm seems the code is not correctly displayed, should be
https://tenantname-my.sharepoint.com/User%20Photos/Profielafbeeldingen/lastnameofuser_yourdomain_yourprefix (nl,org, com)_SThumb.jpg
Has anyone a solutions to retrieve the picture from the profiles? This would be nice if this is possible with the application described in this blog
I would think you can grab some code from the DisplayTemplate (2013) or XSLT for the people search to add a profile picture to the results.
Hi,
I am having an issue with the code, I can get it to return results, but not for the dates I am expecting.
I have January birthdays in my user profile service, but none show up in the web part. If I extend the endtime to = currentTime.AddDays(60);
Then I do get a result, but it is for a person who has a birthday in August. His birthday is entered correctly as August 07.
Any ideas?
Thank you
What date notification do You use?
Not sure exactly what you mean by date notification.
Using the built in birth date with no year, so month day.
Sorry if i am missing something obvious and appreciate the swift response.
Jack
The example code uses the dutch date notation for the query (day-month-year). Maybe just update the query to month-day-year will fix your issue.