Saturday, February 7, 2015

10 Days of Sitecore 8 Analytics. Day 3: A Picture's Worth a Thousand Words

Main point for today

OK, I admit it.  On my recent posts I faked my picture of Abraham Lincoln in my Experience Profile.  I didn't even use PhotoShop; it was just a cheap SnagIt copy-and-paste.  But now, here's the real deal:
A true Abraham Lincoln Sitecore Experience Profile Contact
Why is this such a big deal Mike?  Two reasons:

  1. Looking into how to add a contact's picture to the Sitecore Experience Profile reminded me of how incredible the Sitecore community is.  There are great blogs going back months (from people much more talented than I am) that discuss this subject in great detail.
  2. The main purpose of this blog series was to investigate the power of xDB.  I've been around reporting requirements long enough to know that power comes from modeling whatever it is you want to model, viewing it in whatever way you want to view it.  While my adding a picture here is a tip-of-the-iceberg kind of moment, it will hopefully get the creative juices flowing (it did for me).

About that community

First and foremost, two top examples of how great the Sitecore community is, and representative of much more thorough discussions of this subject than I will have here today:
  1. Anything by Adam Conn is great.  This is a series he did back in September (which shows how far ahead of the curve he is) that does a great job explaining developing against xDB.
  2. Sitecore's great partner, Horizontal Integration, does a fantastic job of showing code samples.

My summarized steps to get Mr. Lincoln's picture in my Experience Profile:

There are much better posts around all things Mongo, development in Sitecore and xDB, etc.  This is my quick list of things that I went through as I investigated this task, using just the information from the above two blogs.

Step 1.  Learn enough Mongo to become dangerous.

As you get into xDB within Mongo, you'll gravitate to the Contacts and Interactions collections.  As you're using RoboMongo or MongoVue or your tool of choice, you'll find yourselves wanting to query the collections for your documents.  Again Adam Conn comes to the rescue with an explanation of how to use ID based queries.  Here are a few find() statements that also helped me:

db.Identifiers.find({"_id" : /extranet\\abr?/i})

In this example, my Identifiers collection has a link between my Contact ID and Abraham Lincoln's Sitecore user record.  The above uses a Regular Expression since in this case the _id field seems to be a string (as opposed to Adam's description of how to deal with identifier types in the Contacts collection).  The RegEX looks for user in the extranet Sitecore security domain, staring with "abr" and case insensitive ("/i").

db.Contacts.find({"Personal.FirstName" : "Abraham"})

Switching to a find in the Contacts collection, above is a way to find a value in an embedded document.  Contacts have a "Personal" document, with an embedded document that can include FirstName and LastName.  The Personal.FirstName syntax allows me to find a value of "Abraham" within.  This could be another use of a RegEX as used in the first example.


db.Contacts.find({_id:new BinData(3, 'zgZHZ6RszESnllHXYIuUrA==')})

Adam's blog will really explain why we need to set up a find query in this way for the Contacts collection.  The example above is just an easy copy and paste (changing out the resultant ID for your system).

Step 2.  Look at an example of a Contacts document.


{
    "_id" : LUUID("4332583d-d8df-3a5c-6382-4cb8037a15f3"),
    "System" : {
        "IntegrationLabel" : ""
    },
    "Identifiers" : {
        "IdentificationLevel" : 2,
        "Identifier" : "extranet\\mike@test.com"
    },
    "ConversionInfo" : {
        "WasConverted" : true
    },
    "Lease" : null,
    "Personal" : {
        "FirstName" : "Mike",
        "Surname" : "Casey"
    },
    "Emails" : {
        "Preferred" : "work",
        "Entries" : {
            "work" : {
                "SmtpAddress" : "mike@test.com"
            }
        }
    }
}

The above document has some entries based on some typical activity on our Launch Sitecore site.  For instance, by registering we've gathered some "Personal" values and "Emails" values.  Notice there is no Pictures section of this document.  As expected with this NoSQL strategy, the document continues to build as information is collected.

Step 3.  Understand a bit about facets

As Adam explains, the Experience Profile makes use of Contact "facets".  As of Sitecore 8, the Sitecore.Analytics.Model.Config file contains the default facets, as shown below:
Default Facets in the Sitecore 8 Sitecore.Analytics.Model.Config

Since "Picture" is already an available facet, nothing to do here.  Adam explains the process of adding new facets and leveraging those new facets in a new SPEAK-based tab on the Experience Profile.

Step 4.  Get some code to write to the Picture facet

Still getting my terminology straight here, but basically we want to add a Picture section to that original Contact document shown in step 2 for Abraham Lincoln.  Thankfully, our friends at Horizontal Integration have already done the heavy lifting here:
Horizontal Integration Code to write to the Contact's Picture
As an aside, you'll be likely looking for some assembly references to use the above, so just in case:


Now, by having a Media Library item with Abraham's picture and replacing the GetItem statement above with its GUID, we're good to go.

Since this isn't a real-world example and just an investigation, I went ahead and created a control that just runs the above code when I visit my page on my local Launch Sitecore instance.  I'm really interested in the real-world sources for this picture--social, CRM, etc.  And now I'm more interested in taking the next steps in understanding the power this type of access to xDB unleashes in Sitecore 8 projects.  I'll leave you with the new section of the Abraham Lincoln Contact document:
Abraham Lincoln Contact Document with Picture


And now we can see good 'ol Abe's smiling face when we access all the great detail of his Experience Profile (and no copy-and-paste this time around!):
Searching for Abe and seeing our new picture facet