Skip to content

Commit

Permalink
[CST-18963] Adds matomo enricher related to the cookie that identifie…
Browse files Browse the repository at this point in the history
…s a visitor
  • Loading branch information
vins01-4science committed Feb 21, 2025
1 parent 5497013 commit 611f353
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.matomo.factory;

import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import jakarta.servlet.http.Cookie;
import org.apache.commons.lang3.StringUtils;
import org.dspace.matomo.model.MatomoRequestDetails;
import org.dspace.usage.UsageEvent;

/**
* Enricher that extracts any {@code _pk_id} cookie sent inside the request
* to track the same {@code id} used to track interaction on the angular side. <br>
* The cookie will have a similar format: {@code _pk_id.1.1fff=3225aebdb98b13f9.1740076196.} <br>
* Where only the first 16 hexadecimal characters represents the id for Matomo.
*
* @author Vincenzo Mecca (vins01-4science - vincenzo.mecca at 4science.com)
**/
public class MatomoRequestCookieIdentifierEnricher implements MatomoRequestDetailsEnricher {

static final String _PK_ID_NAME = "_pk_id";
static final Pattern _pk_id = Pattern.compile("(^([a-f]|[0-9]){16})");

@Override
public MatomoRequestDetails enrich(UsageEvent usageEvent, MatomoRequestDetails matomoRequestDetails) {
Cookie[] cookies = usageEvent.getRequest().getCookies();
if (cookies == null || cookies.length == 0) {
return matomoRequestDetails;
}
Optional<String> pk_id =
Stream.of(cookies)
.filter(cookie -> cookie.getName().startsWith(_PK_ID_NAME))
.map(cookie -> _pk_id.matcher(cookie.getValue()))
.filter(Matcher::find)
.findFirst()
.map(Matcher::group);
return pk_id.filter(StringUtils::isNotEmpty)
.map(id -> matomoRequestDetails.addParameter("_id", id))
.orElse(matomoRequestDetails);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,6 @@
**/
public class MatomoRequestDetailsEnricherFactory {

/*
// Matomo Custom Variable for OAI-PMH ID tracking
Gson gson = new Gson();
Map<String, String[]> jsonMatomoCustomVars = new HashMap<>();
String[] oaipmhID =
new String[]{"oaipmhID", "oai:" + dspaceHostName + ":" + item.getHandle()};
jsonMatomoCustomVars.put("1", oaipmhID);
builder.addParameter("cvar", gson.toJson(jsonMatomoCustomVars));
*/


private MatomoRequestDetailsEnricherFactory() {}

private static final Logger log = LogManager.getLogger(MatomoRequestDetailsEnricherFactory.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
package org.dspace.matomo.factory;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.matomo.model.MatomoRequestDetails;
import org.dspace.service.ClientInfoService;
import org.dspace.usage.UsageEvent;
Expand All @@ -22,7 +20,6 @@
**/
public class MatomoRequestIpAddressEnricher implements MatomoRequestDetailsEnricher {

private static final Logger log = LogManager.getLogger(MatomoRequestIpAddressEnricher.class);
private final ClientInfoService clientInfoService;

public MatomoRequestIpAddressEnricher(@Autowired ClientInfoService clientInfoService) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.Locale;
import java.util.UUID;

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import org.dspace.AbstractUnitTest;
import org.dspace.content.Bitstream;
Expand All @@ -26,6 +27,7 @@
import org.dspace.content.service.DSpaceObjectService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.matomo.factory.MatomoRequestCookieIdentifierEnricher;
import org.dspace.matomo.factory.MatomoRequestCountryEnricher;
import org.dspace.matomo.factory.MatomoRequestDetailsEnricher;
import org.dspace.matomo.factory.MatomoRequestDetailsEnricherFactory;
Expand Down Expand Up @@ -322,4 +324,78 @@ public void testDownloadEnricher() {

}

@Test
public void testMatomoCookieIdentifierEnricher() {
MatomoRequestCookieIdentifierEnricher cookieEnricher = new MatomoRequestCookieIdentifierEnricher();
enrichers.add(cookieEnricher);

Cookie cookie = Mockito.mock(Cookie.class);
Mockito.when(cookie.getName()).thenReturn("_pk_id.1.1fff");
Mockito.when(cookie.getValue()).thenReturn("3225aebdb98b13f9.1740076196.");

Mockito.when(request.getCookies()).thenReturn(new Cookie[] { cookie });
Mockito.when(usageEvent.getRequest()).thenReturn(request);

MatomoRequestDetails requestDetails = builder.build(usageEvent);
assertThat(
requestDetails.parameters,
Matchers.hasEntry(
Matchers.is("_id"),
Matchers.is("3225aebdb98b13f9")
)
);

Mockito.when(request.getCookies()).thenReturn(null);
requestDetails = builder.build(usageEvent);
assertThat(
requestDetails.parameters,
Matchers.not(
Matchers.hasEntry(
Matchers.is("_id"),
Matchers.any(String.class)
)
)
);

Mockito.when(request.getCookies()).thenReturn(new Cookie[] { });
requestDetails = builder.build(usageEvent);
assertThat(
requestDetails.parameters,
Matchers.not(
Matchers.hasEntry(
Matchers.is("_id"),
Matchers.any(String.class)
)
)
);

Mockito.when(cookie.getName()).thenReturn("_pk_id.1.1fff");
Mockito.when(cookie.getValue()).thenReturn("wrongvalue.1.2");
Mockito.when(request.getCookies()).thenReturn(new Cookie[] { cookie });
requestDetails = builder.build(usageEvent);
assertThat(
requestDetails.parameters,
Matchers.not(
Matchers.hasEntry(
Matchers.is("_id"),
Matchers.any(String.class)
)
)
);

Mockito.when(cookie.getName()).thenReturn("_pk_id.1.1fff");
Mockito.when(cookie.getValue()).thenReturn("");
Mockito.when(request.getCookies()).thenReturn(new Cookie[] { cookie });
requestDetails = builder.build(usageEvent);
assertThat(
requestDetails.parameters,
Matchers.not(
Matchers.hasEntry(
Matchers.is("_id"),
Matchers.any(String.class)
)
)
);
}

}
6 changes: 4 additions & 2 deletions dspace/config/modules/matomo.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#---------------------------------------------------------------#

# Enables matomo integration mapped inside the MatomoEventListener
matomo.enabled = true
matomo.enabled = false
# Configured `siteid` inside the matomo dashboard
matomo.request.siteid = 1

Expand All @@ -20,11 +20,13 @@ matomo.request.siteid = 1
#---------------------------------------------------------------#
# The tracking endpoint of matomo
matomo.default-client.baseurl = http://localhost:8081/matomo.php
# The client-token configured inside the matomo instance
# The auth-token configured inside the matomo instance
matomo.default-client.token =

#---------------------------------------------------------------#
#------------------ASYNC CLIENT CONFIGURATION-------------------#
#---------------------------------------------------------------#
# The tracking endpoint of matomo
matomo.async-client.baseurl = http://localhost:8081/matomo.php
# The auth-token configured inside the matomo instance
matomo.async-client.token =
1 change: 1 addition & 0 deletions dspace/config/spring/rest/matomo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<bean id="downloadEnricher" class="org.dspace.matomo.factory.MatomoRequestDetailsEnricherFactory" factory-method="downloadEnricher"/>
<bean id="ipEnricher" class="org.dspace.matomo.factory.MatomoRequestIpAddressEnricher"/>
<bean id="requestCountryEnricher" class="org.dspace.matomo.factory.MatomoRequestCountryEnricher"/>
<bean id="cookieIdEnricher" class="org.dspace.matomo.factory.MatomoRequestCookieIdentifierEnricher"/>
</list>
</constructor-arg>
<constructor-arg name="siteId" value="${matomo.request.siteid:}"/>
Expand Down

0 comments on commit 611f353

Please sign in to comment.