Sitecore:How to track interactions that your contacts have with your website through sitecore channels?
Tags: sitecore
Published: 2019-12-01 11:44:32

Sitecore traffic channels acts as a path that users use to interact with our website for example either directly, organic search,paid search etc.
Website users can interact with your website through various channels like an app on a mobile phone, by clicking on an ad on a social network, or directly land on your website. 

These user interactions along with the traffic type and ChannelID are stored in Interactions collections in Sitecore Analytics database. 
There are few traffic channels provided by Sitecore out of the box, and can be found at Sitecore.Analytics.Compatibility.config.
But many a times we need to create our own custom traffic channel and accordinly we neeed to create a patch file to add the newly created traffic channel to Sitecore.Analytics.Compatibility.config file.

Details about creating a new traffic channel is mentioned below:
https://doc.sitecore.com/developers/90/platform-administration-and-architecture/en/map-traffic-types-to-channels.html

In our website we get traffic from different channels like google ads, facebook, bing ads etc. So we added the custom traffic channels to Sitecore.Analytics.Compatibility.config file as a patch file as shown below:
add trafficType="92" channel="{B5234879-DFFC-47AF-8267-59D4D3DF6226}"

Also have to create traffic and channel type in CMS as shown below:

For creating a new traffic type navigate to /sitecore/system/Settings/Analytics/Traffic Type:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/kyhyuferf8s1596svghq.png)

For creating new channel type navigate to
/sitecore/system/Marketing Control Panel/Taxonomies/Channel

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/c6qtn2k41jph8vy24vnm.png)

So after we added the above traffic type to the Sitecore.Analytics.Compatibility.config file we created two custom sitecore processors to assign traffic type and channel id in the Interactions collection in Mongo DB if any user has landed on the website from the above traffic channel. e.g. If any user has landed on the website through a google ad then in the Interactions collection TrafficType will be set as 92 as shown below:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/5tukh3yjfo4lfctcboha.png)

The two custom processors are patched as shown below:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/x1aid5nfafq9r4baysc4.png)

The logic of custom processors is simple and will look for query string ChannelId= to assign the correct traffictype and channel id. If no query string is present e.g. for direct traffic the custom processors will not overwrite the traffic type and channel.
Each custom channel will have its own channel id, which is the ID generated when we create a new channel under /sitecore/system/Marketing Control Panel/Taxonomies/Channel.

For the above instance since the user has landed on the website through googleads the googleads url will look like:

https://www.googleadservices.com/pagead/aclk?sa=xxxxxxx&ohost=www.google.com&cid=xxxxxxxx&sig=xxxxxxx&ChannelId=="{B5234879-DFFC-47AF-8267-59D4D3DF6226}"

So for each of the other custom channel like bing, facebook etc. we need to append the respective query strings like &ChannelId=(ID of the respective channel under /sitecore/system/Marketing Control Panel/Taxonomies/Channel). 

The first custom processor is QueryStringChannelResolver, which sets the ChannelID based on the query string appended. The code looks like:


    public class QueryStringChannelResolver : DetermineChannelProcessorBase
    {
        public override void Process(DetermineChannelProcessorArgs args)
        {
                try
                {
                    Assert.ArgumentNotNull((object) args, nameof(args));
                    if (Sitecore.Context.Request?.QueryString?.QueryStrings != null &&
                        string.IsNullOrWhiteSpace(Sitecore.Context.Request?.QueryString[ConstantsValues.ChannelId]))
                        return;
                    var channelId = this.GetChannelId();
                    if (!Sitecore.Data.ID.IsNullOrEmpty(channelId))
                    {
                        args.ChannelId = channelId;
                    }
                }
                catch (Exception exception)
                {
                    Sitecore.Diagnostics.Log.Error("Error setting custom channel id for traffic types", exception,
                        typeof(QueryStringChannelResolver));
                }
        
        }

        public ID GetChannelId()
        {
            var queryString = Sitecore.Context.Request?.QueryString["ChannelId"];
            ID channelId;
            if (ID.TryParse(queryString, out channelId))
            {
                return channelId;
            }

            return null;
        }

    }

The second custom processor assigns the traffic type based on the appended query string. The code looks like below:

public class SetCustomTrafficType : CreateVisitProcessor
    {
        public override void Process(CreateVisitArgs args)
        {
                try
                {
                    if (Sitecore.Context.Request?.QueryString != null && 
                        string.IsNullOrWhiteSpace(Sitecore.Context.Request?.QueryString["ChannelId"]))
                        return;
                    XmlNode configNode = Factory.GetConfigNode("compatibility/trafficType");
                    int trafficType = this.GetTrafficType(configNode);
                    if (trafficType > 0)
                    {
                        args.Interaction.TrafficType = trafficType;
                    }
                }
                catch (Exception exception)
                {
                    Sitecore.Diagnostics.Log.Error("Error setting custom traffic type", exception, typeof(SetCustomTrafficType));
                }

            
        }

        public int GetTrafficType(XmlNode configNode)
        {
            var trafficNodes = configNode?.SelectNodes($"//add[@{"channel"}" +
                                                       $"='{Sitecore.Context.Request?.QueryString["ChannelId"]}']");
            if (trafficNodes != null && trafficNodes.Count > 0)
            {
                var xmlAttributeCollection = trafficNodes[0]?.Attributes;
                if (xmlAttributeCollection != null)
                {
                    var trafficId = xmlAttributeCollection["trafficType"]?.Value;
                    int trafficType;
                    int.TryParse(trafficId, out trafficType);
                    return trafficType;
                }
            }
            return 0;
        }


    Please leave a comment if you like, dislike, agree or disagree with this approach.