Custom Campaign Selection

This feature is available since Bloomreach Experience Manager 13.1.0

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:

  1. Campaign 1: Started at 12th of February and runs until the 28th of February
  2. Campaign 2: Started at 9th of February and runs until the 14th of February
  3. 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.

Did you find this page helpful?
How could this documentation serve you better?
On this page
    Did you find this page helpful?
    How could this documentation serve you better?