Skip to main content

Optimizely

Optimizing Experiences with Optimizely: Custom Audience Criteria for Mobile Visitors

SMS-Amazon-Connect

In today’s mobile-first world, delivering personalized experiences to visitors using mobile devices is crucial for maximizing engagement and conversions. Optimizely’s powerful experimentation and personalization platform allows you to define custom audience criteria to target mobile users effectively.

By leveraging Optimizely’s audience segmentation, you can create tailored experiences based on factors such as device type, operating system, screen size, and user behavior. Whether you want to optimize mobile UX, test different layouts, or personalize content for Android vs. iOS users, understanding how to define mobile-specific audience criteria can help you drive better results.

In this blog, we’ll explore how to set up simple custom audience criteria for mobile visitors in Optimizely, the key benefits of mobile targeting, and the best practices to enhance user experiences across devices. Let’s dive in!

This solution is based on Example – Create audience criteria, which you can find in the Optimizely documentation.

Create the settings and criterion classes

First, we need to create two classes in our solution:

Class VisitorDeviceTypeCriterionSettings needs to inherit CriterionModelBase class, and we need only one property (settings) to determine if the visitor is using a desktop or a mobile device.

public bool IsMobile { get; set; }

The abstract CriterionModelBase class requires you to implement the Copy() method. Because you are not using complex reference types, you can implement it by returning a shallow copy as shown (see Create custom audience criteria):

public override ICriterionModel Copy()
{
    return base.ShallowCopy();
}

The entire class will look something like this:

using EPiServer.Data.Dynamic;
using EPiServer.Personalization.VisitorGroups;

namespace AlloyTest.Personalization.Criteria
{
    [EPiServerDataStore(AutomaticallyRemapStore = true)]
    public class VisitorDeviceTypeCriterionSettings : CriterionModelBase
    {
        public bool IsMobile { get; set; }

        public override ICriterionModel Copy()
        {
            // if this class has reference types that require deep copying, then
            // that implementation belongs here. Otherwise, you can just rely on
            // shallow copy from the base class
            return base.ShallowCopy();
        }
    }
}

Now, we need to implement the criterion class VisitorDeviceTypeCriterion and inherit the abstract CriterionBase class with the settings class as the type parameter:

public class VisitorDeviceTypeCriterion : CriterionBase<VisitorDeviceTypeCriterionSettings>

Add a VisitorGroupCriterion attribute to set the category, name, and description of the criterion (for more available VisitorGroupCriterion properties, see Create custom audience criteria:

[VisitorGroupCriterion(
    Category = "MyCustom",
    DisplayName = "Device Type",
    Description = "Criterion that matches type of the user's device"
)]

The abstract CriterionBase class requires you to implement an IsMatch() method that determines whether the current user matches this audience criterion. In this case, we need to determine from which device the visitor is accessing our site. Because Optimizely doesn’t provide this out of the box, we need to figure out that part.

One of the solutions is to use information from the request header, from the User-Agent field and analyze it to determine the OS and device type. We can do that by writing our match method:

public virtual bool MatchBrowserType(string userAgent)
{
    var os =
        new Regex(
            @"(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino",
            RegexOptions.IgnoreCase | RegexOptions.Multiline);
    var device =
        new Regex(
            @"1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-",
            RegexOptions.IgnoreCase | RegexOptions.Multiline);
    var deviceInfo = string.Empty;

    if (os.IsMatch(userAgent))
    {
        deviceInfo = os.Match(userAgent).Groups[0].Value;
    }

    if (device.IsMatch(userAgent.Substring(0, 4)))
    {
        deviceInfo += device.Match(userAgent).Groups[0].Value;
    }

    if (!string.IsNullOrEmpty(deviceInfo))
    {
        return true;
    }

    return false;
}

Now, we can go back and implement the IsMatch() method that is required by CriterionBase abstract class.

public override bool IsMatch(IPrincipal principal, HttpContext httpContext)
{
    return MatchBrowserType(httpContext.Request.Headers["User-Agent"].ToString());
}

 

Test the criterion

In the CMS we need to create a new audience criterion. When you click on the ‘Add Criteria’ button, there will be ‘MyCustom’ criteria group with our criteria:

When you select the ‘Device Type’ criteria, you will see something like this:

We can easily add a label for the checkbox by using Optimizely’s translation functionality. Create a new XML file VisitorGroupCriterion.xml and place it in your translations folder where your translation files are, like this:

Put this into the file that you created:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<languages>
  <language name="English" id="en-us">
    <visitorgroups>
      <criteria>
        <ismobile>
          <key>Is Mobile Device (Use this setting to show content only on Mobile)</key>
        </ismobile>
      </criteria>
    </visitorgroups>
  </language>
</languages>

 

There is one more thing to do. In VisitorDeviceTypeCriterionSettings.cs, decorate the IsMobile property with the translation definition. Add this attribute:

[CriterionPropertyEditor(LabelTranslationKey = "/visitorgroups/criteria/ismobile/key")]

It should look like this:

Now, in the editor view, we have a label for the checkbox.

 

Personalize the content by setting the content for this visitor group.

Desktop view:

 

Mobile view:

You can see that there is content that is only visible if you access the site with a mobile device.

 

And that’s it!

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Nenad Nicevski

Nenad is a Certified Optimizely (former EPiServer) Content Cloud Developer. He is a full-stack developer focused on ASP.NET CMS technologies, mainly ASP.NET Core and ASP.NET with MVC. Nenad is no stranger to WordPress, Drupal 7/8, and Angular JS. In his free time, he loves to play basketball and guitar and make fun of himself to amuse his daughter!

More from this Author

Follow Us