|
| 1 | +--- |
| 2 | +description: >- |
| 3 | + Discover how to create and manage custom segments. |
| 4 | +--- |
| 5 | + |
| 6 | +# Implement your own segment parameters |
| 7 | + |
| 8 | +Umbraco Engage comes with various built-in segment parameters to build a segment, such as "Customer Journey" and "Time of Day". However, you may want to build segments with custom rules that are not part of Engage by default. We've got you covered; you can add your own custom segment parameters to the Engage. |
| 9 | + |
| 10 | +The following guide will explain how this can be done. Note this is aimed at developers. |
| 11 | +There are 3 steps, 2 of which are mandatory and the 3rd is optional: |
| 12 | + |
| 13 | +1. C# definition |
| 14 | +2. AngularJS definition |
| 15 | +3. (optional) Cockpit visualization |
| 16 | + |
| 17 | +This guide will use concrete code samples to add a "Day of week" segment parameter where you can select a single day of the week. If a pageview happens on that day the segment parameter will be satisfied. |
| 18 | + |
| 19 | +## 1. C# definition |
| 20 | + |
| 21 | +Your custom segment parameter will need to be defined in C# in order for the Engage to use it. |
| 22 | +In code we refer to a segment parameter as a "segment rule". |
| 23 | + |
| 24 | +A segment rule is not much more than this: |
| 25 | + |
| 26 | +* A unique rule identifier, e.g. "DayOfWeek". |
| 27 | +* A configuration object, e.g. "{ dayOfWeek: "Monday" }" |
| 28 | + * This is optional, but most rules will have some sort of configuration that the user can alter in the Segment Builder. In our example, the user can configure the specific day of the week. |
| 29 | +* A method that specifies whether the rule is satisfied by the current pageview. |
| 30 | + |
| 31 | +You will have to implement the following interfaces for a new custom parameter: |
| 32 | + |
| 33 | +* Umbraco.Engage.Infrastructure.Personalization.Segments.ISegmentRule |
| 34 | + * You can extend the existing BaseSegmentRule to simplify the implementation. |
| 35 | + * The most important part to implement is the bool IsSatisfied(IPersonalizationProfile context) method. |
| 36 | +* Umbraco.Engage.Infrastructure.Personalization.Segments.Rules.ISegmentRuleFactory |
| 37 | + * Register your implementation of the segment rule factory with Lifetime.Transient in a composer. |
| 38 | + |
| 39 | +For the "Day of week" example, the code looks like this: |
| 40 | + |
| 41 | +```c# |
| 42 | +public class DayOfWeekSegmentRule : BaseSegmentRule |
| 43 | +{ |
| 44 | + public DayOfWeekSegmentRuleConfig TypedConfig { get; } |
| 45 | + |
| 46 | + public override SegmentRuleValidationMode ValidationMode => SegmentRuleValidationMode.Once; |
| 47 | + |
| 48 | + public DayOfWeekSegmentRule(long id, Guid key, long segmentId, string type, string config, bool isNegation, DateTime created, DateTime? updated, DayOfWeekSegmentRuleConfig typedConfig) |
| 49 | + : base(id, segmentId, type, config, isNegation, created, updated) |
| 50 | + => TypedConfig = typedConfig; |
| 51 | + |
| 52 | + public override bool IsSatisfied(IPersonalizationProfile context) |
| 53 | + => context.Pageview.Timestamp.DayOfWeek == TypedConfig.DayOfWeek; |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +And the factory which is used to create an instance of this rule: |
| 58 | + |
| 59 | +```c# |
| 60 | +//The segment rule factory needs to be registered so Engage can use it. |
| 61 | +[RegisterService(ServiceLifetime.Transient)] |
| 62 | +public class DayOfWeekSegmentRuleFactory : ISegmentRuleFactory |
| 63 | +{ |
| 64 | + public string RuleType { get; } = "DayOfWeek"; |
| 65 | + public ISegmentRule CreateRule(string config, bool isNegation, long id, Guid key, long segmentId, DateTime created, DateTime? updated) |
| 66 | + { |
| 67 | + var typedConfig = JsonConvert.DeserializeObject<DayOfWeekSegmentRuleConfig>(config); |
| 68 | + return new DayOfWeekSegmentRule(id, key, segmentId, RuleType, config, isNegation, created, updated, typedConfig); |
| 69 | + } |
| 70 | +} |
| 71 | +``` |
| 72 | + |
| 73 | +We are using the class DayOfWeekSegmentRuleConfig as a representation of the configuration of the rule, which is not strictly necessary but makes it easier. The configuration is stored as a string in the database but in code we like to have intellisense so we parse the stored configuration to this class: |
| 74 | + |
| 75 | +```c# |
| 76 | +//Generating config schema on client side. |
| 77 | +[GenerateEngageSchema] |
| 78 | +public class DayOfWeekSegmentRuleConfig |
| 79 | +{ |
| 80 | + public DayOfWeek DayOfWeek { get; set; } |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +That's the C# part of the custom segment parameter. |
| 85 | + |
| 86 | +## 2. Lit definition |
| 87 | + |
| 88 | +We have implemented the business logic for the segment parameter in the previous step, but the parameter cannot be added to your segments in the backoffice yet. In this step we will add a Lit element to enable you to add and configure your segments in the Engage segment builder. |
| 89 | + |
| 90 | +These steps will once again show concrete code samples that belong to our demo parameter "Day of week". |
| 91 | + |
| 92 | +First, re-generate the DayOfWeek config type on client side using the below command |
| 93 | + |
| 94 | +```text |
| 95 | +npm run generate:api |
| 96 | +``` |
| 97 | + |
| 98 | +Then, create a new Lit element, implemeting new "Day of week" segment. |
| 99 | + |
| 100 | +**segment-rule-day-of-week.ts** |
| 101 | + |
| 102 | +```typescript |
| 103 | +export interface UeSegmentRuleDayOfWeekConfig |
| 104 | + extends DayOfWeekSegmentRuleConfigModel {} |
| 105 | + |
| 106 | +const elementName = "ue-segment-rule-day-of-week"; |
| 107 | + |
| 108 | +@customElement(elementName) |
| 109 | +export class UeSegmentRuleDayOfWeekElement extends UeSegmentRuleBaseElement<UeSegmentRuleDayOfWeekConfig> { |
| 110 | + @state() |
| 111 | + private _options: Array<Options> = []; |
| 112 | + |
| 113 | + connectedCallback(): void { |
| 114 | + super.connectedCallback(); |
| 115 | + this._options = makeArray<DayOfWeek>( |
| 116 | + "Sunday", |
| 117 | + "Monday", |
| 118 | + "Tuesday", |
| 119 | + "Wednesday", |
| 120 | + "Thursday", |
| 121 | + "Friday", |
| 122 | + "Saturday" |
| 123 | + ).map((x, i) => ({ |
| 124 | + value: x, |
| 125 | + name: x, |
| 126 | + selected: this.value?.config.dayOfWeek === x || i === 0, |
| 127 | + })); |
| 128 | + } |
| 129 | + |
| 130 | + renderReadOnly() { |
| 131 | + return html`Day of week: ${this.value?.config.dayOfWeek}`; |
| 132 | + } |
| 133 | + |
| 134 | + renderEditor() { |
| 135 | + return html` |
| 136 | + <umb-property-layout label="Day" orientation="horizontal"> |
| 137 | + <div slot="editor"> |
| 138 | + <uui-select |
| 139 | + .options=${this._options} |
| 140 | + @change=${(e) => this.onSelectChange(e)} |
| 141 | + ></uui-select> |
| 142 | + </div> |
| 143 | + </umb-property-layout> |
| 144 | + `; |
| 145 | + } |
| 146 | + |
| 147 | + onSelectChange(e: UUISelectEvent) { |
| 148 | + if (!this.value) return; |
| 149 | + |
| 150 | + const selectedValue = e.target.value as string; |
| 151 | + |
| 152 | + this.updateParameterValue(selectedValue, "dayOfWeek"); |
| 153 | + } |
| 154 | +} |
| 155 | + |
| 156 | +export { UeSegmentRuleDayOfWeekElement as api }; |
| 157 | + |
| 158 | +declare global { |
| 159 | + interface HTMLElementTagNameMap { |
| 160 | + [elementName]: UeSegmentRuleDayOfWeekElement; |
| 161 | + } |
| 162 | +} |
| 163 | + |
| 164 | +``` |
| 165 | + |
| 166 | +Then, register this element in a manifest file. |
| 167 | + |
| 168 | +**manifest.ts** |
| 169 | + |
| 170 | +```json |
| 171 | +{ |
| 172 | + name: "Day of week", |
| 173 | + type: "DayOfWeek", |
| 174 | + icon: "icon-calendar", |
| 175 | + elementName: "day-of-week", |
| 176 | + config: { dayOfWeek: "Sunday" }, |
| 177 | +} |
| 178 | +``` |
| 179 | + |
| 180 | +That's it. If all went well you will see your custom parameter editor show up in the segment builder: |
| 181 | + |
| 182 | +<figure><img src="../../../.gitbook/assets/engage-tutorials-personalized-segments-v16.png" alt="Day of week Segment."><figcaption><p>Day of week Segment.</p></figcaption></figure> |
| 183 | + |
| 184 | +## 3. (optional) Cockpit visualization |
| 185 | + |
| 186 | +The new segment parameter will show up automatically in the Cockpit that is part of our package. The cockpit is a live view of Engage data for the current visitor. This includes active segments of the current visitor, and therefore your new segment parameter can also show up in the cockpit. By default it will simply display the the raw configuration of the parameter as stored in the database ("{ dayOfWeek: Thursday }" in our example), and if you hover over it you will see the rule identifier "DayOfWeek" rather than a friendly name. |
| 187 | + |
| 188 | +<figure><img src="../../../.gitbook/assets/engage-tutorials-personalized-segments-cockpit-v16.png"></figure> |
| 189 | + |
| 190 | +If you would like to change this to be a bit more readable you can implement the Engage.Web.Cockpit.Segments.ICockpitSegmentRuleFactory interface. For the DayOfWeek demo parameter, this is the implementation: |
| 191 | + |
| 192 | +```c# |
| 193 | +//Registering this factory. |
| 194 | +[RegisterService(ServiceLifetime.Transient)] |
| 195 | +public class DayOfWeekCockpitSegmentRuleFactory : ICockpitSegmentRuleFactory |
| 196 | +{ |
| 197 | + public DayOfWeekCockpitSegmentRuleFactory() { } |
| 198 | + |
| 199 | + public bool TryCreate(ISegmentRule segmentRule, bool isSatisfied, out CockpitSegmentRule? cockpitSegmentRule) |
| 200 | + { |
| 201 | + cockpitSegmentRule = null; |
| 202 | + if (segmentRule is DayOfWeekSegmentRule dayOfWeekRule) |
| 203 | + { |
| 204 | + cockpitSegmentRule = new CockpitSegmentRule |
| 205 | + { |
| 206 | + Name = "Day of week", |
| 207 | + Icon = "/path/to/icon.png", |
| 208 | + Config = dayOfWeekRule.TypedConfig.DayOfWeek.ToString(), |
| 209 | + IsNegation = segmentRule.IsNegation, |
| 210 | + IsSatisfied = isSatisfied, |
| 211 | + Type = segmentRule.Type, |
| 212 | + }; |
| 213 | + return true; |
| 214 | + } |
| 215 | + return false; |
| 216 | + } |
| 217 | +} |
| 218 | +``` |
| 219 | + |
| 220 | +So we simply transform the JSON into a human readable representation and we configure an icon to show up in the cockpit. Make sure to register this class in a composer (you can reuse the composer from step 1): |
| 221 | + |
| 222 | +After that the Engage will use the additional information to properly render your segment parameter in the cockpit as well. Note that the "DayOfWeek test" string is the name of the segment. This segment happens to have only 1 parameter which is the DayOfWeek parameter. |
| 223 | + |
| 224 | +<figure><img src="../../../.gitbook/assets/engage-tutorials-personalized-segments-cockpit-formatted-v16.png"></figure> |
0 commit comments