MVT in MVC – A History Lesson

Multi-Variate Test has been a part of Sitecore DMS for quite some time. It basically allows marketers to vary a component’s datasource or a rendering itself and see which variation does better as measured in the overall engagement value. Testing is a big deal these days and Sitecore 8 attempts to disrupt the status-quo with the new Content Testing feature (aka Page Tests) that I will look into in the next installment of my Sitecore 8 Developer’s Notes (here’s part 1). Before I do so:

Let’s take a look at how MVT evolved and how parts of page’s layout details were not exactly shared even before Sitecore 8

7.0 / 7.1

A test variation is recorded in the presentation details as an attribute of the rendering node:

<r uid="{EF1B9B61-12B0-4A5D-8149-1FEEF9EA7AD8}" 
   ds="{ACCFD363-A6DD-4613-8674-5D09451096FA}" 
   id="{06A2C3F0-13BE-498A-BD6C-30337FA1FEB9}" 
   mvt="{2F505D5B-2760-4A0E-8B07-BCA6EC3A38FE}" 
   ph="Main" />

The mvt attribute points to the test definition item under /sitecore/system/Marketing Center/Test Lab. It will be parsed out in Sitecore.Layouts.RenderingReference (simplified):

private void ParseDefinition(RenderingDefinition definition)
{
    // ...
    this.settings.MultiVariateTest = RenderingReference.ParseMultiVariateTest(definition, this.renderingItem);
    // ..
}

...

private static string ParseMultiVariateTest(RenderingDefinition renderingDefinition, RenderingItem renderingItem)
{
    // ... 
    string multiVariateTest = renderingDefinition.MultiVariateTest;
    // ...
    return multiVariateTest ?? string.Empty;
}

...

[XmlAttribute("mvt")]
public string MultiVariateTest { get; set; }

And then when the time comes for mvc.customizeRendering pipeline to apply MVT it will:

Item variableItem = args.PageContext.Database.GetItem(renderingReference.Settings.MultiVariateTest);

It works and the MVT definition is shared just like the entire layout details are.

7.2

Things changed in 7.2. I am not sure how well it’s known (let alone documented) but MVT in 7.2 is language-specific. That same test variation will be recorded differently in 7.2:

<r uid="{EF1B9B61-12B0-4A5D-8149-1FEEF9EA7AD8}" 
   ds="{ACCFD363-A6DD-4613-8674-5D09451096FA}" 
   id="{06A2C3F0-13BE-498A-BD6C-30337FA1FEB9}" 
   mvt="en={2F505D5B-2760-4A0E-8B07-BCA6EC3A38FE}" 
   ph="Main" />

If you go ahead and create another language version for that page item and open it in Page Editor you won’t see the active test. You can now create a different test for the same component and it will be recorded like this:

<r uid="{EF1B9B61-12B0-4A5D-8149-1FEEF9EA7AD8}" 
   ds="{ACCFD363-A6DD-4613-8674-5D09451096FA}" 
   id="{06A2C3F0-13BE-498A-BD6C-30337FA1FEB9}" 
   mvt="en={2F505D5B-2760-4A0E-8B07-BCA6EC3A38FE}&amp;ru-RU={38B34DBC-6D3C-439F-92AF-D0C2EBCB3AB3}" 
   ph="Main" />

It is indeed language-specific. The problem is – the MVC code that’s using it was not invited to the party. 7.2 has a known defect and MVT doesn’t work in MVC. The mvt attribute is still directly translated into the MultiVariateTest attribute and no database can find an item for en={GUID}. The fix suggested by Ben is a little intrusive and SCORE provides support for using MVT with Sitecore MVC in 7.2 a little differently (feel free to contact me if you’re interested in details).

7.5

MVT is still language-specific in the otherwise shared layout details but the MVC code finally caught up. Here’s a one line change that makes all the difference:

private void ParseDefinition(RenderingDefinition definition)
{
    // ...
    this.settings.MultiVariateTest = RenderingReference.ParseMultiVariateTest(definition, this.renderingItem);
    // ..
}

...

private static string ParseMultiVariateTest(RenderingDefinition renderingDefinition, RenderingItem renderingItem)
{
    // ... 
    string variateTestForLanguage = 
        MultiVariateTestingExtensions.GetMultiVariateTestForLanguage(renderingDefinition, language);
    // ...
    return multiVariateTest ?? string.Empty;
}

...

[XmlAttribute("mvt")]
public string MultiVariateTest { get; set; }

That new helper method is actually available in 7.2. It’s just the MVC didn’t get the memo. And all it does is:

return WebUtil.ParseQueryString(multiVariateTest)[language.Name]

The MVT is working again in MVC.

8.0

8.0 makes a big move. A whole new ball game with the __Final Renderings field (aka versioned layouts). And not only that, there’s a big move towards testing page variations and suggesting what tests to run automatically. I will sure write about it like I promised already but what about good old MVT? Still there. Downgraded back to its original semantic. That same test variation we looked at will be recored as:

<r uid="{EF1B9B61-12B0-4A5D-8149-1FEEF9EA7AD8}" 
   ds="{ACCFD363-A6DD-4613-8674-5D09451096FA}" 
   id="{06A2C3F0-13BE-498A-BD6C-30337FA1FEB9}" 
   mvt="{2F505D5B-2760-4A0E-8B07-BCA6EC3A38FE}" 
   ph="Main" />

It’s not written to the shared __Renderings though. It’s now part of the __Final Renderings so no need to version it individually. The MVC team didn’t need a memo this time. The rendering reference / definition parsing code has also been reverted back to:

// ...
string multiVariateTest = renderingDefinition.MultiVariateTest;
// ...

We have arrived. I hope you enjoyed the journey!

p.s. There’s something else I noticed in 8. Something I haven’t seen before – Personalization Test:

[XmlAttribute("pt")]
public string PersonalizationTest { get; set; }

… Next Time!

Add a Comment

Your email address will not be published. Required fields are marked *

Or request call back