Why the GDPR and (Sitecore) device detection won’t work together
Tags: sitecore, csharp, dotnet
Published: 2020-01-23 10:37:39

As I’ve discussed in of my previous posts  of this series, you can make your Sitecore solution GDPR compliant by blocking the analytics cookie and not starting the tracker unless consent was given. __And it works great but__, as I mentioned in the blogpost, __some things won’t work__. One of those things is personalization. Which is, as you think about it, quite logical: you aren’t allowed to track users so you can’t personalize (since you don’t have user information). 

An attentive reader might say that there are personalization rules which do not require user information, and therefor, they should work. An example of those rules is the device detection rule: _where device is of type smartphone_. Since this rule uses the User Agent string (sent in the header of every request) it does not require any gathered user information or tracking. But, by not initializing the tracker, it won’t work. The questions are why and how do we make it work?

#Why it doesn’t work
It doesn’t work because of two things. Firstly, the whole personalization of rendering is disabled when the tracker isn’t active. This means that no personalization rules are executed at all when the user did not give his consent.  The disabling is done by the _Personalize_ processor inside the _mvc.customizeRendering_ pipeline, which is the pipeline that is started before rendering a component. That processor simply checks is the tracker is active and returns before executing the rules.

Secondly because the device detection rule fetches the User Agent string from the active tracker. If the tracker isn’t active, the device can’t be determined, and the rule will not be executed. When the device is being determined a pipeline, called _getFallbackUserAgent_, is started to determine the User Agent. In that pipeline is a processor, called _Sitecore.Analytics.Pipelines.GetFallbackUserAgent.GetUserAgentFromTracker_ which , as the name suggests, get the User Agent from the tracker.

#How to fix it
In order __fix the first issue__, where all personalization of a rendering is disabled, the checking of the tracker must be removed.  This is easily done by creating your own processor which extends from the _Sitecore.Mvc.Analytics.Pipelines.Response.CustomizeRendering.Personalize_ processor like this:
```c#
 public class YourProcessor : Sitecore.Mvc.Analytics.Pipelines.Response.CustomizeRendering.Personalize
    {
        public override void Process(CustomizeRenderingArgs args)
        {
            Assert.ArgumentNotNull(args, "args");
            if (args.IsCustomized)
            {
                return;
            }

            Evaluate(args);
        }
    }
```
 And then patching that processor instead of the default one:

```xml
  <mvc.customizeRendering>
                <processor type="YourProcessor" patch:instead="processor[@type='Sitecore.Mvc.Analytics.Pipelines.Response.CustomizeRendering.Personalize, Sitecore.Mvc.Analytics']"/>
            </mvc.customizeRendering>
```

__Issue two__, where device detection gets the User Agent from the tracker, can be easily fixed by patching the _Sitecore.Analytics.Pipelines.GetFallbackUserAgent.GetUserAgentFromTracker_ processor with a custom one, which should when the tracker is not enabled use the User Agent from the request:

```c#
public class CustomProcessor : GetFallbackUserAgentProcessor
    {
        protected override string GetUserAgent()
        {
            if (!XdbSettings.Tracking.Enabled || Tracker.Current?.Session?.Interaction == null)
            {
                return (string)System.Web.HttpContext.Current.Request.UserAgent;
            }

            return Tracker.Current?.Session?.Interaction?.UserAgent;
        }
    }
```
Which can be patched: 
```xml
          <getFallbackUserAgent>
            <processor type="CustomProcessor" patch:instead="processor[@type='Sitecore.Analytics.Pipelines.GetFallbackUserAgent.GetUserAgentFromTracker, Sitecore.Analytics']"/>
          </getFallbackUserAgent>
```