AndyButland/UmbracoPersonalisationGroupsCore

Umbraco 13 Custom Criteria

Closed this issue · 2 comments

Hi,
I need to create a custom criteria in order to get some settings defined inside the Umbraco backoffice.

With the current implementation I am only able to define some custom criterias inside the App_Plugins/PersonalisationGroups directory.
I was using the previous version of the library for Umbraco 8 and there was no need to create an Angular controller and the html in the App_Plugin directory.

Is there a way to replicate this behavior of the library? Alternatively what we need to do is to retrieve contents from a content folder in the backoffice and list the items in new custom criteria. Can you please help me?

Thank you in advance!

I also need support with this, I am trying to add a folder in App_Plugins/PersonalisationGroups/Criteria but without success. Could you please provide precise informations in order to create a custom Criteria? Thank you in advance.
@AndyButland

Here is how I've gone about it, adding a bit more detail to the high-level instructions provided here. Firstly, to install the package:

dotnet new install Umbraco.Templates::13.2.2
dotnet new umbraco --name TestProject
cd .\TestProject\
dotnet add package UmbracoPersonalisationGroups --version 3.2.10
code .

Modify Program.cs to setup the package. At some point I'll add a "composer" to do this, but for now these are the necessary steps:

  • Add using statement for Our.Umbraco.PersonalisationGroups.Core
  • Add .AddPersonalisationGroups(builder.Configuration) just before Build() in the chained methods from builder.CreateUmbracoBuilder()
  • Add u.UsePersonalisationGroupsEndpoints(); into .WithEndpoints().
dotnet run

Complete the installer with default options and verify can create simple personalisation group and publish without any issues.

Then I've created an illustrative custom criteria - just copying the built-in "Day of week" criteria to show how it works.

  • Copy the contents of App_Plugins\PersonalisationGroups\Criteria\DayOfWeek into a new folder App_Plugins\PersonalisationGroupsExtensions\Criteria\MyCustomCriteria.
    • Adjust the controller name defined in definition.editor.controller.js and definition.editor.html to something like PersonalisationGroupsExtensions.MyCustomCriteriaPersonalisationGroupCriteriaController
    • Adjust the factory name defined in definition.translator.js to PersonalisationGroups.MyCustomCriteriaTranslatorService
  • Create a package.manifest file at App_Plugins\PersonalisationGroupsExtensions\package.manifest with the following contents:
{
  "javascript": [
    "~/App_Plugins/PersonalisationGroupsExtensions/Criteria/MyCustomCriteria/definition.editor.controller.js",
    "~/App_Plugins/PersonalisationGroupsExtensions/Criteria/MyCustomCriteria/definition.translator.js",
  ],
  "css": [
  ]
}
  • Create a criteria definition in C#. To illustrate here's the example one I've created which is basically a copy of the built-in "day of week" one, with namespaces, alias and name adjusted, and the path to the client-side files configured.
    • For this example, the alias should be myCustomCriteria
namespace Our.Umbraco.PersonalisationGroups.Core.Criteria.DayOfWeek
{
    using Newtonsoft.Json;
    using Our.Umbraco.PersonalisationGroups.Core.Providers.DateTime;
    using System;
    using System.Linq;

    public class MyCustomCriteria : PersonalisationGroupCriteriaBase, IPersonalisationGroupCriteria
    {
        private readonly IDateTimeProvider _dateTimeProvider;

        public MyCustomCriteria(IDateTimeProvider dateTimeProvider)
        {
            _dateTimeProvider = dateTimeProvider;
        }

        public string Name => "My custom criteria";

        public string Alias => "myCustomCriteria";

        public string Description => "Matches visitor session with defined days of the week";

        public override string ClientAssetsFolder => "PersonalisationGroupsExtensions/Criteria";

        public bool MatchesVisitor(string definition)
        {
            if (string.IsNullOrEmpty(definition))
            {
                throw new ArgumentNullException(nameof(definition));
            }

            try
            {
                var definedDays = JsonConvert.DeserializeObject<int[]>(definition);
                return definedDays.Contains((int)_dateTimeProvider.GetCurrentDateTime().DayOfWeek + 1);
            }
            catch (JsonReaderException)
            {
                throw new ArgumentException($"Provided definition is not valid JSON: {definition}");
            }
        }
    }
}
  • Restart the web application.