Sitecore 8 Federated Experience Manager pt. 2 – Pushing renderings to non Sitecore sites

What has always intrigued me with some of the new functionality of Sitecore 8’s Federated Experience Manager is how content is pushed to other sites. This post will explore this concept.

Following on from my first post regarding capturing analytic information from non Sitecore sites, I wanted to see how easy (or difficult) it is to add content to external sites

For this, I will set up a basic Title and Text component and see how we can utilise this rendering on a non Sitecore site. The site I’m going to add this too is the basic default ASP.NET MVC site I configured in part 1 – it is important to point out that the technology behind the site really doesn’t matter (which is cool in itself!)

Setting up a Rendering Component for this test (ascx)

Just to briefly show how the component is set up, below is the markup:

<div>
<h2>
<sc:Text runat="server" Field="Title"/>
</h2>
<sc:Text runat="server" Field="Text"></sc:Text>
</div>

view raw
gistfile1.txt
hosted with ❤ by GitHub

One observation I made when testing this was that the component itself needs to be surrounded via a containing element. Beforehand, my component didn’t contain a surrounding DIV and all that was being rendered was the H2 – so ensure that your component has a containing element and you should be fine.

Below is the Datasoure Template used for this component:

titleandtextdatasourcetemplate

Now, if we open up the Federated ExperienceManager, click on our site and click the “Open in Experience Editor” button, you will open the external site in the Experience Editor ready for personalising.

You will notice that on the Ribbon there is a botton marked “Add Placeholder”. This will allow you to provide an anchor point on the page where the components can be inserted.

When you click onthe “Add Placeholder” button, you’ll notice that all other buttons are grayed out. What you can do now is to click on any element from within the page and a list of options will appear.

addplaceholder

Notice that the selection will display the element that you want to interact with, the “up left” arrow allows you to fine-tune your selection to ensure that the correct element in the DOM is selected.

You will also have three options:

  • Add Before – allows you to add a component before this element
  • Replace – Replace this element entirely
  • Add After – Gives you he option to add components after this element

In this experiment, I’ll select “Add before” and give the placeholder then name of “promo-panel” and select “Test Site” as the parent element.

addplaceholderdialog

Now that we have a placeholder on the page we can select this placeholder to insert our Title and Text component

addtoplaceholder

From this point, you will have the same level of functionality as the standard Experience Editor – so add your component (in my case the Title and Text component and associate a Datasource with it in the standard manner

Once this is done, publish the changes. Now let’s look at our site:

personalisedsite

As you can see, our new component is being rendered onto the page of our non Sitecore site. Pretty clever eh?

How does this look in Sitecore?

Lets inspect the backend of Sitecore and see how this is acheieved. The settings for this are stored in /sitecore/system/Marketing Control Panel/Federated Experience Manager

LocationinSitecore

You’ll notice that our “promo-panel” Placeholder is here. Let’s have a look at that:

promopaneldata

You’ll notice that there is a Selector field. This indicates exactly where in the DOM to insert the content – and the above “Position” field signifies to insert content before this selector.

Now all that’s missing is “what” is inserted into this Placehlder. This is defined in the Presentation Details of the Placeholder:

placeholdersettings

Pretty clever stuff eh? 🙂

From here is should also be possible to provide Personalisation and DMS based rules to the Presentation in the same manner as any other Presentation in Sitecore. I’ll be looking to explore this in a future post.

Hope you have fun with this.

Experiences with Sitecore Federated Experience Manager

Over the past couple of days I’ve been a little fun with Federated Experience Manager and I’m really liking it 🙂 There’s a great deal of functionality and fun (yes I’m like that!) to be had. Especially with the concept of “hooking into” a completely independent site and tracking what pages are visit or even the concept of pushing content to other sites (we’ll explore that concept in a future blog post)

In this blog post I’ll quickly demonstrate how to quickly set up Federated Experience Manager and get started with the basics like tracking analytics.

How do I install Federated Experience Manager?

For my “independent” site I simply created a new Web Application (that contains no functionality – it’s not needed for this purpose) in Visual Studio. For this example I used ASP.NET MVC Application. What’s important to remember is that as it’s independent site to Sitecore it’s actually technology agnostic – you could have set up a demonstration in PHP or even straight HTML :).

So, once my independent site is set up it looks something like this:

testsite

As you can see, I’ve set this up to respond under http://testsite (IIS/hosts files have been configured etc.)

Now we can do the fun but and add a reference to this site in Fereration Experience Manager by adding an “External Site”:

addingexternalsite

There’s not a great deal of information to fill in here – what is very important is the “Tracking Script” (or Tracking Beacon). This is a piece of Javascript that you need to include in your independent site where you want the Federated Experience Manager to hook into. Without this script, there will be no interaction between Sitecore and your external site.

As my site is as out-of-the-box ASP.NET MVC site, I included this tracking script in the <head> element of _SiteLayout.cshtml:

<head>
<meta charset="utf-8" />
<title>@Page.Title – My ASP.NET Web Page</title>
<link href="~/Content/themes/base/jquery.ui.all.css" rel="stylesheet" type="text/css" />
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery-ui-1.10.3.js"></script>
<script src="~/Scripts/modernizr-2.6.2.js"></script>
<!– Tracking Beacon inserted from Sitecore Federation Experience Manager –>
<script src="//sitecore8-150223/bundle/beacon"></script>
<!– End of Tracking Beacon script –>
<meta name="viewport" content="width=device-width" />
</head>

view raw
Tacking Beacon
hosted with ❤ by GitHub

Now that we have the Tracking Script configured on our site, we should be in a position to go to the Federated Experience Manager, select our Test Site and click the “Open in Experience Editor” button. You should see the following appear:

experienceeditor

That made me smile 🙂 My completely independent site opening in the Experience Editor in Sitecore ready for action!

For this simple example all I’m going to show is how to capture someone clicking on the Register button (you would normally plan your events ahead however this shows its simplicity). If you click the “Capture Click Action” button, you should be able to select any HTML element on the page in order to assign a click action to it. For example, if you click on the “Register” button of the website you should see that Sitecore has identified that you have clicked on an Anchor tag and allow you to assign a “click action” to it:

addnewclickaction

You can navigate to the specific element in question if you need to and when you’re happy you can click on the “Add a new action” to further define your click action:

captureclickaction

Once you’ve given your Click Action a name, you can assign any Goals or Analytic Attributes that you already have set up in Sitecore:

settingupgoals

The rest of the UI should be familiar to you in terms of assigning goals/outcomes etc. When this is done ensure that your changes are saved and published – and that’s it 🙂

So, what happens when we browse our site?

When we browse our test site and click on the Register link, the Tracking Beacon Javascript will now call Sitecore to register the event. This can be evidenced in Telerik’s Fiddler tool:

fiddler

Checking that this has worked.

You can verify this has worked in the usual places where you expect gather reports on Experience Analytics, for example, below shows the Page URL’s that have been tracked, which includes visits to my testsite:

pageurls

Also, if you take a look in the Experience Profiler, you will also see the usual profile of the visits that have occured, including visitors of your external sites as shown in the detail of a specific visit below:

detailedreport

I hope this has given you a taste of the level of power you have with Federated Experience Manager. So far I’ve only scratched the surface of what’s achievable. I will be exploring other concepts of FXM in future posts.

Sitecore 8 Experience Analytics and Outcomes

So far, there isn’t a massive amount of resource available on what Outcomes are in Sitecore 8 and how and why you should use them. This post will aim to explore what Outcomes are and give an example of how they could be used in a real life situation.

So, what are Outcomes?

An Outcome is essentially a “Business Significant Result” and can be used in your Personalisation rules and tour Engagement Plans. An Outcome can be put simply as “something that has happened that is of significance”.

Rules Engine usage

You can utilise Outcomes in the Rules Engine to personalise content related to a specific outcome that has occured for the visitor. The following two rules are defined for you:

Outcome Rules

You can see that out of the box there are two rules

  • where the current contact has registered the outcome during any interaction
  • where the current contact has registered the outcome during any interaction where monetary value compares to value

(the Outcome Rule Action on the right-hand side is a custom rule action that I’ve created, I’ll cover this later)

How can we use Outcomes?

To demonstrate how Outcomes can be used, I will set up an example scenario. The scenario will be to register an Outcome if a new Product has been purchased as a result of expressing interest in the Product before it was released. For this example I will set up three basic content pages:

  • To register as a User
  • To register initial interest for the Product
  • To purchase the Product

Page Setup

Each page will register a specific goal. The final page will register a custom goal which will also register the Outcome.

As shown below, I’ve added the following Goals which are used in this example:

  • Purchase Interest Submitted Goal – fired when the Interest Submitted page loads
  • Purchase Product Goal – fired when the Purchased-Product page loads
  • Purchase Product Register Outcome Goal – fired when the above two goals have been fired

Goal Setup

The last goal in the list is a custom goal as it will also register an Outcome. This can be achieved by setting up a custom Rule Action using the below code:

public class TriggerOutcomeRuleAction<T> : RuleAction<T> where T : Sitecore.Rules.RuleContext
{
public override void Apply(T ruleContext)
{
RegisterOutcome();
}
public void RegisterOutcome()
{
ID id = ID.NewID;
ID interactionId = ID.Parse(Tracker.Current.Interaction.InteractionId);
ID contactId = ID.Parse(Tracker.Current.Contact.ContactId);
// Definition for Product Purchase Outcome
var definitionId = new ID("{9016E456-95CB-42E9-AD58-997D6D77AE83}");
var outcome = new ContactOutcome(id, definitionId, contactId)
{
DateTime = DateTime.UtcNow.Date,
MonetaryValue = 10,
InteractionId = interactionId
};
var manager = Factory.CreateObject("outcome/outcomeManager", true) as OutcomeManager;
manager.Save(outcome);
}
}
}

(You can find more information on how to register outcomes on Ian Graham’s blog post here http://coreblimey.azurewebsites.net/sitecore-8-outcomes/)

Then I will set up an Outcome Definition called “Product Purchase” in the new Outcomes section of the Content Editor. This is the Outcome that the Rule Action will fire:

Outcome Definition

Then, for the “Product Purchased Register Outcome” Goal, I will utilise this custom Rule Action to the Rules that are evaluated for that Goal (see Rule 1 below):

Rules for registering Outcome

Now that we have all the pieces to make this work,, I’d like to introduce you to a new feature of Sitecore 8. The Explore Mode of the Experience Editor. This is a very useful way to test and verify that your Goals are converting and your Outcomes are being registered. To find out more about Explore Mode, have a look at Martin Davies’s blog post here:

http://sitecoreskills.blogspot.co.uk/2015/03/explore-mode-aka-sitecore-experience.html

All I will be doing is visiting the three pages in turn (interest-submitted and purchase-product) to simply evidence the Goals have been converted and the Outcome has been fired.

After quickly running through the pages – Explore Mode verified that my Goals had been converted:

Experience Editor

Currently, Explore Mode does not give us a view of any Outcomes that have been fired, but we can use the Experience Profiler to view the. Firstly ensure that everything is published (as you’ll need to browse the site properly for analytics to be captured) and then go into the Experience Profiler and select your visit (once the analytics have been flushed to MongoDB – this happens when the session ends). The Experience Profiler will show information on your visit – with one of the tabs representing Outcomes that have occured.

Outcomes

Arguably I should have named my Outcome a little better (e.g. Product Purchased after registering) but you get the idea.

Hope this is of use to someone 🙂

Utilising simple Data Models in your Sublayouts

In this post I’m going to demonstrate a cleaner approach of  binding information to your Sublayouts by using simple Data Models.

Over the past few years I’ve been a huge advocate for utilising Datasources for absolutely everything. This is absolutely vital if you want to leverage Testability and Personlisation  – and never assume that a piece of content will never want to be personalised, you simply cannot tell what the future holds 🙂

There are cases though where data does not come directly from Datasources but is the product of a Search or some other form of acquisition. Generally this is bound to a Repeater and the fields a loosely typed in terms of pulling the data out:


<asp:Repeater id="rptTest" runat="server">
     <ItemTemplate>
         <%# Eval("Name") %>
         <%# Eval("Author") %>
         <%# Eval("Intro Text") %>
     </ItemTemplate>
 </asp:Repeater>

This post will show you an alternative approach. Nowadays I use Data Models (or View Models?) to represent the information that needs to be rendered on the front end. This ensures that there is a strongly typed class (or data set) that contains what is needed (and no more). This also ensures that we have a consistent entity which can also interact with the rest of your code. In the instance of a Repeater, you can utilise the property ItemType in order to define which Data Model is bound to the repeater. Once this is done it makes it much simpler to pull the data out of the Datasource that is bound to the Repeater.


<asp:Repeater id="rptTest" runat="server" ItemType="SitecoreJim.Entities.Book">
    <ItemTemplate>
        <%# Item.Title %>
        <%# Item.Author %>
        <%# Item.IntroText %>
    </ItemTemplate>
 </asp:Repeater>

Taking this one step further

Generally when I create Sublayouts I inherit from a base class called SublayoutBase which provides a good deal of generic functionality that we use everyday in our components. I have created a new variant of SublayoutBase in which you can pass in your Model type at the point you inherit from it:


public abstract class SublayoutBase<T> : SublayoutBase
{
    public T Model { get; set; }

    public abstract void CreateModel();
}

Also in the SublayoutBase there is an abstract method called CreateModel(). As its an abstract method, the intention is that when you inherit from SublayoutBase the implementation for this method is required –  the model is created in the place that understands how to create it. Now that we have everything in place, when we bind the Data Model to the Repeater and specify the ItemType, it makes it much easier to understand what information is bound to the Repeater and where the information is coming from.

Usage in the Page Editor

Using the methods above it is actually very easy to specify an example Datasource for our repeater specifically designed for the Page Editor. In the CreateModel() method it is a simple case of checking for the Page Editor and creating an example model for rendering

public override void CreateModel()
{
    List<Book> books = new List<Book>();

    if (Sitecore.Context.PageMode.IsPageEditor)
    {
        books.Add(new Book()
        {
            Title = "Black Diamond - How we started",
            Author = "Jamie Little",
            IntroText = "This is a great book"
        });

        books.Add(new Book()
        {
            Title = "From Rags to Riches, back to Rags and finally to Riches again",
            Author = "Stewie Mcnaughty",
            IntroText = "This is another great book";
        });
        books.Add(new Book()
        {
            Title = "Sense and Nonsensability",
            Author = "Fred Cringer";,
            IntroText = "How not to build stuff in Sitecore";
        });
    }
    else
    {
        // Populate Model using data
    }
}

Remember, as this data comes from a different source it would not be content editable anyway, however it’s always good practice to show a representation of the component when the content editor inserts it into a placehder

The new SublayoutBase can be found here:

https://github.com/jamielittle/SitecoreToolbox/blob/master/Sitecore.Toolbox/Sublayout/SublayoutBaseWithModel.cs

This inherits from a SublayoutBase class which you might also want to take a look at.

Anyway, any comments, feel free to leave them below

Sitecore SPEAK Gotcha #2 The StackOverflow exception when ID is part of your Entity

Using Sitecore Services Client is fun, but when the unexpected occurs it can be quite confusing to work out what is going on.

Last night was one of these cases; my code was constantly throwing a StackOverflow exception and I couldn’t understand why. There was no real indication and expected break points in code were not being hit.

After hours of scratching my head I decided to go back to basics with the Entities that I was using in part of my solution. It turns out that one of my Entities had an ID property which was causing the issue.

This is an example of the Entity I was using:

public class Template : Sitecore.Services.Core.Model.EntityIdentity
 {
 public string itemId
 {
 get { return base.Id; }
 set { base.Id = value; }
 }

 public string TemplateName { get; set; }

 private ID _templateId = new ID();
 public ID TemplateID
 {
 get { return _templateId; }
 set
 {
 _templateId = value;
 }
 }
 private List&amp;lt;string&amp;gt; _fields = new List&amp;lt;string&amp;gt;();
 public List&amp;lt;string&amp;gt; Fields
 {
 get { return _fields; }
 set { _fields = value; }
 }
 }

The majority of the Entity above is simple enough, however having an ID property will cause a StackOverflow exception (so it seams). What was confusing though is that when invoking my service manually through a browser I did not experience any issues, only when invoking through a SPEAK application (through the fetchEntity function). Fiddler also confirmed that there was a difference between manual invocation and via the fetchEntity function.

What was going on? A SPEAK application (and related JavaScript) needs to be able to understand the information that is contained in your entities prior to using them (e.g. for client side validation). Currently, only the following simple types are supported:

  • string
  • bool
  • int
  • float
  • double
  • long
  • DateTime
  • Enum

(this is taken from the documentation at: https://sdn.sitecore.net/upload/sitecore7/75/developer%27s_guide_to_sitecore.services.client_sc75-a4.pdf)

What I’m going to take a look at is to see if there is a way of extending this to include other types (such as ID). For now, I’m simply using strings for ID’s until I can find an alternative solution 🙂

Sitecore SPEAK Gotcha #1 Populating itemId from your Entity

Just a quick post regarding a small gotcha I experienced with Sitecore Services Client.

Recently whilst setting up some services with SPEAK and Sitecore Services Client I experienced the following error when calling the “fetchEntities” from my SPEAK app to return information from my Template Service (a service that I’m creating to teach myself Sitecore Services Client and SPEAK – full blog post to appear soon regarding its creation)

Below is the JavaScript I’m using to retrieve my information:


var result = templateService.fetchEntity(selectedItem).execute().then(function (template) {
var title = template.Fields;
});

When inspecting this in the console of Chrome I was noticing the following:

404 (Entity does not exist)

This seemed a little strange, as the entity was present and my code was certainly creating and returning the data (debugging verified this). So why was this appearing?

Well, it appears that in your Entity, you need to populate “itemId” field in the base class (Sitecore.Services.Core.Model.EntityIdentity), otherwise the 404 error will occur.

Huge thanks to Mike Robbins @Sobek1985 for this 🙂

Applying Datasources to Sitecore Controls – The Easy Way

Following on from my post The Importance of Datasources I thought I’d show a neat little trick to ensure Datasources are bound to all Sitecore controls within any component/Sublayout that you create.

The approach I normally take to binding Datasources is to firstly inherit from a base class, and get the base class to expose a DataSourceItem property which returns the Datasource, or if one isn’t provided return the context item:

public Item DataSourceItem
{
    get
    {
        // Ensure at the very least Context Item is returned as a fallback
        Item returnItem = Sitecore.Context.Item;

        if (Sublayout != null)
        {
            string dataSourceString = Sublayout.DataSource;

            if (!string.IsNullOrEmpty(dataSourceString))
            {
                Item dbItem = Sitecore.Context.Database.GetItem(dataSourceString);

                if (dbItem != null)
                {
                    returnItem = dbItem;
                }
            }
        }

        return returnItem;
    }
}

(You can get the full base class I use from GitHub at https://github.com/jamielittle/SitecoreToolbox/blob/master/Sitecore.Toolbox/Sublayout/SublayoutBase.cs)

Then in my Component, bind the DatasourceItem to each Sitecore control that is contained within the component:


scTextField1.Item = DatasourceItem;

scTextField2.Item = DatasourceItem;

scImage1.Item = DatasourceItem;

Doing this in every component is a bit of a chore, especially when there are many Sitecore controls contained within the component. So I’ve created a function that will do this for us:


        public void BindDatasourceToSitecoreControls()
        {
            BindDatasourceToSitecoreControls(DataSourceItem);
        }

        public void BindDatasourceToSitecoreControls(Item dataSource)
        {
            if (Controls.Count &amp;gt; 0)
            {
                BindControls(this.Controls, dataSource);
            }
        }

        private void BindControls(ControlCollection controls, Item dataSource)
        {
            foreach (Control control in controls)
            {
                if (control is FieldControl)
                {
                    var fieldControl = control as FieldControl;
                    fieldControl.Item = dataSource;
                }

                if (control is FieldRenderer)
                {
                    var fieldRenderer = control as FieldRenderer;
                    fieldRenderer.Item = dataSource;
                }

                if (control.Controls.Count &amp;gt; 0)
                {
                    BindControls(control.Controls, dataSource);
                }
            }
        }

The BindControls function can be used to recursively traverse through any control collection and when it encounters a control which is of type FieldRenderer or FieldControl (which covers most of the Sitecore controls) it will assign the Datasource that you pass into the function.

There are also two additional functions

  • BindDatasourceToSitecoreContrls() – This function will simply bind the Datasource that is available to any Sitecore controls it finds. This is part of my SublayoutBase.cs base class (as part of the Sitecore Toolbox) and inherits from System.Web.UI.Control so utilises the control collection that is available. You can simply call BindDatasourceToSitecoreControls() from you Page_Load() when inheriting from SubloayoutBase.
  • BingDatasourceToSitecoreControls(Item dataSource) – This function override can be used if a specific Item is used as a Datasource

The above code is included in the SitecoreToolbox on GitHub:

https://github.com/jamielittle/SitecoreToolbox/tree/master/Sitecore.Toolbox

Hopes this helps when using Datasources.

Feel free to leave a comment if you have any questions 🙂

Sitecore Services Client – Creating a Custom Authorisation Filter

Recently I’ve been looking into the Sitecore Services Client with interest. Sitecore Services Client was developed to provide a consistent way of integrating Client applications with Sitecore. There are many applications for this. You may have a client application (A SPEAK application, or a Single Page Application on a website) or even other systems acting as a “client” which requires to call Sitecore for information.

Sitecore Services Client is very extensible. The aspect I’m going to touch upon in this post in authorisation of requests.

The scenario I’m going to use for this is “Only authorise Sitecore Services Client if the IP address of the caller is the same as Sitecore itself”. This scenario could be useful if you had a bunch of services that are only designed to be available from applications that execute on the same box.

To do this, I’m going to create a LoopbackAuthorisationFilter which is designed to only authorise requests that origniate from the same IP address.

Firstly, create your class, inheriting from AuthorisationFilterAttribute (in the System.Web.Http.Filters namespace) and override the OnAuthorization function.

public class LoopbackAuthorisationFilter : System.Web.Http.Filters.AuthorizationFilterAttribute
    {
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            // Play nicely with the base class
            base.OnAuthorization(actionContext);

            // If the request does not originate from this machine
            if (!System.Web.HttpContext.Current.Request.IsLocal)
            {
                // Create an Unauthorised Access response
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Unauthorised Access");
            }
        }
    }

What I’m doing here is ensuring that the original request originates from the local machine (with the same IP address). If the originating request is different, create a HTTP Unauthorized response back to the caller.

To wire this up in Sitecore Services Client, all you need to do is to add an entry into the section of the Sitecore.Services.Client.config file:

<filter>SSCActionFilter.LoopbackAuthorisationFilter, SSCActionFilter</filter>

It’s as simple as that 🙂

I have an example project on GitHub for you to try if you wish which will compile a DLL for you to use with your Sitecore Serice Client implementation:

https://github.com/jamielittle/sscactionfilter

Whilst this filter is simplistic, it is very easy to extend it to cater for any scenario you require, or even create your own Authorisation Filter.

Hope you have fun with this!

To find out more about the Sitecore Services Client, have a look at the Developers Guide to Sitecore.Services.Client here:

https://sdn.sitecore.net/upload/sitecore7/75/developer%27s_guide_to_sitecore.services.client_sc75-a4.pdf

The Importance of Datasources

Over the years I have been involved in my fair share of “rescue” projects with Sitecore with the most common of issues being projects that do not adhere to the standards and best practices of Sitecore.

One of the biggest complaints I hear is the lack of complete Page Editor functionality and components not being testable. Sitecore themselves make it their business to push personalisation and this is one of the key selling points of the Sitecore platform and goes some way to justify the license costs. That said, the lack of adhering to best practices may work for some (ensuring the quickest turnaround time) however later on down the line this will unravel when clients wish to utilise “out of the box functionality” that Sitecore provides.

Also, I’ve heard worrying phrases such as:

They haven’t been shown that or told to use that feature of the Page Editor

or

They don’t or shouldnt use it like that

or even worse

I can’t see this ever needing to be tested or personalised

Two things I normally advise with in these circumstances:

  1. Never make assumptions on how a client with use the Page Editor. Whilst they may not wish to use its functionality now, they may wish to utilise it in the future – so why make these assumptions in the first place?
  2. There may be a future possibility that the client will employ someone who is well versed in Sitecore who wants to begin to utilise the out of the box features of the Page Editor. Wouldn’t it be embarrassing if they clicked the “Set Associated Content” button in the Page Editor on a component and were unable to create a new Datasource to see what it would look like with different labels? (this is built-in, every component should support this)

Fortunately the above can easily be addressed by ensuring that Sitecore’s best practices of using Datasources for almost everything (unless its Presentation Configuration, in which you may wish to consider Parameter Templates). In fact, I rigidly adhere to Datasources unless there is a good and valid case not to.

Common Problems with components:

  • Not abiding to a Datasource at all – Components who get all of their data from the Context Item (which will be the Page). Bear in mind that the Context Item will be the Page – which normally means that there is a lack of separation of Site Information and Page Content.
  • Hard wired Datasources – the data for a component is pulled in via a link directly to a Content Item. The issue with this is obvious, if the Datasource is recreated it will be assigned a new ID, hence the code that utilises it will need to be updated.
  • Not restricting Datasources – Allowing “any” item to be bound as a Datasource that does not contain the correct fields that are expected by the component. Whilst the component might work, the Content Editor could break a component by assigning an inappropriate Datasource.
  • Inappropriate usage of Datasources – Using Dataosources that contain “too much information” i.e. a Global Item that is bound to the majority of components, or a component that takes data from multiple content items – making if difficult to personalise the component as DMS is only capable of taking control over the Datasource (remember, we should be in the habit of allowing ALL components to be personalised – it’s no extra work!)

To address the above, I normally create a base class that contains a DataSourceItem property. This is then bound to the Item property of all the Sitecore controls on the page. This means that the component doesn’t care where there Datasource is being set as that’s not the concern of the Component. All the component should care about is that it is “given” data by Sitecore.

I have an example of a base class that can be used on GitHub in my Sitecore Toolbox Project:

https://github.com/jamielittle/SitecoreToolbox/blob/master/Sitecore.Toolbox/Sublayout/SublayoutBase.cs

When creating the Sublayout in Sitecore I always ensure that each component is coupled with its related Datasource Template (it’s a good idea to create the Datasource Template first to prevent bouncing from Sublayouts to Templates to create the Datasource Template and back to Sublayouts to assign it to the Component). This ensures that the data that is passed to a component is known by the component (and developer) and prevents the scenario where the component has to make a call to a different Content Item in Sitecore for its information (i.e. the component needing to be knowledgable about your IA).

Coupled with this, it is important to specify Datasource Location fields when creating the Sublayout in Sitecore. This will ensure that all Datasources that are suitable for this Component are located in one location improving the experience for the Content Editor.When these fields are provided, Sitecore will not allow an inappropriate Datasource to be bound to a component and the Datasource Location ensures that all Datasource Items are stored in a logical place in Sitecore.

If there is a situation where data is required from different nodes of the content tree, these can be provided via Droplinks in the Datasource Template o those locations – again, this ensures there is clarity and understanding of the data that the component requires to function. This also improves component testability as if the client wishes to perform any AB/MV testing, this will be possible by creating alternative Datasources.

Even if the Content Editor does not want to utilise MV testing, there are other ways to test a component. I’ve had a client want to create two pages with the same component on both, but each component pointing to two different Datasources. This method was required to show an example of a page that contains different content to the CEO to get approval on which content to use. This did require a small amount of rework (as the component pointed to the Context Item for its data) but after a little rework my client was very pleased with the capability and really started to “get” the power of Sitecore.

If the above is adhered to, this will go a long way to ensure that your components

So, just to recap

  • Always use Dataources, they are very easy to use, and will save you rework in the future when you client wants to begin to utiilise other functionality of Sitecore (Testability/DMS etc.)
  • Adopt “Assumption-less Design” i.e. Never assume anything in the Component. Always get you data from the Datasource (unless there is a very good reason not to – fortunately there are not many of these!)
  • If you are finding that the Datasource is too large, it may be an indication that your component needs to be broken down into sub components.

Remember, as Developers it is our responsibility to design components that can be reused whenever required and to have the power to be testable and “personalisable” (is that a word?).

By taking this approach, you are not only ensuring that your clients gets Value for Money and can justify purchasing a Sitecore license, but also helps ensure the longevity of the components that you create 🙂

Feel free to leave any comments/questions 🙂

Dynamic Menu’s in Sitecore Part 2

Welcome to Part 2 of setting up Dynamic Menu’s in Sitecore. In this post, I will quickly demonstrate how easy it is to utilise the power. Of DMS to alter what is displayed in site navigation and empower users to make choices on which content is displayed.

If you want to have a look at how a dynamic menu can be structured, please read Part 1. This post will follow on from there.

So, just to recap, we now have a navigation Item, which is simply an instance of a Navigation link on your site and a Navigation Collection, which consists of a collection of Navigation Items. The Navigation Collection can then be used as a Datasource Navigation Component.

Let’s choose the simple scenario that you want to have a different navigation displayed for a user that has successfully logged into out site.

First let’s assume that we have the following Navigation Items defined:

Navigation Items

Now lets two navigation collections, one for not logged in and one for logged in:

Navigation Collections

The “Not Logged In” collection will contain links to the “Log in” and “Sign Up” Navigation Items:

Not Logged In Collection

The “Logged In” collection will contain links to the “My profile” and “Log out” Navigation Items”

Logged In Collection

As these two collections are designed to be used as Datasources, we need to establish which Datasource to pass to the Navigation component and what drives this decision. This can be achieved by setting up a Rule Condition

Then, set up a Rule Condition which will detect whether the user has logged in:

{
public class AuthenticatedRuleCondition&lt;T&gt; : TrueCondition&lt;T&gt; where T : RuleContext
{
protected override bool Execute(T ruleContext)
{
Assert.ArgumentNotNull(ruleContext, &amp;amp;amp;amp;quot;ruleContext&amp;amp;amp;amp;quot;);

if (Sitecore.Context.IsLoggedIn)
return true;

return false;
}
}

We also need to register this new Rule Condition in Sitecore. This can be done by inserting a new Conditional Rendering into the following location (replacing <rule-condition-class> the fully qualified namespace/class name and <dll> with the DLL in which the rule resides):

rule

We can now use this Rule Condition to help decide which navigation to display. To do this, “Personalise” the component in the Presentation Layer and make use of this Rule Condition. Essentially what I am saying below is if my Rule Condition is true (i.e. the user is logged in), use a different Datasource to what is the default (the default is Not Logged In Datasource)

personalise

… and that’s it! It really is that simple. Sitecore already has a rule for authentication “when the current user is anonymous” (or the reverse of that rule) however the above can be easily modified to check for presence of a Role:

if (Sitecore.Context.User.IsInRole(&quot;extranet\\membership&quot;);)

{

// Perform some additional checks if necessary

return true; }

… or any other condition necessary.

When all is published, you will notice that Sitecore provides a different Datasource to the Navigation component when the user is logged in (or when the condition is met).

Hope this helps 🙂