This post has been migrated from www.experimentsincode.com, we apologise if some of the images or content is missing
public class IncrementalMultiVariateTestStrategy : IMultiVariateTestStrategy { const string _cookieName ="aegeagaegaeWeafea2"; #region IMultiVariateTestStrategy Members public Item GetTestVariableItem(Item item, Item multiVariateTest) { if (!multiVariateTest.HasChildren) return null; int index = Cookie == -1? 0 : Cookie; if (index >= multiVariateTest.Children.Count) index = 0; Cookie = index + 1; return multiVariateTest.Children[index]; } #endregion private int Cookie { get { int i = -1; if(HttpContext.Current.Request.Cookies[_cookieName]!= null) int.TryParse(HttpContext.Current.Request.Cookies[_cookieName].Value, out i); return i; } set { HttpContext.Current.Response.Cookies.Add(new HttpCookie(_cookieName, value.ToString())); } } }The image below shows the setup in the Marketing Centre with each test variable pointing at the relevant node. Now I just need to setup the Sample Rendering to use the test on the homepage: So publishing the site and doing a couple of refreshes we can see that the content of the sample rendering actually changes. So are multivariate test works!! Ok so it works for XSLTs but what about a sublayout? Si I have created a simple sublayout with the following code behind:
public partial class layouts_MVTest : System.Web.UI.UserControl { protected void Page_Load(object sender, EventArgs e) { output.Text = "Sublayout: " + Sitecore.Context.Item["Title"]; } }I have also updated the home item to include the sublayout and set the sublayout to use the multivariate test: Ok so saving this and publishing it we now get this output: Notice how the XSLT content changes but the sublayout content does not change. So why does this happen? This is caused by how the Sublayouts and XSLTs resolve the current item. I suspect that most Sitecore developers (this is true of where I work and for myself) are used to getting the current item via Sitecore.Context.Item within a sublayout. However if you look at the code that the XSLT uses to render itself (Sitecore.Web.UI.WebControls.XslFile there is a GetItem method inherited from the Sitecore.Web.UI.WebControl class. Within this method the actual item passed to the XSLT is resolved based on the WebControl.DataSource property. The Multivariate Test actually changes the DataSource property to point at the new content item. So how do we get this value in the our Sublayout? Well we have actually look at the parent control of our user control:
Sitecore.Web.UI.WebControls.Sublayout parent = (Sitecore.Web.UI.WebControls.Sublayout)this.Parent; string sourceItem = parent.DataSource;This then gives us the ID of the item injected by the multivariate tests. So what does this mean in terms of development? Well if you want to use multivariate tests on a site that you already developed you will have to replace any reference to Sitecore.Context.Item with a custom solution that looks at the parents DataSource property:
public Item Source { get { Sitecore.Web.UI.WebControls.Sublayout parent = (Sitecore.Web.UI.WebControls.Sublayout)this.Parent; Guid sourceItem = new Guid(parent.DataSource); return Sitecore.Context.Database.GetItem( new Sitecore.Data.ID(sourceItem)) ?? Sitecore.Context.Item; } }What about sub-items, for example you have the following code in your XSLT:
<ul> <xsl:for-each select="./item"> <li> <sc:text field="Title"></sc:text> </li> </xsl:for-each> </ul>Well this actually just breaks as shown in this images below and only works when the original item is requested. The solution is to proxy the subitems below the new nodes: I have summarised the problems you will have to think about when using mutlivariate tests on your site: