diff --git a/pom.xml b/pom.xml index b26b95d..3558026 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 org.sonatype.oss @@ -8,35 +9,37 @@ com.brsanthu google-analytics-java - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT jar 1.8 1.7.25 - 4.11 - 4.5.3 + 4.5.8 + 5.4.2 + 1.4.0 UTF-8 + 2.27.0 + 3.12.0 - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.8 - true - - ossrh - https://oss.sonatype.org/ - true - + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.8 + true + + ossrh + https://oss.sonatype.org/ + true + maven-compiler-plugin - 3.6.2 + 3.8.1 ${java-version} ${java-version} @@ -58,7 +61,7 @@ maven-javadoc-plugin - 2.10.4 + 3.1.0 *.internal.* false @@ -76,7 +79,7 @@ maven-jar-plugin - 2.6 + 3.1.2 true @@ -91,7 +94,7 @@ maven-surefire-plugin - 2.20 + 2.22.2 false @@ -100,7 +103,7 @@ org.apache.felix maven-bundle-plugin - 3.3.0 + 4.2.0 META-INF @@ -129,7 +132,7 @@ org.apache.maven.plugins maven-release-plugin - 2.5.3 + 2.5.3 @@ -156,10 +159,42 @@ + + + com.googlecode.json-simple + json-simple + 1.1.1 + test + + + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.version} + test + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit.jupiter.version} + test + + + org.assertj + assertj-core + ${assertj.version} + test + - junit - junit - ${junit.version} + org.mockito + mockito-core + ${mockito.version} test @@ -175,8 +210,8 @@ https://github.com/brsanthu/google-analytics-java scm:git:git@github.com:brsanthu/google-analytics-java scm:git:git@github.com:brsanthu/google-analytics-java - google-analytics-java-1.1.2 - + google-analytics-java-1.1.2 + github.com https://github.com/brsanthu/google-analytics-java/issues diff --git a/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsBuilder.java b/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsBuilder.java index 4f5e43d..e0c6f56 100644 --- a/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsBuilder.java +++ b/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsBuilder.java @@ -20,6 +20,12 @@ public class GoogleAnalyticsBuilder { private DefaultRequest defaultRequest = new DefaultRequest(); private HttpClient httpClient; private ExecutorService executor; + private GoogleAnalyticsExecutor googleAnalyticsExecutor; + + public GoogleAnalyticsBuilder withGoogleAnalyticsExecutor(GoogleAnalyticsExecutor googleAnalyticsExecutor) { + this.googleAnalyticsExecutor = googleAnalyticsExecutor; + return this; + } public GoogleAnalyticsBuilder withConfig(GoogleAnalyticsConfig config) { this.config = GaUtils.firstNotNull(config, new GoogleAnalyticsConfig()); @@ -64,7 +70,7 @@ public GoogleAnalytics build() { discoverer.discoverParameters(config, defaultRequest); } - return new GoogleAnalyticsImpl(config, defaultRequest, createHttpClient(), createExecutor()); + return new GoogleAnalyticsImpl(config, defaultRequest, createHttpClient(), createExecutor(), googleAnalyticsExecutor); } protected HttpClient createHttpClient() { diff --git a/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsConfig.java b/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsConfig.java index 0644872..93d4a32 100644 --- a/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsConfig.java +++ b/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsConfig.java @@ -43,6 +43,8 @@ public class GoogleAnalyticsConfig { private int batchSize = 20; private String httpUrl = "http://www.google-analytics.com/collect"; private String httpsUrl = "https://www.google-analytics.com/collect"; + private String httpDebugUrl = "http://www.google-analytics.com/debug/collect"; + private String httpsDebugUrl = "https://www.google-analytics.com/debug/collect"; private String batchUrl = "https://www.google-analytics.com/batch"; private String userAgent = null; private String proxyHost = null; @@ -52,6 +54,10 @@ public class GoogleAnalyticsConfig { private boolean discoverRequestParameters = true; private boolean gatherStats = false; private RequestParameterDiscoverer requestParameterDiscoverer = new DefaultRequestParameterDiscoverer(); + private GoogleAnalyticsExceptionHandler exceptionHandler; + private boolean autoQueueTimeEnabled = true; + private boolean anonymizeUserIp = false; + private boolean hitDebug = false; public RequestParameterDiscoverer getRequestParameterDiscoverer() { return requestParameterDiscoverer; @@ -125,7 +131,7 @@ public GoogleAnalyticsConfig setDeriveSystemParameters(boolean deriveSystemPrope *

*/ public GoogleAnalyticsConfig setDiscoverRequestParameters(boolean discoverSystemParameters) { - this.discoverRequestParameters = discoverSystemParameters; + discoverRequestParameters = discoverSystemParameters; return this; } @@ -274,6 +280,9 @@ public GoogleAnalyticsConfig setUseHttps(boolean useHttps) { return this; } + /** + * Future use and not used at the moment. + */ public boolean isValidate() { return validate; } @@ -332,7 +341,15 @@ public GoogleAnalyticsConfig setHttpsUrl(String httpsUrl) { return this; } + /** + * Returns the effective url to which we need to post the GA request to based on if hit debug is enabled and if + * https is enabled. + */ public String getUrl() { + if (isHitDebug()) { + return useHttps ? httpsDebugUrl : httpDebugUrl; + } + return useHttps ? httpsUrl : httpUrl; } @@ -404,4 +421,95 @@ public GoogleAnalyticsConfig setBatchSize(int batchSize) { return this; } + public GoogleAnalyticsExceptionHandler getExceptionHandler() { + return exceptionHandler; + } + + /** + * Set an exception handler which will implement the behavior in case of any exceptions. If not set, default + * behavior is to log a warning message. + * + * @since 2.1 + */ + public GoogleAnalyticsConfig setExceptionHandler(GoogleAnalyticsExceptionHandler exceptionHandler) { + this.exceptionHandler = exceptionHandler; + return this; + } + + public boolean isAutoQueueTimeEnabled() { + return autoQueueTimeEnabled; + } + + /** + * If enabled, library will calculate the queue time (qt) at the time request is being posted to GA based on when + * hit request was created and when it is posted to GA. Defaults to true. + * + * @since 2.1 + */ + public GoogleAnalyticsConfig setAutoQueueTimeEnabled(boolean autoQueueTimeEnabled) { + this.autoQueueTimeEnabled = autoQueueTimeEnabled; + return this; + } + + public boolean isAnonymizeUserIp() { + return anonymizeUserIp; + } + + /** + * If true, and if userIp GA parameter is set, then that ip will be anonymized using same logic that is + * used at GA end. Defaults to false. + *

+ * See for more info: + *

    + *
  • https://github.com/brsanthu/google-analytics-java/issues/57 + *
  • https://support.google.com/analytics/answer/2763052?hl=en + *
+ */ + public GoogleAnalyticsConfig setAnonymizeUserIp(boolean anonymizeUserIp) { + this.anonymizeUserIp = anonymizeUserIp; + return this; + } + + public String getHttpDebugUrl() { + return httpDebugUrl; + } + + public GoogleAnalyticsConfig setHttpDebugUrl(String httpDebugUrl) { + this.httpDebugUrl = httpDebugUrl; + return this; + } + + public String getHttpsDebugUrl() { + return httpsDebugUrl; + } + + public GoogleAnalyticsConfig setHttpsDebugUrl(String httpsDebugUrl) { + this.httpsDebugUrl = httpsDebugUrl; + return this; + } + + public boolean isHitDebug() { + return hitDebug; + } + + /** + * If set to true, then library will use debug urls instead of normal GA urls (debugHttpUrl and + * debugHttpsUrl) which should return the hit validation response as part of http response. This would + * be captured as part of {@link GoogleAnalyticsResponse#getHttpResponse().getBody()}. + *

+ * Library provides convenient validation response models at com.brsanthu.googleanalytics.debug package + * to deserialize http response (which will be in json format) into. + *

+ * Note that to hit debug, disable batching as hit debug is not supported in batch mode. + *

+ * Deserialization itself is not part of the library to avoid the dependency. + *

+ * See this + * for more info. + */ + public GoogleAnalyticsConfig setHitDebug(boolean validateHits) { + hitDebug = validateHits; + return this; + } + } diff --git a/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsExceptionHandler.java b/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsExceptionHandler.java new file mode 100644 index 0000000..5b9ecdf --- /dev/null +++ b/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsExceptionHandler.java @@ -0,0 +1,22 @@ +package com.brsanthu.googleanalytics; + +/** + * Models a handler which can be used to handle exceptions thrown while sending GA requests to google. This can be set + * as config parameter as below. + * + *

+ *  GoogleAnalytics propagatingGa = GoogleAnalytics.builder()withConfig(
+ *      new GoogleAnalyticsConfig().setExceptionHandler(new YourExceptionHandler())
+ *  ).build();
+ * 
+ * + *

+ * Library comes with following implementations. + *

    + *
  • {@link PropagatingExceptionHandler} which propagates the exceptions. + *
+ */ +@FunctionalInterface +public interface GoogleAnalyticsExceptionHandler { + void handle(Throwable t); +} diff --git a/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsStats.java b/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsStats.java index 0982629..b63db1f 100644 --- a/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsStats.java +++ b/src/main/java/com/brsanthu/googleanalytics/GoogleAnalyticsStats.java @@ -1,6 +1,7 @@ package com.brsanthu.googleanalytics; public interface GoogleAnalyticsStats { + long getTotalHits(); long getPageViewHits(); @@ -17,4 +18,4 @@ public interface GoogleAnalyticsStats { long getSocialHits(); long getExceptionHits(); -} \ No newline at end of file +} diff --git a/src/main/java/com/brsanthu/googleanalytics/PropagatingExceptionHandler.java b/src/main/java/com/brsanthu/googleanalytics/PropagatingExceptionHandler.java new file mode 100644 index 0000000..50255c7 --- /dev/null +++ b/src/main/java/com/brsanthu/googleanalytics/PropagatingExceptionHandler.java @@ -0,0 +1,16 @@ +package com.brsanthu.googleanalytics; + +/** + * Exception handler which propagates the exceptions instead of just logging. + */ +public class PropagatingExceptionHandler implements GoogleAnalyticsExceptionHandler { + + @Override + public void handle(Throwable t) { + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } + + throw new GoogleAnalyticsException(t); + } +} diff --git a/src/main/java/com/brsanthu/googleanalytics/hitdebug/HitParsingResult.java b/src/main/java/com/brsanthu/googleanalytics/hitdebug/HitParsingResult.java new file mode 100644 index 0000000..87671c7 --- /dev/null +++ b/src/main/java/com/brsanthu/googleanalytics/hitdebug/HitParsingResult.java @@ -0,0 +1,38 @@ +package com.brsanthu.googleanalytics.hitdebug; + +import java.util.ArrayList; +import java.util.List; + +public class HitParsingResult { + private boolean valid; + private String hit; + private List parserMessage = new ArrayList<>(); + + public boolean isValid() { + return valid; + } + + public HitParsingResult setValid(boolean valid) { + this.valid = valid; + return this; + } + + public String getHit() { + return hit; + } + + public HitParsingResult setHit(String hit) { + this.hit = hit; + return this; + } + + public List getParserMessage() { + return parserMessage; + } + + public HitParsingResult setParserMessage(List parserMessage) { + this.parserMessage = parserMessage; + return this; + } + +} diff --git a/src/main/java/com/brsanthu/googleanalytics/hitdebug/HitValidationResponse.java b/src/main/java/com/brsanthu/googleanalytics/hitdebug/HitValidationResponse.java new file mode 100644 index 0000000..5241cc5 --- /dev/null +++ b/src/main/java/com/brsanthu/googleanalytics/hitdebug/HitValidationResponse.java @@ -0,0 +1,31 @@ +package com.brsanthu.googleanalytics.hitdebug; + +import java.util.ArrayList; +import java.util.List; + +public class HitValidationResponse { + private List hitParsingResult = new ArrayList<>(); + private List parserMessage = new ArrayList<>(); + + public HitValidationResponse() { + // default + } + + public List getHitParsingResult() { + return hitParsingResult; + } + + public HitValidationResponse setHitParsingResult(List hitParsingResult) { + this.hitParsingResult = hitParsingResult; + return this; + } + + public List getParserMessage() { + return parserMessage; + } + + public HitValidationResponse setParserMessage(List parserMessage) { + this.parserMessage = parserMessage; + return this; + } +} diff --git a/src/main/java/com/brsanthu/googleanalytics/hitdebug/ParserMessage.java b/src/main/java/com/brsanthu/googleanalytics/hitdebug/ParserMessage.java new file mode 100644 index 0000000..61b22cc --- /dev/null +++ b/src/main/java/com/brsanthu/googleanalytics/hitdebug/ParserMessage.java @@ -0,0 +1,46 @@ +package com.brsanthu.googleanalytics.hitdebug; + +public class ParserMessage { + private String messageType; + private String description; + private String parameter; + + public String getMessageType() { + return messageType; + } + + public ParserMessage setMessageType(String messageType) { + this.messageType = messageType; + return this; + } + + public String getDescription() { + return description; + } + + public ParserMessage setDescription(String description) { + this.description = description; + return this; + } + + public String getParameter() { + return parameter; + } + + public ParserMessage setParameter(String parameter) { + this.parameter = parameter; + return this; + } + + public boolean isInfo() { + return "info".equalsIgnoreCase(messageType); + } + + public boolean isWarn() { + return "warn".equalsIgnoreCase(messageType); + } + + public boolean isError() { + return "error".equalsIgnoreCase(messageType); + } +} diff --git a/src/main/java/com/brsanthu/googleanalytics/httpclient/ApacheHttpClientImpl.java b/src/main/java/com/brsanthu/googleanalytics/httpclient/ApacheHttpClientImpl.java index 75ed8cf..5e30837 100644 --- a/src/main/java/com/brsanthu/googleanalytics/httpclient/ApacheHttpClientImpl.java +++ b/src/main/java/com/brsanthu/googleanalytics/httpclient/ApacheHttpClientImpl.java @@ -101,6 +101,7 @@ public HttpResponse post(HttpRequest req) { httpResp = execute(req.getUrl(), new UrlEncodedFormEntity(createNameValuePairs(req), StandardCharsets.UTF_8)); resp.setStatusCode(httpResp.getStatusLine().getStatusCode()); + resp.setBody(EntityUtils.toString(httpResp.getEntity(), "UTF-8")); } catch (Exception e) { if (e instanceof UnknownHostException) { diff --git a/src/main/java/com/brsanthu/googleanalytics/httpclient/HttpRequest.java b/src/main/java/com/brsanthu/googleanalytics/httpclient/HttpRequest.java index 75f25f6..1997e6e 100644 --- a/src/main/java/com/brsanthu/googleanalytics/httpclient/HttpRequest.java +++ b/src/main/java/com/brsanthu/googleanalytics/httpclient/HttpRequest.java @@ -3,14 +3,17 @@ import java.util.HashMap; import java.util.Map; +import com.brsanthu.googleanalytics.request.GoogleAnalyticsRequest; + public class HttpRequest { private String contentType; private String method; private String url; private Map bodyParams = new HashMap<>(); + private GoogleAnalyticsRequest googleAnalyticsRequest; public HttpRequest(String url) { - this.setUrl(url); + setUrl(url); } public HttpRequest post() { @@ -53,4 +56,13 @@ public HttpRequest setUrl(String url) { this.url = url; return this; } + + public GoogleAnalyticsRequest getGoogleAnalyticsRequest() { + return googleAnalyticsRequest; + } + + public HttpRequest setGoogleAnalyticsRequest(GoogleAnalyticsRequest googleAnalyticsRequest) { + this.googleAnalyticsRequest = googleAnalyticsRequest; + return this; + } } diff --git a/src/main/java/com/brsanthu/googleanalytics/httpclient/HttpResponse.java b/src/main/java/com/brsanthu/googleanalytics/httpclient/HttpResponse.java index ca337c3..96e0ed2 100644 --- a/src/main/java/com/brsanthu/googleanalytics/httpclient/HttpResponse.java +++ b/src/main/java/com/brsanthu/googleanalytics/httpclient/HttpResponse.java @@ -1,8 +1,13 @@ package com.brsanthu.googleanalytics.httpclient; +import java.util.HashMap; +import java.util.Map; + public class HttpResponse { private int statusCode; + private String body; + private Map headers = new HashMap<>(); public int getStatusCode() { return statusCode; @@ -13,4 +18,22 @@ public HttpResponse setStatusCode(int statusCode) { return this; } + public String getBody() { + return body; + } + + public HttpResponse setBody(String body) { + this.body = body; + return this; + } + + public Map getHeaders() { + return headers; + } + + public HttpResponse setHeaders(Map headers) { + this.headers = headers; + return this; + } + } diff --git a/src/main/java/com/brsanthu/googleanalytics/internal/GoogleAnalyticsImpl.java b/src/main/java/com/brsanthu/googleanalytics/internal/GoogleAnalyticsImpl.java index bd3b0f8..87728f8 100644 --- a/src/main/java/com/brsanthu/googleanalytics/internal/GoogleAnalyticsImpl.java +++ b/src/main/java/com/brsanthu/googleanalytics/internal/GoogleAnalyticsImpl.java @@ -11,7 +11,12 @@ package com.brsanthu.googleanalytics.internal; import static com.brsanthu.googleanalytics.internal.GaUtils.isEmpty; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.QUEUE_TIME; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -63,14 +68,17 @@ public class GoogleAnalyticsImpl implements GoogleAnalytics, GoogleAnalyticsExec protected final DefaultRequest defaultRequest; protected final HttpClient httpClient; protected final ExecutorService executor; + protected final GoogleAnalyticsExecutor googleAnalyticsExecutor; protected GoogleAnalyticsStatsImpl stats = new GoogleAnalyticsStatsImpl(); protected List currentBatch = new ArrayList<>(); - public GoogleAnalyticsImpl(GoogleAnalyticsConfig config, DefaultRequest defaultRequest, HttpClient httpClient, ExecutorService executor) { + public GoogleAnalyticsImpl(GoogleAnalyticsConfig config, DefaultRequest defaultRequest, HttpClient httpClient, ExecutorService executor, + GoogleAnalyticsExecutor googleAnalyticsExecutor) { this.config = config; this.defaultRequest = defaultRequest; this.httpClient = httpClient; this.executor = executor; + this.googleAnalyticsExecutor = googleAnalyticsExecutor; } @Override @@ -83,17 +91,27 @@ public DefaultRequest getDefaultRequest() { } @Override - public Future postAsync(GoogleAnalyticsRequest request) { + public Future postAsync(GoogleAnalyticsRequest gaReq) { + if (googleAnalyticsExecutor != null) { + return googleAnalyticsExecutor.postAsync(gaReq); + } + if (!config.isEnabled()) { return null; } - return executor.submit(() -> post(request)); + return executor.submit(() -> post(gaReq)); } @Override public GoogleAnalyticsResponse post(GoogleAnalyticsRequest gaReq) { + if (googleAnalyticsExecutor != null) { + return googleAnalyticsExecutor.post(gaReq); + } + GoogleAnalyticsResponse response = new GoogleAnalyticsResponse(); + response.setGoogleAnalyticsRequest(gaReq); + if (!config.isEnabled()) { return response; } @@ -105,8 +123,12 @@ public GoogleAnalyticsResponse post(GoogleAnalyticsRequest gaReq) { response = postSingle(gaReq); } - } catch (Exception e) { - logger.warn("Exception while sending the Google Analytics tracker request " + gaReq, e); + } catch (Throwable e) { + if (config.getExceptionHandler() != null) { + config.getExceptionHandler().handle(e); + } else { + logger.warn("Exception while sending the Google Analytics tracker request " + gaReq, e); + } } return response; @@ -114,6 +136,8 @@ public GoogleAnalyticsResponse post(GoogleAnalyticsRequest gaReq) { protected GoogleAnalyticsResponse postBatch(GoogleAnalyticsRequest gaReq) { GoogleAnalyticsResponse resp = new GoogleAnalyticsResponse(); + resp.setGoogleAnalyticsRequest(gaReq); + HttpRequest httpReq = createHttpRequest(gaReq); resp.setRequestParams(httpReq.getBodyParams()); @@ -147,6 +171,8 @@ private void submitBatch(boolean force) { // others will not post it even if multiple threads were to wait at sync block at same time // https://en.wikipedia.org/wiki/Double-checked_locking if (isSubmitBatch(force)) { + processAutoQueueTime(currentBatch); + logger.debug("Submitting a batch of " + currentBatch.size() + " requests to GA"); httpClient.postBatch(new HttpBatchRequest().setUrl(config.getBatchUrl()).setRequests(currentBatch)); currentBatch.clear(); @@ -155,18 +181,60 @@ private void submitBatch(boolean force) { } } + protected HttpRequest processAutoQueueTime(HttpRequest request) { + if (!config.isAutoQueueTimeEnabled()) { + return request; + } + + List requests = new ArrayList<>(); + requests.add(request); + + processAutoQueueTime(requests); + + return request; + } + + protected void processAutoQueueTime(List requests) { + if (!config.isAutoQueueTimeEnabled()) { + return; + } + + // If there is no queue time specified, then set the queue time to time since event occurred to current time + // (time at which event being posted). This is helpful for batched requests as request may be sitting in queue + // for a while and we need to calculate the time. + for (HttpRequest req : requests) { + if (req.getGoogleAnalyticsRequest() == null || req.getGoogleAnalyticsRequest().occurredAt() == null) { + continue; + } + + String qtParamName = QUEUE_TIME.getParameterName(); + + Map params = req.getBodyParams(); + + int millis = (int) ChronoUnit.MILLIS.between(req.getGoogleAnalyticsRequest().occurredAt(), ZonedDateTime.now()); + int qtMillis = params.containsKey(qtParamName) ? millis + Integer.parseInt(params.get(qtParamName)) : millis; + + params.put(qtParamName, String.valueOf(qtMillis)); + + req.getGoogleAnalyticsRequest().queueTime(qtMillis); + } + } + private boolean isSubmitBatch(boolean force) { return force || currentBatch.size() >= config.getBatchSize(); } protected GoogleAnalyticsResponse postSingle(GoogleAnalyticsRequest gaReq) { - HttpRequest httpReq = createHttpRequest(gaReq); + HttpRequest httpReq = processAutoQueueTime(createHttpRequest(gaReq)); HttpResponse httpResp = httpClient.post(httpReq); GoogleAnalyticsResponse response = new GoogleAnalyticsResponse(); + response.setGoogleAnalyticsRequest(gaReq); response.setStatusCode(httpResp.getStatusCode()); response.setRequestParams(httpReq.getBodyParams()); + response.setHttpRequest(httpReq); + response.setHttpResponse(httpResp); if (config.isGatherStats()) { gatherStats(gaReq); @@ -178,21 +246,20 @@ protected GoogleAnalyticsResponse postSingle(GoogleAnalyticsRequest gaReq) { private HttpRequest createHttpRequest(GoogleAnalyticsRequest gaReq) { HttpRequest httpReq = new HttpRequest(config.getUrl()); - // Process the parameters + httpReq.setGoogleAnalyticsRequest(gaReq); + processParameters(gaReq, httpReq); - // Process custom dimensions processCustomDimensionParameters(gaReq, httpReq); - // Process custom metrics processCustomMetricParameters(gaReq, httpReq); return httpReq; } - protected void processParameters(GoogleAnalyticsRequest request, HttpRequest req) { + protected void processParameters(GoogleAnalyticsRequest gaReq, HttpRequest httpReq) { - Map requestParms = request.getParameters(); + Map requestParms = gaReq.getParameters(); Map defaultParms = defaultRequest.getParameters(); for (GoogleAnalyticsParameter parm : defaultParms.keySet()) { @@ -205,8 +272,29 @@ protected void processParameters(GoogleAnalyticsRequest request, HttpRequest } } + anonymizeUserIp(gaReq, httpReq); + for (GoogleAnalyticsParameter key : requestParms.keySet()) { - req.addBodyParam(key.getParameterName(), requestParms.get(key)); + httpReq.addBodyParam(key.getParameterName(), requestParms.get(key)); + } + } + + private void anonymizeUserIp(GoogleAnalyticsRequest gaReq, HttpRequest httpReq) { + if (config.isAnonymizeUserIp() && gaReq.userIp() != null) { + try { + InetAddress ip = InetAddress.getByName(gaReq.userIp()); + byte[] address = ip.getAddress(); + int anonymizedBytes = ip instanceof Inet6Address ? 10 : 1; + + for (int i = 0; i < anonymizedBytes; ++i) { + address[address.length - i - 1] = 0; + } + + String anonymizedIp = InetAddress.getByAddress(address).getHostAddress(); + gaReq.userIp(anonymizedIp); + } catch (Exception e) { + logger.warn("Error anonymizing user ip", e); + } } } @@ -217,7 +305,7 @@ protected void processParameters(GoogleAnalyticsRequest request, HttpRequest * @param postParms */ protected void processCustomDimensionParameters(GoogleAnalyticsRequest request, HttpRequest req) { - Map customDimParms = new HashMap(); + Map customDimParms = new HashMap<>(); for (String defaultCustomDimKey : defaultRequest.customDimensions().keySet()) { customDimParms.put(defaultCustomDimKey, defaultRequest.customDimensions().get(defaultCustomDimKey)); } @@ -239,12 +327,12 @@ protected void processCustomDimensionParameters(GoogleAnalyticsRequest reques * @param postParms */ protected void processCustomMetricParameters(GoogleAnalyticsRequest request, HttpRequest req) { - Map customMetricParms = new HashMap(); - for (String defaultCustomMetricKey : defaultRequest.custommMetrics().keySet()) { - customMetricParms.put(defaultCustomMetricKey, defaultRequest.custommMetrics().get(defaultCustomMetricKey)); + Map customMetricParms = new HashMap<>(); + for (String defaultCustomMetricKey : defaultRequest.customMetrics().keySet()) { + customMetricParms.put(defaultCustomMetricKey, defaultRequest.customMetrics().get(defaultCustomMetricKey)); } - Map requestCustomMetrics = request.custommMetrics(); + Map requestCustomMetrics = request.customMetrics(); for (String requestCustomDimKey : requestCustomMetrics.keySet()) { customMetricParms.put(requestCustomDimKey, requestCustomMetrics.get(requestCustomDimKey)); } diff --git a/src/main/java/com/brsanthu/googleanalytics/internal/GoogleAnalyticsStatsImpl.java b/src/main/java/com/brsanthu/googleanalytics/internal/GoogleAnalyticsStatsImpl.java index ccb9d69..2b90e3b 100644 --- a/src/main/java/com/brsanthu/googleanalytics/internal/GoogleAnalyticsStatsImpl.java +++ b/src/main/java/com/brsanthu/googleanalytics/internal/GoogleAnalyticsStatsImpl.java @@ -1,15 +1,12 @@ /* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package com.brsanthu.googleanalytics.internal; @@ -105,6 +102,12 @@ public long getExceptionHits() { return exceptionHits.get(); } + @Override + public long getTotalHits() { + return pageViewHits.get() + eventHits.get() + screenViewHits.get() + itemHits.get() + transactionHits.get() + timingHits.get() + + socialHits.get() + exceptionHits.get(); + } + @Override public String toString() { return "GoogleAnalyticsStatsImpl [pageViewHits=" + pageViewHits + ", eventHits=" + eventHits + ", screenViewHits=" + screenViewHits diff --git a/src/main/java/com/brsanthu/googleanalytics/request/AnyHit.java b/src/main/java/com/brsanthu/googleanalytics/request/AnyHit.java new file mode 100644 index 0000000..5d33b04 --- /dev/null +++ b/src/main/java/com/brsanthu/googleanalytics/request/AnyHit.java @@ -0,0 +1,1194 @@ +package com.brsanthu.googleanalytics.request; + +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.CURRENCY_CODE; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.DNS_TIME; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_ACTION; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_CATEGORY; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_LABEL; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_VALUE; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EXCEPTION_DESCRIPTION; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EXCEPTION_FATAL; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_CATEGORY; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_CODE; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_NAME; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_PRICE; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_QUANTITY; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.PAGE_DOWNLOAD_TIME; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.PAGE_LOAD_TIME; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.REDIRECT_RESPONSE_TIME; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SCREEN_NAME; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SERVER_RESPONSE_TIME; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SOCIAL_ACTION; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SOCIAL_ACTION_TARGET; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SOCIAL_NETWORK; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TCP_CONNECT_TIME; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_AFFILIATION; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_ID; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_REVENUE; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_SHIPPING; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_TAX; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.USER_TIMING_CATEGORY; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.USER_TIMING_LABEL; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.USER_TIMING_TIME; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.USER_TIMING_VARIABLE_NAME; + +/** + * Represents a generic GA hit which provides access all supported GA parameters as typed accessors. You can use this + * hit type if you want to set GA hit type as dynamic parameter instead of dealing with constructing hit type specific + * instance. + */ +public class AnyHit extends GoogleAnalyticsRequest { + + /** + *

Event Tracking

+ *

+ * Optional. + *

+ *

+ * Specifies the event category. Must not be empty. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ectextNone150 Bytesevent
+ *
Example value: Category
+ * Example usage: ec=Category
+ */ + public AnyHit eventCategory(String value) { + setString(EVENT_CATEGORY, value); + return this; + } + + public String eventCategory() { + return getString(EVENT_CATEGORY); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the event action. Must not be empty. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
eatextNone500 Bytesevent
+ *
Example value: Action
+ * Example usage: ea=Action
+ */ + public AnyHit eventAction(String value) { + setString(EVENT_ACTION, value); + return this; + } + + public String eventAction() { + return getString(EVENT_ACTION); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the event label. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
eltextNone500 Bytesevent
+ *
Example value: Label
+ * Example usage: el=Label
+ */ + public AnyHit eventLabel(String value) { + setString(EVENT_LABEL, value); + return this; + } + + public String eventLabel() { + return getString(EVENT_LABEL); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the event value. Values must be non-negative. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
evintegerNoneNoneevent
+ *
Example value: 55
+ * Example usage: ev=55
+ */ + public AnyHit eventValue(Integer value) { + setInteger(EVENT_VALUE, value); + return this; + } + + public Integer eventValue() { + return getInteger(EVENT_VALUE); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the description of an exception. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
exdtextNone150 Bytesexception
+ *
Example value: DatabaseError
+ * Example usage: exd=DatabaseError
+ */ + public AnyHit exceptionDescription(String value) { + setString(EXCEPTION_DESCRIPTION, value); + return this; + } + + public String exceptionDescription() { + return getString(EXCEPTION_DESCRIPTION); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies whether the exception was fatal. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
exfboolean1Noneexception
+ *
Example value: 0
+ * Example usage: exf=0
+ */ + public AnyHit exceptionFatal(Boolean value) { + setBoolean(EXCEPTION_FATAL, value); + return this; + } + + public Boolean exceptionFatal() { + return getBoolean(EXCEPTION_FATAL); + } + + /** + *
+ *

+ * Required for transaction hit type.
+ * Required for item hit type. + *

+ *

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

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
titextNone500 Bytestransaction, item
+ *
Example value: OD564
+ * Example usage: ti=OD564
+ */ + public AnyHit txId(String value) { + setString(TRANSACTION_ID, value); + return this; + } + + public String txId() { + return getString(TRANSACTION_ID); + } + + /** + *
+ *

+ * Required for item hit type. + *

+ *

+ * Specifies the item name. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
intextNone500 Bytesitem
+ *
Example value: Shoe
+ * Example usage: in=Shoe
+ */ + public AnyHit itemName(String value) { + setString(ITEM_NAME, value); + return this; + } + + public String itemName() { + return getString(ITEM_NAME); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the price for a single item / unit. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ipcurrency0Noneitem
+ *
Example value: 3.50
+ * Example usage: ip=3.50
+ */ + public AnyHit itemPrice(Double value) { + setDouble(ITEM_PRICE, value); + return this; + } + + public Double itemPrice() { + return getDouble(ITEM_PRICE); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the number of items purchased. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
iqinteger0Noneitem
+ *
Example value: 4
+ * Example usage: iq=4
+ */ + public AnyHit itemQuantity(Integer value) { + setInteger(ITEM_QUANTITY, value); + return this; + } + + public Integer itemQuantity() { + return getInteger(ITEM_QUANTITY); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the SKU or item code. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ictextNone500 Bytesitem
+ *
Example value: SKU47
+ * Example usage: ic=SKU47
+ */ + public AnyHit itemCode(String value) { + setString(ITEM_CODE, value); + return this; + } + + public String itemCode() { + return getString(ITEM_CODE); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the category that the item belongs to. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ivtextNone500 Bytesitem
+ *
Example value: Blue
+ * Example usage: iv=Blue
+ */ + public AnyHit itemCategory(String value) { + setString(ITEM_CATEGORY, value); + return this; + } + + public String itemCategory() { + return getString(ITEM_CATEGORY); + } + + /** + *
+ *

+ * Optional. + *

+ *

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

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
cutextNone10 Bytestransaction, item
+ *
Example value: EUR
+ * Example usage: cu=EUR
+ */ + public AnyHit currencyCode(String value) { + setString(CURRENCY_CODE, value); + return this; + } + + public String currencyCode() { + return getString(CURRENCY_CODE); + } + + public AnyHit screenName(String value) { + setString(SCREEN_NAME, value); + return this; + } + + public String screenName() { + return getString(SCREEN_NAME); + } + + /** + *
+ *

+ * Required for social hit type. + *

+ *

+ * Specifies the social network, for example Facebook or Google Plus. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
sntextNone50 Bytessocial
+ *
Example value: facebook
+ * Example usage: sn=facebook
+ */ + public AnyHit socialNetwork(String value) { + setString(SOCIAL_NETWORK, value); + return this; + } + + public String socialNetwork() { + return getString(SOCIAL_NETWORK); + } + + /** + *
+ *

+ * Required for social hit type. + *

+ *

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

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
satextNone50 Bytessocial
+ *
Example value: like
+ * Example usage: sa=like
+ */ + public AnyHit socialAction(String value) { + setString(SOCIAL_ACTION, value); + return this; + } + + public String socialAction() { + return getString(SOCIAL_ACTION); + } + + /** + *
+ *

+ * Required for social hit type. + *

+ *

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

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
sttextNone2048 Bytessocial
+ *
Example value: http://foo.com
+ * Example usage: st=http%3A%2F%2Ffoo.com
+ */ + public AnyHit socialActionTarget(String value) { + setString(SOCIAL_ACTION_TARGET, value); + return this; + } + + public String socialActionTarget() { + return getString(SOCIAL_ACTION_TARGET); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the user timing category. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
utctextNone150 Bytestiming
+ *
Example value: category
+ * Example usage: utc=category
+ */ + public AnyHit userTimingCategory(String value) { + setString(USER_TIMING_CATEGORY, value); + return this; + } + + public String userTimingCategory() { + return getString(USER_TIMING_CATEGORY); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the user timing variable. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
utvtextNone500 Bytestiming
+ *
Example value: lookup
+ * Example usage: utv=lookup
+ */ + public AnyHit userTimingVariableName(String value) { + setString(USER_TIMING_VARIABLE_NAME, value); + return this; + } + + public String userTimingVariableName() { + return getString(USER_TIMING_VARIABLE_NAME); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the user timing value. The value is in milliseconds. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
uttintegerNoneNonetiming
+ *
Example value: 123
+ * Example usage: utt=123
+ */ + public AnyHit userTimingTime(Integer value) { + setInteger(USER_TIMING_TIME, value); + return this; + } + + public Integer userTimingTime() { + return getInteger(USER_TIMING_TIME); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the user timing label. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
utltextNone500 Bytestiming
+ *
Example value: label
+ * Example usage: utl=label
+ */ + public AnyHit userTimingLabel(String value) { + setString(USER_TIMING_LABEL, value); + return this; + } + + public String userTimingLabel() { + return getString(USER_TIMING_LABEL); + } + + /** + *
+ *

+ * Optional. + *

+ *

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

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
pltintegerNoneNonetiming
+ *
Example value: 3554
+ * Example usage: plt=3554
+ */ + public AnyHit pageLoadTime(Integer value) { + setInteger(PAGE_LOAD_TIME, value); + return this; + } + + public Integer pageLoadTime() { + return getInteger(PAGE_LOAD_TIME); + } + + /** + *
+ *

+ * Optional. + *

+ *

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

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
dnsintegerNoneNonetiming
+ *
Example value: 43
+ * Example usage: dns=43
+ */ + public AnyHit dnsTime(Integer value) { + setInteger(DNS_TIME, value); + return this; + } + + public Integer dnsTime() { + return getInteger(DNS_TIME); + } + + /** + *
+ *

+ * Optional. + *

+ *

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

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
pdtintegerNoneNonetiming
+ *
Example value: 500
+ * Example usage: pdt=500
+ */ + public AnyHit pageDownloadTime(Integer value) { + setInteger(PAGE_DOWNLOAD_TIME, value); + return this; + } + + public Integer pageDownloadTime() { + return getInteger(PAGE_DOWNLOAD_TIME); + } + + /** + *
+ *

+ * Optional. + *

+ *

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

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
rrtintegerNoneNonetiming
+ *
Example value: 500
+ * Example usage: rrt=500
+ */ + public AnyHit redirectResponseTime(Integer value) { + setInteger(REDIRECT_RESPONSE_TIME, value); + return this; + } + + public Integer redirectResponseTime() { + return getInteger(REDIRECT_RESPONSE_TIME); + } + + /** + *
+ *

+ * Optional. + *

+ *

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

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
tcpintegerNoneNonetiming
+ *
Example value: 500
+ * Example usage: tcp=500
+ */ + public AnyHit tcpConnectTime(Integer value) { + setInteger(TCP_CONNECT_TIME, value); + return this; + } + + public Integer tcpConnectTime() { + return getInteger(TCP_CONNECT_TIME); + } + + /** + *
+ *

+ * Optional. + *

+ *

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

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
srtintegerNoneNonetiming
+ *
Example value: 500
+ * Example usage: srt=500
+ */ + public AnyHit serverResponseTime(Integer value) { + setInteger(SERVER_RESPONSE_TIME, value); + return this; + } + + public Integer serverResponseTime() { + return getInteger(SERVER_RESPONSE_TIME); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the affiliation or store name. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
tatextNone500 Bytestransaction
+ *
Example value: Member
+ * Example usage: ta=Member
+ */ + public AnyHit txAffiliation(String value) { + setString(TRANSACTION_AFFILIATION, value); + return this; + } + + public String txAffiliation() { + return getString(TRANSACTION_AFFILIATION); + } + + /** + *
+ *

+ * Optional. + *

+ *

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

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
trcurrency0Nonetransaction
+ *
Example value: 15.47
+ * Example usage: tr=15.47
+ */ + public AnyHit txRevenue(Double value) { + setDouble(TRANSACTION_REVENUE, value); + return this; + } + + public Double txRevenue() { + return getDouble(TRANSACTION_REVENUE); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the total shipping cost of the transaction. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
tscurrency0Nonetransaction
+ *
Example value: 3.50
+ * Example usage: ts=3.50
+ */ + public AnyHit txShipping(Double value) { + setDouble(TRANSACTION_SHIPPING, value); + return this; + } + + public Double txShipping() { + return getDouble(TRANSACTION_SHIPPING); + } + + /** + *
+ *

+ * Optional. + *

+ *

+ * Specifies the total tax of the transaction. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ParameterValue TypeDefault ValueMax LengthSupported Hit Types
ttcurrency0Nonetransaction
+ *
Example value: 11.20
+ * Example usage: tt=11.20
+ */ + public AnyHit txTax(Double value) { + setDouble(TRANSACTION_TAX, value); + return this; + } + + public Double txTax() { + return getDouble(TRANSACTION_TAX); + } +} diff --git a/src/main/java/com/brsanthu/googleanalytics/request/DefaultRequest.java b/src/main/java/com/brsanthu/googleanalytics/request/DefaultRequest.java index 6c9a069..5cfa601 100644 --- a/src/main/java/com/brsanthu/googleanalytics/request/DefaultRequest.java +++ b/src/main/java/com/brsanthu/googleanalytics/request/DefaultRequest.java @@ -1,15 +1,12 @@ /* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package com.brsanthu.googleanalytics.request; @@ -47,7 +44,6 @@ import java.util.UUID; -import com.brsanthu.googleanalytics.internal.Constants; import com.brsanthu.googleanalytics.internal.GaUtils; import com.brsanthu.googleanalytics.internal.GoogleAnalyticsImpl; @@ -71,7 +67,7 @@ public DefaultRequest(String hitType) { } public DefaultRequest(String hitType, String trackingId, String appName, String appVersion) { - hitType(GaUtils.isBlank(hitType) ? Constants.HIT_PAGEVIEW : hitType); + hitType(GaUtils.isBlank(hitType) ? HIT_PAGEVIEW : hitType); trackingId(trackingId); applicationName(appName); applicationVersion(appVersion); diff --git a/src/main/java/com/brsanthu/googleanalytics/request/EventHit.java b/src/main/java/com/brsanthu/googleanalytics/request/EventHit.java index 9a16d9e..491a8e9 100644 --- a/src/main/java/com/brsanthu/googleanalytics/request/EventHit.java +++ b/src/main/java/com/brsanthu/googleanalytics/request/EventHit.java @@ -1,19 +1,15 @@ /* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package com.brsanthu.googleanalytics.request; -import static com.brsanthu.googleanalytics.internal.Constants.HIT_EVENT; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_ACTION; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_CATEGORY; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EVENT_LABEL; diff --git a/src/main/java/com/brsanthu/googleanalytics/request/ExceptionHit.java b/src/main/java/com/brsanthu/googleanalytics/request/ExceptionHit.java index c2bd101..6af9b71 100644 --- a/src/main/java/com/brsanthu/googleanalytics/request/ExceptionHit.java +++ b/src/main/java/com/brsanthu/googleanalytics/request/ExceptionHit.java @@ -1,19 +1,15 @@ /* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package com.brsanthu.googleanalytics.request; -import static com.brsanthu.googleanalytics.internal.Constants.HIT_EXCEPTION; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EXCEPTION_DESCRIPTION; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.EXCEPTION_FATAL; diff --git a/src/main/java/com/brsanthu/googleanalytics/request/GoogleAnalyticsRequest.java b/src/main/java/com/brsanthu/googleanalytics/request/GoogleAnalyticsRequest.java index 66281de..686de5d 100644 --- a/src/main/java/com/brsanthu/googleanalytics/request/GoogleAnalyticsRequest.java +++ b/src/main/java/com/brsanthu/googleanalytics/request/GoogleAnalyticsRequest.java @@ -1,15 +1,12 @@ /* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package com.brsanthu.googleanalytics.request; @@ -52,6 +49,7 @@ import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.USER_LANGUAGE; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.VIEWPORT_SIZE; +import java.time.ZonedDateTime; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Future; @@ -72,13 +70,22 @@ * @author Santhosh Kumar */ @SuppressWarnings("unchecked") -public class GoogleAnalyticsRequest { - - protected Map parms = new HashMap(); - protected Map customDimensions = new HashMap(); - protected Map customMetrics = new HashMap(); - +public class GoogleAnalyticsRequest implements Cloneable { + + public static final String HIT_SCREENVIEW = "screenview"; + public static final String HIT_PAGEVIEW = "pageview"; + public static final String HIT_EVENT = "event"; + public static final String HIT_ITEM = "item"; + public static final String HIT_TXN = "transaction"; + public static final String HIT_SOCIAL = "social"; + public static final String HIT_TIMING = "timing"; + public static final String HIT_EXCEPTION = "exception"; + + protected Map parms = new HashMap<>(); + protected Map customDimensions = new HashMap<>(); + protected Map customMetrics = new HashMap<>(); protected GoogleAnalyticsExecutor delegateExecutor = null; + protected ZonedDateTime occurredAt = ZonedDateTime.now(); public GoogleAnalyticsRequest() { this(null, null, null, null); @@ -308,10 +315,20 @@ public Map customDimensions() { return customDimensions; } + /** + * This method name has typo hence has been deprecated. + * + * @deprecated please use {@link #customMetrics} + */ + @Deprecated public Map custommMetrics() { return customMetrics; } + public Map customMetrics() { + return customMetrics; + } + @Override public String toString() { StringBuilder builder = new StringBuilder(); @@ -644,11 +661,11 @@ public String clientId() { * * * - * + * *
Example value: as8eknlll
* Example usage: uid=as8eknlll
- * - * + * + * * * * @param value @@ -1741,7 +1758,7 @@ public String applicationId() { *
*

* Optional. - * + * *

*

* This parameter specifies that this visitor has been exposed to an experiment with the given ID. It should be sent @@ -1765,8 +1782,8 @@ public String applicationId() { * * * - * - * + * + * *

Example value: Qp0gahJ3RAO3DJ18b0XoUQ
* Example usage: xid=Qp0gahJ3RAO3DJ18b0XoUQ
*/ @@ -1783,7 +1800,7 @@ public String experimentId() { *
*

* Optional. - * + * *

*

* This parameter specifies that this visitor has been exposed to a particular variation of an experiment. It should @@ -1880,4 +1897,58 @@ public GoogleAnalyticsRequest setExecutor(GoogleAnalyticsExecutor delegateExe this.delegateExecutor = delegateExecutor; return this; } + + /** + * Indicates the datetime at which this event occurred. This is used to report the qt parameter, if one + * is not set. The occurredAt defaults to datetime when this request was instantiated. + */ + public T occurredAt(ZonedDateTime value) { + this.occurredAt = value; + return (T) this; + } + + public ZonedDateTime occurredAt() { + return occurredAt; + } + + /** + * Deep clones this hit and returns new request of same type. Any changes made to this request after this call, will + * not be reflected in the returned instance. + */ + @Override + public T clone() { + try { + GoogleAnalyticsRequest clonedReq = this.getClass().newInstance(); + clonedReq.occurredAt = ZonedDateTime.now(); + clonedReq.parms = cloneMap(parms); + clonedReq.customDimensions = cloneMap(customDimensions); + clonedReq.customMetrics = cloneMap(customMetrics); + clonedReq.delegateExecutor = delegateExecutor; + + return (T) clonedReq; + } catch (Exception e) { + throw new RuntimeException("Exception while deep cloning " + this, e); + } + } + + private Map cloneMap(Map input) { + Map output = new HashMap<>(); + output.putAll(input); + return output; + } + + /** + * Creates a anyhit wrapper for current request with state shared between this instance and returned {@link AnyHit}. + * If you want a copy, then call {@link #deepClone()} first and then this method. + */ + public AnyHit asAnyHit() { + AnyHit anyHit = new AnyHit(); + anyHit.customDimensions = customDimensions; + anyHit.customMetrics = customMetrics; + anyHit.delegateExecutor = delegateExecutor; + anyHit.parms = parms; + anyHit.occurredAt = occurredAt; + + return anyHit; + } } diff --git a/src/main/java/com/brsanthu/googleanalytics/request/GoogleAnalyticsResponse.java b/src/main/java/com/brsanthu/googleanalytics/request/GoogleAnalyticsResponse.java index eba245f..291be2b 100644 --- a/src/main/java/com/brsanthu/googleanalytics/request/GoogleAnalyticsResponse.java +++ b/src/main/java/com/brsanthu/googleanalytics/request/GoogleAnalyticsResponse.java @@ -1,20 +1,20 @@ /* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package com.brsanthu.googleanalytics.request; import java.util.Map; +import com.brsanthu.googleanalytics.httpclient.HttpRequest; +import com.brsanthu.googleanalytics.httpclient.HttpResponse; + /** * Response for GA tracking request. * @@ -22,18 +22,23 @@ */ public class GoogleAnalyticsResponse { private int statusCode = 200; + private GoogleAnalyticsRequest googleAnalyticsRequest; private Map requestParams = null; + private HttpRequest httpRequest; + private HttpResponse httpResponse; public Map getRequestParams() { return requestParams; } - public void setRequestParams(Map postedParms) { - this.requestParams = postedParms; + public GoogleAnalyticsResponse setRequestParams(Map postedParms) { + requestParams = postedParms; + return this; } - public void setStatusCode(int statusCode) { + public GoogleAnalyticsResponse setStatusCode(int statusCode) { this.statusCode = statusCode; + return this; } public int getStatusCode() { @@ -48,4 +53,31 @@ public String toString() { builder.append("]"); return builder.toString(); } + + public GoogleAnalyticsRequest getGoogleAnalyticsRequest() { + return googleAnalyticsRequest; + } + + public GoogleAnalyticsResponse setGoogleAnalyticsRequest(GoogleAnalyticsRequest googleAnalyticsRequest) { + this.googleAnalyticsRequest = googleAnalyticsRequest; + return this; + } + + public HttpResponse getHttpResponse() { + return httpResponse; + } + + public GoogleAnalyticsResponse setHttpResponse(HttpResponse httpResponse) { + this.httpResponse = httpResponse; + return this; + } + + public HttpRequest getHttpRequest() { + return httpRequest; + } + + public GoogleAnalyticsResponse setHttpRequest(HttpRequest httpRequest) { + this.httpRequest = httpRequest; + return this; + } } diff --git a/src/main/java/com/brsanthu/googleanalytics/request/ItemHit.java b/src/main/java/com/brsanthu/googleanalytics/request/ItemHit.java index c894d85..29887f3 100644 --- a/src/main/java/com/brsanthu/googleanalytics/request/ItemHit.java +++ b/src/main/java/com/brsanthu/googleanalytics/request/ItemHit.java @@ -1,19 +1,15 @@ /* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package com.brsanthu.googleanalytics.request; -import static com.brsanthu.googleanalytics.internal.Constants.HIT_ITEM; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.CURRENCY_CODE; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_CATEGORY; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.ITEM_CODE; diff --git a/src/main/java/com/brsanthu/googleanalytics/request/PageViewHit.java b/src/main/java/com/brsanthu/googleanalytics/request/PageViewHit.java index 566b2ea..1a76e7f 100644 --- a/src/main/java/com/brsanthu/googleanalytics/request/PageViewHit.java +++ b/src/main/java/com/brsanthu/googleanalytics/request/PageViewHit.java @@ -1,20 +1,15 @@ /* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package com.brsanthu.googleanalytics.request; -import static com.brsanthu.googleanalytics.internal.Constants.HIT_PAGEVIEW; - /** * GA request to track a typical web page view * diff --git a/src/main/java/com/brsanthu/googleanalytics/request/ScreenViewHit.java b/src/main/java/com/brsanthu/googleanalytics/request/ScreenViewHit.java index a27e0a1..6f38fe3 100644 --- a/src/main/java/com/brsanthu/googleanalytics/request/ScreenViewHit.java +++ b/src/main/java/com/brsanthu/googleanalytics/request/ScreenViewHit.java @@ -1,19 +1,15 @@ /* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package com.brsanthu.googleanalytics.request; -import static com.brsanthu.googleanalytics.internal.Constants.HIT_SCREENVIEW; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SCREEN_NAME; /** diff --git a/src/main/java/com/brsanthu/googleanalytics/request/SocialHit.java b/src/main/java/com/brsanthu/googleanalytics/request/SocialHit.java index 9d7afb8..a77dce8 100644 --- a/src/main/java/com/brsanthu/googleanalytics/request/SocialHit.java +++ b/src/main/java/com/brsanthu/googleanalytics/request/SocialHit.java @@ -1,19 +1,15 @@ /* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package com.brsanthu.googleanalytics.request; -import static com.brsanthu.googleanalytics.internal.Constants.HIT_SOCIAL; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SOCIAL_ACTION; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SOCIAL_ACTION_TARGET; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.SOCIAL_NETWORK; diff --git a/src/main/java/com/brsanthu/googleanalytics/request/TimingHit.java b/src/main/java/com/brsanthu/googleanalytics/request/TimingHit.java index ed2b5d7..79e62fd 100644 --- a/src/main/java/com/brsanthu/googleanalytics/request/TimingHit.java +++ b/src/main/java/com/brsanthu/googleanalytics/request/TimingHit.java @@ -1,19 +1,15 @@ /* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package com.brsanthu.googleanalytics.request; -import static com.brsanthu.googleanalytics.internal.Constants.HIT_TIMING; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.DNS_TIME; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.PAGE_DOWNLOAD_TIME; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.PAGE_LOAD_TIME; diff --git a/src/main/java/com/brsanthu/googleanalytics/request/TransactionHit.java b/src/main/java/com/brsanthu/googleanalytics/request/TransactionHit.java index f257fab..6d1ebe1 100644 --- a/src/main/java/com/brsanthu/googleanalytics/request/TransactionHit.java +++ b/src/main/java/com/brsanthu/googleanalytics/request/TransactionHit.java @@ -1,19 +1,15 @@ /* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package com.brsanthu.googleanalytics.request; -import static com.brsanthu.googleanalytics.internal.Constants.HIT_TXN; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.CURRENCY_CODE; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_AFFILIATION; import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.TRANSACTION_ID; diff --git a/src/test/java/com/brsanthu/googleanalytics/AwtRequestParameterDiscovererTest.java b/src/test/java/com/brsanthu/googleanalytics/AwtRequestParameterDiscovererTest.java index 9a5c73e..6b016b9 100644 --- a/src/test/java/com/brsanthu/googleanalytics/AwtRequestParameterDiscovererTest.java +++ b/src/test/java/com/brsanthu/googleanalytics/AwtRequestParameterDiscovererTest.java @@ -3,18 +3,18 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.brsanthu.googleanalytics.discovery.AwtRequestParameterDiscoverer; import com.brsanthu.googleanalytics.request.DefaultRequest; public class AwtRequestParameterDiscovererTest { - + @Test public void testDiscoverParameters() throws Exception { AwtRequestParameterDiscoverer discoverer = new AwtRequestParameterDiscoverer(); DefaultRequest request = new DefaultRequest(); - + GoogleAnalyticsConfig config = new GoogleAnalyticsConfig(); assertNull(config.getUserAgent()); @@ -22,14 +22,14 @@ public void testDiscoverParameters() throws Exception { assertNull(request.documentEncoding()); assertNull(request.screenColors()); assertNull(request.screenResolution()); - + discoverer.discoverParameters(config, request); - + assertNotNull(config.getUserAgent()); assertNotNull(request.userLanguage()); assertNotNull(request.documentEncoding()); assertNotNull(request.screenColors()); assertNotNull(request.screenResolution()); } - + } diff --git a/src/test/java/com/brsanthu/googleanalytics/DefaultRequestParameterDiscovererTest.java b/src/test/java/com/brsanthu/googleanalytics/DefaultRequestParameterDiscovererTest.java index 00d320a..a19258c 100644 --- a/src/test/java/com/brsanthu/googleanalytics/DefaultRequestParameterDiscovererTest.java +++ b/src/test/java/com/brsanthu/googleanalytics/DefaultRequestParameterDiscovererTest.java @@ -3,29 +3,29 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.brsanthu.googleanalytics.discovery.DefaultRequestParameterDiscoverer; import com.brsanthu.googleanalytics.request.DefaultRequest; public class DefaultRequestParameterDiscovererTest { - + @Test public void testDiscoverParameters() throws Exception { DefaultRequestParameterDiscoverer discoverer = new DefaultRequestParameterDiscoverer(); DefaultRequest request = new DefaultRequest(); - + GoogleAnalyticsConfig config = new GoogleAnalyticsConfig(); assertNull(config.getUserAgent()); assertNull(request.userLanguage()); assertNull(request.documentEncoding()); - + discoverer.discoverParameters(config, request); - + assertNotNull(config.getUserAgent()); assertNotNull(request.userLanguage()); assertNotNull(request.documentEncoding()); } - + } diff --git a/src/test/java/com/brsanthu/googleanalytics/EventHitTest.java b/src/test/java/com/brsanthu/googleanalytics/EventHitTest.java index a2afe65..3b758ca 100644 --- a/src/test/java/com/brsanthu/googleanalytics/EventHitTest.java +++ b/src/test/java/com/brsanthu/googleanalytics/EventHitTest.java @@ -2,12 +2,12 @@ import static org.junit.Assert.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.brsanthu.googleanalytics.request.EventHit; public class EventHitTest { - + @Test public void testEventHit() throws Exception { EventHit eventHit = new EventHit("eventCategory", "eventAction", "eventLabel", 10); diff --git a/src/test/java/com/brsanthu/googleanalytics/GaUtilsTest.java b/src/test/java/com/brsanthu/googleanalytics/GaUtilsTest.java index 0447c70..2cf936a 100644 --- a/src/test/java/com/brsanthu/googleanalytics/GaUtilsTest.java +++ b/src/test/java/com/brsanthu/googleanalytics/GaUtilsTest.java @@ -1,13 +1,13 @@ package com.brsanthu.googleanalytics; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.brsanthu.googleanalytics.internal.GaUtils; public class GaUtilsTest { - + @Test public void testIsEmpty() throws Exception { assertEquals(true, GaUtils.isEmpty(null)); @@ -16,7 +16,7 @@ public void testIsEmpty() throws Exception { assertEquals(false, GaUtils.isEmpty("value")); assertEquals(false, GaUtils.isEmpty(" value ")); } - + @Test public void isNotEmpty() throws Exception { assertEquals(false, GaUtils.isNotEmpty(null)); @@ -25,7 +25,7 @@ public void isNotEmpty() throws Exception { assertEquals(true, GaUtils.isNotEmpty("value")); assertEquals(true, GaUtils.isNotEmpty(" value ")); } - + @Test public void testAppendSystemProperty() throws Exception { System.setProperty("test", "test"); diff --git a/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsBatchTest.java b/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsBatchTest.java index 2ff0d2a..d35094b 100644 --- a/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsBatchTest.java +++ b/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsBatchTest.java @@ -4,17 +4,17 @@ import java.util.stream.IntStream; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; public class GoogleAnalyticsBatchTest { private static GoogleAnalytics ga = null; - @BeforeClass + @BeforeAll public static void setup() { - ga = GoogleAnalytics.builder().withTrackingId(TEST_TRACKING_ID).withAppName("Junit Test").withAppVersion("1.0.0") - .withConfig(new GoogleAnalyticsConfig().setBatchingEnabled(true).setBatchSize(10)).build(); + ga = GoogleAnalytics.builder().withTrackingId(TEST_TRACKING_ID).withAppName("Junit Test").withAppVersion("1.0.0").withConfig( + new GoogleAnalyticsConfig().setBatchingEnabled(true).setBatchSize(10)).build(); } @Test @@ -23,4 +23,4 @@ public void testPageView() throws Exception { ga.pageView("http://www.google.com", "Search").send(); }); } -} \ No newline at end of file +} diff --git a/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsConfigTest.java b/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsConfigTest.java index e40b26f..c28019a 100644 --- a/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsConfigTest.java +++ b/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsConfigTest.java @@ -1,8 +1,9 @@ package com.brsanthu.googleanalytics; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class GoogleAnalyticsConfigTest { @@ -14,8 +15,28 @@ public void testDefaultConfig() throws Exception { assertEquals(5, config.getMaxThreads()); assertEquals("http://www.google-analytics.com/collect", config.getHttpUrl()); assertEquals("https://www.google-analytics.com/collect", config.getHttpsUrl()); + assertEquals("http://www.google-analytics.com/debug/collect", config.getHttpDebugUrl()); + assertEquals("https://www.google-analytics.com/debug/collect", config.getHttpsDebugUrl()); assertEquals(80, config.getProxyPort()); assertEquals(true, config.isDiscoverRequestParameters()); assertEquals(false, config.isGatherStats()); } + + @Test + void testGetUrl() throws Exception { + + GoogleAnalyticsConfig config = new GoogleAnalyticsConfig(); + + assertThat(config.getUrl()).isEqualTo("https://www.google-analytics.com/collect"); + config.setHitDebug(true); + assertThat(config.getUrl()).isEqualTo("https://www.google-analytics.com/debug/collect"); + + config.setHitDebug(false); + config.setUseHttps(false); + + assertThat(config.getUrl()).isEqualTo("http://www.google-analytics.com/collect"); + config.setHitDebug(true); + assertThat(config.getUrl()).isEqualTo("http://www.google-analytics.com/debug/collect"); + } + } diff --git a/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsDebugTest.java b/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsDebugTest.java new file mode 100644 index 0000000..c49023b --- /dev/null +++ b/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsDebugTest.java @@ -0,0 +1,53 @@ +package com.brsanthu.googleanalytics; + +import static com.brsanthu.googleanalytics.internal.Constants.TEST_TRACKING_ID; +import static org.junit.Assert.assertEquals; + +import java.util.Map; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import com.brsanthu.googleanalytics.request.GoogleAnalyticsResponse; + +public class GoogleAnalyticsDebugTest { + + private static GoogleAnalytics ga = null; + + @BeforeAll + public static void setup() { + ga = GoogleAnalytics.builder().withTrackingId(TEST_TRACKING_ID).withAppName("Junit Test").withAppVersion("1.0.0").withConfig( + new GoogleAnalyticsConfig().setHitDebug(true)).build(); + } + + @SuppressWarnings("unchecked") + @Test + public void testPageViewDebug() throws Exception { + GoogleAnalyticsResponse response = ga.pageView("http://www.google.com", "Search").send(); + + // Sample response from GA + // @formatter:off + /* + { + "hitParsingResult": [ { + "valid": true, + "parserMessage": [ ], + "hit": "/debug/collect?dt=Search\u0026de=UTF-8\u0026qt=1\u0026t=pageview\u0026av=1.0.0\u0026v=1\u0026ul=en-US\u0026dl=http://www.google.com\u0026an=Junit Test\u0026tid=UA-612100-12\u0026cid=7beb1a85-2a9e-440f-8e2d-5e91f8a7e708" + } ], + "parserMessage": [ { + "messageType": "INFO", + "description": "Found 1 hit in the request." + } ] + } + */ + // @formatter:on + String originalResponse = response.getHttpResponse().getBody(); + JSONParser parser = new JSONParser(); + JSONObject json = (JSONObject) parser.parse(originalResponse); + assertEquals(200, response.getStatusCode()); + assertEquals(true, ((Map) ((JSONArray) json.get("hitParsingResult")).get(0)).get("valid")); + } +} diff --git a/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsParameterTest.java b/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsParameterTest.java index 7510dcc..510402f 100644 --- a/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsParameterTest.java +++ b/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsParameterTest.java @@ -4,7 +4,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter; diff --git a/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsRequestTest.java b/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsRequestTest.java index ccd6cf1..37b49ce 100644 --- a/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsRequestTest.java +++ b/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsRequestTest.java @@ -2,7 +2,7 @@ import static org.junit.Assert.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.brsanthu.googleanalytics.request.PageViewHit; diff --git a/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsTest.java b/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsTest.java index 2eab362..11fd188 100644 --- a/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsTest.java +++ b/src/test/java/com/brsanthu/googleanalytics/GoogleAnalyticsTest.java @@ -1,22 +1,42 @@ package com.brsanthu.googleanalytics; import static com.brsanthu.googleanalytics.internal.Constants.TEST_TRACKING_ID; +import static com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter.QUEUE_TIME; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.within; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; -import org.junit.BeforeClass; -import org.junit.Test; +import java.time.ZonedDateTime; +import java.util.concurrent.Future; +import java.util.stream.IntStream; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentMatchers; + +import com.brsanthu.googleanalytics.httpclient.HttpClient; +import com.brsanthu.googleanalytics.httpclient.HttpResponse; +import com.brsanthu.googleanalytics.request.AnyHit; import com.brsanthu.googleanalytics.request.DefaultRequest; +import com.brsanthu.googleanalytics.request.GoogleAnalyticsParameter; +import com.brsanthu.googleanalytics.request.GoogleAnalyticsRequest; import com.brsanthu.googleanalytics.request.GoogleAnalyticsResponse; +import com.brsanthu.googleanalytics.request.ScreenViewHit; public class GoogleAnalyticsTest { private static GoogleAnalytics ga = null; + private static HttpClient client; - @BeforeClass + @BeforeAll public static void setup() { ga = GoogleAnalytics.builder().withTrackingId(TEST_TRACKING_ID).withAppName("Junit Test").withAppVersion("1.0.0").build(); + client = mock(HttpClient.class); + when(client.post(ArgumentMatchers.any())).thenReturn(new HttpResponse().setStatusCode(200)); } @Test @@ -70,8 +90,8 @@ public void testCustomDimensions() throws Exception { // Local ga GoogleAnalytics lga = GoogleAnalytics.builder().withDefaultRequest(defaultRequest).withTrackingId(TEST_TRACKING_ID).build(); - GoogleAnalyticsResponse response = lga.pageView("http://www.google.com", "Search").customDimension(2, "bob").customDimension(5, "alice") - .send(); + GoogleAnalyticsResponse response = lga.pageView("http://www.google.com", "Search").customDimension(2, "bob").customDimension(5, + "alice").send(); assertEquals("foo", response.getRequestParams().get("cd1")); assertEquals("bob", response.getRequestParams().get("cd2")); @@ -101,8 +121,8 @@ public void testUserIpAndAgent() throws Exception { GoogleAnalytics lga = GoogleAnalytics.builder().withDefaultRequest(defaultRequest).withTrackingId(TEST_TRACKING_ID).build(); - GoogleAnalyticsResponse response = lga.pageView("http://www.google.com", "Search").userIp("1.2.3.5") - .userAgent("Chrome/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14").send(); + GoogleAnalyticsResponse response = lga.pageView("http://www.google.com", "Search").userIp("1.2.3.5").userAgent( + "Chrome/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14").send(); assertEquals("1.2.3.5", response.getRequestParams().get("uip")); assertEquals("Chrome/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14", response.getRequestParams().get("ua")); @@ -127,4 +147,154 @@ public void testUserDetails() throws Exception { assertEquals("12345", response.getRequestParams().get("cid")); assertEquals("user2", response.getRequestParams().get("uid")); } + + @Test + void testExceptionHandler() throws Exception { + HttpClient client = mock(HttpClient.class); + when(client.post(ArgumentMatchers.any())).thenThrow(new RuntimeException("Testing Exception")); + + GoogleAnalytics ga = GoogleAnalytics.builder().withHttpClient(client).withConfig(new GoogleAnalyticsConfig()).build(); + + // Since default behavior is to log exception, this function call should work fine. + ga.screenView().send(); + + GoogleAnalytics propagatingGa = GoogleAnalytics.builder().withHttpClient(client).withConfig( + new GoogleAnalyticsConfig().setExceptionHandler(new PropagatingExceptionHandler())).build(); + + assertThatThrownBy(() -> propagatingGa.screenView().send()).hasMessage("Testing Exception"); + + assertThatThrownBy(() -> propagatingGa.screenView().sendAsync().get()).hasMessageContaining("Testing Exception"); + } + + @Test + void testAutoQueueTime() throws Exception { + // By default queue time is added based on when hit was created and posted. In this test case, it should be + // close to 0 + GoogleAnalytics gaAutoTimeEnabled = GoogleAnalytics.builder().withHttpClient(client).withConfig(new GoogleAnalyticsConfig()).build(); + GoogleAnalyticsResponse respEnabled = gaAutoTimeEnabled.screenView().send(); + assertThat(Integer.parseInt(respEnabled.getRequestParams().get(GoogleAnalyticsParameter.QUEUE_TIME.getParameterName()))).isCloseTo(0, + within(100)); + + // We can set occurred at to a past value and if so, it will be used to calcualte queue time. + GoogleAnalytics gaAutoTimeEnabledOccurredAt = GoogleAnalytics.builder().withHttpClient(client).withConfig( + new GoogleAnalyticsConfig()).build(); + GoogleAnalyticsResponse respEnabledOccurredAt = gaAutoTimeEnabledOccurredAt.screenView().occurredAt( + ZonedDateTime.now().minusSeconds(5)).send(); + assertThat(Integer.parseInt(respEnabledOccurredAt.getRequestParams().get(GoogleAnalyticsParameter.QUEUE_TIME.getParameterName()))).isCloseTo( + 5000, within(100)); + + // We can set both occurredAt and queue time, then time based on occurred at will be added to set queue time. + GoogleAnalyticsResponse respEnabledWithSetQueueTime = gaAutoTimeEnabled.screenView().occurredAt( + ZonedDateTime.now().minusSeconds(5)).queueTime(1000).send(); + assertThat(Integer.parseInt( + respEnabledWithSetQueueTime.getRequestParams().get(GoogleAnalyticsParameter.QUEUE_TIME.getParameterName()))).isCloseTo(6000, + within(100)); + + // If we disable auto queue time, then queue time is not calculated + GoogleAnalytics gaAutoTimeDisabled = GoogleAnalytics.builder().withHttpClient(client).withConfig( + new GoogleAnalyticsConfig().setAutoQueueTimeEnabled(false)).build(); + GoogleAnalyticsResponse respDisabled = gaAutoTimeDisabled.screenView().occurredAt(ZonedDateTime.now().minusSeconds(5)).send(); + assertThat(respDisabled.getRequestParams().get(GoogleAnalyticsParameter.QUEUE_TIME.getParameterName())).isNull(); + } + + @Test + void testAutoQueueTimeBatch() throws Exception { + GoogleAnalytics gaAutoTimeEnabled = GoogleAnalytics.builder().withHttpClient(client).withConfig( + new GoogleAnalyticsConfig().setBatchingEnabled(true).setBatchSize(2)).build(); + + // First request will add to batch. + GoogleAnalyticsResponse resp1 = gaAutoTimeEnabled.screenView().send(); + + Thread.sleep(500); + + GoogleAnalyticsResponse resp2 = gaAutoTimeEnabled.screenView().send(); + + assertThat(Integer.parseInt(resp1.getRequestParams().get(QUEUE_TIME.getParameterName()))).isCloseTo(500, within(100)); + + assertThat(Integer.parseInt(resp2.getRequestParams().get(QUEUE_TIME.getParameterName()))).isCloseTo(0, within(100)); + } + + @Test + void testDeepClone() throws Exception { + ScreenViewHit screenhit1 = ga.screenView().adwordsId("test1"); + ScreenViewHit screenhit2 = screenhit1.clone(); + + screenhit1.adwordsId("test1updated"); + + assertThat(screenhit1).isNotSameAs(screenhit2); + assertThat(screenhit1.adwordsId()).isEqualTo("test1updated"); + assertThat(screenhit2.adwordsId()).isEqualTo("test1"); + } + + @Test + void testStats() throws Exception { + GoogleAnalytics ga = GoogleAnalytics.builder().withHttpClient(client).withConfig( + new GoogleAnalyticsConfig().setGatherStats(true).setBatchingEnabled(true).setBatchSize(2)).build(); + + IntStream.rangeClosed(1, 1).forEach(val -> ga.pageView().send()); + IntStream.rangeClosed(1, 2).forEach(val -> ga.event().send()); + IntStream.rangeClosed(1, 3).forEach(val -> ga.screenView().send()); + IntStream.rangeClosed(1, 4).forEach(val -> ga.item().send()); + IntStream.rangeClosed(1, 5).forEach(val -> ga.transaction().send()); + IntStream.rangeClosed(1, 6).forEach(val -> ga.timing().send()); + IntStream.rangeClosed(1, 7).forEach(val -> ga.social().send()); + IntStream.rangeClosed(1, 8).forEach(val -> ga.exception().send()); + + assertThat(ga.getStats().getPageViewHits()).isEqualTo(1); + assertThat(ga.getStats().getEventHits()).isEqualTo(2); + assertThat(ga.getStats().getScreenViewHits()).isEqualTo(3); + assertThat(ga.getStats().getItemHits()).isEqualTo(4); + assertThat(ga.getStats().getTransactionHits()).isEqualTo(5); + assertThat(ga.getStats().getTimingHits()).isEqualTo(6); + assertThat(ga.getStats().getSocialHits()).isEqualTo(7); + assertThat(ga.getStats().getExceptionHits()).isEqualTo(8); + assertThat(ga.getStats().getTotalHits()).isEqualTo(36); + } + + @Test + void testAnyHit() throws Exception { + ScreenViewHit sv = ga.screenView().adwordsId("adsid123"); + + AnyHit anyhit1 = sv.asAnyHit(); + anyhit1.adwordsId("adsid456"); + assertThat(sv.adwordsId()).isEqualTo(anyhit1.adwordsId()); + + AnyHit anyhit2 = sv.clone().asAnyHit(); + anyhit2.adwordsId("adsid789"); + assertThat(sv.adwordsId()).isNotEqualTo(anyhit2.adwordsId()); + } + + @Test + void testAnonymizeUserIp() throws Exception { + String userIp = "176.134.201.004"; + + GoogleAnalytics ga = GoogleAnalytics.builder().withHttpClient(client).withConfig(new GoogleAnalyticsConfig()).build(); + GoogleAnalyticsResponse resp = ga.screenView().userIp(userIp).send(); + assertThat(resp.getRequestParams().get(GoogleAnalyticsParameter.USER_IP.getParameterName())).isEqualTo(userIp); + + GoogleAnalytics ga2 = GoogleAnalytics.builder().withHttpClient(client).withConfig( + new GoogleAnalyticsConfig().setAnonymizeUserIp(true)).build(); + GoogleAnalyticsResponse resp2 = ga2.screenView().userIp(userIp).send(); + assertThat(resp2.getRequestParams().get(GoogleAnalyticsParameter.USER_IP.getParameterName())).isEqualTo("176.134.201.0"); + } + + @Test + void testCustomExecutor() throws Exception { + GoogleAnalyticsExecutor exector = new GoogleAnalyticsExecutor() { + @Override + public Future postAsync(GoogleAnalyticsRequest request) { + return null; + } + + @Override + public GoogleAnalyticsResponse post(GoogleAnalyticsRequest request) { + return new GoogleAnalyticsResponse().setStatusCode(400); + } + }; + + GoogleAnalytics ga = GoogleAnalytics.builder().withGoogleAnalyticsExecutor(exector).build(); + GoogleAnalyticsResponse resp = ga.screenView().send(); + assertThat(resp.getStatusCode()).isEqualTo(400); + + } } diff --git a/src/test/java/com/brsanthu/googleanalytics/HitTypesTest.java b/src/test/java/com/brsanthu/googleanalytics/HitTypesTest.java index ea522dc..0de5b77 100644 --- a/src/test/java/com/brsanthu/googleanalytics/HitTypesTest.java +++ b/src/test/java/com/brsanthu/googleanalytics/HitTypesTest.java @@ -1,9 +1,11 @@ package com.brsanthu.googleanalytics; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import com.brsanthu.googleanalytics.request.AnyHit; import com.brsanthu.googleanalytics.request.EventHit; import com.brsanthu.googleanalytics.request.ExceptionHit; import com.brsanthu.googleanalytics.request.ItemHit; @@ -25,5 +27,6 @@ public void testHitTypes() throws Exception { assertEquals("social", new SocialHit().hitType()); assertEquals("timing", new TimingHit().hitType()); assertEquals("transaction", new TransactionHit().hitType()); + assertThat(new AnyHit().hitType()).isEqualTo("pageview"); } }