001/* 002 * Copyright 2023 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.webanalytics.ga; 017 018import java.net.URISyntaxException; 019import java.util.Random; 020 021import org.apache.commons.lang.StringUtils; 022 023import org.ametys.core.util.URIUtils; 024import org.ametys.web.analytics.AbstractWebAnalyticsProvider; 025import org.ametys.web.repository.site.Site; 026 027/** 028 * The google analytics provider 029 */ 030public class GoogleAnalyticsProvider extends AbstractWebAnalyticsProvider 031{ 032 /** The analytics GIF URL. */ 033 public static final String GA_GIF_URL = "https://www.google-analytics.com/__utm.gif"; 034 035 /** The analytics API version. */ 036 public static final String GA_VERSION = "5.3.8"; 037 038 /** The domain hash. */ 039 public static final String DOMAIN_HASH = "109627128"; // TODO Really hash the domain name? 040 041 private static final Random _RNG = new Random((long) Math.random() * System.nanoTime()); 042 043 public String getEventImageUri(Site site, String category, String action, String label, int value, boolean usePlaceholderTokens) 044 { 045 String gaWebId = site.getValue("google-web-property-id"); 046 if (StringUtils.isNotBlank(gaWebId)) 047 { 048 String identifier = _getEventIdentifier(category, action, label, value); 049 return _getEventImageUri(gaWebId, identifier, usePlaceholderTokens); 050 } 051 052 return null; 053 } 054 055 /** 056 * Get the event identifier 057 * @param category the event category 058 * @param action the event action 059 * @param label the event label 060 * @param value the event value 061 * @return the event identifier 062 */ 063 protected String _getEventIdentifier(String category, String action, String label, int value) 064 { 065 try 066 { 067 StringBuilder eventId = new StringBuilder(); 068 069 eventId.append("5("); 070 eventId.append(_encodeValue(category)); 071 eventId.append('*').append(_encodeValue(action)); 072 eventId.append('*').append(_encodeValue(label)); 073 eventId.append(')'); 074 if (value > 0) 075 { 076 eventId.append('(').append(value).append(')'); 077 } 078 return eventId.toString(); 079 } 080 catch (URISyntaxException e) 081 { 082 getLogger().error("An error occurred computing the event gif uri", e); 083 } 084 085 return null; 086 } 087 088 /** 089 * Get an event image URI. 090 * @param gaWebId the GA web ID. 091 * @param eventIdentifier the event identifier. 092 * @param usePlaceholderTokens True to use tokens instead of randomly generated values 093 * @return the event image URI. 094 */ 095 protected String _getEventImageUri(String gaWebId, String eventIdentifier, boolean usePlaceholderTokens) 096 { 097 long now = System.currentTimeMillis() / 1000L; 098 099 StringBuilder cookieValue = new StringBuilder(); 100 // UTMA 101 cookieValue.append("__utma=").append(DOMAIN_HASH).append('.').append(usePlaceholderTokens ? RANDOM_NUMBER_TOKEN : _RNG.nextInt(Integer.MAX_VALUE)); 102 cookieValue.append('.').append(now).append('.').append(now).append('.').append(now).append(".1"); 103 // UTMZ 104 cookieValue.append(";+__utmz=").append(DOMAIN_HASH).append('.').append(now); 105 cookieValue.append(".1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none);"); 106 107 StringBuilder uri = new StringBuilder(); 108 109 uri.append(GA_GIF_URL); 110 uri.append("?utmwv=").append(GA_VERSION); 111 uri.append("&utmn=").append(usePlaceholderTokens ? RANDOM_NUMBER_TOKEN : _RNG.nextInt(Integer.MAX_VALUE)); 112 uri.append("&utmt=event"); 113 uri.append("&utme=").append(eventIdentifier); 114 uri.append("&utmcs=UTF-8"); 115 uri.append("&utmje=1"); 116 uri.append("&utmhid=").append(usePlaceholderTokens ? RANDOM_NUMBER_TOKEN : _RNG.nextInt(Integer.MAX_VALUE)); 117 // TODO utmhn with main domain? 118 uri.append("&utmr=-"); 119 uri.append("&utmac=").append(gaWebId); 120 121 // Cookie 122 String encodedCookie = URIUtils.encodeParameter(cookieValue.toString()); 123 uri.append("&utmcc=").append(encodedCookie); 124 125 return uri.toString(); 126 } 127 128 public String getEventLinkCampaignParams(Site site, String campaign, String medium, String source) 129 { 130 StringBuilder linkCampaignParams = new StringBuilder(); 131 linkCampaignParams.append("utm_campaign="); 132 linkCampaignParams.append(campaign); 133 linkCampaignParams.append("&utm_medium="); 134 linkCampaignParams.append(medium); 135 linkCampaignParams.append("&utm_source="); 136 linkCampaignParams.append(source); 137 138 return linkCampaignParams.toString(); 139 } 140}