What do I mean by context? How are you accessing this website? Are you on your phone or your tablet, desktop or TV? It’s becoming increasingly important to know what device your users are accessing your content with in order for you to deliver it in the most useful way.
Please Note: Since the time of writing, SDL have bought the Context Engine Cartridge into the core of the product and split the mobile part off into SDL Mobile. This means some of the information in this blog post may no longer be accurate. For up to date information on the Context Engine Cartridge, Eric Huiza does a good presentation in the December 2014 webinar here: http://webinars.julianwraith.com/2014/12/03/december-2014-webinar/
SDL have just released an Ambient Data Framework Cartridge called the Context Engine Cartridge. This is released from SDL Mobile (formed by the acquisition of Bemoko). This cartridge gives access to a wealth of information about the device that a user is accessing your site on. It is supported in both SDL Tridion 2011 SP1 and SDL Tridion 2013. The cartridge is available from Customer support. No additional licence is currently required to use it.
The Ambient Data Framework (ADF) is a Content Delivery technology which creates a store of information about the current session or request. For example, you could create a cartridge which loaded the current weather information for the IP address of the user accessing the site and have that information available to the application. It’s a Java technology but can be used in .NET through the use of a HttpModule. For a better explanation of how ADF works see Eric Huiza’s post.
So the Context Engine Cartridge makes information about the device available to your application. This is accessed using what is known as the Claim Store created by the Ambient Data Framework.
The Claim Store stores properties as Uris and in the case of the Context Engine Cartridge there are 3 aspects with properties we can look at. The aspects are browser, device and os. We create a URL in the following manner:
Uri claimUri = new Uri("taf:claim:context:[ASPECTNAME]:[PROPERTYNAME]")
The Uri is then passed to the current claim store like so:
So for example if we wanted to know that the user was using a tablet:
Uri claimUri = new Uri("taf:claim:context:device:tablet");
string isTablet = Tridion.ContentDelivery.AmbientData.AmbientDataContext.CurrentClaimStore.Get<String>(claimUri);
Now you can probably see that this could get a little unwieldy. Luckily, Nuno has come to the rescue and written a strongly typed wrapper that he’s kindly released onto Github. So the equivalent code is:
var contextEngine = new ContextEngine();
bool isTablet = contextEngine.Device.IsTablet;
How can we use that information? In this example I’m going to show how you can use this information DD4T to present a different View to a mobile user than to a desktop user.
A couple of weeks back we hosted the first Tridion UK User Group, I made a simple DD4T website for my presentation. Here’s the desktop version of my presenter page which uses the PresenterDetail.cshtml Component View.
Now, as everyone knows, electric blue uses less power to display than orange (disclaimer: may not be factually accurate), so on mobile it would be nice if we used that as our main colour instead of that battery eating orange. If I switch my user agent to iPhone 4 (using a handy Chrome extension) we get a nice power friendly layout of Pete’s page.
So we’re showing a different Layout for the iPhone than we are for desktop on the same URL. The desktop uses just _Layout.cshtml as the layout whereas on mobile we get _Layout.SmartPhone.cshtml. Similarly the same happens for the Component Views. Here’s the PresenterDetail.cshtml view
<p>@Model.JobTitle - @Model.Organisation</p>
<img src="@Model.Image.ResizeToWidth(120)" alt="@Model.Name" />
and here’s the Smartphone version (PresenterDetail.SmartPhone.cshtml). Here we’ve moved the heading above the image and rendered a small image using the new BinaryDistributionModule image resizing capabilities.
<img src="@Model.Image.ResizeToWidth(220)" alt="@Model.Name" />
<p>@Model.JobTitle - @Model.Organisation</p>
The core of the solution uses the built in class DisplayModeProvider – part of the .NET MVC framework from MVC4. This class can be used to add a series of rules which are run by the View Engine. This will fill a dictionary of DisplayModes which the View Engine will use to try and locate a suitable view (e.g. for SmartPhone it will look for PresenterDetail.SmartPhone.cshtml), falling back to the default (PresenterDetail.cshtml) if one was not found.
Here’s some code showing how to insert display modes:
provider.Modes.Insert(0, new DefaultDisplayMode("Tablet")
ContextCondition = (context => TabletContext(context))
provider.Modes.Insert(1, new DefaultDisplayMode("SmartPhone")
ContextCondition = (context => SmartPhoneContext(context))
Note that we are passing a delegate to the Context Condition (the name is a coincidence and has nothing to do with the Context Engine Cartridge). Here’s a couple of the tests using the Context Engine (unfortunately I had to wrap these in a try catch as the first call seems to not have the Ambient Data Framework initialised but then still seems to work, I should probably refactor this to do a check for null instead)
You can see the full code here: https://gist.github.com/rsleggett/6390335#file-demodisplaymodehelper-cs
Here’s what I used to achieve this:
As a final thought, I couldn’t talk about mobile without talking about Responsive Web Design – the revolutionary movement that changed the way most web developers think about mobile. In a nutshell, responsive design puts mobile first in the design process and refers to a series of techniques for responding to the user’s device by changing CSS based on the screen size and other tests through the use of media queries. The main driver is that the content should not change, only the way that it is presented.
One of the great things about responsive design is that it’s all managed by CSS so there’s only one set of markup to maintain. So how could the Context Engine Cartridge help with this?
The main issue we see when implementing a responsive design is the number and size of images. There’s a number of ways to serve responsive images but none are perfect because they rely on the client figuring out the context first so for larger images, generally a low quality version must be served first and then a higher quality version once the context is resolved. This problem can be mitigated by a server side solution like Adaptive Images (a PHP solution).
With the Context Engine Cartridge, it should be possible to have much more control over the images we serve. For example we could serve a double resolution image for a device that supports a retina display. In the example above, I showed a smaller image for the smart phone using DD4T’s Binary Distribution Module to do the resize, but you could easily add your own HttpModule to handle requests for images and use the Context Engine within that to serve images more intelligently in a similar way to Adaptive Images.
Other techniques that this could help with:
I hope this has given you a good overview of how the Context Engine Cartridge could be used. For information on downloading it, contact SDL Tridion Customer Support. Details for how to install are online at SDL Live Content.