Let’s face it. We don’t do websites anymore. Websites are what we did last year. Websites are something you develop with Drupal, Joomla or Umbraco.
Sitecore is no longer a Content Managent System. It’s a digital communication platform, allowing your customers to target their customers on every platform.
If we need to read or write to Facebook or Twitter, we build it. If we need to target desktop, tablet and mobile devices, we build it. In the same system. Not by creating parallel, almost-the-same-system systems. No, we make one system that will work on every digital platform we need it to work on.
One of the many Sitecore features that helps us achive this one-system-many-targets goal is the Device concept. It allows you to target different platforms with the same content. With this seperation of content from design, you can create device specific pages for mobile phones, printable pages or whatever you need.
ENOUGH TALK, LETS CODE
Devices are set up in /sitecore/layout/Devices:
When devices are set up, you can add layouts, sublayouts and renderings to each device on your template, or you can create one default fallback device:
But how are the devices changed? You can add the device to the <sites> section in the web.config. You can define an URL parameter that will change the device. Or you can develop a DeviceResolver processor and add it to the httpRequestBegin pipeline.
John West have an article on Using the Sitecore Rules Engine in a Custom Context: Setting the Context Device. This is a cool way to use the Sitecore Rules Engine to determine which device is the current.
But if you think that’s too complicated, or you just would like to know how to do it yourself, here is an example.
CREATING A httpRequestBegin PIPELINE PROCESSOR THAT CHANGES THE DEVICE BASED ON THE CURRENT BROWSER
This is an example on how to determine if the website is running on a Desktop PC, a Tablet (iPad) or a mobile phone (iPhone, Android, …) and change the Sitecore device accordingly.
First of all I will define my 3 devices, Default (Desktop PC), Tablet and Mobile:
public enum DeviceType { Mobile, Tablet, Default }
These 3 devices needs to be defined in my Sitecore installation.
Next step is to create a Device type retrieval service. This service uses the HTTP_USER_AGENT server variable to determine the current browser, and from the browser type I guess the device type.
using System.Linq; using System.Web; namespace PT.SiteRedirect { public class DeviceTypeRetrievalService { public static DeviceType RetrieveContext() { //GETS THE CURRENT USER CONTEXT var context = HttpContext.Current; //FIRST TRY BUILT IN ASP.NET CHECK if (context.Request.Browser.IsMobileDevice) { return DeviceType.Mobile; } //THEN TRY CHECKING FOR THE HTTP_X_WAP_PROFILE HEADER if (context.Request.ServerVariables["HTTP_X_WAP_PROFILE"] != null) { return DeviceType.Mobile; } //THEN TRY CHECKING THAT HTTP_ACCEPT EXISTS AND CONTAINS WAP if (context.Request.ServerVariables["HTTP_ACCEPT"] != null && context.Request.ServerVariables["HTTP_ACCEPT"].ToLower().Contains("wap")) { return DeviceType.Mobile; } //AND FINALLY CHECK THE HTTP_USER_AGENT //HEADER VARIABLE FOR ANY ONE OF THE FOLLOWING if (context.Request.ServerVariables["HTTP_USER_AGENT"] != null) { var userAgent = context.Request.ServerVariables["HTTP_USER_AGENT"].ToLower(); var tablets = new[] { "ipad", "android 3", "xoom", "sch-i800", "tablet", "kindle", "playbook" }; //Loop through each item in the list created above //and check if the header contains that text if (tablets.Any(userAgent.Contains) || (userAgent.Contains("android") && !userAgent.Contains("mobile"))) { return DeviceType.Tablet; } //Create a list of all mobile types var mobiles = new[] { "midp", "j2me", "avant", "docomo", "novarra", "palmos", "palmsource", "240x320", "opwv", "chtml", "pda", "windows ce", "mmp/", "blackberry", "mib/", "symbian", "wireless", "nokia", "hand", "mobi", "phone", "cdm", "up.b", "audio", "SIE-", "SEC-", "samsung", "HTC", "mot-", "mitsu", "sagem", "sony" , "alcatel", "lg", "eric", "vx", "NEC", "philips", "mmm", "xx", "panasonic", "sharp", "wap", "sch", "rover", "pocket", "benq", "java", "pt", "pg", "vox", "amoi", "bird", "compal", "kg", "voda", "sany", "kdd", "dbt", "sendo", "sgh", "gradi", "jb", "dddi", "moto", "iphone", "Opera Mini" }; //Loop through each item in the list created above //and check if the header contains that text if (mobiles.Any(userAgent.Contains)) { return DeviceType.Mobile; } } return DeviceType.Default; } } }
The final piece of code is the device resolver processor itself, the piece of code that is exposed in the httpRequestBegin pipeline.
using System.Web; using Sitecore; using Sitecore.Data.Items; using Sitecore.Pipelines.HttpRequest; namespace PT.SiteRedirect { public class DeviceResolver : HttpRequestProcessor { public override void Process(HttpRequestArgs args) { HttpContext currentHttpContext = HttpContext.Current; if (currentHttpContext == null || Context.Database == null) return; if (Context.Site.Name.ToLower() != "website") return; DeviceType deviceType = DeviceTypeRetrievalService.RetrieveContext(); switch (deviceType) { case DeviceType.Default: break; case DeviceType.Mobile: SetDevice("Mobile"); break; case DeviceType.Tablet: SetDevice("Tablet"); break; } } private void SetDevice(string deviceName) { DeviceItem device = Context.Database.Resources.Devices["Default"]; device = Context.Database.Resources.Devices[deviceName]; Context.Device = device; } } }
The processor is added to the httpRequestBegin pipeline:
... <processor type="Sitecore.Pipelines.HttpRequest.BeginDiagnostics, Sitecore.Kernel" /> <!-- My porocessor --> <processor type="PT.SiteRedirect.DeviceResolver, PT.SiteRedirect" /> <!-- My porocessor --> <processor type="Sitecore.Pipelines.HttpRequest.DeviceResolver, Sitecore.Kernel" /> ...
CONCLUSION
When the processor is added it will change the device to Default, Tablet or Mobile depending on the user agent string.
When using a fallback device to render the layout, it’s still the original device that you can read:
public string CurrentDevice { get { return Sitecore.Context.Device.Name; } }
With this information in hand you can start making server-side based decisions on how content should be rendered. One example could be that you render images in different sizes depending on the device:
</pre> <div class="Logo"><a href="/"> </a></div> <pre> protected void Page_Load(object sender, EventArgs e) { switch (Sitecore.Context.Device.Name.ToLower()) { case "default": break; case "tablet": break; case "mobile": logoImage.MaxWidth = logoImage.MaxWidth / 2; break; } logoImage.DataBind(); }
MORE INFORMATION
- Using the Sitecore Rules Engine in a Custom Context: Setting the Context Device by John West
- WURFL-based mobile device detection for Sitecore CMS by Alex Doroshenko (Also, read the follow-up on performance)
- How Sitecore Determines Which Layout To Use by Adam Conn
- Sitecore Mobile: How to Make Your Site Mobile-Friendly, Fast on your Phone by Paul Caponetti
Thanks to Kim Schiøtt for the initial device resolver.
And here is WURFL-based mobile device detection for Sitecore CMS http://sitecoresnippets.blogspot.com/2011/03/wurfl-based-mobile-detection-solution.html
LikeLike
A nice simple solution. I ended up removing the .NET detection as it was detecting iPad as a mobile as opposed to a tablet. Another nice enhancement is reading the mobiles and tablet strings out of config.
LikeLike