Custom Campaign Selection
Introduction
Goal
Implement a custom heuristic to choose from multiple campaigns running concurrently.
Multiple Campaigns Running Concurrently
If, at a certain point in time, there are multiple campaigns running concurrently for the same channel, then by default the campaign that has the shortest running period will be served to visitors of that channel. For example, if today it is the 13th of February, and the following three campaigns are started but not yet stopped:
- Campaign 1: Started at 12th of February and runs until the 28th of February
- Campaign 2: Started at 9th of February and runs until the 14th of February
- Campaign 3: Started at 7th of February and runs until the 28th of February
Then Campaign 2 will be served because it has started, has not yet stopped, and has the shortest running period. This is how the default heuristic to choose between multiple campaigns running concurrently is implemented. Developers of end projects can however provide a different heuristic which can be injected to override the default heuristic. If, for example, you have a requirement to serve a different campaign, say, based on the location of the visitor (e.g. serve different campaigns in the US and in Europe), this can be achieved in this way.
Implement Custom Campaign Selection
Per HST Site webapp, one single custom campaign selector can be injected via providing a HstSiteProvider implementation and wiring it as a Spring bean in an XML file at:
src/main/resources/META-INF/hst-assembly/overrides
For example in custom-hst-site-provider.xml you can have:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd"> <bean class="com.myproject.campaigns.LocationBasedHstWebSiteProvider"/> </beans>
The LocationBasedHstWebSiteProvider class must implement org.hippoecm.hst.container.site.HstSiteProvider. For example:
import java.util.ArrayList; import java.util.List; import java.util.Map; import com.onehippo.cms7.services.wpm.project.Project; import com.onehippo.cms7.services.wpm.project.ProjectService; import com.onehippo.cms7.services.wpm.project.ProjectState; import org.hippoecm.hst.configuration.site.HstSite; import org.hippoecm.hst.container.site.HstSiteProvider; import org.hippoecm.hst.core.request.HstRequestContext; import org.onehippo.cms7.services.HippoServiceRegistry; public class LocationBasedHstWebSiteProvider implements HstSiteProvider { private final ProjectService projectService; public LocationBasedHstWebSiteProvider() { projectService = HippoServiceRegistry.getService(ProjectService.class); } @Override public HstSite getHstSite(final HstSite core, final Map<String, HstSite> branches, final HstRequestContext requestContext) { if (branches.isEmpty()) { return core; } final List<Project> eligibleCampaigns = new ArrayList<>(); for (Project project : projectService.getProjects().values()) { if (ProjectState.RUNNING.equals(project.getState())) { eligibleCampaigns.add(project); } } final String ip = HstRequestUtils .getFarthestRemoteAddr(requestContext.getServletRequest()); // TODO implement your own geoIpService returning a Location object final Location location = geoIPService.getLocation(ip); final String contentinentCode = location.getContinentCode(); for (Project eligibleCampaign : eligibleCampaigns) { // if there is a continent match with project name, serve that campaign if (contentinentCode.equals(eligibleCampaign.getName())) { final HstSite hstSite = branches.get(eligibleCampaign.getId()); if (hstSite == null) { return core; } return hstSite; } } // no continent match....serve either some eligibleCampaign or return core return core; } }
The above logic can serve a different campaign per continent assuming you implement your own geoIpService returning a Location object based on the IP address of the visitor.