Sitecore Hints: Recently Viewed Products in xDB

Posted 06/17/2015 by Sean Fox

Recently I ran across a request on a project to display Recently Viewed Products on pages for anonymous users in Sitecore 7.5 (with xDB). There was a popular article a while back https://briancaos.wordpress.com/2011/11/18/get-last-visited-pages-from-a-sitecore-dms-oms-profile that essentially wrapped up this kind of functionality and so I was off to the races, or so I thought.

This line: Sitecore.Analytics.Tracker.Visitor.DataContext.Pages.Reverse() is no longer valid with the new Sitecore Analytics API, and the xDB (MongoDB) implementation.

If you remember from before there was a hierarchy similar to this for figuring out the history for a unique visitor on the site and the associated behavior of their experience.

Browser
1. SC_ANALYTICS_GLOBAL_COOKIE
2. SC_ANALYTICS_SESSION_COOKIE

Analytics (SQL) Database
1. Global Session
a. Session
i. Page
ii. Page Event
iii. Page Event Definition (campaign, goal, custom event etc., or what kind of page event)

With the advent of the Sitecore Experience Profile comes the notion of “Contact” (anonymous and/or known to the system) and “User” (known to the system). This is cool as along with known users, those that have logged in, signed up, or registered etc. there is a rich history for anonymous users who are a big part of the target market, potential customers. It’s nice to cater personalization around their experience as well.  If they then later trigger one of those events, the contact becomes a known user and that history is merged and persisted. 

Here is a list of some of the properties for each interaction that I can operate on. In this case I am interested in the Pages array:

1. Pages – Array of Page[] 
2. CustomValues
3. Ip
4. Keywords
5. Language
6. Referrer
7. ReferringSite
8. SiteName
9. UserAgent
10. BrowserInfo
11. CampaignId
12. ContactVisitIndex
13. CurrentPage
14. DeviceId
15. EndDateTime
16. GeoData
17. HasGeoIpData
18. InteractionId
19. LocationId
20. LocationReference
21. NextPage
22. OperatingSystem
23. PageCount
24. PreviousPage
25. Profiles
26. SaveDateTime
27. ScreenInfo
28. StartDateTime
29. TrafficType
30. UserAgentId
31. Value
32. MvTest
33. VisitId

The Page object has 3 properties, which I can use to retrieve the current (language version of the) item:

1. Id
2. Language
3. Version

Essentially what I need to do here is:

1. Populate some datasource with a list of pages (products) a contact (anonymous) has viewed. 
2. This list is stored in blocks of “interactions” which represent sessions. These interactions are aggregated while a user is browsing and at the end of the session written into the xDB, which we can retrieve and query. 
3. As well, I can leverage to the current interaction. The current list together with the list from history will give me what I need.
4. Then I need to iterate through each page, resolving the related item to display its properties.

Let’s code!

Up top I have my required Sitecore Analytics assemblies referenced.

using Sitecore.Analytics;
using Sitecore.Analytics.Data;
using Sitecore.Analytics.Core;
using Sitecore.Analytics.Tracking;

First check the tracker, and contact and make sure they aren’t null.

ITracker tracker = Tracker.Current;
if (tracker == null) return;
if (tracker.Contact == null) return;

Now I will need a dictionary to store the recently viewed products.

Dictionary<string, Item> recentlyViewedProducts = new Dictionary<string, Item>();

The contact isn’t null so try and retrieve a set of interactions, I will try the last ten.

If we are good there, and there are pages I can actually operate on
For each page, try and retrieve the underlying item, and if resolvable add it to a dictionary.

Now I will try and collect pages from the current interaction, if I can retrieve enough, I won’t need to look at the history. For each page, I try and retrieve the underlying item, and if resolvable add it to a dictionary.

if (tracker.Interaction != null && tracker.Interaction.Pages != null && tracker.Interaction.Pages.Length > 0) {
foreach (var page in tracker.Interaction.Pages) { 

   // Validate there is a page item (ItemData)
   if (page.Item == null) continue; 

   // I’m looking for around 10 products, if I’ve reached that limit, stop processing
   if (recentlyViewedProducts.Count > 10) break; 

   // Try and retrieve the item by id, and language
   ID itemId = new ID(page.Item.Id);
   Language language = Language.Parse(page.Item.Language);

   // Try and retrieve the item by id, and language
   Item item = Sitecore.Context.Database.GetItem(itemId, language); 

   // Validate that the language item was resolved
   if (item == null) continue; 

   // Filter duplicates
   if (recentlyViewedProducts.ContainsKey(item.Name)) break;

   // All clear lets add
   recentlyViewedProducts.Add(item.Name, item);
}
}

At this point we’ve checked the current interaction object, if I haven’t reached 10, I need to look at the history. This comes in the form of a collection of IInteractionData, a.k.a. sessions.  The Pages array will be found for each object in this collection.

if (recentlyViewedProducts.Count < 10) {

// I am going to be conservative here, and only look at the last 10 sessions. 
// ** Note the weird spelling of LoadHistorycalData ... that’s not a typo  
IEnumerable<IInteractionData> interactionData = tracker.Contact.LoadHistorycalData(10); 

// Parse the Interaction data 
foreach (IInteractionData data in interactionData) { 
foreach (Page page in data.Pages)
{
// Same logic as before
}
}
}

** Note that in my case there was no requirement to show a particular order for recently viewed product collection

Lastly, I will convert my dictionary into a clean list of items to be used as a datasource for display.

List<Item> items = new List<Item>();
foreach (KeyValuePair<string, Item> pair in recentlyViewedProducts)
{
items.Add(pair.Value);
}
if (items.Count > 0)
{
// bind items here to a datasource
}

And that’s all the processing I need. Thanks, and stay tuned for my next blog post.

- Sean


Share:

Add your comment

 
 

 

Comments

  • Vinod said:
    5/17/2016 11:51 AM

    Thanks for the article. In the sample you are assuming every page as product detail page, is it possible to restrict pages queried from the tracker based on the template?

  • Ayushmati Das said:
    9/28/2017 11:53 AM

    This shall only display the first 10 pages visited in a current session as it simply parses the pages in the tracker using: foreach (var page in tracker.Interaction.Pages) We can update this to continuously display the last 10 pages visited in a current session by using : tracker.Interaction.Pages.OrderByDescending(x => x.DateTime)

  • 企业宣传片制作d2film.com影视视频制作公司QQ30998 said:
    2/4/2018 2:56 PM

    企业宣传片制作价格_企业宣传片拍摄公司_企业宣传片创意视频_企业宣传片制作哪家好影视视频制作d2film.com企业宣传片制作拍摄QQ30998 企业宣传片制作d2film.com影视视频制作公司QQ30998 http://www.d2film.com/

  • 婚礼跟拍视频5aivideo.com婚礼摄影MV-QQ73595 said:
    4/3/2018 7:19 PM

    婚礼短片制作_创意婚礼视频_创意婚礼开场短片_浪漫求婚视频_求婚视频制作婚礼跟拍视频5aivideo.com婚礼摄影MV-QQ73595 婚礼跟拍视频5aivideo.com婚礼摄影MV-QQ73595 http://www.5aivideo.com/

Archive

Syndication