Sitecore - Track user events in a delimited time frame

Almost always we need to track what users have been doing on our site, but what if we need to know if a user has performed a specific action within a certain time period? Recently I was asked to write code that reacts to some form events, e.g. upon submission some forms needed to be hidden and an alert needed to be shown if the submission happened within x days. One of the possible solutions we thought of was to use Sitecore Goals. Once a user submitted a form we registered a goal, on the next page load we checked if the goal was triggered (within a certain time frame) and we hid the form if needed.

The following code will allow you to register goals for the current logged in user:

 public void TriggerGoal(ID goalId, string additionalData)  
     {  
       Assert.IsNotNull(Tracker.Current, "Tracker.Current");  
       Assert.IsNotNull(Tracker.Current.Session, "Tracker.Current.Session");  
       Assert.IsNotNull(goalId, "goalId");  
       using (XConnectClient client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())  
       {  
         try  
         {  
           var reference = new IdentifiedContactReference("xDB.Tracker", Tracker.Current.Session.Contact.ContactId.ToString("N"));  
           var actualContact = client.Get(reference, new ContactExpandOptions());  
           string userAgent = System.Web.HttpContext.Current?.Request.UserAgent;  
           var interaction = new Sitecore.XConnect.Interaction(actualContact, InteractionInitiator.Brand, ChannelIds.OnlineDirectChannelId, userAgent);  
           var goal = new Goal(goalId.ToGuid(), DateTime.UtcNow)  
           {  
             Data = additionalData  
           };  
           interaction.Events.Add(goal);  
           client.AddInteraction(interaction);  
           client.Submit();  
         }  
         catch (Exception ex)  
         {  
           Log.Error(ex.Message, ex, this);  
         }  
       }  
     }  

Something important to see in the code above is this: Tracker.Current.Session.Contact.ContactId.ToString("N") . It is important to format the ContactId, otherwise, we won't be able to get the IdentifiedContactRefetence since the constructor expects the ShortId of the contact and the ContactId is a Guid.

Once we have registered goals for a user, we will be able to check if those goals have been triggered within a certain time frame by using the following code:

 public bool IsGoalTriggered(ID goalId, decimal hours)  
     {  
       Assert.IsNotNull(Tracker.Current, "Tracker.Current");  
       Assert.IsNotNull(Tracker.Current.Session, "Tracker.Current.Session");  
       Assert.IsNotNull(goalId, "goalId");  
       Assert.IsNotNull(hours, "hours");  
       using (XConnectClient client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())  
       {  
         try  
         {  
           var time = decimal.ToDouble(hours);  
           var allInteractionsExpandOptions = new ContactExpandOptions()  
           {  
             Interactions = new RelatedInteractionsExpandOptions()  
             {  
               Limit = int.MaxValue  
             }  
           };  
           var reference = new IdentifiedContactReference("xDB.Tracker", Tracker.Current.Session.Contact.ContactId.ToString("N"));  
           var actualContact = client.Get(reference, allInteractionsExpandOptions);  
           var interactions = actualContact.Interactions;  
           var goals = interactions.Select(x => x.Events.OfType<Goal>()).SelectMany(x=>x).OrderByDescending(x=>x.Timestamp);  
           var desiredGoal = goals.FirstOrDefault(x => TypeExtensions.ToID(x.DefinitionId) == goalId);  
           return desiredGoal?.Timestamp.AddHours(time) >= DateTime.UtcNow;  
         }  
         catch (XdbExecutionException ex)  
         {  
           Log.Error(ex.Message,ex,this);  
         }  
       }  
       return false;  
     }  

By calling the IsGoalTriggered and passing the GoalId and the time, we will be able to see if a goal was registered during that time. The method will return true if the goal was registered within that time frame and false if the goal was not registered in that time period.


Happy Coding!

Comments