diff --git a/.editorconfig b/.editorconfig
index e391ae95..322b027f 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -34,6 +34,10 @@ ij_css_space_before_opening_brace = true
ij_css_use_double_quotes = true
ij_css_value_alignment = do_not_align
+[*.feature]
+indent_size = 2
+ij_gherkin_keep_indents_on_empty_lines = false
+
[*.java]
indent_size = 2
max_line_length = 100
@@ -340,6 +344,53 @@ ij_java_wrap_comments = true
ij_java_wrap_first_method_in_call_chain = false
ij_java_wrap_long_lines = false
+[*.less]
+indent_size = 2
+ij_less_align_closing_brace_with_properties = false
+ij_less_blank_lines_around_nested_selector = 1
+ij_less_blank_lines_between_blocks = 1
+ij_less_block_comment_add_space = false
+ij_less_brace_placement = 0
+ij_less_enforce_quotes_on_format = false
+ij_less_hex_color_long_format = false
+ij_less_hex_color_lower_case = false
+ij_less_hex_color_short_format = false
+ij_less_hex_color_upper_case = false
+ij_less_keep_blank_lines_in_code = 2
+ij_less_keep_indents_on_empty_lines = false
+ij_less_keep_single_line_blocks = false
+ij_less_line_comment_add_space = false
+ij_less_line_comment_at_first_column = false
+ij_less_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
+ij_less_space_after_colon = true
+ij_less_space_before_opening_brace = true
+ij_less_use_double_quotes = true
+ij_less_value_alignment = 0
+
+[*.proto]
+indent_size = 2
+tab_width = 2
+ij_continuation_indent_size = 4
+ij_protobuf_keep_blank_lines_in_code = 2
+ij_protobuf_keep_indents_on_empty_lines = false
+ij_protobuf_keep_line_breaks = true
+ij_protobuf_space_after_comma = true
+ij_protobuf_space_before_comma = false
+ij_protobuf_spaces_around_assignment_operators = true
+ij_protobuf_spaces_within_braces = false
+ij_protobuf_spaces_within_brackets = false
+
+[*.vue]
+indent_size = 2
+tab_width = 2
+ij_continuation_indent_size = 4
+ij_vue_indent_children_of_top_level = template
+ij_vue_interpolation_new_line_after_start_delimiter = true
+ij_vue_interpolation_new_line_before_end_delimiter = true
+ij_vue_interpolation_wrap = off
+ij_vue_keep_indents_on_empty_lines = false
+ij_vue_spaces_within_interpolation_expressions = true
+
[.editorconfig]
ij_editorconfig_align_group_field_declarations = false
ij_editorconfig_space_after_colon = false
@@ -348,7 +399,7 @@ ij_editorconfig_space_before_colon = false
ij_editorconfig_space_before_comma = false
ij_editorconfig_spaces_around_assignment_operators = true
-[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.pom,*.rng,*.tld,*.wadl,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul,phpunit.xml.dist}]
+[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.pom,*.rng,*.tld,*.wadl,*.wsdd,*.wsdl,*.xjb,*.xml,*.xsd,*.xsl,*.xslt,*.xul,phpunit.xml.dist}]
ij_xml_align_attributes = true
ij_xml_align_text = false
ij_xml_attribute_wrap = normal
@@ -946,7 +997,198 @@ ij_php_version_weight = 28
ij_php_while_brace_force = never
ij_php_while_on_new_line = false
-[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,composer.lock,jest.config}]
+[{*.gant,*.groovy,*.gy}]
+ij_groovy_align_group_field_declarations = false
+ij_groovy_align_multiline_array_initializer_expression = false
+ij_groovy_align_multiline_assignment = false
+ij_groovy_align_multiline_binary_operation = false
+ij_groovy_align_multiline_chained_methods = false
+ij_groovy_align_multiline_extends_list = false
+ij_groovy_align_multiline_for = true
+ij_groovy_align_multiline_list_or_map = true
+ij_groovy_align_multiline_method_parentheses = false
+ij_groovy_align_multiline_parameters = true
+ij_groovy_align_multiline_parameters_in_calls = false
+ij_groovy_align_multiline_resources = true
+ij_groovy_align_multiline_ternary_operation = false
+ij_groovy_align_multiline_throws_list = false
+ij_groovy_align_named_args_in_map = true
+ij_groovy_align_throws_keyword = false
+ij_groovy_array_initializer_new_line_after_left_brace = false
+ij_groovy_array_initializer_right_brace_on_new_line = false
+ij_groovy_array_initializer_wrap = off
+ij_groovy_assert_statement_wrap = off
+ij_groovy_assignment_wrap = off
+ij_groovy_binary_operation_wrap = off
+ij_groovy_blank_lines_after_class_header = 0
+ij_groovy_blank_lines_after_imports = 1
+ij_groovy_blank_lines_after_package = 1
+ij_groovy_blank_lines_around_class = 1
+ij_groovy_blank_lines_around_field = 0
+ij_groovy_blank_lines_around_field_in_interface = 0
+ij_groovy_blank_lines_around_method = 1
+ij_groovy_blank_lines_around_method_in_interface = 1
+ij_groovy_blank_lines_before_imports = 1
+ij_groovy_blank_lines_before_method_body = 0
+ij_groovy_blank_lines_before_package = 0
+ij_groovy_block_brace_style = end_of_line
+ij_groovy_block_comment_add_space = false
+ij_groovy_block_comment_at_first_column = true
+ij_groovy_call_parameters_new_line_after_left_paren = false
+ij_groovy_call_parameters_right_paren_on_new_line = false
+ij_groovy_call_parameters_wrap = off
+ij_groovy_catch_on_new_line = false
+ij_groovy_class_annotation_wrap = split_into_lines
+ij_groovy_class_brace_style = end_of_line
+ij_groovy_class_count_to_use_import_on_demand = 5
+ij_groovy_do_while_brace_force = never
+ij_groovy_else_on_new_line = false
+ij_groovy_enable_groovydoc_formatting = true
+ij_groovy_enum_constants_wrap = off
+ij_groovy_extends_keyword_wrap = off
+ij_groovy_extends_list_wrap = off
+ij_groovy_field_annotation_wrap = split_into_lines
+ij_groovy_finally_on_new_line = false
+ij_groovy_for_brace_force = never
+ij_groovy_for_statement_new_line_after_left_paren = false
+ij_groovy_for_statement_right_paren_on_new_line = false
+ij_groovy_for_statement_wrap = off
+ij_groovy_ginq_general_clause_wrap_policy = 2
+ij_groovy_ginq_having_wrap_policy = 1
+ij_groovy_ginq_indent_having_clause = true
+ij_groovy_ginq_indent_on_clause = true
+ij_groovy_ginq_on_wrap_policy = 1
+ij_groovy_ginq_space_after_keyword = true
+ij_groovy_if_brace_force = never
+ij_groovy_import_annotation_wrap = 2
+ij_groovy_imports_layout = *,|,javax.**,java.**,|,$*
+ij_groovy_indent_case_from_switch = true
+ij_groovy_indent_label_blocks = true
+ij_groovy_insert_inner_class_imports = false
+ij_groovy_keep_blank_lines_before_right_brace = 2
+ij_groovy_keep_blank_lines_in_code = 2
+ij_groovy_keep_blank_lines_in_declarations = 2
+ij_groovy_keep_control_statement_in_one_line = true
+ij_groovy_keep_first_column_comment = true
+ij_groovy_keep_indents_on_empty_lines = false
+ij_groovy_keep_line_breaks = true
+ij_groovy_keep_multiple_expressions_in_one_line = false
+ij_groovy_keep_simple_blocks_in_one_line = false
+ij_groovy_keep_simple_classes_in_one_line = true
+ij_groovy_keep_simple_lambdas_in_one_line = true
+ij_groovy_keep_simple_methods_in_one_line = true
+ij_groovy_label_indent_absolute = false
+ij_groovy_label_indent_size = 0
+ij_groovy_lambda_brace_style = end_of_line
+ij_groovy_layout_static_imports_separately = true
+ij_groovy_line_comment_add_space = false
+ij_groovy_line_comment_add_space_on_reformat = false
+ij_groovy_line_comment_at_first_column = true
+ij_groovy_method_annotation_wrap = split_into_lines
+ij_groovy_method_brace_style = end_of_line
+ij_groovy_method_call_chain_wrap = off
+ij_groovy_method_parameters_new_line_after_left_paren = false
+ij_groovy_method_parameters_right_paren_on_new_line = false
+ij_groovy_method_parameters_wrap = off
+ij_groovy_modifier_list_wrap = false
+ij_groovy_names_count_to_use_import_on_demand = 3
+ij_groovy_packages_to_use_import_on_demand = java.awt.*,javax.swing.*
+ij_groovy_parameter_annotation_wrap = off
+ij_groovy_parentheses_expression_new_line_after_left_paren = false
+ij_groovy_parentheses_expression_right_paren_on_new_line = false
+ij_groovy_prefer_parameters_wrap = false
+ij_groovy_resource_list_new_line_after_left_paren = false
+ij_groovy_resource_list_right_paren_on_new_line = false
+ij_groovy_resource_list_wrap = off
+ij_groovy_space_after_assert_separator = true
+ij_groovy_space_after_colon = true
+ij_groovy_space_after_comma = true
+ij_groovy_space_after_comma_in_type_arguments = true
+ij_groovy_space_after_for_semicolon = true
+ij_groovy_space_after_quest = true
+ij_groovy_space_after_type_cast = true
+ij_groovy_space_before_annotation_parameter_list = false
+ij_groovy_space_before_array_initializer_left_brace = false
+ij_groovy_space_before_assert_separator = false
+ij_groovy_space_before_catch_keyword = true
+ij_groovy_space_before_catch_left_brace = true
+ij_groovy_space_before_catch_parentheses = true
+ij_groovy_space_before_class_left_brace = true
+ij_groovy_space_before_closure_left_brace = true
+ij_groovy_space_before_colon = true
+ij_groovy_space_before_comma = false
+ij_groovy_space_before_do_left_brace = true
+ij_groovy_space_before_else_keyword = true
+ij_groovy_space_before_else_left_brace = true
+ij_groovy_space_before_finally_keyword = true
+ij_groovy_space_before_finally_left_brace = true
+ij_groovy_space_before_for_left_brace = true
+ij_groovy_space_before_for_parentheses = true
+ij_groovy_space_before_for_semicolon = false
+ij_groovy_space_before_if_left_brace = true
+ij_groovy_space_before_if_parentheses = true
+ij_groovy_space_before_method_call_parentheses = false
+ij_groovy_space_before_method_left_brace = true
+ij_groovy_space_before_method_parentheses = false
+ij_groovy_space_before_quest = true
+ij_groovy_space_before_record_parentheses = false
+ij_groovy_space_before_switch_left_brace = true
+ij_groovy_space_before_switch_parentheses = true
+ij_groovy_space_before_synchronized_left_brace = true
+ij_groovy_space_before_synchronized_parentheses = true
+ij_groovy_space_before_try_left_brace = true
+ij_groovy_space_before_try_parentheses = true
+ij_groovy_space_before_while_keyword = true
+ij_groovy_space_before_while_left_brace = true
+ij_groovy_space_before_while_parentheses = true
+ij_groovy_space_in_named_argument = true
+ij_groovy_space_in_named_argument_before_colon = false
+ij_groovy_space_within_empty_array_initializer_braces = false
+ij_groovy_space_within_empty_method_call_parentheses = false
+ij_groovy_spaces_around_additive_operators = true
+ij_groovy_spaces_around_assignment_operators = true
+ij_groovy_spaces_around_bitwise_operators = true
+ij_groovy_spaces_around_equality_operators = true
+ij_groovy_spaces_around_lambda_arrow = true
+ij_groovy_spaces_around_logical_operators = true
+ij_groovy_spaces_around_multiplicative_operators = true
+ij_groovy_spaces_around_regex_operators = true
+ij_groovy_spaces_around_relational_operators = true
+ij_groovy_spaces_around_shift_operators = true
+ij_groovy_spaces_within_annotation_parentheses = false
+ij_groovy_spaces_within_array_initializer_braces = false
+ij_groovy_spaces_within_braces = true
+ij_groovy_spaces_within_brackets = false
+ij_groovy_spaces_within_cast_parentheses = false
+ij_groovy_spaces_within_catch_parentheses = false
+ij_groovy_spaces_within_for_parentheses = false
+ij_groovy_spaces_within_gstring_injection_braces = false
+ij_groovy_spaces_within_if_parentheses = false
+ij_groovy_spaces_within_list_or_map = false
+ij_groovy_spaces_within_method_call_parentheses = false
+ij_groovy_spaces_within_method_parentheses = false
+ij_groovy_spaces_within_parentheses = false
+ij_groovy_spaces_within_switch_parentheses = false
+ij_groovy_spaces_within_synchronized_parentheses = false
+ij_groovy_spaces_within_try_parentheses = false
+ij_groovy_spaces_within_tuple_expression = false
+ij_groovy_spaces_within_while_parentheses = false
+ij_groovy_special_else_if_treatment = true
+ij_groovy_ternary_operation_wrap = off
+ij_groovy_throws_keyword_wrap = off
+ij_groovy_throws_list_wrap = off
+ij_groovy_use_flying_geese_braces = false
+ij_groovy_use_fq_class_names = false
+ij_groovy_use_fq_class_names_in_javadoc = true
+ij_groovy_use_relative_indents = false
+ij_groovy_use_single_class_imports = true
+ij_groovy_variable_annotation_wrap = off
+ij_groovy_while_brace_force = never
+ij_groovy_while_on_new_line = false
+ij_groovy_wrap_chain_calls_after_dot = false
+ij_groovy_wrap_long_lines = false
+
+[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,composer.lock,jest.config}]
indent_size = 2
ij_json_array_wrapping = split_into_lines
ij_json_keep_blank_lines_in_code = 0
@@ -963,7 +1205,7 @@ ij_json_spaces_within_braces = false
ij_json_spaces_within_brackets = false
ij_json_wrap_long_lines = false
-[{*.htm,*.html,*.sht,*.shtm,*.shtml}]
+[{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}]
ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
ij_html_align_attributes = true
ij_html_align_text = false
@@ -1101,6 +1343,20 @@ ij_markdown_min_lines_between_paragraphs = 1
ij_markdown_wrap_text_if_long = true
ij_markdown_wrap_text_inside_blockquotes = true
+[{*.pb,*.textproto}]
+indent_size = 2
+tab_width = 2
+ij_continuation_indent_size = 4
+ij_prototext_keep_blank_lines_in_code = 2
+ij_prototext_keep_indents_on_empty_lines = false
+ij_prototext_keep_line_breaks = true
+ij_prototext_space_after_colon = true
+ij_prototext_space_after_comma = true
+ij_prototext_space_before_colon = false
+ij_prototext_space_before_comma = false
+ij_prototext_spaces_within_braces = true
+ij_prototext_spaces_within_brackets = false
+
[{*.properties,spring.handlers,spring.schemas}]
ij_properties_align_group_field_declarations = false
ij_properties_keep_blank_lines = false
diff --git a/README.md b/README.md
index d47af883..fa22bf5d 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,8 @@ Features include:
Please prefer the Java 11 version as the Java 8 will become obsolete in the future.
+You can find our [Developer Guide here](https://developer.matomo.org/api-reference/tracking-java)
+
Further information on Matomo and Matomo HTTP tracking:
* [Matomo PHP Tracker](https://github.com/matomo-org/matomo-php-tracker)
@@ -71,12 +73,14 @@ dependencies. Release notes can be found here: https://github.com/matomo-org/mat
Here are the most important changes:
-* Matomo Java Tracker 3.x is compatible with Matomo 4 and 5
+* Matomo Java Tracker 3.2.0 is compatible with Matomo 4 and 5
* less dependencies
* new dimension parameter
* special types allow to provide valid parameters now
* a new implementation for Java 11 uses the HttpClient available since Java 11
+See also the [Developer Guide here](https://developer.matomo.org/api-reference/tracking-java)
+
## Javadoc
The Javadoc for all versions can be found
@@ -85,6 +89,7 @@ The Javadoc for all versions can be found
## Need help?
+* Check the [Developer Guide](https://developer.matomo.org/api-reference/tracking-java)
* Open an issue in the [Issue Tracker](https://github.com/matomo-org/matomo-java-tracker/issues)
* Use [our GitHub discussions](https://github.com/matomo-org/matomo-java-tracker/discussions)
* Ask your question on [Stackoverflow with the tag `matomo`](https://stackoverflow.com/questions/tagged/matomo)
@@ -106,7 +111,7 @@ Add a dependency on Matomo Java Tracker using Maven. For Java 8:
org.piwik.java.trackingmatomo-java-tracker
- 3.0.0
+ 3.2.0
```
@@ -116,7 +121,7 @@ For Java 11:
org.piwik.java.trackingmatomo-java-tracker-java11
- 3.0.0
+ 3.2.0
```
@@ -124,7 +129,7 @@ or Gradle (Java 8):
```groovy
dependencies {
- implementation("org.piwik.java.tracking:matomo-java-tracker:3.0.0")
+ implementation("org.piwik.java.tracking:matomo-java-tracker:3.2.0")
}
```
@@ -132,20 +137,20 @@ or Gradle (Java 11):
```groovy
dependencies {
- implementation("org.piwik.java.tracking:matomo-java-tracker-java11:3.0.0")
+ implementation("org.piwik.java.tracking:matomo-java-tracker-java11:3.2.0")
}
```
or Gradle with Kotlin DSL (Java 8)
```kotlin
-implementation("org.piwik.java.tracking:matomo-java-tracker:3.0.0")
+implementation("org.piwik.java.tracking:matomo-java-tracker:3.2.0")
```
or Gradle with Kotlin DSL (Java 11)
```kotlin
-implementation("org.piwik.java.tracking:matomo-java-tracker-java11:3.0.0")
+implementation("org.piwik.java.tracking:matomo-java-tracker-java11:3.2.0")
```
### Spring Boot Module
@@ -158,7 +163,7 @@ and allows you to configure the tracker via application properties. Add the foll
org.piwik.java.trackingmatomo-java-tracker-spring-boot-starter
- 3.0.0
+ 3.2.0
```
@@ -166,14 +171,14 @@ or Gradle:
```groovy
dependencies {
- implementation("org.piwik.java.tracking:matomo-java-tracker-spring-boot-starter:3.0.0")
+ implementation("org.piwik.java.tracking:matomo-java-tracker-spring-boot-starter:3.2.0")
}
```
or Gradle with Kotlin DSL
```kotlin
-implementation("org.piwik.java.tracking:matomo-java-tracker-spring-boot-starter:3.0.0")
+implementation("org.piwik.java.tracking:matomo-java-tracker-spring-boot-starter:3.2.0")
```
The following properties are supported:
@@ -272,6 +277,49 @@ the site with id 1. The request will be sent asynchronously, that means the meth
application will not wait for the response of the Matomo server. In the configuration we set the default site id to 1
and configure the default auth token. With `logFailedTracking` we enable logging of failed tracking requests.
+If you want to perform an operation after a successful asynchronous call to Matomo, you can use the completable future
+result like this:
+
+```java
+
+import java.net.URI;
+import org.matomo.java.tracking.MatomoRequests;
+import org.matomo.java.tracking.MatomoTracker;
+import org.matomo.java.tracking.TrackerConfiguration;
+import org.matomo.java.tracking.parameters.VisitorId;
+
+public class ConsumerExample {
+
+ public static void main(String[] args) {
+
+ TrackerConfiguration configuration = TrackerConfiguration
+ .builder()
+ .apiEndpoint(URI.create("https://www.yourdomain.com/matomo.php"))
+ .defaultSiteId(1)
+ .defaultAuthToken("ee6e3dd9ed1b61f5328cf5978b5a8c71")
+ .logFailedTracking(true)
+ .build();
+
+ MatomoTracker tracker = new MatomoTracker(configuration);
+
+ MatomoRequest request = MatomoRequests
+ .event("Training", "Workout completed", "Bench press", 60.0)
+ .visitorId(VisitorId.fromString("customer@mail.com"))
+ .build();
+
+ tracker.sendRequestAsync(request)
+ .thenAccept(req -> System.out.printf("Sent request %s%n", req))
+ .exceptionally(throwable -> {
+ System.err.printf("Failed to send request: %s%n", throwable.getMessage());
+ return null;
+ });
+
+ }
+
+}
+
+```
+
If you have multiple requests to wish to track, it may be more efficient to send them in a single HTTP call. To do this,
send a bulk request. Place your requests in an _Iterable_ data structure and call
@@ -329,6 +377,64 @@ Per default every request has the following default parameters:
Overwrite these properties as desired. We strongly recommend your to determine the visitor id for every user using
a unique identifier, e.g. an email address. If you do not provide a visitor id, a random visitor id will be generated.
+Ecommerce requests contain ecommerce items, that can be fluently build:
+
+```java
+
+import java.net.URI;
+import org.matomo.java.tracking.MatomoRequest;
+import org.matomo.java.tracking.MatomoRequests;
+import org.matomo.java.tracking.MatomoTracker;
+import org.matomo.java.tracking.TrackerConfiguration;
+import org.matomo.java.tracking.parameters.EcommerceItem;
+import org.matomo.java.tracking.parameters.EcommerceItems;
+import org.matomo.java.tracking.parameters.VisitorId;
+
+public class EcommerceExample {
+
+ public static void main(String[] args) {
+
+ TrackerConfiguration configuration = TrackerConfiguration
+ .builder()
+ .apiEndpoint(URI.create("https://www.yourdomain.com/matomo.php"))
+ .defaultSiteId(1)
+ .defaultAuthToken("ee6e3dd9ed1b61f5328cf5978b5a8c71")
+ .logFailedTracking(true)
+ .build();
+
+ MatomoTracker tracker = new MatomoTracker(configuration);
+
+ tracker.sendBulkRequestAsync(MatomoRequests
+ .ecommerceCartUpdate(50.0)
+ .ecommerceItems(EcommerceItems
+ .builder()
+ .item(EcommerceItem
+ .builder()
+ .sku("XYZ12345")
+ .name("Matomo - The big book about web analytics")
+ .category("Education & Teaching")
+ .price(23.1)
+ .quantity(2)
+ .build())
+ .item(EcommerceItem
+ .builder()
+ .sku("B0C2WV3MRJ")
+ .name("Matomo for data visualization")
+ .category("Education & Teaching")
+ .price(15.0)
+ .quantity(1)
+ .build())
+ .build())
+ .visitorId(VisitorId.fromString("customer@mail.com"))
+ .build()
+ );
+
+ }
+
+}
+
+```
+
Note that if you want to be able to track campaigns using *Referrers > Campaigns*, you must add the correct
URL parameters to your actionUrl. See [Tracking Campaigns](https://matomo.org/docs/tracking-campaigns/) for more information. All HTTP query parameters
denoted on the [Matomo Tracking HTTP API](https://developer.matomo.org/api-reference/tracking-api) can be set using the appropriate getters and setters. See
@@ -517,7 +623,7 @@ version can be used in your local Maven repository for testing purposes, e.g.
org.piwik.java.trackingmatomo-java-tracker
- 3.0.0-rc2-SNAPSHOT
+ 3.2.1-SNAPSHOT
```
@@ -608,6 +714,7 @@ provide tests for your changes. We use JUnit 5 for testing. Coverage should be a
## Other Java Matomo Tracker Implementations
+* [The original Piwik Java Tracker Implementation](https://github.com/summitsystemsinc/piwik-java-tracking)
* [Matomo SDK for Android](https://github.com/matomo-org/matomo-sdk-android)
* [Piwik SDK Android]( https://github.com/lkogler/piwik-sdk-android)
* [piwik-tracking](https://github.com/ralscha/piwik-tracking)
diff --git a/core/pom.xml b/core/pom.xml
index dedb5618..e05e2923 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -4,7 +4,7 @@
org.piwik.java.trackingmatomo-java-tracker-parent
- 3.1.2-SNAPSHOT
+ 3.2.1-SNAPSHOT../pom.xml
diff --git a/core/src/main/java/org/matomo/java/tracking/MatomoRequest.java b/core/src/main/java/org/matomo/java/tracking/MatomoRequest.java
index 620ce4fe..ea2ddbfc 100644
--- a/core/src/main/java/org/matomo/java/tracking/MatomoRequest.java
+++ b/core/src/main/java/org/matomo/java/tracking/MatomoRequest.java
@@ -7,16 +7,10 @@
package org.matomo.java.tracking;
-import static java.util.Collections.singleton;
-
import edu.umd.cs.findbugs.annotations.Nullable;
import java.nio.charset.Charset;
import java.time.Instant;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
import java.util.LinkedHashMap;
-import java.util.List;
import java.util.Map;
import java.util.UUID;
import lombok.AllArgsConstructor;
@@ -41,7 +35,7 @@
/**
* A class that implements the
- * Matomo Tracking HTTP API. These requests can be sent using {@link MatomoTracker}.
+ * Matomo Tracking HTTP API. These requests can be sent using {@link MatomoTracker}.
*
* @author brettcsorba
*/
@@ -55,7 +49,7 @@ public class MatomoRequest {
/**
* The ID of the website we're tracking a visit/action for. Only needed, if no default site id is
- * configured
+ * configured.
*/
@TrackingParameter(name = "rec")
@Default
@@ -63,9 +57,12 @@ public class MatomoRequest {
/**
* The ID of the website we're tracking a visit/action for. Only needed, if no default site id is
- * configured
+ * configured.
*/
- @TrackingParameter(name = "idsite")
+ @TrackingParameter(
+ name = "idsite",
+ min = 1
+ )
private Integer siteId;
/**
@@ -130,7 +127,7 @@ public class MatomoRequest {
* database). Then you would manually increment the counts by one on each new visit or "session",
* depending on how you choose to define a visit.
*/
- @TrackingParameter(name = "_idvc")
+ @TrackingParameter(name = "_idvc", min = 0)
private Integer visitorVisitCount;
/**
@@ -156,9 +153,9 @@ public class MatomoRequest {
/**
* The campaign keyword (see
* Tracking Campaigns). Used to
- * populate
- * the Referrers > Campaigns report (clicking on a campaign loads all keywords for
- * this campaign). This parameter will only be used for the first pageview of a visit.
+ * populate the Referrers > Campaigns report (clicking on a campaign loads all
+ * keywords for this campaign). This parameter will only be used for the first pageview of a
+ * visit.
*/
@TrackingParameter(name = "_rck")
private String campaignKeyword;
@@ -172,19 +169,31 @@ public class MatomoRequest {
/**
* The current hour (local time).
*/
- @TrackingParameter(name = "h")
+ @TrackingParameter(
+ name = "h",
+ min = 0,
+ max = 23
+ )
private Integer currentHour;
/**
* The current minute (local time).
*/
- @TrackingParameter(name = "m")
+ @TrackingParameter(
+ name = "m",
+ min = 0,
+ max = 59
+ )
private Integer currentMinute;
/**
* The current second (local time).
*/
- @TrackingParameter(name = "s")
+ @TrackingParameter(
+ name = "s",
+ min = 0,
+ max = 59
+ )
private Integer currentSecond;
/**
@@ -321,7 +330,10 @@ public class MatomoRequest {
* results displayed on the results page. When keywords are tracked with &search_count=0 they will
* appear in the "No Result Search Keyword" report.
*/
- @TrackingParameter(name = "search_count")
+ @TrackingParameter(
+ name = "search_count",
+ min = 0
+ )
private Long searchResultsCount;
/**
@@ -335,9 +347,9 @@ public class MatomoRequest {
/**
* If specified, the tracking request will trigger a conversion for the goal of the website being
- * tracked with this ID.
+ * tracked with this ID. The value 0 tracks an ecommerce interaction.
*/
- @TrackingParameter(name = "idgoal")
+ @TrackingParameter(name = "idgoal", min = 0)
private Integer goalId;
/**
@@ -365,39 +377,39 @@ public class MatomoRequest {
/**
* How long it took to connect to server.
*/
- @TrackingParameter(name = "pf_net")
+ @TrackingParameter(name = "pf_net", min = 0)
private Long networkTime;
/**
* How long it took the server to generate page.
*/
- @TrackingParameter(name = "pf_srv")
+ @TrackingParameter(name = "pf_srv", min = 0)
private Long serverTime;
/**
* How long it takes the browser to download the response from the server.
*/
- @TrackingParameter(name = "pf_tfr")
+ @TrackingParameter(name = "pf_tfr", min = 0)
private Long transferTime;
/**
* How long the browser spends loading the webpage after the response was fully received until the
* user can start interacting with it.
*/
- @TrackingParameter(name = "pf_dm1")
+ @TrackingParameter(name = "pf_dm1", min = 0)
private Long domProcessingTime;
/**
* How long it takes for the browser to load media and execute any Javascript code listening for
* the DOMContentLoaded event.
*/
- @TrackingParameter(name = "pf_dm2")
+ @TrackingParameter(name = "pf_dm2", min = 0)
private Long domCompletionTime;
/**
* How long it takes the browser to execute Javascript code waiting for the window.load event.
*/
- @TrackingParameter(name = "pf_onl")
+ @TrackingParameter(name = "pf_onl", min = 0)
private Long onloadTime;
/**
@@ -450,8 +462,7 @@ public class MatomoRequest {
/**
* The unique string identifier for the ecommerce order (required when tracking an ecommerce
- * order). you must set &idgoal=0 in the request to track an ecommerce interaction: cart update or
- * an ecommerce order.
+ * order).
*/
@TrackingParameter(name = "ec_id")
private String ecommerceId;
@@ -546,13 +557,13 @@ public class MatomoRequest {
/**
* An override value for the visitor's latitude, eg 22.456.
*/
- @TrackingParameter(name = "lat")
+ @TrackingParameter(name = "lat", min = -90, max = 90)
private Double visitorLatitude;
/**
* An override value for the visitor's longitude, eg 22.456.
*/
- @TrackingParameter(name = "long")
+ @TrackingParameter(name = "long", min = -180, max = 180)
private Double visitorLongitude;
/**
@@ -670,7 +681,7 @@ public class MatomoRequest {
*
*
Optional for crash analytics
*/
- @TrackingParameter(name = "cra_rl")
+ @TrackingParameter(name = "cra_rl", min = 0)
private Integer crashLine;
/**
@@ -678,15 +689,14 @@ public class MatomoRequest {
*
*
Optional for crash analytics
*/
- @TrackingParameter(name = "cra_rc")
+ @TrackingParameter(name = "cra_rc", min = 0)
private Integer crashColumn;
/**
* The Matomo session ID sent as a cookie {@code MATOMO_SESSID}.
*
*
If not null a cookie with the name {@code MATOMO_SESSID} will be sent with the value of
- * this
- * parameter.
+ * this parameter.
*/
private String sessionId;
@@ -706,7 +716,7 @@ public class MatomoRequest {
*
For example, you can use this to set the Accept-Language header, or to set the
* Content-Type.
*/
- private Map> additionalParameters;
+ private Map additionalParameters;
/**
* You can set additional HTTP headers for the request sent to Matomo.
@@ -760,17 +770,14 @@ public MatomoRequest(int siteId, String actionUrl) {
*
* @param key the key of the parameter whose list of objects to get. Cannot be null
*
- * @return the list of objects currently stored at the specified key
+ * @return the parameter at the specified key, null if nothing at this key
*/
- public List