This article covers a Bloomreach Experience Manager version 12. There's an updated version available that covers our most recent release.

Public Relevance REST API

Introduction

Goal

Expose a visitor's personal data stored in the Relevance database by enabling the Public Relevance REST API.

Background

The Bloomreach Experience Manager Relevance Module provides an optional Public Relevance REST API which exposes a visitor's personal data stored in the Relevance database. This is one of the requirements to be GDPR-compliant (see GDPR Support more more information).

This page describes how to enable the Public Relevance REST API in your implemantion project and how to extend the API.

Enable Public Relevance REST API

After you have added the Relevance Module to your project, your project's site module will (through the pom dependency hippo-addon-targeting-dependencies-site) automatically pull in the following dependency:

<dependency>
  <groupId>com.onehippo.cms7</groupId>
  <artifactId>hippo-addon-targeting-site-rest</artifactId>
</dependency>

This gives you everything you need to make the Public Relevance REST API available in your application / website. All you need to do is configure the hst:mount nodes below the hosts for which you want to expose the REST API. To be able to serve the personal data of a visitor to be able to be GDPR compliant, you have to configure the REST mounts below every host for which you target visitors: The reason for this is that the visitor cookie is tied to a host in your browser.

Example Relevance REST API Mount Configuration

Assume you have the following HST configuration and you want to add the Relevance REST API to expose the personal data:

/hst:hst:
  /hst:hosts:
    /prod:
      /com:
        /example:
          /www:
            /hst:root:
              jcr:primaryType: hst:mount
              /subsite:
      /org:
        /example:
          /www:
            /hst:root:
              jcr:primaryType: hst:mount
              /subsite:

Above is an example in which you have 2 hosts running 4 channels

  1. www.example.com
  2. www.example.com/subsite
  3. www.example.org
  4. www.example.org/subsite

Now, assume on all channels you are targeting visitors to serve a better experience. For the upcoming GDPR, this means that for all channels you need to be able to serve the personal data you have about a visitor on request of the visitor. The Relevance REST API enables this. You need to decide which URL you want to use to expose the Relevance REST API. Assume you want to expose the personal data of a visitor over

  1. www.example.com/gdpr
  2. www.example.org/gdpr

then the above HST configuration should become:

/hst:hst:
  /hst:hosts:
    /prod:
      /com:
        /example:
          /www:
            /hst:root:
              jcr:primaryType: hst:mount
              /subsite:
                jcr:primaryType: hst:mount
              /gdpr:
                jcr:primaryType: hst:mount
                hst:ismapped: false
                hst:types: rest
                hst:namedpipeline: TargetingRestApiPipeline
      /org:
        /example:
          /www:
            /hst:root:
              jcr:primaryType: hst:mount
              /subsite:
                jcr:primaryType: hst:mount         
              /gdpr:
                jcr:primaryType: hst:mount
                hst:ismapped: false
                hst:types: rest
                hst:namedpipeline: TargetingRestApiPipeline

That is it. By default, the Public Relevance REST API ships with an endpoint /visitorinfo through which you can

  1. Request (GET) the Personal Data about you (the visitor), see Serve Personal Data
  2. Request (DELETE) to be forgotten, see Forget About Me

Extend Public Relevance REST API

In your end project you can add new endpoints or override defaults from the TargetingRestApiPipeline by storing Spring beans below

META-INF/hst-assembly/overrides/addon/com/onehippo/cms7/targeting/restapi

Example Adding an Extra Relevance REST API Endpoint

Below is documented how you can add an extra Relevance REST API endpoint. It is a bit contrived example but serves here just as an example. For a real use case scenarion, if instead of the default /visitorinfo you'd like to serialize the result in a different format or different application type, you can do this by adding an extra REST endpoint serializing the result differently. 

The Example Requirement

Assume you have a third party integration that polls all new visitors of your website for offline data processing / analyzing. Assume you want a REST call to first get all the visitor ids that have a last access time before now and a limit that you can specify, and you want a rest call to get the VisitorInfo for a specific visitor id.  This can be achieved as follows:

In your project's site module, below META-INF/hst-assembly/overrides/addon/com/onehippo/cms7/targeting/restapi add the file (name is free) targeting-site-restapi-extension.xml that contains:

<?xml version="1.0" encoding="UTF-8"?>
<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 id="com.hap.targeting.rest.LatestVisitorsResource" class="com.hap.targeting.rest.LatestVisitorsResource">
    <property name="visitorService" ref="com.onehippo.cms7.targeting.VisitorService"/>
  </bean>

  <bean id="customRestApiResourceProviders" class="org.springframework.beans.factory.config.ListFactoryBean">
    <property name="sourceList">
      <list>
        <bean class="org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider">
          <constructor-arg>
            <ref bean="com.myproject.targeting.rest.LatestVisitorsResource"/>
          </constructor-arg>
        </bean>
      </list>
    </property>
  </bean>
</beans>

And in the java package com.myproject.targeting.rest add:

package com.hap.targeting.rest;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import com.onehippo.cms7.targeting.VisitorInfo;
import com.onehippo.cms7.targeting.VisitorService;

import static javax.ws.rs.core.MediaType.APPLICATION_JSON;

@Path("/visitors")
@Produces(APPLICATION_JSON)
public class VisitorsResource {

    private VisitorService visitorService;
    private final int DEFAULT_LIMIT = 10; 

    public void setVisitorService(final VisitorService visitorService) {
        this.visitorService = visitorService;
    }

    @GET
    @Path("/")
    public List<String> getLatestVisitorsIds(@QueryParam("limit") final int limit) {
        final List<String> latestVisitorsIds = new ArrayList();
        visitorService
                .getLatestVisitors(System.currentTimeMillis(), limit == 0 ? DEFAULT_LIMIT : limit)
                .forEach(visitor -> latestVisitorsIds.add(visitor.getId()));
        return latestVisitorsIds;
    }

    @GET
    @Path("/{visitorId}/")
    @Produces(MediaType.APPLICATION_JSON)
    public VisitorInfo getVisitorDetails(@PathParam("visitorId") final String visitorId) {
            return visitorService.getVisitorInfo(visitorId);
    }

}

With the above changes, you should be able to request (assuming the mount is called 'gdpr')

http://www.example.com/gdpr/visitors

Returning the last 10 visitor ids that accessed the site and then via 

http://www.example.com/gdpr/visitor/{id}

where {id} is one of the visitor ids, you return the visitor info for that visitor (in this case the same data as shown in Serve Personal Data). This example does not take any security (RolesAllowed for example) into account which you most likely want to address in a real implementation.

 

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?