Develop a Collector Plugin
Overview
Starting with version 17.2, the collector plugin extension point uses an Angular-based editor in the Experience manager. For earlier versions, custom ExtJS code was required. For details on ExtJS-based plugins, see Develop a Collector Plugin with ExtJS.
This guide describes how to develop a collector plugin for Bloomreach Content 17.2 or higher. The plugin enables you to override collector data using the Alter Ego feature in the Experience manager.
Use Case
Implement a collector plugin on Bloomreach Content 17.2+ to allow CMS users to override collector data via the Alter Ego functionality.
Alter Ego Functionality
The Alter Ego feature allows CMS users to impersonate a visitor with specific characteristics. In the Experience manager, the 'As viewed by' menu always includes the 'Alter Ego' option. When selected, the system collects targeting data while previewing the channel and displays targeted content accordingly. The 'Edit Alter Ego' button opens a window where users can override collected targeting data with specific values. For example, a user can select a particular location instead of using the location detected by the Relevance Module.
To enable data overrides, you must provide a collector plugin that allows editing the JSON representation of the targeting data. The Java collector plugin registers metadata and frontend options. The Alter Ego UI displays the editor the plugin declares through frontend:editorType (since 17.3). If the plugin declares none, the UI falls back to the built-in editor for the collector ID.
This page outlines the steps 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 defined in a child node of type frontend:pluginconfig. Name the node using the format collector-<ID of your collector>.
Each collector plugin node requires the following properties:
-
collector(String, required): The ID of the collector. -
plugin.class(String, required): The fully qualified Java class name of the collector plugin.
Since 17.3
-
frontend:editorType(String, optional): Specifies the built-in Angular editor used for this collector in the Alter Ego and segment editors. Valid values:checkbox-group,radio-group,property-names,page-views. When not set, the editor is selected by collector ID and falls back to a JSON textarea. See Selectable Values for Custom Collectors. -
frontend:dataField(String, optional): The name of the option that holds the selectable values of this collector. This is also the key the selection is stored under. Default: the collector ID.
You can define additional configuration properties to customize the plugin. These extra properties are passed to the Angular frontend as options and can be enriched in Java.
Example: GroupsCollectorPlugin
The Groups collector plugin allows users to modify the groups a visitor belongs to. The GroupsCollector returns group membership as a comma-separated string. The plugin presents a checkbox group, enabling selection of one or more groups.
The plugin consists of a Java class and a .properties file, or a set of language-specific properties files (for example, GroupsCollectorPlugin_nl.properties).
The following example is a simplified version of the GroupsCollectorPlugin from 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 com.onehippo.cms7.targeting.frontend.plugin.CollectorPlugin; import org.hippoecm.frontend.plugin.IPluginContext; import org.hippoecm.frontend.plugin.config.IPluginConfig; import org.onehippo.cms7.services.HippoServiceRegistry; import org.onehippo.repository.security.SecurityService; /** * 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) { options.put("groups", listGroups()); } private List<String> listGroups() { final SecurityService securityService = HippoServiceRegistry.getService(SecurityService.class); final List<String> groups = new ArrayList<>(); securityService.getGroups(0, 0).forEach(group -> { if (!isExcluded(group.getId())) { groups.add(group.getId()); } }); 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 provides i18n labels. The key collector-description is displayed as the description of the collector in the 'Edit Alter Ego' window.
GroupsCollectorPlugin.properties:
collector-description=is in the user group
To support multiple languages, add language-specific files such as GroupsCollectorPlugin_nl.properties.
Selectable Values for Custom Collectors
Since 17.3
A custom collector is not limited to the JSON textarea. Set frontend:editorType on the plugin
node, and the Alter Ego and segment editors display checkboxes, radio buttons, or a value list
instead, populated from the options the plugin registers in enrichFrontendOptions.
Editor Types
frontend:editorType | Editor | Stored value |
|---|---|---|
checkbox-group | Checkboxes, multiple selection | Array of strings |
radio-group | Radio buttons, single selection | Single string |
property-names | Comma-separated list of free-text values | Array of strings |
page-views | The page-view editor also used by the built-in pageviews collector | Array of strings |
A collector that does not set the property behaves exactly as it did before 17.3, so existing
collectors are unaffected by the upgrade.
Two editor types cannot be declared:
-
geo-location-radiostores a compositecity|countrykey that only the built-ingeocollector understands. -
json-textareais the value an undeclared collector already reports and means "no preference".
An unrecognized editor type — a typo, for example — is ignored rather than applied. The collector falls back to the built-in editor for its ID, or to the JSON textarea. A misconfigured collector degrades gracefully; it does not break the field.
Where the Selectable Values Come From
A collector using one of these editors offers its values under an option named after the collector itself, and stores the user's selection under that same name. A collector configured as collector = product:
-
Registers its values in
options.productfromenrichFrontendOptions(Map). -
Stores a selection as
{"collectorId": "product", "product": ["bike", "car"]}. Aradio-groupstores a single value:"product": "bike".
Each value is either a plain string or a map. A map is read for a value (value, name, code, or type) and a label (name, description, label, value, or type), so both forms work:
options.put("product", List.of("bike", "car")); options.put("product", List.of(Map.of("value", "bike", "name", "Bicycle")));
The registered options also supply the labels shown in the Alter Ego summary, whichever editor type the collector uses. A stored value with no matching option is displayed as stored.
Set frontend:dataField only when the collector's data shape does not follow its own name. A collector collector = product that already stores its data under products sets frontend:dataField = products rather than renaming its data.
Example: A Custom 'product' Collector
Plugin configuration:
definitions: config: /hippo:configuration/hippo:frontend/cms/hippo-targeting/collector-product: jcr:primaryType: frontend:plugin collector: product frontend:editorType: checkbox-group plugin.class: com.example.targeting.frontend.plugin.ProductCollectorPlugin
ProductCollectorPlugin.java:
public class ProductCollectorPlugin extends CollectorPlugin { public ProductCollectorPlugin(final IPluginContext context, final IPluginConfig config) { super(context, config); } @Override public void enrichFrontendOptions(final Map<String, Object> options) { options.put("product", List.of("bike", "car", "skateboard")); } }
ProductCollectorPlugin.properties:
collector-description=is interested in
The 'Edit Alter Ego' window now displays three checkboxes instead of a JSON textarea.
Java API
com.onehippo.cms7.targeting.frontend.plugin.CollectorPlugin
Base class for collector plugins.
Configuration properties:
-
collector(String, required): The ID of the collector. -
plugin.class(String, required): The fully qualified Java class name of the collector plugin.
Since 17.3
-
frontend:editorType(String, optional): Specifies the built-in Angular editor. Valid values:checkbox-group,radio-group,property-names,page-views. See Selectable Values for Custom Collectors. -
frontend:dataField(String, optional): The name of the option holding the selectable values, and the key the selection is stored under. Default: the collector ID.
A plugin can also declare its editor in Java by overriding getAngularEditorType() instead of setting frontend:editorType. The built-in collector plugins do this, so a subclass of a built-in collector inherits its editor. The configuration property exists so that a custom collector does not have to subclass anything.
com.onehippo.cms7.targeting.frontend.plugin.dayofweek.DayOfWeekCollectorPlugin
Enables editing the current day of the week.
com.onehippo.cms7.targeting.frontend.plugin.geo.GeoIPCollectorPlugin
Enables editing the visitor's location.
Configuration properties:
locations(multipleString): List of location strings shown as selectable options in the editor. Each string must use the format"city | country | latitude | longitude".
com.onehippo.cms7.targeting.frontend.plugin.groups.GroupsCollectorPlugin
Enables editing the groups a visitor belongs to.
Configuration properties:
excludes(multipleString): List of regular expression patterns. Groups matching these patterns are excluded from the selectable options in the editor.
com.onehippo.cms7.targeting.frontend.plugin.referrer.ReferrerCollectorPlugin
Enables editing the referrer URL.
com.onehippo.cms7.targeting.frontend.plugin.returningvisitor.ReturningVisitorCollectorPlugin
Enables editing whether the visitor is new or returning.
Built-in Alter Ego Editors
Angular-based editors are available for several built-in collectors. If your custom collector does not use one of the following IDs: groups, documenttypes, engagement, dayofweek, returningvisitor, tracking, referrer, pageviews, or geo, the editor will display a JSON textarea for editing.
Angular-based editors are available for the built-in collectors. Each built-in collector declares its own editor:
| Collector ID | Editor |
|---|---|
groups, documenttypes, engagement | checkbox-group |
dayofweek, returningvisitor, tracking | radio-group |
referrer | property-names |
pageviews | page-views |
geo | geo-location-radio |
A custom collector that does not declare an editor displays a JSON textarea.
Changed in 17.3. Before 17.3, the only way to give a custom collector a real editor was to give the collector the ID of a built-in collector so that it would inherit that collector's editor. This approach supported at most one custom collector per built-in ID and is no longer recommended. Give the collector its own ID and set frontend:editorType instead, as described in Selectable Values for Custom Collectors. The geo-location-radio editor cannot be declared this way, because it stores a composite city|country key that only the built-in geo collector understands.
Upgrade Checklist for 17.3
No changes are required. Collectors upgraded to 17.2 continue to work unchanged.
If a custom collector was given the ID of a built-in collector in order to inherit its editor, revert that workaround:
-
Give the collector its own ID.
-
Set
frontend:editorTypeon the plugin node. -
Register the selectable values under an option named after the collector, as described in Selectable Values for Custom Collectors.
This is what allows more than one custom collector with a selectable editor in the same project.
Upgrade Checklist for 17.2
To upgrade custom collectors for use with version 17.2, complete the following steps:
In the Java class:
-
Remove all
@ExtClassannotations and ExtJS plugin classes. -
Change the
getIcon()method fromprotectedtopublic. -
Replace any
onRenderPropertiesoverrides with
public void enrichFrontendOptions(Map<String, Object> options). -
Remove any
renderHeadoverrides. -
Remove unused imports.
Remove any ExtJS JavaScript or CSS resources previously added in renderHead.
In the associated properties file(s), remove entries used only by ExtJS JavaScript files.