Monday, November 2, 2015

A final post, and a transition

As I transition from my post at Sitecore, I wanted to take a quick moment to thank everyone at this great company.  It has really been an honor to represent a great product in a great market with an amazing partner channel of such talented and committed professionals.  I have learned so very much from you in these last 7 1/2 years, and I am truly grateful for the opportunities that have been available to me because of my time at Sitecore.

In particular, I wanted to thank Bjarne Hansen, who has been such a steady and significant influence.  His teachings have been admittedly simple--treat people fairly and honestly, a deal is only good if it's good for everyone--but they will continue to guide me in this and any future chapter.

I look forward to continuing the great conversations we've had and look forward to our ongoing study of the tools, techniques and technologies that drive the quest for the best digital experiences on the planet.  Look for (much more consistent) posts as I dive into my new adventure @ThunderheadONE.

Mike Casey

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


Tuesday, February 3, 2015

10 Days of Sitecore 8 Analytics. Day 2: Insights from the Experience Profile

Introduction to today's discussion

The Experience Profile is a new Sitecore view into analytics that provides incredible insight at a visitor (Contact) level.  From pages viewed, to patterns / personas matched to campaigns triggered to goals achieved, the Experience Profile paints a full picture of your visitors' interactions with your brand.

Today we'll take a bit of a deeper dive into this Experience Profile.  For those of you on the tech side, this view shows the power of what SPEAK interfaces can become in Sitecore, and as we get to the end of this series we'll see the ability to customize these views, add tabs to the reporting interface and more.  For this post I wanted make sure that some of the simple goals, campaigns and page events in our Launch Sitecore site are ready for the Experience Profile, and ready for those deeper conversations.

A reminder of what the Experience Profile looks like and what we'll be drilling into

Experience Profile with the Contact Timeline showing

Marketing Control Panel Considerations for the timeline


Campaign

For this exercise, I set up a new Campaign in Sitecore's Marketing Control Panel (as everything now is, one click away in the Sitecore 8 Launch Pad).  To those familiar with DMS, this is the same idea as the Marketing Center, the area of the content tree dedicated to setting up marketing initiatives.  I set up a new Campaign to track called "Video Blog Campaign" (our team is working on demo and other instructional videos that we plan to have a home for soon).


Some things to note that have been added to Sitecore 8.  The Campaign Group is a drop-down selector to allow us to start considering a richer taxonomies for our campaign organization.  This will become important later as we start looking at Campaign reports.  I added a new Campaign Group (Mike Campaigns) in this Taxonomies section, and it became available in the Campaign Group drop-list as I set up the Video Blog Campaign itself:

New Taxonomies Section for Campaign Management
  

Goals and Page Events

We can keep the goals we already have in place for Launch Sitecore.  These represent simple "transactions" that we are trying to encourage our visitors to take part in, like downloading the Launch Sitecore package, visiting certain targeted pages, adding articles to a logged in user's persistent profile:
List of Goals for LaunchSitecore.net

One interesting addition to Goals is shown below:

A Goal item shown in the Content Editor
Note that a new "Experience Profile Options" section with two checkbox field are now available for Goals (they are also available for Page Events).  This gives us the option to make sure these goals / conversions are prominently displayed on our Contacts' Experience Profile Reports.

With these simple Campaigns and Goals in place (and making sure all of these items are Deployed and Published), we can now start to see Abraham Lincoln's visit history start to take shape.

Below is a section of the Timeline where we can start to chart various interaction points with our Contact:

The Timeline gives us visual cues representing Goals achieved and Campaigns triggered.  It gives us a bar graph indication of value for the various visits from our Contact.  Below the Timeline we are able to see specific Goals achieved, the nature of the Campaign that was triggered, Page Views, Value and more.

Since we had many of the Digital Marketing considerations in place with Launch Sitecore (which started on Sitecore 6.6), we were able to ready the site for new Sitecore 8 features very easily.  The public site at launchsitecore.net is now on Sitecore 8 and tracking all this great Contact data so that we can enjoy the new insights that the Experience Profile and other analytics views provide.

Wednesday, January 28, 2015

10 Days of Sitecore 8 Analytics. Day 1: Where are we now?

An intro to this series

As I prepare for a discussion around Sitecore 8 Analytics coming up in a couple weeks, I figured a concentrated blog series on the topic would help in my investigation and preparation.  Those of you that attended Symposium and now have had a chance to see the generally available release of Sitecore 8 are undoubtedly excited to dive into all the details that make this release so great and so fundamental to the future of the platform.  This post will set the stage for a detailed look into the specific analytics features of Sitecore 8.  Since analytics is pervasive now in Sitecore (think Engagement Plans, the new Path Analyzer, Multivariate Test results reports and more), I will be touching on some features that aren't directly based on analytics reports.

How did we get here?

For those of you that have followed Sitecore's analytics evolution, Sitecore 8 is an incredibly exciting stage for this platform.  It is, at the same time, a culmination of lessons learned from the Online Marketing Suite through the Digital Marketing System days, combined with the beginning of a truly new frontier in analytics capabilities and possibilities for Sitecore.  OMS and DMS introduced amazing capabilities into Sitecore.  Sitecore 8 takes the best of these features, expands on them, introduces a wide array of new features, and makes the entire system scale to previously unreachable heights and scope.

An introduction to xDB

The single feature (really the single architectural decision) that makes this all possible is xDB.  xDB is an incredibly scalable collection and reporting system.  If you are just starting out in your investigation of xDB and Sitecore 8, please take a few minutes and read the xDB Overview and Architecture document on sdn.sitecore.net.  I'll take a couple of minutes to describes some key points, but the document does a really nice job in explaining the basics.

Taking apart one of the Overview document's diagrams, let's briefly look at the main components of the system.  The tier below includes:
  1. Content Delivery, our tried and true friend.
  2. Session State, always available to our .NET application, but this is a new version for xDB.  Session State is separated between Shared and Private, basically allowing data for a "Contact" (a Visitor that can have many Visits across any number of Devices) to be efficiently collected at a Visit level and also at the Contact level.
  3. Collection, a new system leveraging MongoDB to scale the collection of analytics data to unbelievable new heights.
Visitor Data Collection and State Management

Tackling the next grouping:

Processing for xDB Reporting Database storage
  1. Processing Server (also referred to as Aggregation).  This is a new Sitecore server tasked with dealing with all that great, expansive analytics collection.  It is able to make sense of widescale collection, mapping it to the tables and structure of the SQL Server reporting database described next.  This is also where some really interesting things can happen with ties to additional datasources like CRMs, demographic data web services and much more.
  2. Reporting Database.  We can think of this as very similar to the existing Analytics / Reporting database found in DMS.  In 7.5 and 8 and beyond, this table structure is very different, modeled for the scalability of the new collection system, and tuned for the various applications that will request data and reports from it.
Lastly:
Reporting Components of xDB

  1. xDB contains a Reporting Service that accepts requests from reporting applications / API calls.  This service can sit on another Sitecore server or can be a dedicated Sitecore server.
  2. Reporting applications (like the Experience Profile which shows insights around a single Contact, or the new Sitecore 8 Dashboard of out-of-the-box analytics reports) leverage the Reporting Service and format the data it responds with.

What if I don't want to understand anything about what you just talked about?

You're in luck.  Sitecore is working with MongoDB and Microsoft Azure to make this entire stack available to you via an xDB Cloud offering.  Sitecore offers a subscription model based on the volume of data collect (specifically the number of Contacts and their interactions with your sites).  The beauty of this subscription model is that all of the components described above (with the exception of Reporting Applications that you'll want locally) is architected, maintained and scaled for you.

What do some of these new Reporting Applications look like?

For now we'll just take a high-level look at some of the reporting applications and interfaces.  Further into this series we'll do more detailed investigation into some of these, as well as discuss the possibilities that xDB unleashes in terms of connected external data, customized reporting and more.


First, the overall Sitecore 8 Launch Pad, with a couple of default reports on my dashboard:
The new Sitecore 8 Experience Platform Launch Pad
By selecting Experience Analytics, we get to the new Analytics Dashboard, with an impressive list of out-of-the-box reports and a default dashboard:
Sitecore 8 Experience Analytics Dashboard

The Experience Profile, which we'll investigate more closely in this series, shows the insight you can gain around a particular Contact important to your organization:
The Experience Profile
Lastly, the Path Analyzer shows valuable paths through our site based on goals and outcomes we've set up in Sitecore.
Sitecore 8 Path Analyzer

Setting the stage for our investigation

Hopefully this high-level introduction sets the stage for this series to take a detailed look at some of these reports, the data that drives them, and the possibilities that xDB brings us.  In the next post, we'll start setting up a campaign that follows this series.  As always, go to www.launchsitecore.net and register to get your own copy of this evaluation site in Sitecore 8.

Monday, September 8, 2014

On the way to Sitecore Symposium

One of my very favorite events is when Bjarne Hansen—president of Sitecore North America—spends a few traditional moments at the annual sales kickoff and company celebration.  He is the single best person in the world to relay the company’s history, and he takes these moments to ask people to stand in recognition of their achievements in the order they joined Sitecore.  (Note: he is able to do this in the context of how many company celebrations you’ve attended with significant others, an amazing thing in and of itself).  “If you were at the very first company celebration…..”  Literally a handful of the great North American founders stand.  Huge applause.  2nd, 3rd, 4th, 5th celebration attendees stand in turn.  More applause as bigger chunks of the room stand.   “If you joined this last year….”.  The remainder of the room--more than half of its total attendees--stand to applause as the already standing welcome the new crew, excited about how they will help continue to grow the well-oiled machine in place.
I’m on a plane from Boston to Las Vegas and thinking about those events that I’ve had the privilege to attend, trying to get through some chapters of a MongoDB text recently purchased, and looking forward to a fantastic week at Sitecore Symposium 2014.  The tradition that Bjarne keeps is always an incredibly tangible, live-person-bar-graph way of seeing the phenomenal growth at Sitecore.  Symposium is another such event—this one having the added benefit of our incredible partners and customers joining in the fun.  And while Bjarne’s exercise drives home the growth of the fantastic people working for Sitecore the company, this event rounds out the story by adding the growth highlights within the product, partner channel and customer base that makes this amazing ecosystem that is Sitecore.  Bjarne is always clear about this achieved goal—we have the best people, the best partners, the best product and the best customers in this industry.  Period.  It would be silly to say this goal is easy and foolish to say it’s ever fully realized, but the consistency of this message drives this ecosystem to fantastic new heights every year, heights that will be very tangible in Las Vegas.
Symposium 2014 will be yet another reminder to me of how far we’ve come.  I left the original Dreamcore with a great feeling (“wow, we’ve arrived”), and looking through the session agenda this year makes it incredibly clear how much further this platform and its people have evolved.  It is truly amazing to see the breadth of what is to be covered this week and it makes me look forward to the side conversations between and after sessions that will fill gaps left by presentations I couldn’t attend.  When at Dreamcore we were certainly talking Web Content Management (which itself filled an impressive session agenda).  Now, with that WCMS engine still incredibly important, foundational and fundamental, we’re able to have the discussion about the set of layers that leverage that Rocks-solid foundation.  From mobile development, publish once / use everywhere, content-as-a-service, content marketing, testing, analytics, insights-driven personalization, EXPERIENCE….the list goes on and on.  An incredible new analytics architecture drives the next phase while holding true to time-tested features and methodologies.
The customer and partner sessions reinforce that feeling of pride I had way back at Dreamcore—there is truly an army of Sitecore-powered professionals that do amazing things with this platform.  There is no one Sitecore solution, there is only the right Sitecore solution for you or your customer.  The collection of challenges and solutions described in these sessions really brings that point home for me, and reminds me that software projects are never perfect, but they are made more perfect by the skill of this ecosystem and the breadth and flexibility of this platform.
With the sneak-peak of Sitecore 8 (look at all of those tiles and applications in this platform!), I’m continually blown away at how much this system can do.  Sitecore 8 really drives the point home of how powerful it is to have all this under one hood, one set of user interfaces, one incredibly consistent underlying structure and model.  Oh, and to top it off, Sitecore Experience Platform and Commerce—a bond with obvious and far reaching potential—is now being realized.  The scalability of Sitecore search and content/product modeling with the ability to test and optimize and present in the right place, at the right time, coupled with the amazingly granular insights that drive this continuous optimization.  Wow.
In my own job, I get to support the best presales engineering team in the biz.  We challenge ourselves with keeping ahead of this growth, keeping on top of an ever-evolving product and technological landscape.  Check out Chris Castle’s and Brandon Royal’s session as they discuss their own experiences moving Launch Sitecore to Sitecore 7.5/8 and a cloud-powered architecture.  We are excited by the challenging level of expertise that you expect and deserve from us and are looking forward to the heights our combined expertise and the Sitecore Experience Platform will take us this year.  We look forward to working closely with all of you as together we unlock the potential of this platform and stand up together in celebration of all the successful Sitecore solutions ahead.
As Bjarne reminds us, more than anything, it’s the people.  It’s the ecosystem at this event (and those at home still ferociously working the project) that makes me incredibly proud to represent this platform and this company.  Software projects are people projects that succeed and fail with the level of skill, resourcefulness, drive and teamwork of the people that undertake them.  I am truly honored to be among those of you that will be in this impressive Symposium audience, and those of you that work to drive successful Sitecore projects every day.  Please seek out as many of your Sitecore employee hosts as you can at this great event (there are lots that have just joined this year, but we’re all easy to find in our purple shirts).  Say hello and let’s talk about how we can continue on this great journey together.

Tuesday, March 18, 2014

A Sitecore 7.2 feature worth the wait: Search-driven controls

As always, I want to provide both the technical and business benefits to a discussion topic.  I've written about this use case in the past, but with Sitecore 7.2 there is now an out-of-the-box feature that it makes the solution to it very straightforward and available to both the business and technical sides of the house.

Basically, since Sitecore controls are so flexible and can bind to a "datasource" based on any number of conditions, the ability to use search interfaces and results to drive this datasource is a natural improvement to the platform.

So take for example the controls on the right hand side of this page:

A Launch Sitecore "Contributor" page with added controls in the right column

The Articles control at the top is set up to look at a specific field of this "contributor" content type / data template.  All Articles have a checklist field so that we can appropriately credit our contributors with their article contribution.  In this way, the control is going to always show a full list of my articles without my having to go back to our development team and rework the control every time I write a new one (which, at any rate, is not all that often).

Similarly, the control below the articles control shows another list.  This list can be driven by a pre-built query against the entire content tree.  I've always been a fan of this technique, as we can create a nice bridge between our development team and our business team.  The business folks could describe in words what they want:

"I need a list of a all articles that have been tagged for Marketers".

Developers (or really anyone that has become familiar with Sitecore queries could come up with something like this item:
A pre-built search query item


In reality it isn't even necessary to be familiar with this search syntax since the "Build Query" feature within this Content Editor view would allow you to use the search interface within Sitecore to prepare the pre-built query item.  Once the item was built, now the business folks could use this item as a datasource for the control and our use case solution for an ongoing dynamic query control would once again be complete.

(In older solutions to this use case, we used the same technique as above, but used Sitecore Query notation).

Now, in 7.2, using these search queries as control datasources is even more cool and direct.  Let's rework the control on our page.  The good thing is, Chris Castle's Launch Sitecore control is already written so well that it doesn't need changing:

Selecting the LS Queried List control for our page

As the dialog appears to select an associated datasource for the control, we can see that we now get the ability to Search for Content on the left (previously we would have chosen a specific content item):

Searching for associated content

There are two areas we could use here to come up with our result set.  The right hand side of the screen will show us the available facets (template, date range, author, etc.).  These facets are impressive by default and fully extensible to enable the inclusion of specific attributes important to your business.  In addition, the drop arrow on the left of the search box provides a choice to use pre-built search filters.  For the example below, I'll use this technique to choose:
  • Items that match the Article Data Template (they have to be Launch Sitecore articles)
  • Items that were initially created by Mike Casey
Both Template and Article are pre-built search filters, so I can easily choose them from the list.  There's also a nice "intellisense"-like feature that allows me to start typing and see available options based on my keystrokes.

Setting up the search query with pre-built search filters
If I click on the magnifying glass to run the query so far, I notice I have 65 results:

Initial search results for Mike Casey as author, Article as Data Template

My team will tell you that I haven't contributed nearly that many articles.  In fact, in the Template facet on the right, we see that of the 65 items returned, 22 were articles, 9 were images, and so on.  By default this is a logical "or" query, so we're getting too many results for our list's purpose.

By clicking to the left of each chosen search filter, we can toggle through a "must have", "must not have" "can have" logical operator set.  For our list, we want to ensure that both filter criteria are true:

Tweaking the query with logical operators
With the "Must Have" criteria in place and by clicking the magnifying glass again, we get the expected four article result, and we are satisfied with our search query:

Finished product

Now think about the fact that you can set up personalization or multvariate tests on this control using different search criteria.  The search criteria can be coupled with any other conditions Sitecore has access to (GeoIP, campaign, etc.).  You're off an running with a truly dynamic experience for your visitor.
 

Snippet for the Developers:

For the developers, the reason that this already works in your current Launch Sitecore package is that Chris Castle thought through the various datasource items that might be passed.  Here is a little snippet of the resulting logic if the datasource is deemed to be a query string (rather than a specific item GUID).  This full code is available via the DataSourceList.ascx control in the project:
 
        // if the datasource was not a query item try to process the datasource as a query
try
{
//Open search context based off the current item
using (IProviderSearchContext context = ContentSearchManager.CreateSearchContext((SitecoreIndexableItem)(Sitecore.Context.Item)))
{
string languageCode = Sitecore.Context.Language.CultureInfo.TwoLetterISOLanguageName.ToString();
IQueryable<Item> queryable = (from toItem in LinqHelper.CreateQuery(context, UIFilterHelpers.ParseDatasourceString(Attributes["sc_datasource"]))
where toItem.Language == languageCode
select toItem.GetItem());

// the master index will have each version so we need to remove the duplicates.
if (Sitecore.Context.Item.Database.Name.ToLower() == "master")
return queryable.ToList<Item>().Distinct(new ItemIDComparer()).ToList<Item>();
else
return
queryable.ToList<Item>();
}
}

Sunday, March 16, 2014

Checking with your own data to drive a Sitecore personalization condition

Why should I care about this?

Sitecore comes with an impressive list of prebuilt conditions to drive personalization--from referring URLs to the fact that a visitor comes to the site as a campaign respondent to GeoIP attributes of country, zip code and more.  In many discussions I have on the topic of personalization, the conversation inevitably leads to "yeah, but I want to use THIS thing."

To generalize, the THIS thing is some existing system or service, external to Sitecore, which holds a key piece of information.  Since this external system should remain the system of record for that piece of information, it makes sense for Sitecore to simply leverage the data where it sits, rather than enforcing that it move directly into the Sitecore content tree.  For those of you that have worked with Sitecore, you know it’s built for this.  Rather than enforce a migration of data to the content repository, a well developed Sitecore strategy continues to take advantage of data and application functionality wherever it is best served from.  Personalization conditions are no different.

Below I will work through a common scenario.  We want to develop a condition that queries an external database and determines whether a product is available before showing the promotion our marketing team has created for it.  With the condition in place, it will be easy for us to build a rule that does something when the condition is true.  This is a classic “When” condition, and we can think of all kinds of rules that might be appropriate based on the true / false value returned.

Who in my organization creates these conditions?

As an aside, many of my conversations lately have involved questions like "who sets up personalization in Sitecore?”.  A very fair question.  I enjoy the discussion because it really highlights that there is a transition going on here.  Sure, every piece of conditional logic could be developed separately (it is software, and everything is possible), but the question is sparked because this capability is now in the hands of many more people in the organization.  It’s not JUST for developers anymore.  While developers are certainly creating the great methods that evaluate conditions and implement rule-driven functionality, others in the organization (you get to decide who) are mapping the business processes and visualizing the results.  These two sides are equally important, and those organizations who find the people with the right combination of skills will certainly benefit.

Creating the custom condition

Back to it.  1st step is to create an item to define the condition.  Who does this?  Well, in most cases this one’s for the developer.  The reason is that we’re coding brand new logic here.  If you’re talking about the rich set of standard Sitecore personalization conditions (Geolocation info, DNS info, authenticated user profile attributes, etc), then there’s no work to do here.  These Conditions are already defined and available to you as you build a rule to evaluate that particular Condition.  More on that later.  The screenshot below shows the beginning of the scrollable list of prebuilt Conditions:




In standard Sitecore fashion, all prebuilt Sitecore functionality is built and referenced in the same way you’ll build your specialized or customized functionality.  If you look in the Content Editor at:

/sitecore/system/Settings/Rules/Definitions/Elements/GeoIP/Area Code

you’ll see the definition (the Item in the tree) that represents the condition.  Even though this is a standard Sitecore Condition, we are still able to see where this code is called from in the core application (in this case, the Sitecore.Analytics assembly contains the code for this condition):

The Default "Area Code" condition in Sitecore


You’ll notice that the AreaCodeCondition class in the Sitecore.Analytics assembly is referenced.  You’ll also see that the Text field allows you to define placeholders where a content author can enter additional parameters to the condition evaluation (this Text appears in the Rules Editor when adjusting the specific condition for a personalization rule).

So for our purposes today, it’s going to be even easier.  Rather that doing a compare of values between Analytics data and content author entered parameters, we’re simply going to check the “trueness” of a condition.  Does the product have any availability?  Based on the result, we can then decide what to do about it.

A strategy for setting up custom conditions and rules

In regards to the question again about "who does what?", this is a typical thought process around setting up these types of conditional rules:
  • A cross-functional team discusses the Conditions that need to be evaluated.  Many will be available in Sitecore already, some will have to do with your business-specific data that Sitecore couldn't possibly know about natively.
  • A cross-functional team discusses the Rules, the things that should HAPPEN when a Condition is evaluated.  Again many will exist in Sitecore already (easily hiding or showing a control, having a control display a different piece of content, moving a control to a different area of the page, initiating a specific Email Campaign, etc.) and some will do fun and exciting things outside of the Sitecore application domain and context.
  • A cross-functional team discusses where and when these rules are appropriate, and which groups should have the ability to adjust the rule set.
  • A cross-functional team ensures that both sides of the brain communicate, and that the development efforts and the business process mapping stay on the same (albeit flexibly winding) trail.  
The point here isn’t that you need a huge cross-functional team.  The point is that if you’re a team of one (or 2, or 10, or 100), you need to think cross-functionally.  Nothing new here.

The three steps to implement the custom condition and rule

OK, so again for this example we simply want to rely on an external system to determine whether a condition exists.  We'll use the freely available AdventureWorks database from Microsoft.  The basic idea will be to:
  1. Add a new condition item to Sitecore (so that someone in our organization can choose the condition as part of their personalization rules for a control).
  2. Write a custom condition that looks to AdventureWorks to find out if there is product inventory for a certain product.
  3. Add our new condition to control on the Launch Sitecore home page so we show a different spot if the product is available.

Step #1

We need to add the new item to the content tree to reference our custom condition.  I put the item at

/sitecore/system/Settings/Rules/Definitions/Elements/Fields/

...so it would show up near the top of our list when we apply it to a control.

Our new custom condition

Since we're making the condition check very simple (we're going to always look for product availability for a product with an ID of 1), we don't need to set up the Text field with any macro replacement possibilities.  In the real world, we'd want to either allow an author to choose a specific product using this technique, or we could think about making that decision based on which page the control is on (i.e., a product page dedicated to a particular product could also pass that product ID directly to our inventory check routine).

Step #2

Now we need to write some code for the actual condition check.  The main Execute method is shown below.  Note that I used the freely available Entity Data Model Wizard within Visual Studio to set up an easy LINQ query to the AdventureWorks database.

        protected bool Execute(T ruleContext)
        {
            var numUnits = 0;
            try
            {
              using (AdventureWorks2012Entities context = new AdventureWorks2012Entities())

                numUnits = (from m in context.ProductInventories
                                where m.ProductID == 1
                                select m.Quantity).FirstOrDefault();

                return numUnits > 0;
            }
            Catch

            { return false; }


        }


Now, when a personalization rule includes this condition check, we'll simply go to the AdventureWorks database and check for availability of ProductID 1.  Since the conditional check is basically a true/false result, we'll return whether or not the product availability for that product is greater than 1.  With my new condition added to the content tree (described above), this is where we can see it (in the Fields section).  You can organize your custom conditions anywhere that makes sense.

Our new condition shows up in the list for a business user to choose


Step #3

Now we can add this to the simple spot controls on the Launch Sitecore home page, showing the Einstein spot if this condition is true.  Below shows the Page Editor view where I can add a New Condition to my control, calling out my check to AdventureWorks, and the "Step 1" content item the control will use as its datasource if my inventory check returns True:

Our new condition is now part of the Rule Set for our Home Page control

Hopefully this sheds some light on how achievable it is to consider external data personalization sources in Sitecore.  Taking the next steps and creating bridges to product catalogs, existing systems of record and web services can really open up your personalization options without changing repositories and services that already do their jobs incredibly well.