In this tutorial you create a custom trait. A trait is an attribute or property of a visitor or visit, such as age or gender, that you can use to personalize content. Here we create a trait that detects the visitor's operating system. We then serve the visitor a personalized software download page: EXE download for Windows and DMG download for Mac OS X. The trait extracts the operating system from the User-Agent header. Magnolia 5.3+
Create a module
A trait is deployed with a Magnolia module. Create a module first. Choose from these options depending on your skill level:
Option 1: Clone the project in Git
Choose this option if you know how to work with a Magnolia project and Git. Choose this option also if you want to examine the code locally in your IDE. You get a ready-made project that you can customize to your needs.
Import the project into your IDE. Here's what the project looks like in IntelliJ IDEA:
- Build the project into a JAR and deploy it to Magnolia instance. Or run the project in your IDE. To run it in an IDE, add the module as a dependency to your Magnolia bundle POM file, see option 2.
Option 2: Add the project as a dependency to your bundle
Choose this option if you run Magnolia in your IDE but don't plan to work on the code. Add the project as a dependency in the POM files of your Magnolia bundle.
For the Enterprise Edition bundle:
dependencyManagementsection of the EE-bundle parent POM file, add a
dependencyelement with a version number:
dependenciessection of the enterprise-webapp POM file, add a
dependencyelement without a version number:
If you use IMB WebSphere or Oracle WebLogic, add the
dependencyelement in the appropriate POM file of the webapp of your choice.
If you are using a custom bundle, add the
dependency element with a version number in the POM file of your customized bundle.
Option 3: Download the module JAR
Choose this option if you are new to Magnolia and don't have a development environment (IDE). You can use the trait but won't be able to look at the code.
- Install the Magnolia Tomcat bundle.
- Download documentation-trait-tutorial-1.1.jar from Nexus.
- Copy the JAR into
<CATALINA_HOME>/webapps/<contextPath>/WEB-INF/libfolder. Typically this is
- Restart your Magnolia instance and run the Web update. This will install the
Registering a trait
Any module can register a trait. Magnolia observes the
traits folder under module configuration and adds new traits to a trait registry. Registered traits are then displayed to editors in the user interface.
<trait name>: Choose a name that is easy for editors to understand such as
ruleField: A field that is used to define permitted values for a trait.
valueField: A field that is used to enter a single value to test personalized content delivery.
converterClass: A converter class which must implement
defaultPreviewTrait: Optional. Adds the trait to the Preview app by default. Set this property to
truefor any traits that editors preview content with routinely. It makes the Preview app faster to use. If a trait is used rarely, leave the property out. Default value is
false. Example: defaultPreviewTrait-sc.png.
defaultRuleTrait: Optional. Adds the trait in the Choose audience dialog in the Pages app by default. Set this property to
truefor any traits that editors use routinely. It makes choosing an audience faster. If a trait is used rarely, leave the property out. Default value is
false. Example: defaultRuleTrait-sc.png.
traitClass: The class of your trait. Doesn't have to explicitly implement any interface. Usually it is just a plain Java object which allows you to specify the trait and its characteristics.
voterClass: The voter class must extend
AbstractBoolVoter<TraitCollector>. See Voters.
A rule field is used to define permitted values for a trait. For example, you need two rule fields to define a date range: one for start date and another for end date. Magnolia uses the input entered into the rule field(s) to construct a voter. The voter then decides whether the visitor or visit matches the rule or not. When the rule is met, personalized content is delivered.
Choose a field definition class that lets the user specify the permitted values. In some cases, a simple text field is enough (country). Other times, you must let the user specify a list of permitted values (new visitor, registered visitor, logged-in visitor). If the value is complex, use a complex field. See an example in
class: The definition class of the field. The field must be known to the system. If you introduce a new field and want it only available in your module, you should configure it under the
/modules/<module name>/fieldTypesnode. See Custom fields.
type: The type in this case is a bean property of the superclass (
TextFieldDefinition) of the definition class. The type is not needed in every case.
The rule field is displayed to users in the Choose audience dialog.
A value field is used to enter to test variant delivery. The field is displayed to users in Preview app. When you enter a value that matches the rule, such as date that falls within the permitted date range, the personalized content variant is served. The voter tests the value against the rule.
class: The definition-class of the field. When introducing a new field, the same is true as mentioned above, but typically such a field is very "common".
type: Again the type here is a bean-property of of the definition class.
The value field is displayed to users in the Preview app.
Once you have registered a new trait and applied it to some page variants, provide a
TraitDetectorFilter and register it in the filter chain to make sure the appropriate page variant is served.
<filter name>: Name the filter after your trait, ideally the same name as you used in trait registration. In our example the filter name is
userAgent. The system doesn't require that they both have the same name but it makes it easier to identify the purpose of the filter.
class: A class that implements
AbstractTraitDetectorFilter<Object>. In our example it should implement
Position of the filter in the chain
Make sure the filter is in the right position in the chain. Filters are executed in the order they are in the chain, from top to bottom. You want to position the filter right after the
When installing a module, you can define the position with
In the example above the configuration tree is simplified. Other filters may also want to be right after
contentType. In a production environment it may look like this:
Creating the pages
Now you can create page variants and choose an audience for them using the new trait. The module installs a page tree with an example page and two variants:
Both variants have an additional "local rule" in their audience-settings:
Testing the result
If you did everything correctly, we can see now variations of the Downloads page (
/documentation-personalization-examples-home/services/downloads) depending on the user agent. You can test this with 2 computers - the first running Windows, the second with OS-X-version. If you do not have access to two machines with two different operating systems, use a browser plugin such as Override User Agent to impersonate a user agent.
Downloads-page on OS X:
Downloads page on Windows (actually also on a Mac using the Override User Agent plugin):