Skip to main content

custom personalisation rules XP/XM

in order to deliver personalised experiences via Sitecore using XP/XM without the Personalise product based on internal rules you will need to implement the WhenCondition RuleContext.

what makes this even more powerful is the ability for the user to select a "type" when adding the personalisation rule; e.g. allow the selection of "user is in X pot"; where the X is a data item and can be chosen by the editor. This allows a single rule to be created but used in multiple cases.

the below example will show the above with a predefined list of cases; however this can be further customised by letting the user create and choose variants, to achieve this you'd need to use the Sitecore db to get the value from said item by using Database.GetItem(AudienceItemId).

namespace MyNamespace
{
/// <summary>
/// Rule Condition which checks if the user is Filter Type
/// </summary>
/// <typeparam name="T">The Rule Context passed in by Sitecore</typeparam>
[ExcludeFromCodeCoverage]
public class MyRuleCondition<T> : WhenCondition<T> where T : RuleContext
{
public string MyFilter { get; set; }

private static readonly Dictionary<string, FilterType> _filters = new Dictionary<string, FilterType>()
{
{
"{guid-to-sitecore-item}",
Enums.FilterType.None
},
{
"{guid-to-sitecore-item}",
Enums.FilterType.Extra
}
};

/// <summary>
/// Return whether the user is the requested filter type
/// </summary>
/// <param name="ruleContext">The Sitecore Rule Context</param>
/// <returns></returns>
protected override bool Execute(T ruleContext)
{
var filterTypeProcessor = ServiceLocator.ServiceProvider.GetService<IFilterTypeProcessor>();

if (!_rewardsTypes.TryGetValue(FilterType, out var filterType))
{
client.TrackTrace($"MyRuleCondition: FilterType not recognised.", SeverityLevel.Error);
return false;
}

if (filterTypeProcessor == null)
{
client.TrackTrace($"MyRuleCondition: filterTypeProcessor is null, IFilterTypeProcessor could not be found. Aborting rule condition ", SeverityLevel.Error);
return false;
}

bool result;
try
{
// Call a downstream service to determine if the user is the requested filter type
result = filterTypeProcessor.IsFilterType(filterType);
}
catch (Exception e)
{
client.TrackException(e);
client.Flush();
return false;
}

client.TrackTrace($"MyRuleCondition: Ending execution of Rule Condition, FilterType:{filterType} Result:{result}", SeverityLevel.Information);
return result;
}
}
}

to go with the above code you will want to configure a number of items within Sitecore; namely:

  • Create a /sitecore/templates/System/Rules/Condition in an appropriate folder under /sitecore/system/Settings/Rules/Definitions/Elements
    • You will want to populate the Type property and set that to the RuleCondition code implemented above
    • You can use something like the below for the Text property:
      • user has [filterType,Tree,root={new-folder-as-below-id}&setRootAsSearchRoot=true,filter type]
  • Underneath the above Condition you can insert a Folder and Standard Template items that can be used to allow the user to set specific filters; the name of these are important for the user, the guid is important for the RuleCondition code above.
tip

This is loosely based on some Sitecore docs here: