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.web.analytics; 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.repository.site.Site; 025 026/** 027 * The google analytics provider 028 */ 029public class GoogleAnalyticsProvider extends AbstractWebAnalyticsProvider 030{ 031 /** The analytics GIF URL. */ 032 public static final String GA_GIF_URL = "https://www.google-analytics.com/__utm.gif"; 033 034 /** The analytics API version. */ 035 public static final String GA_VERSION = "5.3.8"; 036 037 /** The domain hash. */ 038 public static final String DOMAIN_HASH = "109627128"; // TODO Really hash the domain name? 039 040 private static final Random _RNG = new Random((long) Math.random() * System.nanoTime()); 041 042 public String getEventImageUri(Site site, String category, String action, String label, int value, boolean usePlaceholderTokens) 043 { 044 String gaWebId = site.getValue("google-web-property-id"); 045 if (StringUtils.isNotBlank(gaWebId)) 046 { 047 String identifier = _getEventIdentifier(category, action, label, value); 048 return _getEventImageUri(gaWebId, identifier, usePlaceholderTokens); 049 } 050 051 return null; 052 } 053 054 /** 055 * Get the event identifier 056 * @param category the event category 057 * @param action the event action 058 * @param label the event label 059 * @param value the event value 060 * @return the event identifier 061 */ 062 protected String _getEventIdentifier(String category, String action, String label, int value) 063 { 064 try 065 { 066 StringBuilder eventId = new StringBuilder(); 067 068 eventId.append("5("); 069 eventId.append(_encodeValue(category)); 070 eventId.append('*').append(_encodeValue(action)); 071 eventId.append('*').append(_encodeValue(label)); 072 eventId.append(')'); 073 if (value > 0) 074 { 075 eventId.append('(').append(value).append(')'); 076 } 077 return eventId.toString(); 078 } 079 catch (URISyntaxException e) 080 { 081 getLogger().error("An error occurred computing the event gif uri", e); 082 } 083 084 return null; 085 } 086 087 /** 088 * Get an event image URI. 089 * @param gaWebId the GA web ID. 090 * @param eventIdentifier the event identifier. 091 * @param usePlaceholderTokens True to use tokens instead of randomly generated values 092 * @return the event image URI. 093 */ 094 protected String _getEventImageUri(String gaWebId, String eventIdentifier, boolean usePlaceholderTokens) 095 { 096 long now = System.currentTimeMillis() / 1000L; 097 098 StringBuilder cookieValue = new StringBuilder(); 099 // UTMA 100 cookieValue.append("__utma=").append(DOMAIN_HASH).append('.').append(usePlaceholderTokens ? RANDOM_NUMBER_TOKEN : _RNG.nextInt(Integer.MAX_VALUE)); 101 cookieValue.append('.').append(now).append('.').append(now).append('.').append(now).append(".1"); 102 // UTMZ 103 cookieValue.append(";+__utmz=").append(DOMAIN_HASH).append('.').append(now); 104 cookieValue.append(".1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none);"); 105 106 StringBuilder uri = new StringBuilder(); 107 108 uri.append(GA_GIF_URL); 109 uri.append("?utmwv=").append(GA_VERSION); 110 uri.append("&utmn=").append(usePlaceholderTokens ? RANDOM_NUMBER_TOKEN : _RNG.nextInt(Integer.MAX_VALUE)); 111 uri.append("&utmt=event"); 112 uri.append("&utme=").append(eventIdentifier); 113 uri.append("&utmcs=UTF-8"); 114 uri.append("&utmje=1"); 115 uri.append("&utmhid=").append(usePlaceholderTokens ? RANDOM_NUMBER_TOKEN : _RNG.nextInt(Integer.MAX_VALUE)); 116 // TODO utmhn with main domain? 117 uri.append("&utmr=-"); 118 uri.append("&utmac=").append(gaWebId); 119 120 // Cookie 121 String encodedCookie = URIUtils.encodeParameter(cookieValue.toString()); 122 uri.append("&utmcc=").append(encodedCookie); 123 124 return uri.toString(); 125 } 126 127 public String getEventLinkCampaignParams(Site site, String campaign, String medium, String source) 128 { 129 StringBuilder linkCampaignParams = new StringBuilder(); 130 linkCampaignParams.append("utm_campaign="); 131 linkCampaignParams.append(campaign); 132 linkCampaignParams.append("&utm_medium="); 133 linkCampaignParams.append(medium); 134 linkCampaignParams.append("&utm_source="); 135 linkCampaignParams.append(source); 136 137 return linkCampaignParams.toString(); 138 } 139}