Develop a Collector Plugin
Introduction
Goal
Develop a collector plugin, on brXM 17.2 or higher, to override collector data using the Experience manager's Alter Ego feature.
Background
The Alter Ego functionality allows a CMS user to impersonate a visitor with certain characteristics. The 'As viewed by' menu in the Experience manager always contains the option 'Alter Ego'. When the 'Alter Ego' option is selected, targeting data will be collected while previewing the channel, and targeted content will be shown. The 'Edit Alter Ego' button opens a window in which collected targeting data can be overridden with a specific value. For example, it is possible to select a specific location instead of location collected by the Relevance Module.
To be able to override collector data, a collector plugin must be provided to edit the (JSON representation) of the targeting data. The Java collector plugin registers metadata and frontend options. The Experience manager Alter Ego UI uses a built-in editor based on the collector id and those options.
This page explains how to implement a collector plugin.
Configuration
Collector plugins are configured in the repository at:
/hippo:configuration/hippo:frontend/cms/hippo-targeting
Each collector plugin is configured in one child node of type frontend:pluginconfig. As a best practice, name the node collector-<ID of your collector>. Each collector plugin node can have the following properties:
- collector (String, mandatory) The ID of the collector.
- plugin.class (String, mandatory) The Java class name of the collector plugin.
A collector plugin can define more configuration properties to customize the plugin. Extra properties are passed through to the Angular frontend as options (and can be enriched in Java).
Example: GroupsCollectorPlugin
The groups collector plugin allows you to alter the groups a user is a member of. The targeting data of the GroupsCollector simply returns the groups as a comma-separated string. The groups collector plugin consists of a checkbox group in which one or more groups can be selected.
The plugin consist of a Java class and a .properties file, or a bundle of language variants, e.g. add a *_nl.properties too.
The code shown below is a slightly simplified version of the GroupsCollectorPlugin in the Relevance Module.
Java Class
GroupsCollectorPlugin.java:
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.query.Query;
import com.onehippo.cms7.targeting.frontend.plugin.CollectorPlugin;
import org.hippoecm.frontend.plugin.IPluginContext;
import org.hippoecm.frontend.plugin.config.IPluginConfig;
import org.hippoecm.frontend.session.UserSession;
/**
* Plugin for the groups collector. Available plugin properties:
* <ul>
* <li>groups: multi-value String property, each string specifies
* a selectable group</li>
* </ul>
*/
@SuppressWarnings("unused")
public class GroupsCollectorPlugin extends CollectorPlugin {
private final List<Pattern> excludes;
public GroupsCollectorPlugin(final IPluginContext context,
final IPluginConfig config) {
super(context, config);
final String[] excludesConfig = config.getStringArray("excludes");
excludes = new ArrayList<>();
if (excludesConfig != null) {
for (String exclude : excludesConfig) {
excludes.add(Pattern.compile(exclude));
}
}
}
@Override
public void enrichFrontendOptions(final Map<String, Object> options) {
try {
options.put("groups", listGroups());
} catch (RepositoryException e) {
throw new RuntimeException(e);
}
}
private List<String> listGroups() throws RepositoryException {
final Session session = UserSession.get().getJcrSession();
final String statement = "//element(*, " + "hipposys:group" + ") order by @jcr:name";
final Query q = session.getWorkspace().getQueryManager()
.createQuery(statement, Query.XPATH);
final List<String> groups = new ArrayList<>();
final NodeIterator nodes = q.execute().getNodes();
while (nodes.hasNext()) {
final String group = nodes.nextNode().getName();
if (!isExcluded(group)) {
groups.add(group);
}
}
return groups;
}
private boolean isExcluded(final String group) {
if (group.equals("everybody")) {
return true;
}
for (Pattern exclude : excludes) {
if (exclude.matcher(group).matches()) {
return true;
}
}
return false;
}
}
Properties File(s)
The .properties file contains the i18n labels. The special key collector-description is shown as the description of the collector in the 'Edit Alter Ego' window.
GroupsCollectorPlugin.properties:
collector-description=is in the user group
For different languages variants, add typical language variants like GroupsCollectorPlugin_nl.properties too.
Java API
com.onehippo.cms7.targeting.frontend.plugin.CollectorPlugin
Base class for collector plugins.
Plugin configuration properties:
- collector( String, mandatory) The ID of the collector.
- plugin.class( String, mandatory) The Java class name of the collector plugin.
com.onehippo.cms7.targeting.frontend.plugin.dayofweek.DayOfWeekCollectorPlugin
Plugin to alter the current day of the week.
com.onehippo.cms7.targeting.frontend.plugin.geo.GeoIPCollectorPlugin
Plugin to alter the location of the visitor.
Plugin configuration properties:
- locations(multiple String) A list of location strings to show as selectable options in the editor. Each location string has the format "city | country | latitude | longitude".
com.onehippo.cms7.targeting.frontend.plugin.groups.GroupsCollectorPlugin
Plugin to alter the groups a visitor is a member of.
Plugin configuration properties:
- excludes(multiple String) A list of regular expression of patterns of group names to exclude from showing as selectable options in the editor.
com.onehippo.cms7.targeting.frontend.plugin.referrer.ReferrerCollectorPlugin
Plugin to alter the referrer URL.
com.onehippo.cms7.targeting.frontend.plugin.returningvisitor.ReturningVisitorCollectorPlugin
Plugin to alter whether the visitor is new or returning.
Built-in Alter Ego Editors
There are Angular-based editors to render the UI part for various out-of-the-box collectors. Unless the custom collector overrides one of the ids groups, documenttypes, engagement, dayofweek, returningvisitor, tracking, referrer, pageviews or geo, the editor will be a rendered JSON textarea.
Upgrade Path towards 17.2
If there are custom collectors in your project that need to be upgraded to 17.2, follow this checklist:
In the Java class:
- Remove @ExtClass annotations and ExtJS plugin classes
- Change getIcon() method from protected to public
- Replace onRenderProperties override with
public void enrichFrontendOptions(Map<String, Object> options) - Remove renderHead overrides
- Remove unused imports
Remove any ExtJS JS/CSS resources that used to be added in the renderHead.
In the associated properties file(s), remove any entries that used to be used only in the ExtJS Javascript files.