├── src ├── main │ └── java │ │ └── com │ │ └── brsanthu │ │ └── googleanalytics │ │ ├── logger │ │ ├── Logger.java │ │ ├── LoggerFactory.java │ │ └── DefaultLoggerFactory.java │ │ ├── httpclient │ │ ├── NameValuePair.java │ │ ├── HttpClient.java │ │ ├── HttpResponse.java │ │ ├── HttpBatchResponse.java │ │ ├── HttpBatchRequest.java │ │ ├── BatchUrlEncodedFormEntity.java │ │ ├── HttpRequest.java │ │ └── ApacheHttpClientImpl.java │ │ ├── GoogleAnalyticsStats.java │ │ ├── discovery │ │ ├── RequestParameterDiscoverer.java │ │ ├── AwtRequestParameterDiscoverer.java │ │ └── DefaultRequestParameterDiscoverer.java │ │ ├── GoogleAnalyticsExecutor.java │ │ ├── internal │ │ ├── Constants.java │ │ ├── GoogleAnalyticsThreadFactory.java │ │ ├── GaUtils.java │ │ ├── ParameterGetterSetterGenerator.java │ │ ├── GoogleAnalyticsStatsImpl.java │ │ └── GoogleAnalyticsImpl.java │ │ ├── GoogleAnalyticsException.java │ │ ├── GoogleAnalytics.java │ │ ├── request │ │ ├── PageViewHit.java │ │ ├── GoogleAnalyticsResponse.java │ │ ├── ScreenViewHit.java │ │ ├── ExceptionHit.java │ │ ├── SocialHit.java │ │ ├── EventHit.java │ │ ├── GoogleAnalyticsParameter.java │ │ ├── ItemHit.java │ │ ├── TransactionHit.java │ │ ├── TimingHit.java │ │ └── DefaultRequest.java │ │ ├── GoogleAnalyticsBuilder.java │ │ └── GoogleAnalyticsConfig.java └── test │ └── java │ └── com │ └── brsanthu │ └── googleanalytics │ ├── EventHitTest.java │ ├── GoogleAnalyticsBatchTest.java │ ├── GoogleAnalyticsConfigTest.java │ ├── GoogleAnalyticsRequestTest.java │ ├── DefaultRequestParameterDiscovererTest.java │ ├── HitTypesTest.java │ ├── AwtRequestParameterDiscovererTest.java │ ├── GaUtilsTest.java │ ├── GoogleAnalyticsTest.java │ └── GoogleAnalyticsParameterTest.java ├── .gitignore ├── README.md └── pom.xml /src/main/java/com/brsanthu/googleanalytics/logger/Logger.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.logger; 2 | 3 | public interface Logger { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/logger/LoggerFactory.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.logger; 2 | 3 | public interface LoggerFactory { 4 | Logger getLogger(Class cls); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/httpclient/NameValuePair.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.httpclient; 2 | 3 | public interface NameValuePair { 4 | 5 | String getName(); 6 | 7 | String getValue(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/logger/DefaultLoggerFactory.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.logger; 2 | 3 | public class DefaultLoggerFactory implements LoggerFactory { 4 | 5 | @Override 6 | public Logger getLogger(Class cls) { 7 | return null; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/httpclient/HttpClient.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.httpclient; 2 | 3 | public interface HttpClient extends AutoCloseable { 4 | HttpResponse post(HttpRequest req); 5 | 6 | boolean isBatchSupported(); 7 | 8 | HttpBatchResponse postBatch(HttpBatchRequest req); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/httpclient/HttpResponse.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.httpclient; 2 | 3 | public class HttpResponse { 4 | 5 | private int statusCode; 6 | 7 | public int getStatusCode() { 8 | return statusCode; 9 | } 10 | 11 | public HttpResponse setStatusCode(int statusCode) { 12 | this.statusCode = statusCode; 13 | return this; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/httpclient/HttpBatchResponse.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.httpclient; 2 | 3 | public class HttpBatchResponse { 4 | private int statusCode; 5 | 6 | public int getStatusCode() { 7 | return statusCode; 8 | } 9 | 10 | public HttpBatchResponse setStatusCode(int statusCode) { 11 | this.statusCode = statusCode; 12 | return this; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsStats.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics; 2 | 3 | public interface GoogleAnalyticsStats { 4 | 5 | long getPageViewHits(); 6 | 7 | long getEventHits(); 8 | 9 | long getScreenViewHits(); 10 | 11 | long getItemHits(); 12 | 13 | long getTransactionHits(); 14 | 15 | long getTimingHits(); 16 | 17 | long getSocialHits(); 18 | 19 | long getExceptionHits(); 20 | } -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/discovery/RequestParameterDiscoverer.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.discovery; 2 | 3 | import com.brsanthu.googleanalytics.GoogleAnalyticsConfig; 4 | import com.brsanthu.googleanalytics.request.DefaultRequest; 5 | 6 | /** 7 | * Mechanism to discover some default request parameters. 8 | */ 9 | public interface RequestParameterDiscoverer { 10 | 11 | public DefaultRequest discoverParameters(GoogleAnalyticsConfig config, DefaultRequest request); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsExecutor.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics; 2 | 3 | import java.util.concurrent.Future; 4 | 5 | import com.brsanthu.googleanalytics.request.GoogleAnalyticsRequest; 6 | import com.brsanthu.googleanalytics.request.GoogleAnalyticsResponse; 7 | 8 | public interface GoogleAnalyticsExecutor { 9 | GoogleAnalyticsResponse post(GoogleAnalyticsRequest request); 10 | 11 | Future postAsync(GoogleAnalyticsRequest request); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/internal/Constants.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.internal; 2 | 3 | public interface Constants { 4 | String HIT_SCREENVIEW = "screenview"; 5 | String HIT_PAGEVIEW = "pageview"; 6 | String HIT_EVENT = "event"; 7 | String HIT_ITEM = "item"; 8 | String HIT_TXN = "transaction"; 9 | String HIT_SOCIAL = "social"; 10 | String HIT_TIMING = "timing"; 11 | String HIT_EXCEPTION = "exception"; 12 | 13 | String TYPE_INTEGER = "integer"; 14 | String TYPE_TEXT = "text"; 15 | String TYPE_BOOLEAN = "boolean"; 16 | String TYPE_CURRENCY = "currency"; 17 | 18 | String TEST_TRACKING_ID = "UA-612100-12"; 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/com/brsanthu/googleanalytics/EventHitTest.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | import com.brsanthu.googleanalytics.request.EventHit; 8 | 9 | public class EventHitTest { 10 | 11 | @Test 12 | public void testEventHit() throws Exception { 13 | EventHit eventHit = new EventHit("eventCategory", "eventAction", "eventLabel", 10); 14 | assertEquals("eventCategory", eventHit.eventCategory()); 15 | assertEquals("eventAction", eventHit.eventAction()); 16 | assertEquals("eventLabel", eventHit.eventLabel()); 17 | assertEquals(new Integer(10), eventHit.eventValue()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/httpclient/HttpBatchRequest.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.httpclient; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class HttpBatchRequest { 7 | private String url; 8 | private List requests = new ArrayList<>(); 9 | 10 | public HttpBatchRequest addRequest(HttpRequest request) { 11 | requests.add(request); 12 | return this; 13 | } 14 | 15 | public List getRequests() { 16 | return requests; 17 | } 18 | 19 | public HttpBatchRequest setRequests(List requests) { 20 | this.requests = requests; 21 | return this; 22 | } 23 | 24 | public String getUrl() { 25 | return url; 26 | } 27 | 28 | public HttpBatchRequest setUrl(String url) { 29 | this.url = url; 30 | return this; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsBatchTest.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics; 2 | 3 | import static com.brsanthu.googleanalytics.internal.Constants.TEST_TRACKING_ID; 4 | 5 | import java.util.stream.IntStream; 6 | 7 | import org.junit.BeforeClass; 8 | import org.junit.Test; 9 | 10 | public class GoogleAnalyticsBatchTest { 11 | 12 | private static GoogleAnalytics ga = null; 13 | 14 | @BeforeClass 15 | public static void setup() { 16 | ga = GoogleAnalytics.builder().withTrackingId(TEST_TRACKING_ID).withAppName("Junit Test").withAppVersion("1.0.0") 17 | .withConfig(new GoogleAnalyticsConfig().setBatchingEnabled(true).setBatchSize(10)).build(); 18 | } 19 | 20 | @Test 21 | public void testPageView() throws Exception { 22 | IntStream.range(0, 50).forEach(i -> { 23 | ga.pageView("http://www.google.com", "Search").send(); 24 | }); 25 | } 26 | } -------------------------------------------------------------------------------- /src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsConfigTest.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | public class GoogleAnalyticsConfigTest { 8 | 9 | @Test 10 | public void testDefaultConfig() throws Exception { 11 | GoogleAnalyticsConfig config = new GoogleAnalyticsConfig(); 12 | assertEquals("googleanalyticsjava-thread-{0}", config.getThreadNameFormat()); 13 | assertEquals(0, config.getMinThreads()); 14 | assertEquals(5, config.getMaxThreads()); 15 | assertEquals("http://www.google-analytics.com/collect", config.getHttpUrl()); 16 | assertEquals("https://www.google-analytics.com/collect", config.getHttpsUrl()); 17 | assertEquals(80, config.getProxyPort()); 18 | assertEquals(true, config.isDiscoverRequestParameters()); 19 | assertEquals(false, config.isGatherStats()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/internal/GoogleAnalyticsThreadFactory.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.internal; 2 | 3 | import java.text.MessageFormat; 4 | import java.util.concurrent.ThreadFactory; 5 | import java.util.concurrent.atomic.AtomicInteger; 6 | 7 | public class GoogleAnalyticsThreadFactory implements ThreadFactory { 8 | private final AtomicInteger threadNumber = new AtomicInteger(1); 9 | private String threadNameFormat = null; 10 | 11 | public GoogleAnalyticsThreadFactory(String threadNameFormat) { 12 | this.threadNameFormat = threadNameFormat; 13 | } 14 | 15 | @Override 16 | public Thread newThread(Runnable r) { 17 | Thread thread = new Thread(Thread.currentThread().getThreadGroup(), r, MessageFormat.format(threadNameFormat, threadNumber.getAndIncrement()), 18 | 0); 19 | thread.setDaemon(true); 20 | thread.setPriority(Thread.MIN_PRIORITY); 21 | return thread; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsRequestTest.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | import com.brsanthu.googleanalytics.request.PageViewHit; 8 | 9 | public class GoogleAnalyticsRequestTest { 10 | 11 | @Test 12 | public void testRequestSetterGetter() throws Exception { 13 | PageViewHit request = new PageViewHit(); 14 | 15 | assertEquals("1.2.3.4", request.userIp("1.2.3.4").userIp()); 16 | assertEquals("Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14", 17 | request.userAgent("Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14").userAgent()); 18 | } 19 | 20 | @Test 21 | public void testExperimentArgs() throws Exception { 22 | PageViewHit pageViewHit = new PageViewHit().experimentId("1234567890").experimentVariant("some variation"); 23 | assertEquals("1234567890", pageViewHit.experimentId()); 24 | assertEquals("some variation", pageViewHit.experimentVariant()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | 8 | META-INF/ 9 | 10 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 11 | hs_err_pid* 12 | 13 | # Eclipse Core 14 | 15 | .classpath 16 | .project 17 | .settings/ 18 | .metadata/ 19 | .recommenders/ 20 | run-* 21 | 22 | # Ignore build artfacts at all sub folder level 23 | target/ 24 | bin/ 25 | src/test/resources/run-* 26 | 27 | # Locally stored "Eclipse launch configurations" 28 | *.launch 29 | 30 | # Eclipse CDT-specific 31 | .cproject 32 | 33 | ## IntelliJ 34 | *.iml 35 | .idea/ 36 | 37 | # Java annotation processor (APT) 38 | .factorypath 39 | 40 | # PDT-specific 41 | .buildpath 42 | 43 | # sbteclipse plugin 44 | .target 45 | 46 | # TeXlipse plugin 47 | .texlipse 48 | 49 | # STS (Spring Tool Suite) 50 | .springBeans 51 | 52 | #Netbeans 53 | nbactions.xml 54 | 55 | #Mac finder files 56 | .DS_Store 57 | 58 | #node js 59 | node_modules/ 60 | 61 | #JRebel files 62 | rebel.xml 63 | .rebel.xml.bak 64 | 65 | nohup.out 66 | 67 | core-search-service 68 | core-dns-service 69 | /.gitignore 70 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/httpclient/BatchUrlEncodedFormEntity.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.httpclient; 2 | 3 | import java.nio.charset.StandardCharsets; 4 | import java.util.List; 5 | 6 | import org.apache.http.NameValuePair; 7 | import org.apache.http.client.utils.URLEncodedUtils; 8 | import org.apache.http.entity.ContentType; 9 | import org.apache.http.entity.StringEntity; 10 | 11 | public class BatchUrlEncodedFormEntity extends StringEntity { 12 | 13 | public BatchUrlEncodedFormEntity(List> parameters) { 14 | super(constructCombinedEntityString(parameters), ContentType.create(URLEncodedUtils.CONTENT_TYPE)); 15 | } 16 | 17 | private static String constructCombinedEntityString(final List> parameters) { 18 | StringBuilder builder = new StringBuilder(); 19 | 20 | for (List param : parameters) { 21 | builder.append(URLEncodedUtils.format(param, StandardCharsets.UTF_8)); 22 | builder.append("\r\n"); 23 | } 24 | 25 | return builder.toString(); 26 | } 27 | } -------------------------------------------------------------------------------- /src/test/java/com/brsanthu/googleanalytics/DefaultRequestParameterDiscovererTest.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics; 2 | 3 | import static org.junit.Assert.assertNotNull; 4 | import static org.junit.Assert.assertNull; 5 | 6 | import org.junit.Test; 7 | 8 | import com.brsanthu.googleanalytics.discovery.DefaultRequestParameterDiscoverer; 9 | import com.brsanthu.googleanalytics.request.DefaultRequest; 10 | 11 | public class DefaultRequestParameterDiscovererTest { 12 | 13 | @Test 14 | public void testDiscoverParameters() throws Exception { 15 | DefaultRequestParameterDiscoverer discoverer = new DefaultRequestParameterDiscoverer(); 16 | DefaultRequest request = new DefaultRequest(); 17 | 18 | GoogleAnalyticsConfig config = new GoogleAnalyticsConfig(); 19 | 20 | assertNull(config.getUserAgent()); 21 | assertNull(request.userLanguage()); 22 | assertNull(request.documentEncoding()); 23 | 24 | discoverer.discoverParameters(config, request); 25 | 26 | assertNotNull(config.getUserAgent()); 27 | assertNotNull(request.userLanguage()); 28 | assertNotNull(request.documentEncoding()); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/internal/GaUtils.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.internal; 2 | 3 | public class GaUtils { 4 | public static boolean isNotEmpty(String value) { 5 | return !isEmpty(value); 6 | } 7 | 8 | public static boolean isEmpty(String value) { 9 | return value == null || value.trim().length() == 0; 10 | } 11 | 12 | public static StringBuilder appendSystemProperty(StringBuilder sb, String property) { 13 | String value = System.getProperty(property); 14 | if (isNotEmpty(value)) { 15 | if (isNotEmpty(sb.toString())) { 16 | sb.append("/"); 17 | } 18 | sb.append(value); 19 | } 20 | 21 | return sb; 22 | } 23 | 24 | @SafeVarargs 25 | public static T firstNotNull(T... values) { 26 | if (values != null) { 27 | for (T value : values) { 28 | if (value != null) { 29 | return value; 30 | } 31 | } 32 | } 33 | 34 | return null; 35 | } 36 | 37 | public static boolean isBlank(String string) { 38 | return string == null || string.trim().length() == 0; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/com/brsanthu/googleanalytics/HitTypesTest.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | import com.brsanthu.googleanalytics.request.EventHit; 8 | import com.brsanthu.googleanalytics.request.ExceptionHit; 9 | import com.brsanthu.googleanalytics.request.ItemHit; 10 | import com.brsanthu.googleanalytics.request.PageViewHit; 11 | import com.brsanthu.googleanalytics.request.ScreenViewHit; 12 | import com.brsanthu.googleanalytics.request.SocialHit; 13 | import com.brsanthu.googleanalytics.request.TimingHit; 14 | import com.brsanthu.googleanalytics.request.TransactionHit; 15 | 16 | public class HitTypesTest { 17 | 18 | @Test 19 | public void testHitTypes() throws Exception { 20 | assertEquals("item", new ItemHit().hitType()); 21 | assertEquals("screenview", new ScreenViewHit().hitType()); 22 | assertEquals("event", new EventHit().hitType()); 23 | assertEquals("exception", new ExceptionHit().hitType()); 24 | assertEquals("pageview", new PageViewHit().hitType()); 25 | assertEquals("social", new SocialHit().hitType()); 26 | assertEquals("timing", new TimingHit().hitType()); 27 | assertEquals("transaction", new TransactionHit().hitType()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/com/brsanthu/googleanalytics/AwtRequestParameterDiscovererTest.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics; 2 | 3 | import static org.junit.Assert.assertNotNull; 4 | import static org.junit.Assert.assertNull; 5 | 6 | import org.junit.Test; 7 | 8 | import com.brsanthu.googleanalytics.discovery.AwtRequestParameterDiscoverer; 9 | import com.brsanthu.googleanalytics.request.DefaultRequest; 10 | 11 | public class AwtRequestParameterDiscovererTest { 12 | 13 | @Test 14 | public void testDiscoverParameters() throws Exception { 15 | AwtRequestParameterDiscoverer discoverer = new AwtRequestParameterDiscoverer(); 16 | DefaultRequest request = new DefaultRequest(); 17 | 18 | GoogleAnalyticsConfig config = new GoogleAnalyticsConfig(); 19 | 20 | assertNull(config.getUserAgent()); 21 | assertNull(request.userLanguage()); 22 | assertNull(request.documentEncoding()); 23 | assertNull(request.screenColors()); 24 | assertNull(request.screenResolution()); 25 | 26 | discoverer.discoverParameters(config, request); 27 | 28 | assertNotNull(config.getUserAgent()); 29 | assertNotNull(request.userLanguage()); 30 | assertNotNull(request.documentEncoding()); 31 | assertNotNull(request.screenColors()); 32 | assertNotNull(request.screenResolution()); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | package com.brsanthu.googleanalytics; 16 | 17 | /** 18 | * Any exception thrown (usually due to validation), it would be of this type. 19 | * 20 | * @author Santhosh Kumar 21 | */ 22 | public class GoogleAnalyticsException extends RuntimeException { 23 | 24 | private static final long serialVersionUID = 1L; 25 | 26 | public GoogleAnalyticsException() { 27 | super(); 28 | } 29 | 30 | public GoogleAnalyticsException(String message, Throwable cause) { 31 | super(message, cause); 32 | } 33 | 34 | public GoogleAnalyticsException(String message) { 35 | super(message); 36 | } 37 | 38 | public GoogleAnalyticsException(Throwable cause) { 39 | super(cause); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/httpclient/HttpRequest.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.httpclient; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class HttpRequest { 7 | private String contentType; 8 | private String method; 9 | private String url; 10 | private Map bodyParams = new HashMap<>(); 11 | 12 | public HttpRequest(String url) { 13 | this.setUrl(url); 14 | } 15 | 16 | public HttpRequest post() { 17 | setMethod("POST"); 18 | return this; 19 | } 20 | 21 | public HttpRequest addBodyParam(String key, String value) { 22 | bodyParams.put(key, value); 23 | return this; 24 | } 25 | 26 | public Map getBodyParams() { 27 | return bodyParams; 28 | } 29 | 30 | public String getContentType() { 31 | return contentType; 32 | } 33 | 34 | public HttpRequest setContentType(String contentType) { 35 | this.contentType = contentType; 36 | return this; 37 | } 38 | 39 | public String getMethod() { 40 | return method; 41 | } 42 | 43 | public HttpRequest setMethod(String method) { 44 | this.method = method; 45 | return this; 46 | } 47 | 48 | public String getUrl() { 49 | return url; 50 | } 51 | 52 | public HttpRequest setUrl(String url) { 53 | this.url = url; 54 | return this; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/com/brsanthu/googleanalytics/GaUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | import com.brsanthu.googleanalytics.internal.GaUtils; 8 | 9 | public class GaUtilsTest { 10 | 11 | @Test 12 | public void testIsEmpty() throws Exception { 13 | assertEquals(true, GaUtils.isEmpty(null)); 14 | assertEquals(true, GaUtils.isEmpty("")); 15 | assertEquals(true, GaUtils.isEmpty(" ")); 16 | assertEquals(false, GaUtils.isEmpty("value")); 17 | assertEquals(false, GaUtils.isEmpty(" value ")); 18 | } 19 | 20 | @Test 21 | public void isNotEmpty() throws Exception { 22 | assertEquals(false, GaUtils.isNotEmpty(null)); 23 | assertEquals(false, GaUtils.isNotEmpty("")); 24 | assertEquals(false, GaUtils.isNotEmpty(" ")); 25 | assertEquals(true, GaUtils.isNotEmpty("value")); 26 | assertEquals(true, GaUtils.isNotEmpty(" value ")); 27 | } 28 | 29 | @Test 30 | public void testAppendSystemProperty() throws Exception { 31 | System.setProperty("test", "test"); 32 | assertEquals("", GaUtils.appendSystemProperty(new StringBuilder(), "nonexistent").toString()); 33 | assertEquals("test", GaUtils.appendSystemProperty(new StringBuilder(), "test").toString()); 34 | assertEquals("foo/test", GaUtils.appendSystemProperty(new StringBuilder("foo"), "test").toString()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/GoogleAnalytics.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics; 2 | 3 | import com.brsanthu.googleanalytics.request.EventHit; 4 | import com.brsanthu.googleanalytics.request.ExceptionHit; 5 | import com.brsanthu.googleanalytics.request.ItemHit; 6 | import com.brsanthu.googleanalytics.request.PageViewHit; 7 | import com.brsanthu.googleanalytics.request.ScreenViewHit; 8 | import com.brsanthu.googleanalytics.request.SocialHit; 9 | import com.brsanthu.googleanalytics.request.TimingHit; 10 | import com.brsanthu.googleanalytics.request.TransactionHit; 11 | 12 | public interface GoogleAnalytics extends AutoCloseable { 13 | 14 | EventHit event(); 15 | 16 | ExceptionHit exception(); 17 | 18 | ItemHit item(); 19 | 20 | PageViewHit pageView(); 21 | 22 | PageViewHit pageView(String url, String title); 23 | 24 | PageViewHit pageView(String url, String title, String description); 25 | 26 | ScreenViewHit screenView(); 27 | 28 | ScreenViewHit screenView(String appName, String screenName); 29 | 30 | SocialHit social(); 31 | 32 | SocialHit social(String socialNetwork, String socialAction, String socialTarget); 33 | 34 | TimingHit timing(); 35 | 36 | TransactionHit transaction(); 37 | 38 | GoogleAnalyticsStats getStats(); 39 | 40 | GoogleAnalyticsConfig getConfig(); 41 | 42 | void ifEnabled(Runnable runnable); 43 | 44 | void resetStats(); 45 | 46 | static GoogleAnalyticsBuilder builder() { 47 | return new GoogleAnalyticsBuilder(); 48 | } 49 | 50 | void flush(); 51 | } -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/internal/ParameterGetterSetterGenerator.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.internal; 2 | 3 | import com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter; 4 | 5 | public class ParameterGetterSetterGenerator { 6 | 7 | public static void main(String[] args) { 8 | GoogleAnalyticsParameter[] enumConstants = GoogleAnalyticsParameter.class.getEnumConstants(); 9 | for (GoogleAnalyticsParameter parameter : enumConstants) { 10 | String methodName = null;// CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, parameter.toString()); 11 | String constName = parameter.toString(); 12 | 13 | String type = "String"; 14 | 15 | if (parameter.getType().equalsIgnoreCase("integer")) { 16 | type = "Integer"; 17 | 18 | } else if (parameter.getType().equalsIgnoreCase("boolean")) { 19 | type = "Boolean"; 20 | 21 | } else if (parameter.getType().equalsIgnoreCase("currency")) { 22 | type = "Double"; 23 | } 24 | 25 | System.out.println("public T " + methodName + "(" + type + " value) {"); 26 | System.out.println(" set" + type + "(" + constName + ", value);"); 27 | System.out.println(" return (T) this;"); 28 | System.out.println("}"); 29 | 30 | System.out.println("public " + type + " " + methodName + "() {"); 31 | System.out.println(" return get" + type + "(" + constName + ");"); 32 | System.out.println("}"); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/request/PageViewHit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | package com.brsanthu.googleanalytics.request; 15 | 16 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_PAGEVIEW; 17 | 18 | /** 19 | * GA request to track a typical web page view 20 | * 21 | *

22 | * For more information, see 23 | * GA Parameters 24 | * Reference 25 | *

26 | * 27 | * @author Santhosh Kumar 28 | */ 29 | public class PageViewHit extends GoogleAnalyticsRequest { 30 | public PageViewHit() { 31 | this(null, null, null); 32 | } 33 | 34 | public PageViewHit(String url, String title) { 35 | this(url, title, null); 36 | } 37 | 38 | public PageViewHit(String url, String title, String description) { 39 | super(HIT_PAGEVIEW); 40 | documentUrl(url); 41 | documentTitle(title); 42 | contentDescription(description); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/request/GoogleAnalyticsResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | package com.brsanthu.googleanalytics.request; 15 | 16 | import java.util.Map; 17 | 18 | /** 19 | * Response for GA tracking request. 20 | * 21 | * @author Santhosh Kumar 22 | */ 23 | public class GoogleAnalyticsResponse { 24 | private int statusCode = 200; 25 | private Map requestParams = null; 26 | 27 | public Map getRequestParams() { 28 | return requestParams; 29 | } 30 | 31 | public void setRequestParams(Map postedParms) { 32 | this.requestParams = postedParms; 33 | } 34 | 35 | public void setStatusCode(int statusCode) { 36 | this.statusCode = statusCode; 37 | } 38 | 39 | public int getStatusCode() { 40 | return statusCode; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | StringBuilder builder = new StringBuilder(); 46 | builder.append("Response [statusCode="); 47 | builder.append(statusCode); 48 | builder.append("]"); 49 | return builder.toString(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/request/ScreenViewHit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | package com.brsanthu.googleanalytics.request; 15 | 16 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_SCREENVIEW; 17 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SCREEN_NAME; 18 | 19 | /** 20 | * GA request to track a typical web page view 21 | * 22 | *

23 | * For more information, see 24 | * GA Parameters 25 | * Reference 26 | *

27 | * 28 | * @author Santhosh Kumar 29 | */ 30 | public class ScreenViewHit extends GoogleAnalyticsRequest { 31 | public ScreenViewHit() { 32 | this(null, null); 33 | } 34 | 35 | public ScreenViewHit(String appName, String screenName) { 36 | super(HIT_SCREENVIEW); 37 | screenName(screenName); 38 | applicationName(appName); 39 | } 40 | 41 | public ScreenViewHit screenName(String value) { 42 | setString(SCREEN_NAME, value); 43 | return this; 44 | } 45 | 46 | public String screenName() { 47 | return getString(SCREEN_NAME); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/discovery/AwtRequestParameterDiscoverer.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.discovery; 2 | 3 | import static com.brsanthu.googleanalytics.internal.GaUtils.isEmpty; 4 | 5 | import java.awt.Dimension; 6 | import java.awt.GraphicsDevice; 7 | import java.awt.GraphicsEnvironment; 8 | import java.awt.Toolkit; 9 | 10 | import com.brsanthu.googleanalytics.GoogleAnalyticsConfig; 11 | import com.brsanthu.googleanalytics.request.DefaultRequest; 12 | 13 | /** 14 | * Clases uses AWT classes to discover following properties. 15 | *
    16 | *
  • Screen Resolution
  • 17 | *
  • Screen Colors
  • 18 | *
19 | * 20 | * @author Santhosh Kumar 21 | */ 22 | public class AwtRequestParameterDiscoverer extends DefaultRequestParameterDiscoverer { 23 | 24 | @Override 25 | public DefaultRequest discoverParameters(GoogleAnalyticsConfig config, DefaultRequest request) { 26 | super.discoverParameters(config, request); 27 | 28 | Toolkit toolkit = Toolkit.getDefaultToolkit(); 29 | 30 | if (isEmpty(request.screenResolution())) { 31 | Dimension screenSize = toolkit.getScreenSize(); 32 | request.screenResolution( 33 | ((int) screenSize.getWidth()) + "x" + ((int) screenSize.getHeight()) + ", " + toolkit.getScreenResolution() + " dpi"); 34 | } 35 | 36 | if (isEmpty(request.screenColors())) { 37 | GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment(); 38 | GraphicsDevice[] graphicsDevices = graphicsEnvironment.getScreenDevices(); 39 | 40 | StringBuilder sb = new StringBuilder(); 41 | for (GraphicsDevice graphicsDevice : graphicsDevices) { 42 | if (sb.length() != 0) { 43 | sb.append(", "); 44 | } 45 | sb.append(graphicsDevice.getDisplayMode().getBitDepth()); 46 | } 47 | request.screenColors(sb.toString()); 48 | } 49 | 50 | return request; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/discovery/DefaultRequestParameterDiscoverer.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.discovery; 2 | 3 | import static com.brsanthu.googleanalytics.internal.GaUtils.appendSystemProperty; 4 | import static com.brsanthu.googleanalytics.internal.GaUtils.isEmpty; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import com.brsanthu.googleanalytics.GoogleAnalyticsConfig; 10 | import com.brsanthu.googleanalytics.request.DefaultRequest; 11 | 12 | /** 13 | * Default request parameter discoverer. Discovers following parameters. 14 | *
    15 | *
  • Creates User Agent as java/1.6.0_45-b06/Sun Microsystems Inc./Java HotSpot(TM) 64-Bit Server VM/Windows 16 | * 7/6.1/amd64
  • 17 | *
  • User Language, and Country
  • 18 | *
  • File Encoding
  • 19 | *
20 | * 21 | * @author Santhosh Kumar 22 | */ 23 | public class DefaultRequestParameterDiscoverer implements RequestParameterDiscoverer { 24 | 25 | private static final Logger logger = LoggerFactory.getLogger(DefaultRequestParameterDiscoverer.class); 26 | public static final DefaultRequestParameterDiscoverer INSTANCE = new DefaultRequestParameterDiscoverer(); 27 | 28 | @Override 29 | public DefaultRequest discoverParameters(GoogleAnalyticsConfig config, DefaultRequest request) { 30 | try { 31 | if (isEmpty(config.getUserAgent())) { 32 | config.setUserAgent(getUserAgentString()); 33 | } 34 | 35 | if (isEmpty(request.userLanguage())) { 36 | String region = System.getProperty("user.region"); 37 | if (isEmpty(region)) { 38 | region = System.getProperty("user.country"); 39 | } 40 | request.userLanguage(System.getProperty("user.language") + "-" + region); 41 | } 42 | 43 | if (isEmpty(request.documentEncoding())) { 44 | request.documentEncoding(System.getProperty("file.encoding")); 45 | } 46 | 47 | } catch (Exception e) { 48 | logger.warn("Exception while deriving the System properties for request " + request, e); 49 | } 50 | 51 | return request; 52 | } 53 | 54 | protected String getUserAgentString() { 55 | StringBuilder sb = new StringBuilder("java"); 56 | appendSystemProperty(sb, "java.runtime.version"); 57 | appendSystemProperty(sb, "java.specification.vendor"); 58 | appendSystemProperty(sb, "java.vm.name"); 59 | appendSystemProperty(sb, "os.name"); 60 | appendSystemProperty(sb, "os.version"); 61 | appendSystemProperty(sb, "os.arch"); 62 | 63 | return sb.toString(); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsBuilder.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.LinkedBlockingDeque; 5 | import java.util.concurrent.ThreadFactory; 6 | import java.util.concurrent.ThreadPoolExecutor; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | import com.brsanthu.googleanalytics.discovery.DefaultRequestParameterDiscoverer; 10 | import com.brsanthu.googleanalytics.discovery.RequestParameterDiscoverer; 11 | import com.brsanthu.googleanalytics.httpclient.ApacheHttpClientImpl; 12 | import com.brsanthu.googleanalytics.httpclient.HttpClient; 13 | import com.brsanthu.googleanalytics.internal.GaUtils; 14 | import com.brsanthu.googleanalytics.internal.GoogleAnalyticsImpl; 15 | import com.brsanthu.googleanalytics.internal.GoogleAnalyticsThreadFactory; 16 | import com.brsanthu.googleanalytics.request.DefaultRequest; 17 | 18 | public class GoogleAnalyticsBuilder { 19 | private GoogleAnalyticsConfig config = new GoogleAnalyticsConfig(); 20 | private DefaultRequest defaultRequest = new DefaultRequest(); 21 | private HttpClient httpClient; 22 | private ExecutorService executor; 23 | 24 | public GoogleAnalyticsBuilder withConfig(GoogleAnalyticsConfig config) { 25 | this.config = GaUtils.firstNotNull(config, new GoogleAnalyticsConfig()); 26 | return this; 27 | } 28 | 29 | public GoogleAnalyticsBuilder withTrackingId(String trackingId) { 30 | defaultRequest.trackingId(trackingId); 31 | return this; 32 | } 33 | 34 | public GoogleAnalyticsBuilder withAppName(String value) { 35 | defaultRequest.applicationName(value); 36 | return this; 37 | } 38 | 39 | public GoogleAnalyticsBuilder withAppVersion(String value) { 40 | defaultRequest.applicationVersion(value); 41 | return this; 42 | } 43 | 44 | public GoogleAnalyticsBuilder withDefaultRequest(DefaultRequest defaultRequest) { 45 | this.defaultRequest = GaUtils.firstNotNull(defaultRequest, new DefaultRequest()); 46 | return this; 47 | } 48 | 49 | public GoogleAnalyticsBuilder withExecutor(ExecutorService executor) { 50 | this.executor = executor; 51 | return this; 52 | } 53 | 54 | public GoogleAnalyticsBuilder withHttpClient(HttpClient httpClient) { 55 | this.httpClient = httpClient; 56 | return this; 57 | } 58 | 59 | public GoogleAnalytics build() { 60 | if (config.isDiscoverRequestParameters()) { 61 | RequestParameterDiscoverer discoverer = GaUtils.firstNotNull(config.getRequestParameterDiscoverer(), 62 | DefaultRequestParameterDiscoverer.INSTANCE); 63 | 64 | discoverer.discoverParameters(config, defaultRequest); 65 | } 66 | 67 | return new GoogleAnalyticsImpl(config, defaultRequest, createHttpClient(), createExecutor()); 68 | } 69 | 70 | protected HttpClient createHttpClient() { 71 | if (httpClient != null) { 72 | return httpClient; 73 | } 74 | 75 | return new ApacheHttpClientImpl(config); 76 | } 77 | 78 | protected ExecutorService createExecutor() { 79 | if (executor != null) { 80 | return executor; 81 | } 82 | 83 | return new ThreadPoolExecutor(config.getMinThreads(), config.getMaxThreads(), config.getThreadTimeoutSecs(), TimeUnit.SECONDS, 84 | new LinkedBlockingDeque(config.getThreadQueueSize()), createThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy()); 85 | } 86 | 87 | protected ThreadFactory createThreadFactory() { 88 | return new GoogleAnalyticsThreadFactory(config.getThreadNameFormat()); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/internal/GoogleAnalyticsStatsImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | package com.brsanthu.googleanalytics.internal; 16 | 17 | import java.util.concurrent.atomic.AtomicLong; 18 | 19 | import com.brsanthu.googleanalytics.GoogleAnalyticsStats; 20 | 21 | /** 22 | * Collects the basic stats about successful events that have been posted to GA. 23 | * 24 | * @author Santhosh Kumar 25 | */ 26 | public class GoogleAnalyticsStatsImpl implements GoogleAnalyticsStats { 27 | private AtomicLong pageViewHits = new AtomicLong(); 28 | private AtomicLong eventHits = new AtomicLong(); 29 | private AtomicLong screenViewHits = new AtomicLong(); 30 | private AtomicLong itemHits = new AtomicLong(); 31 | private AtomicLong transactionHits = new AtomicLong(); 32 | private AtomicLong timingHits = new AtomicLong(); 33 | private AtomicLong socialHits = new AtomicLong(); 34 | private AtomicLong exceptionHits = new AtomicLong(); 35 | 36 | public void exceptionHit() { 37 | exceptionHits.incrementAndGet(); 38 | } 39 | 40 | public void pageViewHit() { 41 | pageViewHits.incrementAndGet(); 42 | } 43 | 44 | public void eventHit() { 45 | eventHits.incrementAndGet(); 46 | } 47 | 48 | public void screenViewHit() { 49 | screenViewHits.incrementAndGet(); 50 | } 51 | 52 | public void itemHit() { 53 | itemHits.incrementAndGet(); 54 | } 55 | 56 | public void transactionHit() { 57 | transactionHits.incrementAndGet(); 58 | } 59 | 60 | public void socialHit() { 61 | socialHits.incrementAndGet(); 62 | } 63 | 64 | public void timingHit() { 65 | timingHits.incrementAndGet(); 66 | } 67 | 68 | @Override 69 | public long getPageViewHits() { 70 | return pageViewHits.get(); 71 | } 72 | 73 | @Override 74 | public long getEventHits() { 75 | return eventHits.get(); 76 | } 77 | 78 | @Override 79 | public long getScreenViewHits() { 80 | return screenViewHits.get(); 81 | } 82 | 83 | @Override 84 | public long getItemHits() { 85 | return itemHits.get(); 86 | } 87 | 88 | @Override 89 | public long getTransactionHits() { 90 | return transactionHits.get(); 91 | } 92 | 93 | @Override 94 | public long getTimingHits() { 95 | return timingHits.get(); 96 | } 97 | 98 | @Override 99 | public long getSocialHits() { 100 | return socialHits.get(); 101 | } 102 | 103 | @Override 104 | public long getExceptionHits() { 105 | return exceptionHits.get(); 106 | } 107 | 108 | @Override 109 | public String toString() { 110 | return "GoogleAnalyticsStatsImpl [pageViewHits=" + pageViewHits + ", eventHits=" + eventHits + ", screenViewHits=" + screenViewHits 111 | + ", itemHits=" + itemHits + ", transactionHits=" + transactionHits + ", timingHits=" + timingHits + ", socialHits=" + socialHits 112 | + ", exceptionHits=" + exceptionHits + "]"; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/request/ExceptionHit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | package com.brsanthu.googleanalytics.request; 15 | 16 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_EXCEPTION; 17 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EXCEPTION_DESCRIPTION; 18 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EXCEPTION_FATAL; 19 | 20 | /** 21 | * GA request to track exceptions. 22 | * 23 | *

24 | * For more information, see 25 | * GA Parameters 26 | * Reference 27 | *

28 | * 29 | * @author Santhosh Kumar 30 | */ 31 | public class ExceptionHit extends GoogleAnalyticsRequest { 32 | 33 | public ExceptionHit() { 34 | this(null); 35 | } 36 | 37 | public ExceptionHit(String exceptionDescription) { 38 | this(exceptionDescription, false); 39 | } 40 | 41 | public ExceptionHit(String exceptionDescription, Boolean fatal) { 42 | super(HIT_EXCEPTION); 43 | exceptionDescription(exceptionDescription); 44 | exceptionFatal(fatal); 45 | } 46 | 47 | /** 48 | *
49 | *

50 | * Optional. 51 | *

52 | *

53 | * Specifies the description of an exception. 54 | *

55 | * 56 | * 57 | * 58 | * 59 | * 60 | * 61 | * 62 | * 63 | * 64 | * 65 | * 66 | * 67 | * 68 | * 69 | * 70 | * 71 | * 72 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
exdtextNone150 Bytesexception
73 | *
Example value: DatabaseError
74 | * Example usage: exd=DatabaseError
75 | */ 76 | public ExceptionHit exceptionDescription(String value) { 77 | setString(EXCEPTION_DESCRIPTION, value); 78 | return this; 79 | } 80 | 81 | public String exceptionDescription() { 82 | return getString(EXCEPTION_DESCRIPTION); 83 | } 84 | 85 | /** 86 | *
87 | *

88 | * Optional. 89 | *

90 | *

91 | * Specifies whether the exception was fatal. 92 | *

93 | * 94 | * 95 | * 96 | * 97 | * 98 | * 99 | * 100 | * 101 | * 102 | * 103 | * 104 | * 105 | * 106 | * 107 | * 108 | * 109 | * 110 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
exfboolean1Noneexception
111 | *
Example value: 0
112 | * Example usage: exf=0
113 | */ 114 | public ExceptionHit exceptionFatal(Boolean value) { 115 | setBoolean(EXCEPTION_FATAL, value); 116 | return this; 117 | } 118 | 119 | public Boolean exceptionFatal() { 120 | return getBoolean(EXCEPTION_FATAL); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/request/SocialHit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | package com.brsanthu.googleanalytics.request; 15 | 16 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_SOCIAL; 17 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SOCIAL_ACTION; 18 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SOCIAL_ACTION_TARGET; 19 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SOCIAL_NETWORK; 20 | 21 | /** 22 | * GA request to track social interactions 23 | * 24 | *

25 | * For more information, see 26 | * GA Parameters 27 | * Reference 28 | *

29 | * 30 | * @author Santhosh Kumar 31 | */ 32 | public class SocialHit extends GoogleAnalyticsRequest { 33 | 34 | public SocialHit() { 35 | this(null, null, null); 36 | } 37 | 38 | public SocialHit(String socialNetwork, String socialAction, String socialTarget) { 39 | super(HIT_SOCIAL); 40 | socialAction(socialAction); 41 | socialNetwork(socialNetwork); 42 | socialActionTarget(socialTarget); 43 | } 44 | 45 | /** 46 | *
47 | *

48 | * Required for social hit type. 49 | *

50 | *

51 | * Specifies the social network, for example Facebook or Google Plus. 52 | *

53 | * 54 | * 55 | * 56 | * 57 | * 58 | * 59 | * 60 | * 61 | * 62 | * 63 | * 64 | * 65 | * 66 | * 67 | * 68 | * 69 | * 70 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
sntextNone50 Bytessocial
71 | *
Example value: facebook
72 | * Example usage: sn=facebook
73 | */ 74 | public SocialHit socialNetwork(String value) { 75 | setString(SOCIAL_NETWORK, value); 76 | return this; 77 | } 78 | 79 | public String socialNetwork() { 80 | return getString(SOCIAL_NETWORK); 81 | } 82 | 83 | /** 84 | *
85 | *

86 | * Required for social hit type. 87 | *

88 | *

89 | * Specifies the social interaction action. For example on Google Plus when a user clicks the +1 button, the social 90 | * action is 'plus'. 91 | *

92 | * 93 | * 94 | * 95 | * 96 | * 97 | * 98 | * 99 | * 100 | * 101 | * 102 | * 103 | * 104 | * 105 | * 106 | * 107 | * 108 | * 109 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
satextNone50 Bytessocial
110 | *
Example value: like
111 | * Example usage: sa=like
112 | */ 113 | public SocialHit socialAction(String value) { 114 | setString(SOCIAL_ACTION, value); 115 | return this; 116 | } 117 | 118 | public String socialAction() { 119 | return getString(SOCIAL_ACTION); 120 | } 121 | 122 | /** 123 | *
124 | *

125 | * Required for social hit type. 126 | *

127 | *

128 | * Specifies the target of a social interaction. This value is typically a URL but can be any text. 129 | *

130 | * 131 | * 132 | * 133 | * 134 | * 135 | * 136 | * 137 | * 138 | * 139 | * 140 | * 141 | * 142 | * 143 | * 144 | * 145 | * 146 | * 147 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
sttextNone2048 Bytessocial
148 | *
Example value: http://foo.com
149 | * Example usage: st=http%3A%2F%2Ffoo.com
150 | */ 151 | public SocialHit socialActionTarget(String value) { 152 | setString(SOCIAL_ACTION_TARGET, value); 153 | return this; 154 | } 155 | 156 | public String socialActionTarget() { 157 | return getString(SOCIAL_ACTION_TARGET); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsTest.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics; 2 | 3 | import static com.brsanthu.googleanalytics.internal.Constants.TEST_TRACKING_ID; 4 | import static org.junit.Assert.assertEquals; 5 | import static org.junit.Assert.assertNotNull; 6 | 7 | import org.junit.BeforeClass; 8 | import org.junit.Test; 9 | 10 | import com.brsanthu.googleanalytics.request.DefaultRequest; 11 | import com.brsanthu.googleanalytics.request.GoogleAnalyticsResponse; 12 | 13 | public class GoogleAnalyticsTest { 14 | 15 | private static GoogleAnalytics ga = null; 16 | 17 | @BeforeClass 18 | public static void setup() { 19 | ga = GoogleAnalytics.builder().withTrackingId(TEST_TRACKING_ID).withAppName("Junit Test").withAppVersion("1.0.0").build(); 20 | } 21 | 22 | @Test 23 | public void testPageView() throws Exception { 24 | ga.pageView("http://www.google.com", "Search").send(); 25 | ga.pageView("http://www.google.com", "Search").sendAsync(); 26 | } 27 | 28 | @Test 29 | public void testSocial() throws Exception { 30 | ga.social("Facebook", "Like", "https://www.google.com").send(); 31 | ga.social("Google+", "Post", "It is a comment").send(); 32 | ga.social("Twitter", "Repost", "Post").send(); 33 | } 34 | 35 | @Test 36 | public void testGatherStats() throws Exception { 37 | ga.getConfig().setGatherStats(false); 38 | ga.resetStats(); 39 | ga.pageView().send(); 40 | ga.pageView().send(); 41 | ga.pageView().send(); 42 | ga.screenView().send(); 43 | ga.screenView().send(); 44 | ga.item().send(); 45 | 46 | assertEquals(0, ga.getStats().getPageViewHits()); 47 | assertEquals(0, ga.getStats().getScreenViewHits()); 48 | assertEquals(0, ga.getStats().getItemHits()); 49 | 50 | ga.getConfig().setGatherStats(true); 51 | ga.resetStats(); 52 | ga.pageView().send(); 53 | ga.pageView().send(); 54 | ga.pageView().send(); 55 | ga.screenView().send(); 56 | ga.screenView().send(); 57 | ga.item().send(); 58 | 59 | assertEquals(3, ga.getStats().getPageViewHits()); 60 | assertEquals(2, ga.getStats().getScreenViewHits()); 61 | assertEquals(1, ga.getStats().getItemHits()); 62 | } 63 | 64 | @Test 65 | public void testCustomDimensions() throws Exception { 66 | DefaultRequest defaultRequest = new DefaultRequest(); 67 | defaultRequest.customDimension(1, "foo"); 68 | defaultRequest.customDimension(5, "bar"); 69 | 70 | // Local ga 71 | GoogleAnalytics lga = GoogleAnalytics.builder().withDefaultRequest(defaultRequest).withTrackingId(TEST_TRACKING_ID).build(); 72 | 73 | GoogleAnalyticsResponse response = lga.pageView("http://www.google.com", "Search").customDimension(2, "bob").customDimension(5, "alice") 74 | .send(); 75 | 76 | assertEquals("foo", response.getRequestParams().get("cd1")); 77 | assertEquals("bob", response.getRequestParams().get("cd2")); 78 | assertEquals("alice", response.getRequestParams().get("cd5")); 79 | } 80 | 81 | @Test 82 | public void testCustomMetrics() throws Exception { 83 | DefaultRequest defaultRequest = new DefaultRequest(); 84 | defaultRequest.customMetric(1, "foo"); 85 | defaultRequest.customMetric(5, "bar"); 86 | 87 | GoogleAnalytics lga = GoogleAnalytics.builder().withDefaultRequest(defaultRequest).withTrackingId(TEST_TRACKING_ID).build(); 88 | 89 | GoogleAnalyticsResponse response = lga.pageView("http://www.google.com", "Search").customMetric(2, "bob").customMetric(5, "alice").send(); 90 | 91 | assertEquals("foo", response.getRequestParams().get("cm1")); 92 | assertEquals("bob", response.getRequestParams().get("cm2")); 93 | assertEquals("alice", response.getRequestParams().get("cm5")); 94 | } 95 | 96 | @Test 97 | public void testUserIpAndAgent() throws Exception { 98 | DefaultRequest defaultRequest = new DefaultRequest(); 99 | defaultRequest.userIp("1.2.3.4"); 100 | defaultRequest.userAgent("Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14"); 101 | 102 | GoogleAnalytics lga = GoogleAnalytics.builder().withDefaultRequest(defaultRequest).withTrackingId(TEST_TRACKING_ID).build(); 103 | 104 | GoogleAnalyticsResponse response = lga.pageView("http://www.google.com", "Search").userIp("1.2.3.5") 105 | .userAgent("Chrome/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14").send(); 106 | 107 | assertEquals("1.2.3.5", response.getRequestParams().get("uip")); 108 | assertEquals("Chrome/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14", response.getRequestParams().get("ua")); 109 | } 110 | 111 | @Test 112 | public void testUserDetails() throws Exception { 113 | GoogleAnalyticsResponse response = ga.pageView("http://www.google.com", "Search").send(); 114 | assertNotNull(response.getRequestParams().get("cid")); 115 | 116 | DefaultRequest defaultRequest = new DefaultRequest(); 117 | defaultRequest.clientId("1234"); 118 | defaultRequest.userId("user1"); 119 | 120 | GoogleAnalytics lga = GoogleAnalytics.builder().withDefaultRequest(defaultRequest).withTrackingId(TEST_TRACKING_ID).build(); 121 | 122 | response = lga.pageView("http://www.google.com", "Search").send(); 123 | assertEquals("1234", response.getRequestParams().get("cid")); 124 | assertEquals("user1", response.getRequestParams().get("uid")); 125 | 126 | response = lga.pageView("http://www.google.com", "Search").clientId("12345").userId("user2").send(); 127 | assertEquals("12345", response.getRequestParams().get("cid")); 128 | assertEquals("user2", response.getRequestParams().get("uid")); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/httpclient/ApacheHttpClientImpl.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics.httpclient; 2 | 3 | import static com.brsanthu.googleanalytics.internal.GaUtils.isNotEmpty; 4 | 5 | import java.io.IOException; 6 | import java.net.UnknownHostException; 7 | import java.nio.charset.StandardCharsets; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.stream.Collectors; 11 | 12 | import org.apache.http.HttpEntity; 13 | import org.apache.http.HttpHost; 14 | import org.apache.http.NameValuePair; 15 | import org.apache.http.auth.AuthScope; 16 | import org.apache.http.auth.UsernamePasswordCredentials; 17 | import org.apache.http.client.ClientProtocolException; 18 | import org.apache.http.client.entity.UrlEncodedFormEntity; 19 | import org.apache.http.client.methods.CloseableHttpResponse; 20 | import org.apache.http.client.methods.HttpPost; 21 | import org.apache.http.impl.client.BasicCredentialsProvider; 22 | import org.apache.http.impl.client.CloseableHttpClient; 23 | import org.apache.http.impl.client.HttpClientBuilder; 24 | import org.apache.http.impl.client.HttpClients; 25 | import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; 26 | import org.apache.http.message.BasicNameValuePair; 27 | import org.apache.http.util.EntityUtils; 28 | import org.slf4j.Logger; 29 | import org.slf4j.LoggerFactory; 30 | 31 | import com.brsanthu.googleanalytics.GoogleAnalyticsConfig; 32 | 33 | public class ApacheHttpClientImpl implements HttpClient { 34 | private static final Logger logger = LoggerFactory.getLogger(ApacheHttpClientImpl.class); 35 | 36 | private CloseableHttpClient apacheHttpClient; 37 | 38 | public ApacheHttpClientImpl(GoogleAnalyticsConfig config) { 39 | apacheHttpClient = createHttpClient(config); 40 | } 41 | 42 | @Override 43 | public void close() { 44 | try { 45 | apacheHttpClient.close(); 46 | } catch (IOException e) { 47 | // ignore 48 | } 49 | } 50 | 51 | protected CloseableHttpClient createHttpClient(GoogleAnalyticsConfig config) { 52 | PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(); 53 | connManager.setDefaultMaxPerRoute(Math.max(config.getMaxHttpConnectionsPerRoute(), 1)); 54 | 55 | HttpClientBuilder builder = HttpClients.custom().setConnectionManager(connManager); 56 | 57 | if (isNotEmpty(config.getUserAgent())) { 58 | builder.setUserAgent(config.getUserAgent()); 59 | } 60 | 61 | if (isNotEmpty(config.getProxyHost())) { 62 | builder.setProxy(new HttpHost(config.getProxyHost(), config.getProxyPort())); 63 | 64 | if (isNotEmpty(config.getProxyUserName())) { 65 | BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); 66 | credentialsProvider.setCredentials(new AuthScope(config.getProxyHost(), config.getProxyPort()), 67 | new UsernamePasswordCredentials(config.getProxyUserName(), config.getProxyPassword())); 68 | builder.setDefaultCredentialsProvider(credentialsProvider); 69 | } 70 | } 71 | 72 | return builder.build(); 73 | } 74 | 75 | @Override 76 | public boolean isBatchSupported() { 77 | return true; 78 | } 79 | 80 | protected CloseableHttpResponse execute(String url, HttpEntity entity) throws ClientProtocolException, IOException { 81 | 82 | HttpPost httpPost = new HttpPost(url); 83 | 84 | httpPost.setEntity(entity); 85 | 86 | return apacheHttpClient.execute(httpPost); 87 | } 88 | 89 | protected List createNameValuePairs(HttpRequest req) { 90 | List parmas = new ArrayList<>(); 91 | req.getBodyParams().forEach((key, value) -> parmas.add(new BasicNameValuePair(key, value))); 92 | return parmas; 93 | } 94 | 95 | @Override 96 | public HttpResponse post(HttpRequest req) { 97 | HttpResponse resp = new HttpResponse(); 98 | CloseableHttpResponse httpResp = null; 99 | 100 | try { 101 | 102 | httpResp = execute(req.getUrl(), new UrlEncodedFormEntity(createNameValuePairs(req), StandardCharsets.UTF_8)); 103 | resp.setStatusCode(httpResp.getStatusLine().getStatusCode()); 104 | 105 | } catch (Exception e) { 106 | if (e instanceof UnknownHostException) { 107 | logger.warn("Couldn't connect to Google Analytics. Internet may not be available. " + e.toString()); 108 | } else { 109 | logger.warn("Exception while sending the Google Analytics tracker request " + req, e); 110 | } 111 | 112 | } finally { 113 | EntityUtils.consumeQuietly(httpResp.getEntity()); 114 | try { 115 | httpResp.close(); 116 | } catch (Exception e2) { 117 | // ignore 118 | } 119 | } 120 | 121 | return resp; 122 | } 123 | 124 | @Override 125 | public HttpBatchResponse postBatch(HttpBatchRequest req) { 126 | HttpBatchResponse resp = new HttpBatchResponse(); 127 | CloseableHttpResponse httpResp = null; 128 | 129 | try { 130 | List> listOfReqPairs = req.getRequests().stream().map(this::createNameValuePairs).collect(Collectors.toList()); 131 | httpResp = execute(req.getUrl(), new BatchUrlEncodedFormEntity(listOfReqPairs)); 132 | resp.setStatusCode(httpResp.getStatusLine().getStatusCode()); 133 | 134 | } catch (Exception e) { 135 | if (e instanceof UnknownHostException) { 136 | logger.warn("Couldn't connect to Google Analytics. Internet may not be available. " + e.toString()); 137 | } else { 138 | logger.warn("Exception while sending the Google Analytics tracker request " + req, e); 139 | } 140 | 141 | } finally { 142 | EntityUtils.consumeQuietly(httpResp.getEntity()); 143 | try { 144 | httpResp.close(); 145 | } catch (Exception e2) { 146 | // ignore 147 | } 148 | } 149 | 150 | return resp; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/request/EventHit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | package com.brsanthu.googleanalytics.request; 15 | 16 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_EVENT; 17 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_ACTION; 18 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_CATEGORY; 19 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_LABEL; 20 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_VALUE; 21 | 22 | /** 23 | * GA request to track events. 24 | * 25 | *

26 | * For more information, see 27 | * GA Parameters 28 | * Reference 29 | *

30 | * 31 | * @author Santhosh Kumar 32 | */ 33 | public class EventHit extends GoogleAnalyticsRequest { 34 | 35 | public EventHit() { 36 | this(null, null, null, null); 37 | } 38 | 39 | public EventHit(String eventCategory, String eventAction) { 40 | this(eventCategory, eventAction, null, null); 41 | } 42 | 43 | public EventHit(String eventCategory, String eventAction, String eventLabel, Integer eventValue) { 44 | super(HIT_EVENT); 45 | eventCategory(eventCategory); 46 | eventAction(eventAction); 47 | eventLabel(eventLabel); 48 | eventValue(eventValue); 49 | } 50 | 51 | /** 52 | *

Event Tracking

53 | *

54 | * Optional. 55 | *

56 | *

57 | * Specifies the event category. Must not be empty. 58 | *

59 | * 60 | * 61 | * 62 | * 63 | * 64 | * 65 | * 66 | * 67 | * 68 | * 69 | * 70 | * 71 | * 72 | * 73 | * 74 | * 75 | * 76 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ectextNone150 Bytesevent
77 | *
Example value: Category
78 | * Example usage: ec=Category
79 | */ 80 | public EventHit eventCategory(String value) { 81 | setString(EVENT_CATEGORY, value); 82 | return this; 83 | } 84 | 85 | public String eventCategory() { 86 | return getString(EVENT_CATEGORY); 87 | } 88 | 89 | /** 90 | *
91 | *

92 | * Optional. 93 | *

94 | *

95 | * Specifies the event action. Must not be empty. 96 | *

97 | * 98 | * 99 | * 100 | * 101 | * 102 | * 103 | * 104 | * 105 | * 106 | * 107 | * 108 | * 109 | * 110 | * 111 | * 112 | * 113 | * 114 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
eatextNone500 Bytesevent
115 | *
Example value: Action
116 | * Example usage: ea=Action
117 | */ 118 | public EventHit eventAction(String value) { 119 | setString(EVENT_ACTION, value); 120 | return this; 121 | } 122 | 123 | public String eventAction() { 124 | return getString(EVENT_ACTION); 125 | } 126 | 127 | /** 128 | *
129 | *

130 | * Optional. 131 | *

132 | *

133 | * Specifies the event label. 134 | *

135 | * 136 | * 137 | * 138 | * 139 | * 140 | * 141 | * 142 | * 143 | * 144 | * 145 | * 146 | * 147 | * 148 | * 149 | * 150 | * 151 | * 152 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
eltextNone500 Bytesevent
153 | *
Example value: Label
154 | * Example usage: el=Label
155 | */ 156 | public EventHit eventLabel(String value) { 157 | setString(EVENT_LABEL, value); 158 | return this; 159 | } 160 | 161 | public String eventLabel() { 162 | return getString(EVENT_LABEL); 163 | } 164 | 165 | /** 166 | *
167 | *

168 | * Optional. 169 | *

170 | *

171 | * Specifies the event value. Values must be non-negative. 172 | *

173 | * 174 | * 175 | * 176 | * 177 | * 178 | * 179 | * 180 | * 181 | * 182 | * 183 | * 184 | * 185 | * 186 | * 187 | * 188 | * 189 | * 190 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
evintegerNoneNoneevent
191 | *
Example value: 55
192 | * Example usage: ev=55
193 | */ 194 | public EventHit eventValue(Integer value) { 195 | setInteger(EVENT_VALUE, value); 196 | return this; 197 | } 198 | 199 | public Integer eventValue() { 200 | return getInteger(EVENT_VALUE); 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/request/GoogleAnalyticsParameter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License")), 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | package com.brsanthu.googleanalytics.request; 15 | 16 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_EVENT; 17 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_EXCEPTION; 18 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_ITEM; 19 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_SCREENVIEW; 20 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_SOCIAL; 21 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_TIMING; 22 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_TXN; 23 | import static com.brsanthu.googleanalytics.internal.Constants.TYPE_BOOLEAN; 24 | import static com.brsanthu.googleanalytics.internal.Constants.TYPE_CURRENCY; 25 | import static com.brsanthu.googleanalytics.internal.Constants.TYPE_INTEGER; 26 | import static com.brsanthu.googleanalytics.internal.Constants.TYPE_TEXT; 27 | 28 | /** 29 | * Google Analytics Measurement Protocol Parameters. 30 | * 31 | *

32 | * For more information, see 33 | * GA Parameters 34 | * Reference 35 | *

36 | * 37 | * @author Santhosh Kumar 38 | */ 39 | public enum GoogleAnalyticsParameter { 40 | // General 41 | PROTOCOL_VERSION("v", true), 42 | TRACKING_ID("tid", true), 43 | ANONYMIZE_IP("aip", TYPE_BOOLEAN), 44 | QUEUE_TIME("qt", TYPE_INTEGER), 45 | CACHE_BUSTER("z"), 46 | DATA_SOURCE("ds"), 47 | 48 | // Visitor 49 | CLIENT_ID("cid", true), 50 | USER_ID("uid"), 51 | 52 | // Session 53 | SESSION_CONTROL("sc"), 54 | USER_IP("uip"), 55 | USER_AGENT("ua"), 56 | 57 | // geoid 58 | GEOID("geoid"), 59 | 60 | // Traffic Sources 61 | DOCUMENT_REFERRER("dr", 2048), 62 | CAMPAIGN_NAME("cn", 100), 63 | CAMPAIGN_SOURCE("cs", 100), 64 | CAMPAIGN_MEDIUM("cm", 50), 65 | CAMPAIGN_KEYWORD("ck", 500), 66 | CAMPAIGN_CONTENT("cc", 500), 67 | CAMPAIGN_ID("ci", 100), 68 | ADWORDS_ID("gclid"), 69 | DISPLAY_ADS_ID("dclid"), 70 | 71 | // System Info 72 | SCREEN_RESOLUTION("sr", 20), 73 | VIEWPORT_SIZE("vp", 20), 74 | DOCUMENT_ENCODING("de", 20), 75 | SCREEN_COLORS("sd", 20), 76 | USER_LANGUAGE("ul", 20), 77 | JAVA_ENABLED("je", TYPE_BOOLEAN), 78 | FLASH_VERSION("fl", 20), 79 | 80 | // Hit 81 | HIT_TYPE("t", true), 82 | NON_INTERACTION_HIT("ni"), 83 | 84 | // Content Information 85 | DOCUMENT_URL("dl", 2048), 86 | DOCUMENT_HOST_NAME("dh", 100), 87 | DOCUMENT_PATH("dp", 2048), 88 | DOCUMENT_TITLE("dt", 1500), 89 | 90 | CONTENT_DESCRIPTION("cd"), 91 | 92 | LINK_ID("linkid"), 93 | 94 | // App Tracking 95 | APPLICATION_NAME("an", 100), 96 | APPLICATION_ID("aid", 150), 97 | APPLICATION_VERSION("av", 100), 98 | APPLICATION_INSTALLER_ID("aiid", 150), 99 | 100 | // Event Tracking 101 | EVENT_CATEGORY("ec", new String[] { HIT_EVENT }, 150), 102 | EVENT_ACTION("ea", new String[] { HIT_EVENT }, 500), 103 | EVENT_LABEL("el", new String[] { HIT_EVENT }, 500), 104 | EVENT_VALUE("ev", false, TYPE_INTEGER, new String[] { HIT_EVENT }), 105 | 106 | // E-Commerce 107 | TRANSACTION_ID("ti", new String[] { HIT_TXN, HIT_ITEM }, 500), 108 | TRANSACTION_AFFILIATION("ta", new String[] { HIT_TXN }, 500), 109 | TRANSACTION_REVENUE("tr", false, TYPE_CURRENCY, new String[] { HIT_TXN }), 110 | TRANSACTION_SHIPPING("ts", false, TYPE_CURRENCY, new String[] { HIT_TXN }), 111 | TRANSACTION_TAX("tt", false, TYPE_CURRENCY, new String[] { HIT_TXN }), 112 | ITEM_NAME("in", new String[] { HIT_ITEM }, 500), 113 | ITEM_PRICE("ip", false, TYPE_CURRENCY, new String[] { HIT_ITEM }), 114 | ITEM_QUANTITY("iq", false, TYPE_INTEGER, new String[] { HIT_ITEM }), 115 | ITEM_CODE("ic", new String[] { HIT_ITEM }, 500), 116 | ITEM_CATEGORY("iv", new String[] { HIT_ITEM }, 500), 117 | CURRENCY_CODE("cu", new String[] { HIT_TXN, HIT_ITEM }, 10), 118 | 119 | // Social Interactions 120 | SOCIAL_NETWORK("sn", new String[] { HIT_SOCIAL }, 50), 121 | SOCIAL_ACTION("sa", new String[] { HIT_SOCIAL }, 50), 122 | SOCIAL_ACTION_TARGET("st", new String[] { HIT_SOCIAL }, 2048), 123 | 124 | // Timing 125 | USER_TIMING_CATEGORY("utc", new String[] { HIT_TIMING }, 150), 126 | USER_TIMING_VARIABLE_NAME("utv", new String[] { HIT_TIMING }, 500), 127 | USER_TIMING_TIME("utt", false, TYPE_INTEGER, new String[] { HIT_TIMING }), 128 | USER_TIMING_LABEL("utl", new String[] { HIT_TIMING }, 500), 129 | PAGE_LOAD_TIME("plt", false, TYPE_INTEGER, new String[] { HIT_TIMING }), 130 | DNS_TIME("dns", false, TYPE_INTEGER, new String[] { HIT_TIMING }), 131 | PAGE_DOWNLOAD_TIME("pdt", false, TYPE_INTEGER, new String[] { HIT_TIMING }), 132 | REDIRECT_RESPONSE_TIME("rrt", false, TYPE_INTEGER, new String[] { HIT_TIMING }), 133 | TCP_CONNECT_TIME("tcp", false, TYPE_INTEGER, new String[] { HIT_TIMING }), 134 | SERVER_RESPONSE_TIME("srt", false, TYPE_INTEGER, new String[] { HIT_TIMING }), 135 | 136 | // Exceptions 137 | EXCEPTION_DESCRIPTION("exd", new String[] { HIT_EXCEPTION }, 150), 138 | EXCEPTION_FATAL("exf", false, TYPE_BOOLEAN, new String[] { HIT_EXCEPTION }), 139 | 140 | // Experiment Variations 141 | EXPERIMENT_ID("xid", 40), 142 | EXPERIMENT_VARIANT("xvar"), 143 | 144 | // Screen view parameters 145 | SCREEN_NAME("cd", true, TYPE_TEXT, new String[] { HIT_SCREENVIEW }, 2048); 146 | 147 | private String parameterName = null; 148 | private boolean required = false; 149 | private String type = TYPE_TEXT; 150 | private String[] supportedHitTypes = null; 151 | private int maxLength = 0; 152 | 153 | private GoogleAnalyticsParameter(String name) { 154 | this(name, false); 155 | } 156 | 157 | private GoogleAnalyticsParameter(String name, int maxLength) { 158 | this(name, false, null, null, maxLength); 159 | } 160 | 161 | private GoogleAnalyticsParameter(String name, boolean required) { 162 | this(name, required, TYPE_TEXT, null, 0); 163 | } 164 | 165 | private GoogleAnalyticsParameter(String name, String type) { 166 | this(name, false, type, null, 0); 167 | } 168 | 169 | private GoogleAnalyticsParameter(String name, String[] supportedHitTypes) { 170 | this(name, false, TYPE_TEXT, supportedHitTypes, 0); 171 | } 172 | 173 | private GoogleAnalyticsParameter(String name, String[] supportedHitTypes, int maxLength) { 174 | this(name, false, TYPE_TEXT, supportedHitTypes, maxLength); 175 | } 176 | 177 | private GoogleAnalyticsParameter(String name, boolean required, String type, String[] supportedHitTypes) { 178 | this(name, required, type, supportedHitTypes, 0); 179 | } 180 | 181 | private GoogleAnalyticsParameter(String name, boolean required, String type, String[] supportedHitTypes, int maxLength) { 182 | this.parameterName = name; 183 | this.required = required; 184 | if (type == null) { 185 | type = TYPE_TEXT; 186 | } 187 | this.type = type; 188 | this.supportedHitTypes = supportedHitTypes; 189 | this.maxLength = maxLength; 190 | } 191 | 192 | public String getParameterName() { 193 | return parameterName; 194 | } 195 | 196 | public String[] getSupportedHitTypes() { 197 | return supportedHitTypes; 198 | } 199 | 200 | public String getType() { 201 | return type; 202 | } 203 | 204 | public boolean isRequired() { 205 | return required; 206 | } 207 | 208 | public int getMaxLength() { 209 | return maxLength; 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsParameterTest.java: -------------------------------------------------------------------------------- 1 | package com.brsanthu.googleanalytics; 2 | 3 | import static org.junit.Assert.assertArrayEquals; 4 | import static org.junit.Assert.assertEquals; 5 | import static org.junit.Assert.assertNull; 6 | 7 | import org.junit.Test; 8 | 9 | import com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter; 10 | 11 | public class GoogleAnalyticsParameterTest { 12 | 13 | @Test 14 | public void testParameters() throws Exception { 15 | assertParameter("v", true, "text", null, 0, GoogleAnalyticsParameter.PROTOCOL_VERSION); 16 | assertParameter("tid", true, "text", null, 0, GoogleAnalyticsParameter.TRACKING_ID); 17 | assertParameter("aip", false, "boolean", null, 0, GoogleAnalyticsParameter.ANONYMIZE_IP); 18 | assertParameter("qt", false, "integer", null, 0, GoogleAnalyticsParameter.QUEUE_TIME); 19 | assertParameter("z", false, "text", null, 0, GoogleAnalyticsParameter.CACHE_BUSTER); 20 | 21 | assertParameter("cid", true, "text", null, 0, GoogleAnalyticsParameter.CLIENT_ID); 22 | assertParameter("uid", false, "text", null, 0, GoogleAnalyticsParameter.USER_ID); 23 | 24 | assertParameter("sc", false, "text", null, 0, GoogleAnalyticsParameter.SESSION_CONTROL); 25 | assertParameter("uip", false, "text", null, 0, GoogleAnalyticsParameter.USER_IP); 26 | assertParameter("ua", false, "text", null, 0, GoogleAnalyticsParameter.USER_AGENT); 27 | assertParameter("aid", false, "text", null, 150, GoogleAnalyticsParameter.APPLICATION_ID); 28 | 29 | assertParameter("ds", false, "text", null, 0, GoogleAnalyticsParameter.DATA_SOURCE); 30 | 31 | assertParameter("aiid", false, "text", null, 150, GoogleAnalyticsParameter.APPLICATION_INSTALLER_ID); 32 | 33 | assertParameter("geoid", false, "text", null, 0, GoogleAnalyticsParameter.GEOID); 34 | } 35 | 36 | public void testParametersOld() throws Exception { 37 | 38 | assertEquals("v", GoogleAnalyticsParameter.PROTOCOL_VERSION.getParameterName()); 39 | assertEquals("gclid", GoogleAnalyticsParameter.ADWORDS_ID.getParameterName()); 40 | assertEquals("aip", GoogleAnalyticsParameter.ANONYMIZE_IP.getParameterName()); 41 | assertEquals("an", GoogleAnalyticsParameter.APPLICATION_NAME.getParameterName()); 42 | assertEquals("av", GoogleAnalyticsParameter.APPLICATION_VERSION.getParameterName()); 43 | assertEquals("z", GoogleAnalyticsParameter.CACHE_BUSTER.getParameterName()); 44 | assertEquals("cc", GoogleAnalyticsParameter.CAMPAIGN_CONTENT.getParameterName()); 45 | assertEquals("ci", GoogleAnalyticsParameter.CAMPAIGN_ID.getParameterName()); 46 | assertEquals("ck", GoogleAnalyticsParameter.CAMPAIGN_KEYWORD.getParameterName()); 47 | assertEquals("cm", GoogleAnalyticsParameter.CAMPAIGN_MEDIUM.getParameterName()); 48 | assertEquals("cn", GoogleAnalyticsParameter.CAMPAIGN_NAME.getParameterName()); 49 | assertEquals("cs", GoogleAnalyticsParameter.CAMPAIGN_SOURCE.getParameterName()); 50 | assertEquals("cid", GoogleAnalyticsParameter.CLIENT_ID.getParameterName()); 51 | assertEquals("uid", GoogleAnalyticsParameter.USER_ID.getParameterName()); 52 | assertEquals("cd", GoogleAnalyticsParameter.CONTENT_DESCRIPTION.getParameterName()); 53 | assertEquals("cu", GoogleAnalyticsParameter.CURRENCY_CODE.getParameterName()); 54 | assertEquals("dclid", GoogleAnalyticsParameter.DISPLAY_ADS_ID.getParameterName()); 55 | assertEquals("dns", GoogleAnalyticsParameter.DNS_TIME.getParameterName()); 56 | assertEquals("de", GoogleAnalyticsParameter.DOCUMENT_ENCODING.getParameterName()); 57 | assertEquals("dh", GoogleAnalyticsParameter.DOCUMENT_HOST_NAME.getParameterName()); 58 | assertEquals("dl", GoogleAnalyticsParameter.DOCUMENT_URL.getParameterName()); 59 | assertEquals("dp", GoogleAnalyticsParameter.DOCUMENT_PATH.getParameterName()); 60 | assertEquals("dr", GoogleAnalyticsParameter.DOCUMENT_REFERRER.getParameterName()); 61 | assertEquals("dt", GoogleAnalyticsParameter.DOCUMENT_TITLE.getParameterName()); 62 | assertEquals("ea", GoogleAnalyticsParameter.EVENT_ACTION.getParameterName()); 63 | assertEquals("ec", GoogleAnalyticsParameter.EVENT_CATEGORY.getParameterName()); 64 | assertEquals("el", GoogleAnalyticsParameter.EVENT_LABEL.getParameterName()); 65 | assertEquals("ev", GoogleAnalyticsParameter.EVENT_VALUE.getParameterName()); 66 | assertEquals("exd", GoogleAnalyticsParameter.EXCEPTION_DESCRIPTION.getParameterName()); 67 | assertEquals("exf", GoogleAnalyticsParameter.EXCEPTION_FATAL.getParameterName()); 68 | assertEquals("fl", GoogleAnalyticsParameter.FLASH_VERSION.getParameterName()); 69 | assertEquals("t", GoogleAnalyticsParameter.HIT_TYPE.getParameterName()); 70 | assertEquals("iv", GoogleAnalyticsParameter.ITEM_CATEGORY.getParameterName()); 71 | assertEquals("ic", GoogleAnalyticsParameter.ITEM_CODE.getParameterName()); 72 | assertEquals("in", GoogleAnalyticsParameter.ITEM_NAME.getParameterName()); 73 | assertEquals("ip", GoogleAnalyticsParameter.ITEM_PRICE.getParameterName()); 74 | assertEquals("iq", GoogleAnalyticsParameter.ITEM_QUANTITY.getParameterName()); 75 | assertEquals("je", GoogleAnalyticsParameter.JAVA_ENABLED.getParameterName()); 76 | assertEquals("ni", GoogleAnalyticsParameter.NON_INTERACTION_HIT.getParameterName()); 77 | assertEquals("pdt", GoogleAnalyticsParameter.PAGE_DOWNLOAD_TIME.getParameterName()); 78 | assertEquals("plt", GoogleAnalyticsParameter.PAGE_LOAD_TIME.getParameterName()); 79 | assertEquals("qt", GoogleAnalyticsParameter.QUEUE_TIME.getParameterName()); 80 | assertEquals("rrt", GoogleAnalyticsParameter.REDIRECT_RESPONSE_TIME.getParameterName()); 81 | assertEquals("sd", GoogleAnalyticsParameter.SCREEN_COLORS.getParameterName()); 82 | assertEquals("sr", GoogleAnalyticsParameter.SCREEN_RESOLUTION.getParameterName()); 83 | assertEquals("srt", GoogleAnalyticsParameter.SERVER_RESPONSE_TIME.getParameterName()); 84 | assertEquals("sc", GoogleAnalyticsParameter.SESSION_CONTROL.getParameterName()); 85 | assertEquals("sa", GoogleAnalyticsParameter.SOCIAL_ACTION.getParameterName()); 86 | assertEquals("st", GoogleAnalyticsParameter.SOCIAL_ACTION_TARGET.getParameterName()); 87 | assertEquals("sn", GoogleAnalyticsParameter.SOCIAL_NETWORK.getParameterName()); 88 | assertEquals("tcp", GoogleAnalyticsParameter.TCP_CONNECT_TIME.getParameterName()); 89 | assertEquals("tid", GoogleAnalyticsParameter.TRACKING_ID.getParameterName()); 90 | assertEquals("ta", GoogleAnalyticsParameter.TRANSACTION_AFFILIATION.getParameterName()); 91 | assertEquals("ti", GoogleAnalyticsParameter.TRANSACTION_ID.getParameterName()); 92 | assertEquals("tr", GoogleAnalyticsParameter.TRANSACTION_REVENUE.getParameterName()); 93 | assertEquals("ts", GoogleAnalyticsParameter.TRANSACTION_SHIPPING.getParameterName()); 94 | assertEquals("tt", GoogleAnalyticsParameter.TRANSACTION_TAX.getParameterName()); 95 | assertEquals("ul", GoogleAnalyticsParameter.USER_LANGUAGE.getParameterName()); 96 | assertEquals("utc", GoogleAnalyticsParameter.USER_TIMING_CATEGORY.getParameterName()); 97 | assertEquals("utl", GoogleAnalyticsParameter.USER_TIMING_LABEL.getParameterName()); 98 | assertEquals("utt", GoogleAnalyticsParameter.USER_TIMING_TIME.getParameterName()); 99 | assertEquals("utv", GoogleAnalyticsParameter.USER_TIMING_VARIABLE_NAME.getParameterName()); 100 | assertEquals("vp", GoogleAnalyticsParameter.VIEWPORT_SIZE.getParameterName()); 101 | assertEquals("uip", GoogleAnalyticsParameter.USER_ID.getParameterName()); 102 | assertEquals("ua", GoogleAnalyticsParameter.USER_AGENT.getParameterName()); 103 | 104 | assertEquals("xid", GoogleAnalyticsParameter.EXPERIMENT_ID.getParameterName()); 105 | assertNull(GoogleAnalyticsParameter.EXPERIMENT_ID.getSupportedHitTypes()); 106 | assertEquals("text", GoogleAnalyticsParameter.EXPERIMENT_ID.getType()); 107 | 108 | assertEquals("xvar", GoogleAnalyticsParameter.EXPERIMENT_VARIANT.getParameterName()); 109 | assertNull(GoogleAnalyticsParameter.EXPERIMENT_VARIANT.getSupportedHitTypes()); 110 | assertEquals("text", GoogleAnalyticsParameter.EXPERIMENT_VARIANT.getType()); 111 | } 112 | 113 | private void assertParameter(String name, boolean required, String type, String[] hitTypes, int maxLength, GoogleAnalyticsParameter param) { 114 | assertEquals(name, param.getParameterName()); 115 | assertEquals(required, param.isRequired()); 116 | assertEquals(type, param.getType()); 117 | assertArrayEquals(hitTypes, param.getSupportedHitTypes()); 118 | assertEquals(maxLength, param.getMaxLength()); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/request/ItemHit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | package com.brsanthu.googleanalytics.request; 15 | 16 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_ITEM; 17 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.CURRENCY_CODE; 18 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_CATEGORY; 19 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_CODE; 20 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_NAME; 21 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_PRICE; 22 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_QUANTITY; 23 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_ID; 24 | 25 | /** 26 | * GA request to track items as part of ecommerce transaction. 27 | * 28 | *

29 | * For more information, see 30 | * GA Parameters 31 | * Reference 32 | *

33 | * 34 | * @author Santhosh Kumar 35 | */ 36 | public class ItemHit extends GoogleAnalyticsRequest { 37 | 38 | public ItemHit() { 39 | super(HIT_ITEM); 40 | } 41 | 42 | /** 43 | *
44 | *

45 | * Required for transaction hit type.
46 | * Required for item hit type. 47 | *

48 | *

49 | * A unique identifier for the transaction. This value should be the same for both the Transaction hit and Items 50 | * hits associated to the particular transaction. 51 | *

52 | * 53 | * 54 | * 55 | * 56 | * 57 | * 58 | * 59 | * 60 | * 61 | * 62 | * 63 | * 64 | * 65 | * 66 | * 67 | * 68 | * 69 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
titextNone500 Bytestransaction, item
70 | *
Example value: OD564
71 | * Example usage: ti=OD564
72 | */ 73 | public ItemHit txId(String value) { 74 | setString(TRANSACTION_ID, value); 75 | return this; 76 | } 77 | 78 | public String txId() { 79 | return getString(TRANSACTION_ID); 80 | } 81 | 82 | /** 83 | *
84 | *

85 | * Required for item hit type. 86 | *

87 | *

88 | * Specifies the item name. 89 | *

90 | * 91 | * 92 | * 93 | * 94 | * 95 | * 96 | * 97 | * 98 | * 99 | * 100 | * 101 | * 102 | * 103 | * 104 | * 105 | * 106 | * 107 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
intextNone500 Bytesitem
108 | *
Example value: Shoe
109 | * Example usage: in=Shoe
110 | */ 111 | public ItemHit itemName(String value) { 112 | setString(ITEM_NAME, value); 113 | return this; 114 | } 115 | 116 | public String itemName() { 117 | return getString(ITEM_NAME); 118 | } 119 | 120 | /** 121 | *
122 | *

123 | * Optional. 124 | *

125 | *

126 | * Specifies the price for a single item / unit. 127 | *

128 | * 129 | * 130 | * 131 | * 132 | * 133 | * 134 | * 135 | * 136 | * 137 | * 138 | * 139 | * 140 | * 141 | * 142 | * 143 | * 144 | * 145 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ipcurrency0Noneitem
146 | *
Example value: 3.50
147 | * Example usage: ip=3.50
148 | */ 149 | public ItemHit itemPrice(Double value) { 150 | setDouble(ITEM_PRICE, value); 151 | return this; 152 | } 153 | 154 | public Double itemPrice() { 155 | return getDouble(ITEM_PRICE); 156 | } 157 | 158 | /** 159 | *
160 | *

161 | * Optional. 162 | *

163 | *

164 | * Specifies the number of items purchased. 165 | *

166 | * 167 | * 168 | * 169 | * 170 | * 171 | * 172 | * 173 | * 174 | * 175 | * 176 | * 177 | * 178 | * 179 | * 180 | * 181 | * 182 | * 183 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
iqinteger0Noneitem
184 | *
Example value: 4
185 | * Example usage: iq=4
186 | */ 187 | public ItemHit itemQuantity(Integer value) { 188 | setInteger(ITEM_QUANTITY, value); 189 | return this; 190 | } 191 | 192 | public Integer itemQuantity() { 193 | return getInteger(ITEM_QUANTITY); 194 | } 195 | 196 | /** 197 | *
198 | *

199 | * Optional. 200 | *

201 | *

202 | * Specifies the SKU or item code. 203 | *

204 | * 205 | * 206 | * 207 | * 208 | * 209 | * 210 | * 211 | * 212 | * 213 | * 214 | * 215 | * 216 | * 217 | * 218 | * 219 | * 220 | * 221 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ictextNone500 Bytesitem
222 | *
Example value: SKU47
223 | * Example usage: ic=SKU47
224 | */ 225 | public ItemHit itemCode(String value) { 226 | setString(ITEM_CODE, value); 227 | return this; 228 | } 229 | 230 | public String itemCode() { 231 | return getString(ITEM_CODE); 232 | } 233 | 234 | /** 235 | *
236 | *

237 | * Optional. 238 | *

239 | *

240 | * Specifies the category that the item belongs to. 241 | *

242 | * 243 | * 244 | * 245 | * 246 | * 247 | * 248 | * 249 | * 250 | * 251 | * 252 | * 253 | * 254 | * 255 | * 256 | * 257 | * 258 | * 259 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ivtextNone500 Bytesitem
260 | *
Example value: Blue
261 | * Example usage: iv=Blue
262 | */ 263 | public ItemHit itemCategory(String value) { 264 | setString(ITEM_CATEGORY, value); 265 | return this; 266 | } 267 | 268 | public String itemCategory() { 269 | return getString(ITEM_CATEGORY); 270 | } 271 | 272 | /** 273 | *
274 | *

275 | * Optional. 276 | *

277 | *

278 | * When present indicates the local currency for all transaction currency values. Value should be a valid ISO 4217 279 | * currency code. 280 | *

281 | * 282 | * 283 | * 284 | * 285 | * 286 | * 287 | * 288 | * 289 | * 290 | * 291 | * 292 | * 293 | * 294 | * 295 | * 296 | * 297 | * 298 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
cutextNone10 Bytestransaction, item
299 | *
Example value: EUR
300 | * Example usage: cu=EUR
301 | */ 302 | public ItemHit currencyCode(String value) { 303 | setString(CURRENCY_CODE, value); 304 | return this; 305 | } 306 | 307 | public String currencyCode() { 308 | return getString(CURRENCY_CODE); 309 | } 310 | 311 | } 312 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/request/TransactionHit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | package com.brsanthu.googleanalytics.request; 15 | 16 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_TXN; 17 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.CURRENCY_CODE; 18 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_AFFILIATION; 19 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_ID; 20 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_REVENUE; 21 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_SHIPPING; 22 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_TAX; 23 | 24 | /** 25 | * GA request to track ecommerce transaction. 26 | * 27 | *

28 | * For more information, see 29 | * GA Parameters 30 | * Reference 31 | *

32 | * 33 | * @author Santhosh Kumar 34 | */ 35 | public class TransactionHit extends GoogleAnalyticsRequest { 36 | 37 | public TransactionHit() { 38 | this(null); 39 | } 40 | 41 | public TransactionHit(String txId) { 42 | this(txId, null); 43 | } 44 | 45 | public TransactionHit(String txId, Double txRevenue) { 46 | this(txId, null, txRevenue); 47 | } 48 | 49 | public TransactionHit(String txId, String txAffiliation, Double txRevenue) { 50 | this(txId, txAffiliation, txRevenue, null, null, "USD"); 51 | } 52 | 53 | public TransactionHit(String txId, String txAffiliation, Double txRevenue, String currencyCode) { 54 | this(txId, txAffiliation, txRevenue, null, null, currencyCode); 55 | } 56 | 57 | public TransactionHit(String txId, String txAffiliation, Double txRevenue, Double txShipping, Double txTax, String currencyCode) { 58 | super(HIT_TXN); 59 | txId(txId); 60 | txAffiliation(txAffiliation); 61 | txRevenue(txRevenue); 62 | txShipping(txShipping); 63 | txTax(txTax); 64 | currencyCode(currencyCode); 65 | } 66 | 67 | /** 68 | *
69 | *

70 | * Required for transaction hit type.
71 | * Required for item hit type. 72 | *

73 | *

74 | * A unique identifier for the transaction. This value should be the same for both the Transaction hit and Items 75 | * hits associated to the particular transaction. 76 | *

77 | * 78 | * 79 | * 80 | * 81 | * 82 | * 83 | * 84 | * 85 | * 86 | * 87 | * 88 | * 89 | * 90 | * 91 | * 92 | * 93 | * 94 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
titextNone500 Bytestransaction, item
95 | *
Example value: OD564
96 | * Example usage: ti=OD564
97 | */ 98 | public TransactionHit txId(String value) { 99 | setString(TRANSACTION_ID, value); 100 | return this; 101 | } 102 | 103 | public String txId() { 104 | return getString(TRANSACTION_ID); 105 | } 106 | 107 | /** 108 | *
109 | *

110 | * Optional. 111 | *

112 | *

113 | * Specifies the affiliation or store name. 114 | *

115 | * 116 | * 117 | * 118 | * 119 | * 120 | * 121 | * 122 | * 123 | * 124 | * 125 | * 126 | * 127 | * 128 | * 129 | * 130 | * 131 | * 132 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
tatextNone500 Bytestransaction
133 | *
Example value: Member
134 | * Example usage: ta=Member
135 | */ 136 | public TransactionHit txAffiliation(String value) { 137 | setString(TRANSACTION_AFFILIATION, value); 138 | return this; 139 | } 140 | 141 | public String txAffiliation() { 142 | return getString(TRANSACTION_AFFILIATION); 143 | } 144 | 145 | /** 146 | *
147 | *

148 | * Optional. 149 | *

150 | *

151 | * Specifies the total revenue associated with the transaction. This value should include any shipping or tax costs. 152 | *

153 | * 154 | * 155 | * 156 | * 157 | * 158 | * 159 | * 160 | * 161 | * 162 | * 163 | * 164 | * 165 | * 166 | * 167 | * 168 | * 169 | * 170 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
trcurrency0Nonetransaction
171 | *
Example value: 15.47
172 | * Example usage: tr=15.47
173 | */ 174 | public TransactionHit txRevenue(Double value) { 175 | setDouble(TRANSACTION_REVENUE, value); 176 | return this; 177 | } 178 | 179 | public Double txRevenue() { 180 | return getDouble(TRANSACTION_REVENUE); 181 | } 182 | 183 | /** 184 | *
185 | *

186 | * Optional. 187 | *

188 | *

189 | * Specifies the total shipping cost of the transaction. 190 | *

191 | * 192 | * 193 | * 194 | * 195 | * 196 | * 197 | * 198 | * 199 | * 200 | * 201 | * 202 | * 203 | * 204 | * 205 | * 206 | * 207 | * 208 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
tscurrency0Nonetransaction
209 | *
Example value: 3.50
210 | * Example usage: ts=3.50
211 | */ 212 | public TransactionHit txShipping(Double value) { 213 | setDouble(TRANSACTION_SHIPPING, value); 214 | return this; 215 | } 216 | 217 | public Double txShipping() { 218 | return getDouble(TRANSACTION_SHIPPING); 219 | } 220 | 221 | /** 222 | *
223 | *

224 | * Optional. 225 | *

226 | *

227 | * Specifies the total tax of the transaction. 228 | *

229 | * 230 | * 231 | * 232 | * 233 | * 234 | * 235 | * 236 | * 237 | * 238 | * 239 | * 240 | * 241 | * 242 | * 243 | * 244 | * 245 | * 246 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ttcurrency0Nonetransaction
247 | *
Example value: 11.20
248 | * Example usage: tt=11.20
249 | */ 250 | public TransactionHit txTax(Double value) { 251 | setDouble(TRANSACTION_TAX, value); 252 | return this; 253 | } 254 | 255 | public Double txTax() { 256 | return getDouble(TRANSACTION_TAX); 257 | } 258 | 259 | /** 260 | *
261 | *

262 | * Optional. 263 | *

264 | *

265 | * When present indicates the local currency for all transaction currency values. Value should be a valid ISO 4217 266 | * currency code. 267 | *

268 | * 269 | * 270 | * 271 | * 272 | * 273 | * 274 | * 275 | * 276 | * 277 | * 278 | * 279 | * 280 | * 281 | * 282 | * 283 | * 284 | * 285 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
cutextNone10 Bytestransaction, item
286 | *
Example value: EUR
287 | * Example usage: cu=EUR
288 | */ 289 | public TransactionHit currencyCode(String value) { 290 | setString(CURRENCY_CODE, value); 291 | return this; 292 | } 293 | 294 | public String currencyCode() { 295 | return getString(CURRENCY_CODE); 296 | } 297 | 298 | } 299 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Overview 2 | == 3 | Java API for Google Analytics Measurement Protocol (part of Universal Analytics). This library 4 | is released under liberal Apache Open source License 2.0 5 | 6 | Google Analytics Measurement Protocol is new tracking protocol, which will replace the legacy Tracking protocol. 7 | This protocol is documented at https://developers.google.com/analytics/devguides/collection/protocol/v1/ 8 | 9 | The library is available in Maven Central. Add the following dependency and you are good to go. 10 | 11 | Maven: 12 | 13 | 14 | com.brsanthu 15 | google-analytics-java 16 | 2.0.0 17 | 18 | 19 | Gradle: 20 | 21 | compile 'com.brsanthu:google-analytics-java:2.0.0' 22 | 23 | Others: [Check Here](https://search.maven.org/#artifactdetails%7Ccom.brsanthu%7Cgoogle-analytics-java%7C2.0.0%7Cjar) 24 | 25 | To get a local build, do 26 | 27 | git clone https://github.com/brsanthu/google-analytics-java.git 28 | mvn install 29 | 30 | View Javadocs [here](https://www.javadoc.io/doc/com.brsanthu/google-analytics-java) 31 | 32 | 1.x vs 2.x 33 | == 34 | Note that Version 2.x has different api than 1.x. Version 2.x is refactoring of majority of structure of the library with goal of making library 35 | easy to use and make it feel fluently. It is based on Java 1.8. 36 | 37 | Here is [V1 Readme](https://github.com/brsanthu/google-analytics-java/wiki/V1-Readme) 38 | 39 | Features 40 | == 41 | This library implements the measurement protocol with following features. 42 | 43 | * Supports all parameters and hit types. 44 | * Able to configure default parameters, which would be used for each request. 45 | * Type safe data types as appropriate (String, Integer, Double and Boolean) 46 | * Convenient hit specific request types for easy construction. 47 | * Synchronous or Asynchronous Event Processing. 48 | * Support for delayed request construction. 49 | * Asynchronous processing uses Java Concurrent Executor Service. 50 | * Uses the latest Apache Http Client (4.3) for high performing event posting. 51 | * Event posting can be enabled/disabled at run time at configuration level. 52 | * Supports connections via Proxy 53 | * Gathers some basic information from the underlying Jvm (File Encoding, User Language, Screen Size, Color Depth etc) 54 | * Validates the request and can throw exception or log warning if validation fails (still wip) 55 | * Logging uses SLF4J api 56 | * Gathers basic stats (number of events posted for each hit type) if requested in the configuration. 57 | * Implementation is Thread Safe 58 | * Jar files are OSGi ready, so could be used with Eclipse 59 | * Build against Java 1.8 60 | * Supports batching of requests 61 | * Complete Measurement Protocol parameter information is made available as Javadocs 62 | 63 | Usage 64 | == 65 | 66 | Init 67 | -- 68 | Before using the library to post events, `GoogleAnalytics` instance needs to be initialized. Once it is initialized, same instance can be used 69 | to post events across multiple threads and instance is designed to be thread-safe. 70 | 71 | It can be initialized with two types of information. Set of information called configuration (via `GoogleAnalyticsConfig`), which is used by the library and default request settings (`DefaultRequest`), which defines the default attributes for all subsequent requests. 72 | 73 | Builder also provides typed methods to set most-relavent attributes of default request for readability. 74 | 75 | Simplified initialization with all defaults is as follows. 76 | 77 | ga = GoogleAnalytics.builder() 78 | .withTrackingId("UA-00000000") 79 | .build(); 80 | 81 | To build with custom configuration: 82 | 83 | ga = GoogleAnalytics.builder() 84 | .withConfig(new GoogleAnalyticsConfig().setBatchingEnabled(true).setBatchSize(10)) 85 | .withTrackingId("UA-00000000") 86 | .build(); 87 | 88 | To build with custom configuration and some default request attributes: 89 | 90 | ga = GoogleAnalytics.builder() 91 | .withConfig(new GoogleAnalyticsConfig().setBatchingEnabled(true).setBatchSize(10)) 92 | .withDefaultRequest(new DefaultRequest().userIp("127.0.0.1").trackingId("UA-00000000")) 93 | .build(); 94 | 95 | Note that tracking id can be set to one value for all requests (using default request attributes) or it can be set on per request basis. 96 | 97 | Sending Events 98 | -- 99 | To send reqeusts, create one of the event type requests, configure the values for that event and call `send()`. 100 | 101 | Here are some examples: 102 | 103 | ga.screenView() 104 | .sessionControl("start") 105 | .send(); 106 | 107 | ga.pageView() 108 | .documentTitle(entry.getPage()) 109 | .documentPath("/" + entry.getPage()) 110 | .clientId("Some Id") 111 | .customDimension(1, "Product") 112 | .customDimension(1, "Version") 113 | .userIp("198.165.0.1") 114 | .send(); 115 | 116 | ga.exception() 117 | .exceptionDescription(e.getMessage()) 118 | .send(); 119 | 120 | ga.screenView() 121 | .sessionControl("end") 122 | .send(); 123 | 124 | Async Posting 125 | -- 126 | Sending request to Google Analytics is network call and hence it may take a little bit of time. If you would like to avoid this overhead, you can opt in 127 | to send requests asynchronously. 128 | 129 | Executor is created to process the requests async with default config of `minThreads=0, maxThreads=5, threadFormat=googleanalyticsjava-thread-{0}, threadTimeoutSecs=300, queueSize=1000. rejectExecutor=CallerRunsPolicy`. 130 | 131 | If you want to change these values, configure them before building `GoogleAnalytics` instance. You can also set your own executor in the config, in that case that executor will be used. 132 | 133 | To send request async, call `.sendAsync()` instead of `.send()` as follows 134 | 135 | ga.screenView() 136 | .sessionControl("end") 137 | .sendAsync(); 138 | 139 | Batching 140 | -- 141 | Google Analytics api supports sending events in batch to reduce the network overhead. Batching is disabled by default but it can be enabled using `batchingEnabled` config. This needs to be set before Google Analytics is built. 142 | 143 | Once batching is enabled, usage is same as non-batching. Upon submission, request will be held in a internal list and upon reaching the batch limit, it will be posted to Google api. Note that batching can be used along with Async posting and it work in the same way. 144 | 145 | Max batch size is 20 requests and that is the default, which can be changed using config `batchSize` 146 | 147 | Master Switch 148 | -- 149 | Library provides a master switch with config `enabled`. If set to `false` then requests will be accepted and silently dropped. This config variable can be changed before or after building the `ga` instance. 150 | 151 | Discovering Request Parameters 152 | -- 153 | Library tries to discover some default request parameters, which is controlled via config `discoverRequestParameters` with default value of `true`. Parameters are discoverd during the building process so it is one time activity. 154 | 155 | It discovers following parameters: 156 | 157 | * user agent 158 | * user language 159 | * docuemnt encoding 160 | * screen resolution 161 | * screen colors 162 | 163 | To discover scren resolution and colors, it needs access to `java.awt`. Since not all environments have access to awt, it is not enabled by default. If would like to use it, set config `requestParameterDiscoverer` to instance of `AwtRequestParameterDiscoverer` 164 | 165 | Http Client 166 | -- 167 | Library abstracts http client interaction via `HttpClient` interface with default implementation based on Apache HttpClient. If you want to use your own version of http client, set config `httpClient`. 168 | 169 | 170 | Release Notes 171 | == 172 | Version 2.0.0 - Jan 24 2018 173 | -- 174 | * API redesign based on builder and fluent pattern 175 | * Added support for batching requests 176 | 177 | Version 1.1.2 - Apr 29 2015 178 | -- 179 | 180 | 181 | Version 1.1.1 - May 21 2014 182 | -- 183 | * Fixed the issue #14. Https Collection url has been updated to latest one. 184 | * Fixed the issue #15. Added new parameter User Id (uid). As part of this, another change was made to move initializing the default ClientId parameter from GoogleAnalyticsRequest to DefaultRequest. This way, whatever the default clientid you use, will be used for all requests. Previously, default client id wasn't referred. 185 | 186 | Version 1.1.0 - Apr 22 2014 187 | -- 188 | * Fixed the issue #5. Fix changes some of the existing behavior. If you are using discover system parameters, then by default Screen Colors and Screen Resolution will not be populated. If you would like, you need to set AwtRequestParameterDiscoverer in the GoogleAnalyticsConfig before initializing the GoogleAnalytics. This change is to ensure that it can be used in a environment where JVM has no access to java.awt.* classes. 189 | 190 | Version 1.0.5 - Apr 09 2014 191 | -- 192 | * Fixed the issue #12 193 | 194 | Version 1.0.4 - Mar 3 2014 195 | -- 196 | * Fixed the issue #8 197 | 198 | Version 1.0.3 - Jan 20 2014 199 | -- 200 | * Fixed the issue #6 201 | 202 | Other Implementations 203 | == 204 | There are few Java implementation of Google Analytics api, but found some issues (or protocol mismatch) with each of them. 205 | 206 | https://github.com/nhnopensource/universal-analytics-java 207 | * Doesn't implement all parameters of Measurement Protocol. 208 | * Cannot specify default parameters 209 | * Only one unit test case and coverage is very minimal 210 | * Uses Legacy Apache Http Client (3.x) 211 | 212 | https://code.google.com/p/jgoogleanalyticstracker/ 213 | * Implements Legacy Google Analytics protocol 214 | 215 | https://github.com/siddii/jgoogleanalytics 216 | * Implements Legacy Google Analytics protocol 217 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | org.sonatype.oss 5 | oss-parent 6 | 9 7 | 8 | 9 | com.brsanthu 10 | google-analytics-java 11 | 2.0.1-SNAPSHOT 12 | jar 13 | 14 | 15 | 1.8 16 | 1.7.25 17 | 4.11 18 | 4.5.3 19 | UTF-8 20 | 21 | 22 | 23 | 24 | 25 | 26 | org.sonatype.plugins 27 | nexus-staging-maven-plugin 28 | 1.6.8 29 | true 30 | 31 | ossrh 32 | https://oss.sonatype.org/ 33 | true 34 | 35 | 36 | 37 | 38 | maven-compiler-plugin 39 | 3.6.2 40 | 41 | ${java-version} 42 | ${java-version} 43 | true 44 | true 45 | 46 | 47 | 48 | maven-source-plugin 49 | 3.0.1 50 | 51 | 52 | 53 | jar 54 | 55 | 56 | 57 | 58 | 59 | 60 | maven-javadoc-plugin 61 | 2.10.4 62 | 63 | *.internal.* 64 | false 65 | -Xdoclint:none 66 | 67 | 68 | 69 | 70 | jar 71 | 72 | true 73 | 74 | 75 | 76 | 77 | 78 | maven-jar-plugin 79 | 2.6 80 | 81 | true 82 | 83 | true 84 | 85 | true 86 | true 87 | 88 | 89 | 90 | 91 | 92 | 93 | maven-surefire-plugin 94 | 2.20 95 | 96 | false 97 | 98 | 99 | 100 | 101 | org.apache.felix 102 | maven-bundle-plugin 103 | 3.3.0 104 | 105 | META-INF 106 | 107 | ${project.groupId}.${project.artifactId} 108 | *;version=! 109 | 110 | 111 | 112 | 113 | bundle-manifest 114 | process-classes 115 | 116 | manifest 117 | 118 | 119 | 120 | bundle 121 | package 122 | 123 | bundle 124 | 125 | 126 | 127 | 128 | 129 | 130 | org.apache.maven.plugins 131 | maven-release-plugin 132 | 2.5.3 133 | 134 | 135 | 136 | 137 | 138 | 139 | org.slf4j 140 | slf4j-api 141 | ${slf4j-version} 142 | 143 | 144 | org.slf4j 145 | jcl-over-slf4j 146 | ${slf4j-version} 147 | 148 | 149 | org.apache.httpcomponents 150 | httpclient 151 | ${httpclient-version} 152 | 153 | 154 | commons-logging 155 | commons-logging 156 | 157 | 158 | 159 | 160 | junit 161 | junit 162 | ${junit.version} 163 | test 164 | 165 | 166 | Google Analytics Java API 167 | https://github.com/brsanthu/google-analytics-java 168 | This is Java API for Google Analytics (Measurement Protocol). More information about the protocol is available at https://developers.google.com/analytics/devguides/collection/protocol/v1/. 169 | Sep 2013 170 | 171 | http://www.brsanthu.com 172 | brsanthu Inc 173 | 174 | 175 | https://github.com/brsanthu/google-analytics-java 176 | scm:git:git@github.com:brsanthu/google-analytics-java 177 | scm:git:git@github.com:brsanthu/google-analytics-java 178 | google-analytics-java-1.1.2 179 | 180 | 181 | github.com 182 | https://github.com/brsanthu/google-analytics-java/issues 183 | 184 | 185 | 186 | Santhosh Kumar 187 | http://www.brsanthu.com 188 | http://www.brsanthu.com 189 | 190 | Initiator 191 | Commiter 192 | 193 | brsanthu at gmail 194 | 195 | 196 | 197 | 198 | The Apache Software License, Version 2.0 199 | http://www.apache.org/licenses/LICENSE-2.0.txt 200 | repo 201 | 202 | 203 | 204 | 205 | 206 | release-sign-artifacts 207 | 208 | 209 | performRelease 210 | true 211 | 212 | 213 | 214 | 215 | 216 | org.apache.maven.plugins 217 | maven-gpg-plugin 218 | 1.6 219 | 220 | 221 | sign-artifacts 222 | verify 223 | 224 | sign 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/request/TimingHit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | package com.brsanthu.googleanalytics.request; 15 | 16 | import static com.brsanthu.googleanalytics.internal.Constants.HIT_TIMING; 17 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.DNS_TIME; 18 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.PAGE_DOWNLOAD_TIME; 19 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.PAGE_LOAD_TIME; 20 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.REDIRECT_RESPONSE_TIME; 21 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SERVER_RESPONSE_TIME; 22 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TCP_CONNECT_TIME; 23 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.USER_TIMING_CATEGORY; 24 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.USER_TIMING_LABEL; 25 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.USER_TIMING_TIME; 26 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.USER_TIMING_VARIABLE_NAME; 27 | 28 | /** 29 | * GA request to track performance timings like page load time, server response time etc. 30 | * 31 | *

32 | * For more information, see 33 | * GA Parameters 34 | * Reference 35 | *

36 | * 37 | * @author Santhosh Kumar 38 | */ 39 | public class TimingHit extends GoogleAnalyticsRequest { 40 | public TimingHit() { 41 | super(HIT_TIMING); 42 | } 43 | 44 | /** 45 | *
46 | *

47 | * Optional. 48 | *

49 | *

50 | * Specifies the user timing category. 51 | *

52 | * 53 | * 54 | * 55 | * 56 | * 57 | * 58 | * 59 | * 60 | * 61 | * 62 | * 63 | * 64 | * 65 | * 66 | * 67 | * 68 | * 69 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
utctextNone150 Bytestiming
70 | *
Example value: category
71 | * Example usage: utc=category
72 | */ 73 | public TimingHit userTimingCategory(String value) { 74 | setString(USER_TIMING_CATEGORY, value); 75 | return this; 76 | } 77 | 78 | public String userTimingCategory() { 79 | return getString(USER_TIMING_CATEGORY); 80 | } 81 | 82 | /** 83 | *
84 | *

85 | * Optional. 86 | *

87 | *

88 | * Specifies the user timing variable. 89 | *

90 | * 91 | * 92 | * 93 | * 94 | * 95 | * 96 | * 97 | * 98 | * 99 | * 100 | * 101 | * 102 | * 103 | * 104 | * 105 | * 106 | * 107 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
utvtextNone500 Bytestiming
108 | *
Example value: lookup
109 | * Example usage: utv=lookup
110 | */ 111 | public TimingHit userTimingVariableName(String value) { 112 | setString(USER_TIMING_VARIABLE_NAME, value); 113 | return this; 114 | } 115 | 116 | public String userTimingVariableName() { 117 | return getString(USER_TIMING_VARIABLE_NAME); 118 | } 119 | 120 | /** 121 | *
122 | *

123 | * Optional. 124 | *

125 | *

126 | * Specifies the user timing value. The value is in milliseconds. 127 | *

128 | * 129 | * 130 | * 131 | * 132 | * 133 | * 134 | * 135 | * 136 | * 137 | * 138 | * 139 | * 140 | * 141 | * 142 | * 143 | * 144 | * 145 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
uttintegerNoneNonetiming
146 | *
Example value: 123
147 | * Example usage: utt=123
148 | */ 149 | public TimingHit userTimingTime(Integer value) { 150 | setInteger(USER_TIMING_TIME, value); 151 | return this; 152 | } 153 | 154 | public Integer userTimingTime() { 155 | return getInteger(USER_TIMING_TIME); 156 | } 157 | 158 | /** 159 | *
160 | *

161 | * Optional. 162 | *

163 | *

164 | * Specifies the user timing label. 165 | *

166 | * 167 | * 168 | * 169 | * 170 | * 171 | * 172 | * 173 | * 174 | * 175 | * 176 | * 177 | * 178 | * 179 | * 180 | * 181 | * 182 | * 183 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
utltextNone500 Bytestiming
184 | *
Example value: label
185 | * Example usage: utl=label
186 | */ 187 | public TimingHit userTimingLabel(String value) { 188 | setString(USER_TIMING_LABEL, value); 189 | return this; 190 | } 191 | 192 | public String userTimingLabel() { 193 | return getString(USER_TIMING_LABEL); 194 | } 195 | 196 | /** 197 | *
198 | *

199 | * Optional. 200 | *

201 | *

202 | * Specifies the time it took for a page to load. The value is in milliseconds. 203 | *

204 | * 205 | * 206 | * 207 | * 208 | * 209 | * 210 | * 211 | * 212 | * 213 | * 214 | * 215 | * 216 | * 217 | * 218 | * 219 | * 220 | * 221 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
pltintegerNoneNonetiming
222 | *
Example value: 3554
223 | * Example usage: plt=3554
224 | */ 225 | public TimingHit pageLoadTime(Integer value) { 226 | setInteger(PAGE_LOAD_TIME, value); 227 | return this; 228 | } 229 | 230 | public Integer pageLoadTime() { 231 | return getInteger(PAGE_LOAD_TIME); 232 | } 233 | 234 | /** 235 | *
236 | *

237 | * Optional. 238 | *

239 | *

240 | * Specifies the time it took to do a DNS lookup.The value is in milliseconds. 241 | *

242 | * 243 | * 244 | * 245 | * 246 | * 247 | * 248 | * 249 | * 250 | * 251 | * 252 | * 253 | * 254 | * 255 | * 256 | * 257 | * 258 | * 259 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
dnsintegerNoneNonetiming
260 | *
Example value: 43
261 | * Example usage: dns=43
262 | */ 263 | public TimingHit dnsTime(Integer value) { 264 | setInteger(DNS_TIME, value); 265 | return this; 266 | } 267 | 268 | public Integer dnsTime() { 269 | return getInteger(DNS_TIME); 270 | } 271 | 272 | /** 273 | *
274 | *

275 | * Optional. 276 | *

277 | *

278 | * Specifies the time it took for the page to be downloaded. The value is in milliseconds. 279 | *

280 | * 281 | * 282 | * 283 | * 284 | * 285 | * 286 | * 287 | * 288 | * 289 | * 290 | * 291 | * 292 | * 293 | * 294 | * 295 | * 296 | * 297 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
pdtintegerNoneNonetiming
298 | *
Example value: 500
299 | * Example usage: pdt=500
300 | */ 301 | public TimingHit pageDownloadTime(Integer value) { 302 | setInteger(PAGE_DOWNLOAD_TIME, value); 303 | return this; 304 | } 305 | 306 | public Integer pageDownloadTime() { 307 | return getInteger(PAGE_DOWNLOAD_TIME); 308 | } 309 | 310 | /** 311 | *
312 | *

313 | * Optional. 314 | *

315 | *

316 | * Specifies the time it took for any redirects to happen. The value is in milliseconds. 317 | *

318 | * 319 | * 320 | * 321 | * 322 | * 323 | * 324 | * 325 | * 326 | * 327 | * 328 | * 329 | * 330 | * 331 | * 332 | * 333 | * 334 | * 335 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
rrtintegerNoneNonetiming
336 | *
Example value: 500
337 | * Example usage: rrt=500
338 | */ 339 | public TimingHit redirectResponseTime(Integer value) { 340 | setInteger(REDIRECT_RESPONSE_TIME, value); 341 | return this; 342 | } 343 | 344 | public Integer redirectResponseTime() { 345 | return getInteger(REDIRECT_RESPONSE_TIME); 346 | } 347 | 348 | /** 349 | *
350 | *

351 | * Optional. 352 | *

353 | *

354 | * Specifies the time it took for a TCP connection to be made. The value is in milliseconds. 355 | *

356 | * 357 | * 358 | * 359 | * 360 | * 361 | * 362 | * 363 | * 364 | * 365 | * 366 | * 367 | * 368 | * 369 | * 370 | * 371 | * 372 | * 373 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
tcpintegerNoneNonetiming
374 | *
Example value: 500
375 | * Example usage: tcp=500
376 | */ 377 | public TimingHit tcpConnectTime(Integer value) { 378 | setInteger(TCP_CONNECT_TIME, value); 379 | return this; 380 | } 381 | 382 | public Integer tcpConnectTime() { 383 | return getInteger(TCP_CONNECT_TIME); 384 | } 385 | 386 | /** 387 | *
388 | *

389 | * Optional. 390 | *

391 | *

392 | * Specifies the time it took for the server to respond after the connect time. The value is in milliseconds. 393 | *

394 | * 395 | * 396 | * 397 | * 398 | * 399 | * 400 | * 401 | * 402 | * 403 | * 404 | * 405 | * 406 | * 407 | * 408 | * 409 | * 410 | * 411 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
srtintegerNoneNonetiming
412 | *
Example value: 500
413 | * Example usage: srt=500
414 | */ 415 | public TimingHit serverResponseTime(Integer value) { 416 | setInteger(SERVER_RESPONSE_TIME, value); 417 | return this; 418 | } 419 | 420 | public Integer serverResponseTime() { 421 | return getInteger(SERVER_RESPONSE_TIME); 422 | } 423 | } 424 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/internal/GoogleAnalyticsImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 3 | * the License. You may obtain a copy of the License at 4 | * 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * 7 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 8 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | * specific language governing permissions and limitations under the License. 10 | */ 11 | package com.brsanthu.googleanalytics.internal; 12 | 13 | import static com.brsanthu.googleanalytics.internal.GaUtils.isEmpty; 14 | 15 | import java.util.ArrayList; 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.Map; 19 | import java.util.concurrent.ExecutorService; 20 | import java.util.concurrent.Future; 21 | 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import com.brsanthu.googleanalytics.GoogleAnalytics; 26 | import com.brsanthu.googleanalytics.GoogleAnalyticsConfig; 27 | import com.brsanthu.googleanalytics.GoogleAnalyticsExecutor; 28 | import com.brsanthu.googleanalytics.GoogleAnalyticsStats; 29 | import com.brsanthu.googleanalytics.httpclient.HttpBatchRequest; 30 | import com.brsanthu.googleanalytics.httpclient.HttpClient; 31 | import com.brsanthu.googleanalytics.httpclient.HttpRequest; 32 | import com.brsanthu.googleanalytics.httpclient.HttpResponse; 33 | import com.brsanthu.googleanalytics.request.DefaultRequest; 34 | import com.brsanthu.googleanalytics.request.EventHit; 35 | import com.brsanthu.googleanalytics.request.ExceptionHit; 36 | import com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter; 37 | import com.brsanthu.googleanalytics.request.GoogleAnalyticsRequest; 38 | import com.brsanthu.googleanalytics.request.GoogleAnalyticsResponse; 39 | import com.brsanthu.googleanalytics.request.ItemHit; 40 | import com.brsanthu.googleanalytics.request.PageViewHit; 41 | import com.brsanthu.googleanalytics.request.ScreenViewHit; 42 | import com.brsanthu.googleanalytics.request.SocialHit; 43 | import com.brsanthu.googleanalytics.request.TimingHit; 44 | import com.brsanthu.googleanalytics.request.TransactionHit; 45 | 46 | /** 47 | * This is the main class of this library that accepts the requests from clients and sends the events to Google 48 | * Analytics (GA). 49 | * 50 | * Clients needs to instantiate this object with {@link GoogleAnalyticsConfig} and {@link DefaultRequest}. Configuration 51 | * contains sensible defaults so one could just initialize using one of the convenience constructors. 52 | * 53 | * This object is ThreadSafe and it is intended that clients create one instance of this for each GA Tracker Id and 54 | * reuse each time an event needs to be posted. 55 | * 56 | * This object contains resources which needs to be shutdown/disposed. So {@link #close()} method is called to release 57 | * all resources. Once close method is called, this instance cannot be reused so create new instance if required. 58 | */ 59 | public class GoogleAnalyticsImpl implements GoogleAnalytics, GoogleAnalyticsExecutor { 60 | protected static final Logger logger = LoggerFactory.getLogger(GoogleAnalyticsImpl.class); 61 | 62 | protected final GoogleAnalyticsConfig config; 63 | protected final DefaultRequest defaultRequest; 64 | protected final HttpClient httpClient; 65 | protected final ExecutorService executor; 66 | protected GoogleAnalyticsStatsImpl stats = new GoogleAnalyticsStatsImpl(); 67 | protected List currentBatch = new ArrayList<>(); 68 | 69 | public GoogleAnalyticsImpl(GoogleAnalyticsConfig config, DefaultRequest defaultRequest, HttpClient httpClient, ExecutorService executor) { 70 | this.config = config; 71 | this.defaultRequest = defaultRequest; 72 | this.httpClient = httpClient; 73 | this.executor = executor; 74 | } 75 | 76 | @Override 77 | public GoogleAnalyticsConfig getConfig() { 78 | return config; 79 | } 80 | 81 | public DefaultRequest getDefaultRequest() { 82 | return defaultRequest; 83 | } 84 | 85 | @Override 86 | public Future postAsync(GoogleAnalyticsRequest request) { 87 | if (!config.isEnabled()) { 88 | return null; 89 | } 90 | 91 | return executor.submit(() -> post(request)); 92 | } 93 | 94 | @Override 95 | public GoogleAnalyticsResponse post(GoogleAnalyticsRequest gaReq) { 96 | GoogleAnalyticsResponse response = new GoogleAnalyticsResponse(); 97 | if (!config.isEnabled()) { 98 | return response; 99 | } 100 | 101 | try { 102 | if (config.isBatchingEnabled()) { 103 | response = postBatch(gaReq); 104 | } else { 105 | response = postSingle(gaReq); 106 | } 107 | 108 | } catch (Exception e) { 109 | logger.warn("Exception while sending the Google Analytics tracker request " + gaReq, e); 110 | } 111 | 112 | return response; 113 | } 114 | 115 | protected GoogleAnalyticsResponse postBatch(GoogleAnalyticsRequest gaReq) { 116 | GoogleAnalyticsResponse resp = new GoogleAnalyticsResponse(); 117 | HttpRequest httpReq = createHttpRequest(gaReq); 118 | resp.setRequestParams(httpReq.getBodyParams()); 119 | 120 | if (config.isGatherStats()) { 121 | gatherStats(gaReq); 122 | } 123 | 124 | synchronized (currentBatch) { 125 | currentBatch.add(httpReq); 126 | } 127 | 128 | // If the batch size has reached the configured max, 129 | // then send the batch to google then clear the batch to start a new batch 130 | submitBatch(false); 131 | 132 | return resp; 133 | } 134 | 135 | private void submitBatch(boolean force) { 136 | if (currentBatch.isEmpty()) { 137 | return; 138 | } 139 | 140 | if (isSubmitBatch(force)) { 141 | 142 | // Synchronized block is to ensure only one of the writers will actually write the batch. 143 | synchronized (currentBatch) { 144 | 145 | // If two threads pass the if condition and then one of them actually writes, 146 | // other will do the same since they were blocked sync block. this ensures that 147 | // others will not post it even if multiple threads were to wait at sync block at same time 148 | // https://en.wikipedia.org/wiki/Double-checked_locking 149 | if (isSubmitBatch(force)) { 150 | logger.debug("Submitting a batch of " + currentBatch.size() + " requests to GA"); 151 | httpClient.postBatch(new HttpBatchRequest().setUrl(config.getBatchUrl()).setRequests(currentBatch)); 152 | currentBatch.clear(); 153 | } 154 | } 155 | } 156 | } 157 | 158 | private boolean isSubmitBatch(boolean force) { 159 | return force || currentBatch.size() >= config.getBatchSize(); 160 | } 161 | 162 | protected GoogleAnalyticsResponse postSingle(GoogleAnalyticsRequest gaReq) { 163 | 164 | HttpRequest httpReq = createHttpRequest(gaReq); 165 | HttpResponse httpResp = httpClient.post(httpReq); 166 | 167 | GoogleAnalyticsResponse response = new GoogleAnalyticsResponse(); 168 | response.setStatusCode(httpResp.getStatusCode()); 169 | response.setRequestParams(httpReq.getBodyParams()); 170 | 171 | if (config.isGatherStats()) { 172 | gatherStats(gaReq); 173 | } 174 | 175 | return response; 176 | } 177 | 178 | private HttpRequest createHttpRequest(GoogleAnalyticsRequest gaReq) { 179 | HttpRequest httpReq = new HttpRequest(config.getUrl()); 180 | 181 | // Process the parameters 182 | processParameters(gaReq, httpReq); 183 | 184 | // Process custom dimensions 185 | processCustomDimensionParameters(gaReq, httpReq); 186 | 187 | // Process custom metrics 188 | processCustomMetricParameters(gaReq, httpReq); 189 | 190 | return httpReq; 191 | } 192 | 193 | protected void processParameters(GoogleAnalyticsRequest request, HttpRequest req) { 194 | 195 | Map requestParms = request.getParameters(); 196 | Map defaultParms = defaultRequest.getParameters(); 197 | 198 | for (GoogleAnalyticsParameter parm : defaultParms.keySet()) { 199 | 200 | String value = requestParms.get(parm); 201 | String defaultValue = defaultParms.get(parm); 202 | 203 | if (isEmpty(value) && !isEmpty(defaultValue)) { 204 | requestParms.put(parm, defaultValue); 205 | } 206 | } 207 | 208 | for (GoogleAnalyticsParameter key : requestParms.keySet()) { 209 | req.addBodyParam(key.getParameterName(), requestParms.get(key)); 210 | } 211 | } 212 | 213 | /** 214 | * Processes the custom dimensions and adds the values to list of parameters, which would be posted to GA. 215 | * 216 | * @param request 217 | * @param postParms 218 | */ 219 | protected void processCustomDimensionParameters(GoogleAnalyticsRequest request, HttpRequest req) { 220 | Map customDimParms = new HashMap(); 221 | for (String defaultCustomDimKey : defaultRequest.customDimensions().keySet()) { 222 | customDimParms.put(defaultCustomDimKey, defaultRequest.customDimensions().get(defaultCustomDimKey)); 223 | } 224 | 225 | Map requestCustomDims = request.customDimensions(); 226 | for (String requestCustomDimKey : requestCustomDims.keySet()) { 227 | customDimParms.put(requestCustomDimKey, requestCustomDims.get(requestCustomDimKey)); 228 | } 229 | 230 | for (String key : customDimParms.keySet()) { 231 | req.addBodyParam(key, customDimParms.get(key)); 232 | } 233 | } 234 | 235 | /** 236 | * Processes the custom metrics and adds the values to list of parameters, which would be posted to GA. 237 | * 238 | * @param request 239 | * @param postParms 240 | */ 241 | protected void processCustomMetricParameters(GoogleAnalyticsRequest request, HttpRequest req) { 242 | Map customMetricParms = new HashMap(); 243 | for (String defaultCustomMetricKey : defaultRequest.custommMetrics().keySet()) { 244 | customMetricParms.put(defaultCustomMetricKey, defaultRequest.custommMetrics().get(defaultCustomMetricKey)); 245 | } 246 | 247 | Map requestCustomMetrics = request.custommMetrics(); 248 | for (String requestCustomDimKey : requestCustomMetrics.keySet()) { 249 | customMetricParms.put(requestCustomDimKey, requestCustomMetrics.get(requestCustomDimKey)); 250 | } 251 | 252 | for (String key : customMetricParms.keySet()) { 253 | req.addBodyParam(key, customMetricParms.get(key)); 254 | } 255 | } 256 | 257 | protected void gatherStats(GoogleAnalyticsRequest request) { 258 | String hitType = request.hitType(); 259 | 260 | if (Constants.HIT_PAGEVIEW.equalsIgnoreCase(hitType)) { 261 | stats.pageViewHit(); 262 | 263 | } else if (Constants.HIT_SCREENVIEW.equals(hitType)) { 264 | stats.screenViewHit(); 265 | 266 | } else if (Constants.HIT_EVENT.equals(hitType)) { 267 | stats.eventHit(); 268 | 269 | } else if (Constants.HIT_ITEM.equals(hitType)) { 270 | stats.itemHit(); 271 | 272 | } else if (Constants.HIT_TXN.equals(hitType)) { 273 | stats.transactionHit(); 274 | 275 | } else if (Constants.HIT_SOCIAL.equals(hitType)) { 276 | stats.socialHit(); 277 | 278 | } else if (Constants.HIT_TIMING.equals(hitType)) { 279 | stats.timingHit(); 280 | 281 | } else if (Constants.HIT_EXCEPTION.equals(hitType)) { 282 | stats.exceptionHit(); 283 | } 284 | } 285 | 286 | @Override 287 | public void close() { 288 | flush(); 289 | 290 | try { 291 | executor.shutdown(); 292 | } catch (Exception e) { 293 | // ignore 294 | } 295 | 296 | try { 297 | httpClient.close(); 298 | } catch (Exception e) { 299 | // ignore 300 | } 301 | } 302 | 303 | @Override 304 | public GoogleAnalyticsStats getStats() { 305 | return stats; 306 | } 307 | 308 | @Override 309 | public void resetStats() { 310 | stats = new GoogleAnalyticsStatsImpl(); 311 | } 312 | 313 | @Override 314 | public EventHit event() { 315 | return (EventHit) new EventHit().setExecutor(this); 316 | } 317 | 318 | @Override 319 | public ExceptionHit exception() { 320 | return (ExceptionHit) new ExceptionHit().setExecutor(this); 321 | } 322 | 323 | @Override 324 | public ItemHit item() { 325 | return (ItemHit) new ItemHit().setExecutor(this); 326 | } 327 | 328 | @Override 329 | public PageViewHit pageView() { 330 | return (PageViewHit) new PageViewHit().setExecutor(this); 331 | } 332 | 333 | @Override 334 | public PageViewHit pageView(String url, String title) { 335 | return pageView().documentUrl(url).documentTitle(title); 336 | } 337 | 338 | @Override 339 | public PageViewHit pageView(String url, String title, String description) { 340 | return pageView(url, title).contentDescription(description); 341 | } 342 | 343 | @Override 344 | public ScreenViewHit screenView() { 345 | return (ScreenViewHit) new ScreenViewHit().setExecutor(this); 346 | } 347 | 348 | @Override 349 | public ScreenViewHit screenView(String appName, String screenName) { 350 | return screenView().applicationName(appName).screenName(screenName); 351 | } 352 | 353 | @Override 354 | public SocialHit social() { 355 | return (SocialHit) new SocialHit().setExecutor(this); 356 | } 357 | 358 | @Override 359 | public SocialHit social(String socialNetwork, String socialAction, String socialTarget) { 360 | return social().socialNetwork(socialNetwork).socialAction(socialAction).socialActionTarget(socialTarget); 361 | } 362 | 363 | @Override 364 | public TimingHit timing() { 365 | return (TimingHit) new TimingHit().setExecutor(this); 366 | } 367 | 368 | @Override 369 | public TransactionHit transaction() { 370 | return (TransactionHit) new TransactionHit().setExecutor(this); 371 | } 372 | 373 | @Override 374 | public void ifEnabled(Runnable runnable) { 375 | if (!config.isEnabled()) { 376 | return; 377 | } 378 | 379 | runnable.run(); 380 | } 381 | 382 | @Override 383 | public void flush() { 384 | submitBatch(true); 385 | } 386 | 387 | } 388 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 3 | * the License. You may obtain a copy of the License at 4 | * 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * 7 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 8 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | * specific language governing permissions and limitations under the License. 10 | */ 11 | package com.brsanthu.googleanalytics; 12 | 13 | import com.brsanthu.googleanalytics.discovery.AwtRequestParameterDiscoverer; 14 | import com.brsanthu.googleanalytics.discovery.DefaultRequestParameterDiscoverer; 15 | import com.brsanthu.googleanalytics.discovery.RequestParameterDiscoverer; 16 | import com.brsanthu.googleanalytics.internal.GoogleAnalyticsImpl; 17 | import com.brsanthu.googleanalytics.internal.GoogleAnalyticsStatsImpl; 18 | 19 | /** 20 | * Properties that can be configured in this library. These would include any properties that are required to process 21 | * the tracking request or enhance the tracking request (but not specified in measurement protocol like User agent). 22 | *

23 | * Most of the properties are initialization level and request level. If a property is a initialization level property, 24 | * it should be set at the time of GoogleAnalytics object initialization. If a property is a request level property, it 25 | * can be set any time and it will be effective. 26 | *

27 | * All properties of this config object supports method chaining. So for example, you could do, 28 | * new GoogleAnalyticsConfig().setMaxThreads(2).setThreadNameFormat("name"); 29 | * 30 | * @author Santhosh Kumar 31 | */ 32 | public class GoogleAnalyticsConfig { 33 | private String threadNameFormat = "googleanalyticsjava-thread-{0}"; 34 | private boolean enabled = true; 35 | private int minThreads = 0; 36 | private int maxThreads = 5; 37 | private int threadTimeoutSecs = 300; 38 | private int threadQueueSize = 1000; 39 | private int maxHttpConnectionsPerRoute = 10; 40 | private boolean useHttps = true; 41 | private boolean validate = true; 42 | private boolean batchingEnabled = false; 43 | private int batchSize = 20; 44 | private String httpUrl = "http://www.google-analytics.com/collect"; 45 | private String httpsUrl = "https://www.google-analytics.com/collect"; 46 | private String batchUrl = "https://www.google-analytics.com/batch"; 47 | private String userAgent = null; 48 | private String proxyHost = null; 49 | private int proxyPort = 80; 50 | private String proxyUserName = null; 51 | private String proxyPassword = null; 52 | private boolean discoverRequestParameters = true; 53 | private boolean gatherStats = false; 54 | private RequestParameterDiscoverer requestParameterDiscoverer = new DefaultRequestParameterDiscoverer(); 55 | 56 | public RequestParameterDiscoverer getRequestParameterDiscoverer() { 57 | return requestParameterDiscoverer; 58 | } 59 | 60 | /** 61 | * Sets the appropriate request parameter discoverer. Default is {@link DefaultRequestParameterDiscoverer} but can 62 | * be changed to {@link AwtRequestParameterDiscoverer} if you want to use Toolkit to derive the screen resolution 63 | * etc. 64 | * 65 | * Please make sure you also enable the discovery using {@link #setDiscoverRequestParameters(boolean)} 66 | * 67 | * @param requestParameterDiscoverer can be null and is so, parameters will not be discovered. 68 | * @return 69 | */ 70 | public GoogleAnalyticsConfig setRequestParameterDiscoverer(RequestParameterDiscoverer requestParameterDiscoverer) { 71 | this.requestParameterDiscoverer = requestParameterDiscoverer; 72 | return this; 73 | } 74 | 75 | public boolean isGatherStats() { 76 | return gatherStats; 77 | } 78 | 79 | /** 80 | * If set to true, {@link GoogleAnalyticsImpl} will collect the basic stats about successful event postings for 81 | * various hit types and keeps a copy of {@link GoogleAnalyticsStatsImpl}, which can be retrieved using 82 | * {@link GoogleAnalyticsImpl#getStats()} 83 | * 84 | * @param gatherStats 85 | * @return 86 | */ 87 | public GoogleAnalyticsConfig setGatherStats(boolean gatherStats) { 88 | this.gatherStats = gatherStats; 89 | return this; 90 | } 91 | 92 | /** 93 | * Sets the thread name format that should be while creating the threads. 94 | *

95 | * Default is "googleanalytics-thread-{0}" where {0} is the thread counter. If you specify a custom format, make 96 | * sure {0} is there somewhere otherwise all threads will be nameed same and can be an issue for troubleshooting. 97 | * 98 | * @param threadNameFormat non-null string for thread name. 99 | */ 100 | public GoogleAnalyticsConfig setThreadNameFormat(String threadNameFormat) { 101 | this.threadNameFormat = threadNameFormat; 102 | return this; 103 | } 104 | 105 | public String getThreadNameFormat() { 106 | return threadNameFormat; 107 | } 108 | 109 | /** 110 | * Deprecated since 1.0.6 111 | * 112 | * @deprecated Use {@link #setDiscoverRequestParameters(boolean)} instead 113 | */ 114 | @Deprecated 115 | public GoogleAnalyticsConfig setDeriveSystemParameters(boolean deriveSystemProperties) { 116 | return setDiscoverRequestParameters(deriveSystemProperties); 117 | } 118 | 119 | /** 120 | * If true, derives the system properties (User Language, Region, Country, Screen Size, Color Depth, and File 121 | * encoding) and adds to the default request. 122 | * 123 | *

124 | * This is initialization level configuration (must be set while creating GoogleAnalytics object). 125 | *

126 | */ 127 | public GoogleAnalyticsConfig setDiscoverRequestParameters(boolean discoverSystemParameters) { 128 | this.discoverRequestParameters = discoverSystemParameters; 129 | return this; 130 | } 131 | 132 | public boolean isDiscoverRequestParameters() { 133 | return discoverRequestParameters; 134 | } 135 | 136 | /** 137 | * Sets the user name which should be used to authenticate to the proxy server. This is applicable only if 138 | * {@link #setProxyHost(String)} is not empty. 139 | * 140 | *

141 | * This is initialization level configuration (must be set while creating GoogleAnalytics object). 142 | *

143 | */ 144 | public GoogleAnalyticsConfig setProxyUserName(String proxyUserName) { 145 | this.proxyUserName = proxyUserName; 146 | return this; 147 | } 148 | 149 | public String getProxyUserName() { 150 | return proxyUserName; 151 | } 152 | 153 | public String getProxyPassword() { 154 | return proxyPassword; 155 | } 156 | 157 | /** 158 | * Sets the password which should be used to authenticate to the proxy server. This is applicable only if 159 | * {@link #setProxyHost(String)} and {@link #setProxyUserName(String)} is not empty. 160 | * 161 | *

162 | * This is initialization level configuration (must be set while creating GoogleAnalytics object). 163 | *

164 | */ 165 | public GoogleAnalyticsConfig setProxyPassword(String proxyPassword) { 166 | this.proxyPassword = proxyPassword; 167 | return this; 168 | } 169 | 170 | public String getProxyHost() { 171 | return proxyHost; 172 | } 173 | 174 | /** 175 | * Sets the host name of the proxy server, to connect to Google analytics. 176 | * 177 | *

178 | * This is initialization level configuration (must be set while creating GoogleAnalytics object). 179 | *

180 | */ 181 | public GoogleAnalyticsConfig setProxyHost(String proxyHost) { 182 | this.proxyHost = proxyHost; 183 | return this; 184 | } 185 | 186 | public int getProxyPort() { 187 | return proxyPort; 188 | } 189 | 190 | /** 191 | * Sets the host name of the proxy server, to connect to Google analytics. 192 | * 193 | *

194 | * This is initialization level configuration (must be set while creating GoogleAnalytics object). 195 | *

196 | */ 197 | public GoogleAnalyticsConfig setProxyPort(int proxyPort) { 198 | this.proxyPort = proxyPort; 199 | return this; 200 | } 201 | 202 | public String getUserAgent() { 203 | return userAgent; 204 | } 205 | 206 | /** 207 | * Sets the user agent string that should be sent while making the http request. Default is Apache Http Client's 208 | * user agent, which looks something similar to this. Apache-HttpClient/release (java 1.5) 209 | * 210 | *

211 | * This is initialization level configuration (must be set while creating GoogleAnalytics object). 212 | *

213 | */ 214 | public GoogleAnalyticsConfig setUserAgent(String userAgent) { 215 | this.userAgent = userAgent; 216 | return this; 217 | } 218 | 219 | public boolean isEnabled() { 220 | return enabled; 221 | } 222 | 223 | /** 224 | * Enables or disables the GoogleAnalytics posting. If disabled, library will continue to accept the send/post 225 | * requests but silently skips sending the event and returns successful response. Default is false. 226 | * 227 | *

228 | * This is request level configuration (can be changed any time). 229 | *

230 | */ 231 | public GoogleAnalyticsConfig setEnabled(boolean enabled) { 232 | this.enabled = enabled; 233 | return this; 234 | } 235 | 236 | /** 237 | * Maximum threads to use to process the asynchronous event posting and Http client connection pooling. Default is 238 | * 239 | *

240 | * This is initialization level configuration (must be set while creating GoogleAnalytics object). 241 | *

242 | */ 243 | public int getMaxThreads() { 244 | return maxThreads; 245 | } 246 | 247 | public GoogleAnalyticsConfig setMaxThreads(int maxThreads) { 248 | this.maxThreads = maxThreads; 249 | return this; 250 | } 251 | 252 | public int getMinThreads() { 253 | return minThreads; 254 | } 255 | 256 | public GoogleAnalyticsConfig setMinThreads(int minThreads) { 257 | this.minThreads = minThreads; 258 | return this; 259 | } 260 | 261 | public boolean isUseHttps() { 262 | return useHttps; 263 | } 264 | 265 | /** 266 | * Instructs to use https url to send the events. Default is true. 267 | * 268 | *

269 | * This is request level configuration (can be changed any time). 270 | *

271 | */ 272 | public GoogleAnalyticsConfig setUseHttps(boolean useHttps) { 273 | this.useHttps = useHttps; 274 | return this; 275 | } 276 | 277 | public boolean isValidate() { 278 | return validate; 279 | } 280 | 281 | /** 282 | * If set, validates the request before sending to Google Analytics. If any errors found, GoogleAnalyticsException 283 | * will be thrown with details. Default is false. Note that, if you are sending the event in async mode, then 284 | * request is always validated and logged to log file as warnings irrespective of this flag. 285 | * 286 | *

287 | * This is request level configuration (can be changed any time). 288 | *

289 | */ 290 | public GoogleAnalyticsConfig setValidate(boolean validate) { 291 | this.validate = validate; 292 | return this; 293 | } 294 | 295 | public String getHttpUrl() { 296 | return httpUrl; 297 | } 298 | 299 | /** 300 | * URL to use when posting the event in http mode. This url is Google Analytics service url and usually not updated 301 | * by the clients. 302 | * 303 | *

304 | * Default value is http://www.google-analytics.com/collect 305 | *

306 | * 307 | *

308 | * This is request level configuration (can be changed any time). 309 | *

310 | */ 311 | public GoogleAnalyticsConfig setHttpUrl(String httpUrl) { 312 | this.httpUrl = httpUrl; 313 | return this; 314 | } 315 | 316 | public String getHttpsUrl() { 317 | return httpsUrl; 318 | } 319 | 320 | /** 321 | * URL to use when posting the event in https mode. This url is Google Analytics service url and usually not updated 322 | * by the clients. 323 | *

324 | * Default value is https://www.google-analytics.com/collect 325 | * 326 | *

327 | * This is request level configuration (can be changed any time). 328 | *

329 | */ 330 | public GoogleAnalyticsConfig setHttpsUrl(String httpsUrl) { 331 | this.httpsUrl = httpsUrl; 332 | return this; 333 | } 334 | 335 | public String getUrl() { 336 | return useHttps ? httpsUrl : httpUrl; 337 | } 338 | 339 | public int getMaxHttpConnectionsPerRoute() { 340 | return maxHttpConnectionsPerRoute; 341 | } 342 | 343 | public GoogleAnalyticsConfig setMaxHttpConnectionsPerRoute(int maxHttpConnectionsPerRoute) { 344 | this.maxHttpConnectionsPerRoute = maxHttpConnectionsPerRoute; 345 | return this; 346 | } 347 | 348 | @Override 349 | public String toString() { 350 | return "GoogleAnalyticsConfig [threadNameFormat=" + threadNameFormat + ", enabled=" + enabled + ", minThreads=" + minThreads + ", maxThreads=" 351 | + maxThreads + ", threadTimeoutSecs=" + threadTimeoutSecs + ", threadQueueSize=" + threadQueueSize + ", maxHttpConnectionsPerRoute=" 352 | + maxHttpConnectionsPerRoute + ", useHttps=" + useHttps + ", validate=" + validate + ", httpUrl=" + httpUrl + ", httpsUrl=" + httpsUrl 353 | + ", userAgent=" + userAgent + ", proxyHost=" + proxyHost + ", proxyPort=" + proxyPort + ", proxyUserName=" + proxyUserName 354 | + ", proxyPassword=" + mask(proxyPassword) + ", discoverRequestParameters=" + discoverRequestParameters + ", gatherStats=" 355 | + gatherStats + ", requestParameterDiscoverer=" + requestParameterDiscoverer + "]"; 356 | } 357 | 358 | public static String mask(String value) { 359 | return value == null ? null : "********"; 360 | } 361 | 362 | public int getThreadQueueSize() { 363 | return threadQueueSize; 364 | } 365 | 366 | public GoogleAnalyticsConfig setThreadQueueSize(int threadQueueSize) { 367 | this.threadQueueSize = threadQueueSize; 368 | return this; 369 | } 370 | 371 | public int getThreadTimeoutSecs() { 372 | return threadTimeoutSecs; 373 | } 374 | 375 | public GoogleAnalyticsConfig setThreadTimeoutSecs(int threadTimeoutSecs) { 376 | this.threadTimeoutSecs = threadTimeoutSecs; 377 | return this; 378 | } 379 | 380 | public String getBatchUrl() { 381 | return batchUrl; 382 | } 383 | 384 | public GoogleAnalyticsConfig setBatchUrl(String batchUrl) { 385 | this.batchUrl = batchUrl; 386 | return this; 387 | } 388 | 389 | public boolean isBatchingEnabled() { 390 | return batchingEnabled; 391 | } 392 | 393 | public GoogleAnalyticsConfig setBatchingEnabled(boolean batchingEnabled) { 394 | this.batchingEnabled = batchingEnabled; 395 | return this; 396 | } 397 | 398 | public int getBatchSize() { 399 | return batchSize; 400 | } 401 | 402 | public GoogleAnalyticsConfig setBatchSize(int batchSize) { 403 | this.batchSize = batchSize; 404 | return this; 405 | } 406 | 407 | } 408 | -------------------------------------------------------------------------------- /src/main/java/com/brsanthu/googleanalytics/request/DefaultRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | package com.brsanthu.googleanalytics.request; 16 | 17 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.CURRENCY_CODE; 18 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.DNS_TIME; 19 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_ACTION; 20 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_CATEGORY; 21 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_LABEL; 22 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_VALUE; 23 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EXCEPTION_DESCRIPTION; 24 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EXCEPTION_FATAL; 25 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_CATEGORY; 26 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_CODE; 27 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_NAME; 28 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_PRICE; 29 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_QUANTITY; 30 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.PAGE_DOWNLOAD_TIME; 31 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.PAGE_LOAD_TIME; 32 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.REDIRECT_RESPONSE_TIME; 33 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SERVER_RESPONSE_TIME; 34 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SOCIAL_ACTION; 35 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SOCIAL_ACTION_TARGET; 36 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SOCIAL_NETWORK; 37 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TCP_CONNECT_TIME; 38 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_AFFILIATION; 39 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_ID; 40 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_REVENUE; 41 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_SHIPPING; 42 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_TAX; 43 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.USER_TIMING_CATEGORY; 44 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.USER_TIMING_LABEL; 45 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.USER_TIMING_TIME; 46 | import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.USER_TIMING_VARIABLE_NAME; 47 | 48 | import java.util.UUID; 49 | 50 | import com.brsanthu.googleanalytics.internal.Constants; 51 | import com.brsanthu.googleanalytics.internal.GaUtils; 52 | import com.brsanthu.googleanalytics.internal.GoogleAnalyticsImpl; 53 | 54 | /** 55 | * Default request that captures default value for any of the parameters. Create an instance of this object and specify 56 | * as constructor parameter to {@link GoogleAnalyticsImpl} or set one any time using 57 | * {@link GoogleAnalyticsImpl#setDefaultRequest(DefaultRequest)} method. 58 | * 59 | * @author Santhosh Kumar 60 | */ 61 | public class DefaultRequest extends GoogleAnalyticsRequest { 62 | 63 | private final static String DEFAULT_CLIENT_ID = UUID.randomUUID().toString(); 64 | 65 | public DefaultRequest() { 66 | this(null, null, null, null); 67 | } 68 | 69 | public DefaultRequest(String hitType) { 70 | this(hitType, null, null, null); 71 | } 72 | 73 | public DefaultRequest(String hitType, String trackingId, String appName, String appVersion) { 74 | hitType(GaUtils.isBlank(hitType) ? Constants.HIT_PAGEVIEW : hitType); 75 | trackingId(trackingId); 76 | applicationName(appName); 77 | applicationVersion(appVersion); 78 | 79 | clientId(DEFAULT_CLIENT_ID); 80 | } 81 | 82 | /** 83 | *

Event Tracking

84 | *

85 | * Optional. 86 | *

87 | *

88 | * Specifies the event category. Must not be empty. 89 | *

90 | * 91 | * 92 | * 93 | * 94 | * 95 | * 96 | * 97 | * 98 | * 99 | * 100 | * 101 | * 102 | * 103 | * 104 | * 105 | * 106 | * 107 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ectextNone150 Bytesevent
108 | *
Example value: Category
109 | * Example usage: ec=Category
110 | */ 111 | public DefaultRequest eventCategory(String value) { 112 | setString(EVENT_CATEGORY, value); 113 | return this; 114 | } 115 | 116 | public String eventCategory() { 117 | return getString(EVENT_CATEGORY); 118 | } 119 | 120 | /** 121 | *
122 | *

123 | * Optional. 124 | *

125 | *

126 | * Specifies the event action. Must not be empty. 127 | *

128 | * 129 | * 130 | * 131 | * 132 | * 133 | * 134 | * 135 | * 136 | * 137 | * 138 | * 139 | * 140 | * 141 | * 142 | * 143 | * 144 | * 145 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
eatextNone500 Bytesevent
146 | *
Example value: Action
147 | * Example usage: ea=Action
148 | */ 149 | public DefaultRequest eventAction(String value) { 150 | setString(EVENT_ACTION, value); 151 | return this; 152 | } 153 | 154 | public String eventAction() { 155 | return getString(EVENT_ACTION); 156 | } 157 | 158 | /** 159 | *
160 | *

161 | * Optional. 162 | *

163 | *

164 | * Specifies the event label. 165 | *

166 | * 167 | * 168 | * 169 | * 170 | * 171 | * 172 | * 173 | * 174 | * 175 | * 176 | * 177 | * 178 | * 179 | * 180 | * 181 | * 182 | * 183 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
eltextNone500 Bytesevent
184 | *
Example value: Label
185 | * Example usage: el=Label
186 | */ 187 | public DefaultRequest eventLabel(String value) { 188 | setString(EVENT_LABEL, value); 189 | return this; 190 | } 191 | 192 | public String eventLabel() { 193 | return getString(EVENT_LABEL); 194 | } 195 | 196 | /** 197 | *
198 | *

199 | * Optional. 200 | *

201 | *

202 | * Specifies the event value. Values must be non-negative. 203 | *

204 | * 205 | * 206 | * 207 | * 208 | * 209 | * 210 | * 211 | * 212 | * 213 | * 214 | * 215 | * 216 | * 217 | * 218 | * 219 | * 220 | * 221 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
evintegerNoneNoneevent
222 | *
Example value: 55
223 | * Example usage: ev=55
224 | */ 225 | public DefaultRequest eventValue(Integer value) { 226 | setInteger(EVENT_VALUE, value); 227 | return this; 228 | } 229 | 230 | public Integer eventValue() { 231 | return getInteger(EVENT_VALUE); 232 | } 233 | 234 | /** 235 | *
236 | *

237 | * Optional. 238 | *

239 | *

240 | * Specifies the description of an exception. 241 | *

242 | * 243 | * 244 | * 245 | * 246 | * 247 | * 248 | * 249 | * 250 | * 251 | * 252 | * 253 | * 254 | * 255 | * 256 | * 257 | * 258 | * 259 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
exdtextNone150 Bytesexception
260 | *
Example value: DatabaseError
261 | * Example usage: exd=DatabaseError
262 | */ 263 | public DefaultRequest exceptionDescription(String value) { 264 | setString(EXCEPTION_DESCRIPTION, value); 265 | return this; 266 | } 267 | 268 | public String exceptionDescription() { 269 | return getString(EXCEPTION_DESCRIPTION); 270 | } 271 | 272 | /** 273 | *
274 | *

275 | * Optional. 276 | *

277 | *

278 | * Specifies whether the exception was fatal. 279 | *

280 | * 281 | * 282 | * 283 | * 284 | * 285 | * 286 | * 287 | * 288 | * 289 | * 290 | * 291 | * 292 | * 293 | * 294 | * 295 | * 296 | * 297 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
exfboolean1Noneexception
298 | *
Example value: 0
299 | * Example usage: exf=0
300 | */ 301 | public DefaultRequest exceptionFatal(Boolean value) { 302 | setBoolean(EXCEPTION_FATAL, value); 303 | return this; 304 | } 305 | 306 | public Boolean exceptionFatal() { 307 | return getBoolean(EXCEPTION_FATAL); 308 | } 309 | 310 | /** 311 | *
312 | *

313 | * Required for item hit type. 314 | *

315 | *

316 | * Specifies the item name. 317 | *

318 | * 319 | * 320 | * 321 | * 322 | * 323 | * 324 | * 325 | * 326 | * 327 | * 328 | * 329 | * 330 | * 331 | * 332 | * 333 | * 334 | * 335 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
intextNone500 Bytesitem
336 | *
Example value: Shoe
337 | * Example usage: in=Shoe
338 | */ 339 | public DefaultRequest itemName(String value) { 340 | setString(ITEM_NAME, value); 341 | return this; 342 | } 343 | 344 | public String itemName() { 345 | return getString(ITEM_NAME); 346 | } 347 | 348 | /** 349 | *
350 | *

351 | * Optional. 352 | *

353 | *

354 | * Specifies the price for a single item / unit. 355 | *

356 | * 357 | * 358 | * 359 | * 360 | * 361 | * 362 | * 363 | * 364 | * 365 | * 366 | * 367 | * 368 | * 369 | * 370 | * 371 | * 372 | * 373 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ipcurrency0Noneitem
374 | *
Example value: 3.50
375 | * Example usage: ip=3.50
376 | */ 377 | public DefaultRequest itemPrice(Double value) { 378 | setDouble(ITEM_PRICE, value); 379 | return this; 380 | } 381 | 382 | public Double itemPrice() { 383 | return getDouble(ITEM_PRICE); 384 | } 385 | 386 | /** 387 | *
388 | *

389 | * Optional. 390 | *

391 | *

392 | * Specifies the number of items purchased. 393 | *

394 | * 395 | * 396 | * 397 | * 398 | * 399 | * 400 | * 401 | * 402 | * 403 | * 404 | * 405 | * 406 | * 407 | * 408 | * 409 | * 410 | * 411 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
iqinteger0Noneitem
412 | *
Example value: 4
413 | * Example usage: iq=4
414 | */ 415 | public DefaultRequest itemQuantity(Integer value) { 416 | setInteger(ITEM_QUANTITY, value); 417 | return this; 418 | } 419 | 420 | public Integer itemQuantity() { 421 | return getInteger(ITEM_QUANTITY); 422 | } 423 | 424 | /** 425 | *
426 | *

427 | * Optional. 428 | *

429 | *

430 | * Specifies the SKU or item code. 431 | *

432 | * 433 | * 434 | * 435 | * 436 | * 437 | * 438 | * 439 | * 440 | * 441 | * 442 | * 443 | * 444 | * 445 | * 446 | * 447 | * 448 | * 449 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ictextNone500 Bytesitem
450 | *
Example value: SKU47
451 | * Example usage: ic=SKU47
452 | */ 453 | public DefaultRequest itemCode(String value) { 454 | setString(ITEM_CODE, value); 455 | return this; 456 | } 457 | 458 | public String itemCode() { 459 | return getString(ITEM_CODE); 460 | } 461 | 462 | /** 463 | *
464 | *

465 | * Optional. 466 | *

467 | *

468 | * Specifies the category that the item belongs to. 469 | *

470 | * 471 | * 472 | * 473 | * 474 | * 475 | * 476 | * 477 | * 478 | * 479 | * 480 | * 481 | * 482 | * 483 | * 484 | * 485 | * 486 | * 487 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ivtextNone500 Bytesitem
488 | *
Example value: Blue
489 | * Example usage: iv=Blue
490 | */ 491 | public DefaultRequest itemCategory(String value) { 492 | setString(ITEM_CATEGORY, value); 493 | return this; 494 | } 495 | 496 | public String itemCategory() { 497 | return getString(ITEM_CATEGORY); 498 | } 499 | 500 | /** 501 | *
502 | *

503 | * Optional. 504 | *

505 | *

506 | * When present indicates the local currency for all transaction currency values. Value should be a valid ISO 4217 507 | * currency code. 508 | *

509 | * 510 | * 511 | * 512 | * 513 | * 514 | * 515 | * 516 | * 517 | * 518 | * 519 | * 520 | * 521 | * 522 | * 523 | * 524 | * 525 | * 526 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
cutextNone10 Bytestransaction, item
527 | *
Example value: EUR
528 | * Example usage: cu=EUR
529 | */ 530 | public DefaultRequest currencyCode(String value) { 531 | setString(CURRENCY_CODE, value); 532 | return this; 533 | } 534 | 535 | public String currencyCode() { 536 | return getString(CURRENCY_CODE); 537 | } 538 | 539 | /** 540 | *
541 | *

542 | * Required for social hit type. 543 | *

544 | *

545 | * Specifies the social network, for example Facebook or Google Plus. 546 | *

547 | * 548 | * 549 | * 550 | * 551 | * 552 | * 553 | * 554 | * 555 | * 556 | * 557 | * 558 | * 559 | * 560 | * 561 | * 562 | * 563 | * 564 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
sntextNone50 Bytessocial
565 | *
Example value: facebook
566 | * Example usage: sn=facebook
567 | */ 568 | public DefaultRequest socialNetwork(String value) { 569 | setString(SOCIAL_NETWORK, value); 570 | return this; 571 | } 572 | 573 | public String socialNetwork() { 574 | return getString(SOCIAL_NETWORK); 575 | } 576 | 577 | /** 578 | *
579 | *

580 | * Required for social hit type. 581 | *

582 | *

583 | * Specifies the social interaction action. For example on Google Plus when a user clicks the +1 button, the social 584 | * action is 'plus'. 585 | *

586 | * 587 | * 588 | * 589 | * 590 | * 591 | * 592 | * 593 | * 594 | * 595 | * 596 | * 597 | * 598 | * 599 | * 600 | * 601 | * 602 | * 603 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
satextNone50 Bytessocial
604 | *
Example value: like
605 | * Example usage: sa=like
606 | */ 607 | public DefaultRequest socialAction(String value) { 608 | setString(SOCIAL_ACTION, value); 609 | return this; 610 | } 611 | 612 | public String socialAction() { 613 | return getString(SOCIAL_ACTION); 614 | } 615 | 616 | /** 617 | *
618 | *

619 | * Required for social hit type. 620 | *

621 | *

622 | * Specifies the target of a social interaction. This value is typically a URL but can be any text. 623 | *

624 | * 625 | * 626 | * 627 | * 628 | * 629 | * 630 | * 631 | * 632 | * 633 | * 634 | * 635 | * 636 | * 637 | * 638 | * 639 | * 640 | * 641 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
sttextNone2048 Bytessocial
642 | *
Example value: http://foo.com
643 | * Example usage: st=http%3A%2F%2Ffoo.com
644 | */ 645 | public DefaultRequest socialActionTarget(String value) { 646 | setString(SOCIAL_ACTION_TARGET, value); 647 | return this; 648 | } 649 | 650 | public String socialActionTarget() { 651 | return getString(SOCIAL_ACTION_TARGET); 652 | } 653 | 654 | /** 655 | *
656 | *

657 | * Optional. 658 | *

659 | *

660 | * Specifies the user timing category. 661 | *

662 | * 663 | * 664 | * 665 | * 666 | * 667 | * 668 | * 669 | * 670 | * 671 | * 672 | * 673 | * 674 | * 675 | * 676 | * 677 | * 678 | * 679 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
utctextNone150 Bytestiming
680 | *
Example value: category
681 | * Example usage: utc=category
682 | */ 683 | public DefaultRequest userTimingCategory(String value) { 684 | setString(USER_TIMING_CATEGORY, value); 685 | return this; 686 | } 687 | 688 | public String userTimingCategory() { 689 | return getString(USER_TIMING_CATEGORY); 690 | } 691 | 692 | /** 693 | *
694 | *

695 | * Optional. 696 | *

697 | *

698 | * Specifies the user timing variable. 699 | *

700 | * 701 | * 702 | * 703 | * 704 | * 705 | * 706 | * 707 | * 708 | * 709 | * 710 | * 711 | * 712 | * 713 | * 714 | * 715 | * 716 | * 717 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
utvtextNone500 Bytestiming
718 | *
Example value: lookup
719 | * Example usage: utv=lookup
720 | */ 721 | public DefaultRequest userTimingVariableName(String value) { 722 | setString(USER_TIMING_VARIABLE_NAME, value); 723 | return this; 724 | } 725 | 726 | public String userTimingVariableName() { 727 | return getString(USER_TIMING_VARIABLE_NAME); 728 | } 729 | 730 | /** 731 | *
732 | *

733 | * Optional. 734 | *

735 | *

736 | * Specifies the user timing value. The value is in milliseconds. 737 | *

738 | * 739 | * 740 | * 741 | * 742 | * 743 | * 744 | * 745 | * 746 | * 747 | * 748 | * 749 | * 750 | * 751 | * 752 | * 753 | * 754 | * 755 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
uttintegerNoneNonetiming
756 | *
Example value: 123
757 | * Example usage: utt=123
758 | */ 759 | public DefaultRequest userTimingTime(Integer value) { 760 | setInteger(USER_TIMING_TIME, value); 761 | return this; 762 | } 763 | 764 | public Integer userTimingTime() { 765 | return getInteger(USER_TIMING_TIME); 766 | } 767 | 768 | /** 769 | *
770 | *

771 | * Optional. 772 | *

773 | *

774 | * Specifies the user timing label. 775 | *

776 | * 777 | * 778 | * 779 | * 780 | * 781 | * 782 | * 783 | * 784 | * 785 | * 786 | * 787 | * 788 | * 789 | * 790 | * 791 | * 792 | * 793 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
utltextNone500 Bytestiming
794 | *
Example value: label
795 | * Example usage: utl=label
796 | */ 797 | public DefaultRequest userTimingLabel(String value) { 798 | setString(USER_TIMING_LABEL, value); 799 | return this; 800 | } 801 | 802 | public String userTimingLabel() { 803 | return getString(USER_TIMING_LABEL); 804 | } 805 | 806 | /** 807 | *
808 | *

809 | * Optional. 810 | *

811 | *

812 | * Specifies the time it took for a page to load. The value is in milliseconds. 813 | *

814 | * 815 | * 816 | * 817 | * 818 | * 819 | * 820 | * 821 | * 822 | * 823 | * 824 | * 825 | * 826 | * 827 | * 828 | * 829 | * 830 | * 831 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
pltintegerNoneNonetiming
832 | *
Example value: 3554
833 | * Example usage: plt=3554
834 | */ 835 | public DefaultRequest pageLoadTime(Integer value) { 836 | setInteger(PAGE_LOAD_TIME, value); 837 | return this; 838 | } 839 | 840 | public Integer pageLoadTime() { 841 | return getInteger(PAGE_LOAD_TIME); 842 | } 843 | 844 | /** 845 | *
846 | *

847 | * Optional. 848 | *

849 | *

850 | * Specifies the time it took to do a DNS lookup.The value is in milliseconds. 851 | *

852 | * 853 | * 854 | * 855 | * 856 | * 857 | * 858 | * 859 | * 860 | * 861 | * 862 | * 863 | * 864 | * 865 | * 866 | * 867 | * 868 | * 869 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
dnsintegerNoneNonetiming
870 | *
Example value: 43
871 | * Example usage: dns=43
872 | */ 873 | public DefaultRequest dnsTime(Integer value) { 874 | setInteger(DNS_TIME, value); 875 | return this; 876 | } 877 | 878 | public Integer dnsTime() { 879 | return getInteger(DNS_TIME); 880 | } 881 | 882 | /** 883 | *
884 | *

885 | * Optional. 886 | *

887 | *

888 | * Specifies the time it took for the page to be downloaded. The value is in milliseconds. 889 | *

890 | * 891 | * 892 | * 893 | * 894 | * 895 | * 896 | * 897 | * 898 | * 899 | * 900 | * 901 | * 902 | * 903 | * 904 | * 905 | * 906 | * 907 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
pdtintegerNoneNonetiming
908 | *
Example value: 500
909 | * Example usage: pdt=500
910 | */ 911 | public DefaultRequest pageDownloadTime(Integer value) { 912 | setInteger(PAGE_DOWNLOAD_TIME, value); 913 | return this; 914 | } 915 | 916 | public Integer pageDownloadTime() { 917 | return getInteger(PAGE_DOWNLOAD_TIME); 918 | } 919 | 920 | /** 921 | *
922 | *

923 | * Optional. 924 | *

925 | *

926 | * Specifies the time it took for any redirects to happen. The value is in milliseconds. 927 | *

928 | * 929 | * 930 | * 931 | * 932 | * 933 | * 934 | * 935 | * 936 | * 937 | * 938 | * 939 | * 940 | * 941 | * 942 | * 943 | * 944 | * 945 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
rrtintegerNoneNonetiming
946 | *
Example value: 500
947 | * Example usage: rrt=500
948 | */ 949 | public DefaultRequest redirectResponseTime(Integer value) { 950 | setInteger(REDIRECT_RESPONSE_TIME, value); 951 | return this; 952 | } 953 | 954 | public Integer redirectResponseTime() { 955 | return getInteger(REDIRECT_RESPONSE_TIME); 956 | } 957 | 958 | /** 959 | *
960 | *

961 | * Optional. 962 | *

963 | *

964 | * Specifies the time it took for a TCP connection to be made. The value is in milliseconds. 965 | *

966 | * 967 | * 968 | * 969 | * 970 | * 971 | * 972 | * 973 | * 974 | * 975 | * 976 | * 977 | * 978 | * 979 | * 980 | * 981 | * 982 | * 983 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
tcpintegerNoneNonetiming
984 | *
Example value: 500
985 | * Example usage: tcp=500
986 | */ 987 | public DefaultRequest tcpConnectTime(Integer value) { 988 | setInteger(TCP_CONNECT_TIME, value); 989 | return this; 990 | } 991 | 992 | public Integer tcpConnectTime() { 993 | return getInteger(TCP_CONNECT_TIME); 994 | } 995 | 996 | /** 997 | *
998 | *

999 | * Optional. 1000 | *

1001 | *

1002 | * Specifies the time it took for the server to respond after the connect time. The value is in milliseconds. 1003 | *

1004 | * 1005 | * 1006 | * 1007 | * 1008 | * 1009 | * 1010 | * 1011 | * 1012 | * 1013 | * 1014 | * 1015 | * 1016 | * 1017 | * 1018 | * 1019 | * 1020 | * 1021 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
srtintegerNoneNonetiming
1022 | *
Example value: 500
1023 | * Example usage: srt=500
1024 | */ 1025 | public DefaultRequest serverResponseTime(Integer value) { 1026 | setInteger(SERVER_RESPONSE_TIME, value); 1027 | return this; 1028 | } 1029 | 1030 | public Integer serverResponseTime() { 1031 | return getInteger(SERVER_RESPONSE_TIME); 1032 | } 1033 | 1034 | /** 1035 | *
1036 | *

1037 | * Required for transaction hit type.
1038 | * Required for item hit type. 1039 | *

1040 | *

1041 | * A unique identifier for the transaction. This value should be the same for both the Transaction hit and Items 1042 | * hits associated to the particular transaction. 1043 | *

1044 | * 1045 | * 1046 | * 1047 | * 1048 | * 1049 | * 1050 | * 1051 | * 1052 | * 1053 | * 1054 | * 1055 | * 1056 | * 1057 | * 1058 | * 1059 | * 1060 | * 1061 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
titextNone500 Bytestransaction, item
1062 | *
Example value: OD564
1063 | * Example usage: ti=OD564
1064 | */ 1065 | public DefaultRequest txId(String value) { 1066 | setString(TRANSACTION_ID, value); 1067 | return this; 1068 | } 1069 | 1070 | public String txId() { 1071 | return getString(TRANSACTION_ID); 1072 | } 1073 | 1074 | /** 1075 | *
1076 | *

1077 | * Optional. 1078 | *

1079 | *

1080 | * Specifies the affiliation or store name. 1081 | *

1082 | * 1083 | * 1084 | * 1085 | * 1086 | * 1087 | * 1088 | * 1089 | * 1090 | * 1091 | * 1092 | * 1093 | * 1094 | * 1095 | * 1096 | * 1097 | * 1098 | * 1099 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
tatextNone500 Bytestransaction
1100 | *
Example value: Member
1101 | * Example usage: ta=Member
1102 | */ 1103 | public DefaultRequest txAffiliation(String value) { 1104 | setString(TRANSACTION_AFFILIATION, value); 1105 | return this; 1106 | } 1107 | 1108 | public String txAffiliation() { 1109 | return getString(TRANSACTION_AFFILIATION); 1110 | } 1111 | 1112 | /** 1113 | *
1114 | *

1115 | * Optional. 1116 | *

1117 | *

1118 | * Specifies the total revenue associated with the transaction. This value should include any shipping or tax costs. 1119 | *

1120 | * 1121 | * 1122 | * 1123 | * 1124 | * 1125 | * 1126 | * 1127 | * 1128 | * 1129 | * 1130 | * 1131 | * 1132 | * 1133 | * 1134 | * 1135 | * 1136 | * 1137 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
trcurrency0Nonetransaction
1138 | *
Example value: 15.47
1139 | * Example usage: tr=15.47
1140 | */ 1141 | public DefaultRequest txRevenue(Double value) { 1142 | setDouble(TRANSACTION_REVENUE, value); 1143 | return this; 1144 | } 1145 | 1146 | public Double txRevenue() { 1147 | return getDouble(TRANSACTION_REVENUE); 1148 | } 1149 | 1150 | /** 1151 | *
1152 | *

1153 | * Optional. 1154 | *

1155 | *

1156 | * Specifies the total shipping cost of the transaction. 1157 | *

1158 | * 1159 | * 1160 | * 1161 | * 1162 | * 1163 | * 1164 | * 1165 | * 1166 | * 1167 | * 1168 | * 1169 | * 1170 | * 1171 | * 1172 | * 1173 | * 1174 | * 1175 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
tscurrency0Nonetransaction
1176 | *
Example value: 3.50
1177 | * Example usage: ts=3.50
1178 | */ 1179 | public DefaultRequest txShipping(Double value) { 1180 | setDouble(TRANSACTION_SHIPPING, value); 1181 | return this; 1182 | } 1183 | 1184 | public Double txShipping() { 1185 | return getDouble(TRANSACTION_SHIPPING); 1186 | } 1187 | 1188 | /** 1189 | *
1190 | *

1191 | * Optional. 1192 | *

1193 | *

1194 | * Specifies the total tax of the transaction. 1195 | *

1196 | * 1197 | * 1198 | * 1199 | * 1200 | * 1201 | * 1202 | * 1203 | * 1204 | * 1205 | * 1206 | * 1207 | * 1208 | * 1209 | * 1210 | * 1211 | * 1212 | * 1213 | *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ttcurrency0Nonetransaction
1214 | *
Example value: 11.20
1215 | * Example usage: tt=11.20
1216 | */ 1217 | public DefaultRequest txTax(Double value) { 1218 | setDouble(TRANSACTION_TAX, value); 1219 | return this; 1220 | } 1221 | 1222 | public Double txTax() { 1223 | return getDouble(TRANSACTION_TAX); 1224 | } 1225 | } 1226 | --------------------------------------------------------------------------------