Custom Sitecore Intel Transformers To Modify Date Format In Experience Profile
Going through the recently published Sitecore StackExchange site, I came across a question regarding modifying the date format of visits in Experience Profile since it shows the dd.mm.yyyy format by default. In case you don't know what I am talking about, here is what it looks like:
It's not just that one view, the default date format seems to apply to other views as well:
My obvious thought here was that there has to be a config setting somewhere that controls this date format. Here is my process of elimination:
It's not just that one view, the default date format seems to apply to other views as well:
My obvious thought here was that there has to be a config setting somewhere that controls this date format. Here is my process of elimination:
- Eliminated Experience Profile configs since it did not contain any date related settings
- Looked at showconfig.aspx and found some index fields that contained date formats but eliminated since the default format was yyyy/mm/dd
- Eliminated the Reporting Database since the data formats were different
- Looked at the service calls made by Experience Explorer to fetch view data and found this:
"InteractionStartDateTime":"2016-10-20T15:34:20.449" "FormattedInteractionStartDateTime":"20.10.2016 11:34:20 (23hr:31min)"
I was starting to see light at the end of the rabbit hole.
Digging further I found that Sitecore.Cintel.Client.dll is responsible for providing the data for the views, which took me back to Sitecore.ExperienceProfile.Client.config, specifically the following section:
<experienceProfile>
<!-- Provides a hook to modify view results before they are displayed by Experience Profile appliction. -->
<resultTransformManager>
<!-- If http request header "X-SC-CintelTransformerClientName" matches clientName element, then the result transformer provider is applied.
Header value has to be: X-SC-CintelTransformerClientName: speakClient -->
<resultTransformProvider clientName="speakClient" type="Sitecore.Cintel.Endpoint.Transfomers.ResultTransformProvider" singleInstance="true">
<!-- If http request header "X-SC-CintelTransfomerKey" matches a viewName element, then the result transformer is applied.
For example, header value could read as: X-SC-CintelTransfomerKey: visits -->
<intelResultTransformers>
<add viewName="visits" type="Sitecore.Cintel.Client.Transformers.Contact.VisitResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="goals" type="Sitecore.Cintel.Client.Transformers.Contact.GoalResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="campaigns" type="Sitecore.Cintel.Client.Transformers.Contact.CampaignResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="events" type="Sitecore.Cintel.Client.Transformers.Contact.EventResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="latest-statistics" type="Sitecore.Cintel.Client.Transformers.Contact.OverviewResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="latest-events" type="Sitecore.Cintel.Client.Transformers.Contact.LatestEventResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="recent-campaigns" type="Sitecore.Cintel.Client.Transformers.Contact.RecentCampaignsResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="best-pattern-matches" type="Sitecore.Cintel.Client.Transformers.Contact.BestPatternMatchesResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="visit-summary" type="Sitecore.Cintel.Client.Transformers.Contact.VisitSummaryResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="visit-pages" type="Sitecore.Cintel.Client.Transformers.Contact.VisitPagesResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="visit-internal-searches" type="Sitecore.Cintel.Client.Transformers.Contact.VisitInternalSearchesResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="profile-info" type="Sitecore.Cintel.Client.Transformers.Contact.ProfilingProfilesResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="external-keyword-summary" type="Sitecore.Cintel.Client.Transformers.Contact.KeywordResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="internal-keyword-summary" type="Sitecore.Cintel.Client.Transformers.Contact.InternalKeywordSummaryResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="paid-keyword-summary" type="Sitecore.Cintel.Client.Transformers.Contact.KeywordResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="external-keyword-detail" type="Sitecore.Cintel.Client.Transformers.Contact.KeywordDetailResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="internal-keyword-detail" type="Sitecore.Cintel.Client.Transformers.Contact.KeywordDetailResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="paid-keyword-detail" type="Sitecore.Cintel.Client.Transformers.Contact.KeywordDetailResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="latest-visitors" type="Sitecore.Cintel.Client.Transformers.Contact.LatestVisitorsResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="journey" type="Sitecore.Cintel.Client.Transformers.Contact.JourneyResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="journey-detail-outcome" type="Sitecore.Cintel.Client.Transformers.Contact.JourneyOutcomeDetailResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="journey-detail-online-interaction" type="Sitecore.Cintel.Client.Transformers.Contact.JourneyOnlineInteractionDetailResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="channel-interaction-distribution" type="Sitecore.Cintel.Client.Transformers.Contact.ChannelInteractionDistributionResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="channel-goal-distribution" type="Sitecore.Cintel.Client.Transformers.Contact.ChannelGoalDistributionResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="channel-summary" type="Sitecore.Cintel.Client.Transformers.Contact.ChannelSummaryResultTransformer, Sitecore.Cintel.Client"/>
<add viewName="outcome-detail" type="Sitecore.Cintel.Client.Transformers.Contact.OutcomeDetailTransformer, Sitecore.Cintel.Client"/>
</intelResultTransformers>
<!-- If http request header "X-SC-CintelTransfomerKey" matches key element, then the result transformer is applied.
Header value has to be: X-SC-CintelTransfomerKey: default -->
<contactSearchResultTransformer>
<add key="default" type="Sitecore.Cintel.Client.Transformers.Contact.ContactSearchResultTransformer, Sitecore.Cintel.Client" />
</contactSearchResultTransformer>
<!-- If http request header "X-SC-CintelTransfomerKey" matches key element, then the result transformer is applied.
Header value has to be: X-SC-CintelTransfomerKey: default -->
<contactDetailsTransformer>
<add key="default" type="Sitecore.Cintel.Client.Transformers.Contact.ContactDetailsTransformer, Sitecore.Cintel.Client" />
</contactDetailsTransformer>
</resultTransformProvider>
</resultTransformManager>
</experienceProfile>
So here is the Aha moment!
Good news - found what needs to be modified!
Bad news - can't believe Sitecore hardcoded the date formats!
SOLUTION:
- Add config setting for date format
- Write a custom TimeConverter
- Write a custom ClientFactory that provides the custom TimeConverter
- Write a custom Transformer that use the custom ClientFactory
NOTE: To fix the timeline view I wrote a custom JourneyOnlineInteractionDetailResultTransformer. Some Transformers actually format the date within the Transform() method itself in which case you can skip steps 1 thru 3, for e.g. OverviewResultTransformer.
Here is the code:
Step 1: Config setting for date format
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<settings>
<!-- Date format for visit date in Experience Profile
-->
<setting name="ExprienceProfile.DateFormat" value="MM.dd.yyyy HH:mm:ss" />
</settings>
</sitecore>
</configuration>
Step 2 & 3: Custom TimeConverter and ClientFactory
using Sitecore.Cintel.Client;
using Sitecore.Cintel.Client.Transformers;
namespace Sc.Cintel.Client
{
public class CustomClientFactory : ClientFactory
{
public new static CustomClientFactory Instance { get; set; } = new CustomClientFactory();
public new ResultSetExtender GetResultSetExtender()
{
return new ResultSetExtender(this.GetResultSetHelper(), this.GetTimeConverter(), this.GetTextConverter());
}
public new TimeConverter GetTimeConverter()
{
return new CustomTimeConverter(this.GetRepository(), this.GetContextUtil());
}
}
}
Step 4: Custom Transformerusing Sitecore.Cintel.Client;
using Sitecore.Cintel.Client.Transformers;
namespace Sc.Cintel.Client
{
public class CustomClientFactory : ClientFactory
{
public new static CustomClientFactory Instance { get; set; } = new CustomClientFactory();
public new ResultSetExtender GetResultSetExtender()
{
return new ResultSetExtender(this.GetResultSetHelper(), this.GetTimeConverter(), this.GetTextConverter());
}
public new TimeConverter GetTimeConverter()
{
return new CustomTimeConverter(this.GetRepository(), this.GetContextUtil());
}
}
}
Finally, don't forget to replace the default transformer with your custom one in the config file.
<add viewName="journey-detail-online-interaction" type="Sc.Cintel.Client.Transformers.Contact.CustomJourneyOnlineInteractionDetailTransformer, Sc.Cintel.Client"/>
As always, there is more than one solution to a problem. This was the one I could think of. So, please feel free to leave a comment or suggestion for better approaches.
This comment has been removed by the author.
ReplyDelete