Magnolia 5.3 reached end of life on June 30, 2017. This branch is no longer supported, see End-of-life policy.
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+
A trait is deployed with a Magnolia module. Create a module first. Choose from these options depending on your skill level:
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.
Clone the documentation-trait-tutorial
repository.
git clone http://git.magnolia-cms.com/git/documentation/documentation-trait-tutorial.git
Import the project into your IDE. Here's what the project looks like in IntelliJ IDEA:
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:
In the dependencyManagement
section of the EE-bundle parent POM file, add a dependency
element with a version number:
<dependencyManagement> <dependencies> <dependency> <groupId>info.magnolia.documentation</groupId> <artifactId>documentation-trait-tutorial</artifactId> <version>1.1</version> </dependency> </dependencies> </dependencyManagement>
In the dependencies
section of the enterprise-webapp POM file, add a dependency
element without a version number:
<dependencies> <dependency> <groupId>info.magnolia.documentation</groupId> <artifactId>documentation-trait-tutorial</artifactId> </dependency> </dependencies>
If you use IMB WebSphere or Oracle WebLogic, add the
dependency
element 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.
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.
<CATALINA_HOME>/webapps/<contextPath>/WEB-INF/lib
folder. Typically this is <CATALINA_HOME>/webapps/magnoliaAuthor/WEB-INF/lib
.documentation-personalization-samples
module.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.
Node name | Value |
---|---|
modules |
|
documentation-trait-tutorial |
|
traits |
|
userAgent |
|
ruleField |
|
valueField |
|
converterClass | info.magnolia.documentation.examples.personalization.useragent.UserAgentParameterConverter |
defaultPreviewTrait | true |
defaultRuleTrait | true |
traitClass | info.magnolia.documentation.examples.personalization.useragent.UserAgent |
voterClass | info.magnolia.documentation.examples.personalization.useragent.UserAgentVoter |
Properties:
<trait name>
: Choose a name that is easy for editors to understand such as country
, date
or userAgent
. 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 info.magnolia.personalization.preview.parameter.PreviewParameterConverter<Object>
. defaultPreviewTrait
: Optional. Adds the trait to the Preview app by default. Set this property to true
for 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 true
for 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 /modules/personalization-samples/traits/visitor/ruleField
.
Node name | Value |
---|---|
ruleField |
|
class | info.magnolia.ui.form.field.definition.TextFieldDefinition |
type | String |
Properties:
ruleField
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>/fieldTypes
node. 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.
Node name | Value |
---|---|
valueField |
|
class | info.magnolia.ui.form.field.definition.TextFieldDefinition |
type | String |
Properties:
valueField
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.
Node name | Value |
---|---|
server |
|
filters |
|
context |
|
contentType |
|
userAgent |
|
class | info.magnolia.documentation.examples.personalization.useragent.UserAgentDetectorFilter |
<more filters> |
Properties:
server
filters
<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 AbstractTraitDetectorFilter<UserAgent>
.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 contentType
filter.
When installing a module, you can define the position with ModuleVersionHandler#getExtraInstallTasks
.
public class PersonalizationExamplesModuleVersionHandler extends DefaultModuleVersionHandler { @Override protected List<Task> getExtraInstallTasks(InstallContext installContext) { List<Task> tasks = new ArrayList<Task>(); tasks.add(new FilterOrderingTask("userAgent", new String[]{"contentType"})); return tasks; } }
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:
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:
/documentation-personalization-examples-home/services/downloads/variants/variant-osx
/documentation-personalization-examples-home/services/downloads/variants/variant-window
Both variants have an additional "local rule" in their audience-settings:
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):