Modified: unomi/website/manual/latest/index.html
URL: 
http://svn.apache.org/viewvc/unomi/website/manual/latest/index.html?rev=1903308&r1=1903307&r2=1903308&view=diff
==============================================================================
--- unomi/website/manual/latest/index.html (original)
+++ unomi/website/manual/latest/index.html Tue Aug  9 12:02:22 2022
@@ -53,14 +53,6 @@
 <li><a href="#_where_to_go_from_here">2.3.6. Where to go from here</a></li>
 </ul>
 </li>
-<li><a href="#_web_tracker">2.4. Web Tracker</a>
-<ul class="sectlevel3">
-<li><a href="#_getting_started">2.4.1. Getting started</a></li>
-<li><a href="#_how_to_contribute">2.4.2. How to contribute</a></li>
-<li><a href="#_tracking_page_views">2.4.3. Tracking page views</a></li>
-<li><a href="#_tracking_form_submissions">2.4.4. Tracking form 
submissions</a></li>
-</ul>
-</li>
 </ul>
 </li>
 <li><a href="#_configuration">3. Configuration</a>
@@ -94,313 +86,341 @@
 </li>
 </ul>
 </li>
-<li><a href="#_migrations">4. Migrations</a>
+<li><a href="#_json_schemas">4. JSON schemas</a>
+<ul class="sectlevel2">
+<li><a href="#_introduction_2">4.1. Introduction</a>
+<ul class="sectlevel3">
+<li><a href="#_what_is_a_json_schema">4.1.1. What is a JSON Schema</a></li>
+<li><a href="#_key_concepts">4.1.2. Key concepts</a></li>
+<li><a href="#_how_are_json_schema_used_in_unomi">4.1.3. How are JSON Schema 
used in Unomi</a></li>
+</ul>
+</li>
+<li><a href="#_json_schema_api">4.2. JSON schema API</a>
+<ul class="sectlevel3">
+<li><a href="#_list_existing_schemas">4.2.1. List existing schemas</a></li>
+<li><a href="#_read_a_schema">4.2.2. Read a schema</a></li>
+<li><a href="#_create_update_a_json_schema_to_validate_an_event">4.2.3. Create 
/ update a JSON schema to validate an event</a></li>
+<li><a href="#_deleting_a_schema">4.2.4. Deleting a schema</a></li>
+<li><a href="#_error_management">4.2.5. Error Management</a></li>
+<li><a href="#_details_on_invalid_events">4.2.6. Details on invalid 
events</a></li>
+</ul>
+</li>
+<li><a href="#_extend_an_existing_schema">4.3. Extend an existing schema</a>
+<ul class="sectlevel3">
+<li><a href="#_when_a_extension_is_needed">4.3.1. When a extension is 
needed?</a></li>
+<li><a href="#_understanding_how_extensions_are_merged_in_unomi">4.3.2. 
Understanding how extensions are merged in unomi</a></li>
+<li><a href="#_how_to_add_an_extension_through_the_api">4.3.3. How to add an 
extension through the API</a></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><a href="#_migrations">5. Migrations</a>
 <ul class="sectlevel2">
-<li><a href="#_from_version_1_4_to_1_5">4.1. From version 1.4 to 1.5</a>
+<li><a href="#_from_version_1_4_to_1_5">5.1. From version 1.4 to 1.5</a>
 <ul class="sectlevel3">
-<li><a href="#_data_model_and_elasticsearch_7">4.1.1. Data model and 
ElasticSearch 7</a></li>
-<li><a href="#_api_changes">4.1.2. API changes</a></li>
-<li><a href="#_migration_steps">4.1.3. Migration steps</a></li>
+<li><a href="#_data_model_and_elasticsearch_7">5.1.1. Data model and 
ElasticSearch 7</a></li>
+<li><a href="#_api_changes">5.1.2. API changes</a></li>
+<li><a href="#_migration_steps">5.1.3. Migration steps</a></li>
 </ul>
 </li>
-<li><a 
href="#_important_changes_in_public_servlets_since_version_1_5_5_and_2_0_0">4.2.
 Important changes in public servlets since version 1.5.5 and 2.0.0</a></li>
+<li><a 
href="#_important_changes_in_public_servlets_since_version_1_5_5_and_2_0_0">5.2.
 Important changes in public servlets since version 1.5.5 and 2.0.0</a></li>
 </ul>
 </li>
-<li><a href="#_queries_and_aggregations">5. Queries and aggregations</a>
+<li><a href="#_queries_and_aggregations">6. Queries and aggregations</a>
 <ul class="sectlevel2">
-<li><a href="#_query_counts">5.1. Query counts</a></li>
-<li><a href="#_metrics">5.2. Metrics</a></li>
-<li><a href="#_aggregations">5.3. Aggregations</a>
+<li><a href="#_query_counts">6.1. Query counts</a></li>
+<li><a href="#_metrics">6.2. Metrics</a></li>
+<li><a href="#_aggregations">6.3. Aggregations</a>
 <ul class="sectlevel3">
-<li><a href="#_aggregation_types">5.3.1. Aggregation types</a></li>
+<li><a href="#_aggregation_types">6.3.1. Aggregation types</a></li>
 </ul>
 </li>
 </ul>
 </li>
-<li><a href="#_profile_import_export">6. Profile import &amp; export</a>
+<li><a href="#_profile_import_export">7. Profile import &amp; export</a>
 <ul class="sectlevel2">
-<li><a href="#_importing_profiles">6.1. Importing profiles</a>
+<li><a href="#_importing_profiles">7.1. Importing profiles</a>
 <ul class="sectlevel3">
-<li><a href="#_import_api">6.1.1. Import API</a></li>
+<li><a href="#_import_api">7.1.1. Import API</a></li>
 </ul>
 </li>
-<li><a href="#_exporting_profiles">6.2. Exporting profiles</a>
+<li><a href="#_exporting_profiles">7.2. Exporting profiles</a>
 <ul class="sectlevel3">
-<li><a href="#_export_api">6.2.1. Export API</a></li>
+<li><a href="#_export_api">7.2.1. Export API</a></li>
 </ul>
 </li>
-<li><a href="#_configuration_in_details">6.3. Configuration in details</a></li>
+<li><a href="#_configuration_in_details">7.3. Configuration in details</a></li>
 </ul>
 </li>
-<li><a href="#_consent_management">7. Consent management</a>
+<li><a href="#_consent_management">8. Consent management</a>
 <ul class="sectlevel2">
-<li><a href="#_consent_api">7.1. Consent API</a>
+<li><a href="#_consent_api">8.1. Consent API</a>
 <ul class="sectlevel3">
-<li><a href="#_profiles_with_consents">7.1.1. Profiles with consents</a></li>
-<li><a href="#_consent_type_definitions">7.1.2. Consent type 
definitions</a></li>
-<li><a href="#_creating_update_a_visitor_consent">7.1.3. Creating / update a 
visitor consent</a></li>
-<li><a href="#_how_it_works_internally">7.1.4. How it works 
(internally)</a></li>
+<li><a href="#_profiles_with_consents">8.1.1. Profiles with consents</a></li>
+<li><a href="#_consent_type_definitions">8.1.2. Consent type 
definitions</a></li>
+<li><a href="#_creating_update_a_visitor_consent">8.1.3. Creating / update a 
visitor consent</a></li>
+<li><a href="#_how_it_works_internally">8.1.4. How it works 
(internally)</a></li>
 </ul>
 </li>
 </ul>
 </li>
-<li><a href="#_privacy_management">8. Privacy management</a>
+<li><a href="#_privacy_management">9. Privacy management</a>
 <ul class="sectlevel2">
-<li><a href="#_setting_up_access_to_the_privacy_endpoint">8.1. Setting up 
access to the privacy endpoint</a></li>
-<li><a href="#_anonymizing_a_profile">8.2. Anonymizing a profile</a></li>
-<li><a href="#_downloading_profile_data">8.3. Downloading profile data</a></li>
-<li><a href="#_deleting_a_profile">8.4. Deleting a profile</a></li>
-<li><a href="#_related">8.5. Related</a></li>
+<li><a href="#_setting_up_access_to_the_privacy_endpoint">9.1. Setting up 
access to the privacy endpoint</a></li>
+<li><a href="#_anonymizing_a_profile">9.2. Anonymizing a profile</a></li>
+<li><a href="#_downloading_profile_data">9.3. Downloading profile data</a></li>
+<li><a href="#_deleting_a_profile">9.4. Deleting a profile</a></li>
+<li><a href="#_related">9.5. Related</a></li>
 </ul>
 </li>
-<li><a href="#_cluster_setup">9. Cluster setup</a>
+<li><a href="#_cluster_setup">10. Cluster setup</a>
 <ul class="sectlevel2">
-<li><a href="#_cluster_setup_2">9.1. Cluster setup</a></li>
+<li><a href="#_cluster_setup_2">10.1. Cluster setup</a></li>
 </ul>
 </li>
-<li><a href="#_reference">10. Reference</a>
+<li><a href="#_reference">11. Reference</a>
 <ul class="sectlevel2">
-<li><a href="#_useful_apache_unomi_urls">10.1. Useful Apache Unomi 
URLs</a></li>
-<li><a href="#_how_profile_tracking_works">10.2. How profile tracking works</a>
+<li><a href="#_useful_apache_unomi_urls">11.1. Useful Apache Unomi 
URLs</a></li>
+<li><a href="#_how_profile_tracking_works">11.2. How profile tracking works</a>
 <ul class="sectlevel3">
-<li><a href="#_steps">10.2.1. Steps</a></li>
+<li><a href="#_steps">11.2.1. Steps</a></li>
 </ul>
 </li>
-<li><a href="#_context_request_flow">10.3. Context Request Flow</a></li>
-<li><a href="#_data_model_overview">10.4. Data Model Overview</a></li>
-<li><a href="#_scope">10.5. Scope</a>
+<li><a href="#_context_request_flow">11.3. Context Request Flow</a></li>
+<li><a href="#_data_model_overview">11.4. Data Model Overview</a></li>
+<li><a href="#_scope">11.5. Scope</a>
 <ul class="sectlevel3">
-<li><a href="#_example">10.5.1. Example</a></li>
+<li><a href="#_example">11.5.1. Example</a></li>
 </ul>
 </li>
-<li><a href="#_item">10.6. Item</a>
+<li><a href="#_item">11.6. Item</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition">10.6.1. Structure definition</a></li>
+<li><a href="#_structure_definition">11.6.1. Structure definition</a></li>
 </ul>
 </li>
-<li><a href="#_metadata">10.7. Metadata</a>
+<li><a href="#_metadata">11.7. Metadata</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition_2">10.7.1. Structure definition</a></li>
-<li><a href="#_example_2">10.7.2. Example</a></li>
+<li><a href="#_structure_definition_2">11.7.1. Structure definition</a></li>
+<li><a href="#_example_2">11.7.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_metadataitem">10.8. MetadataItem</a>
+<li><a href="#_metadataitem">11.8. MetadataItem</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition_3">10.8.1. Structure definition</a></li>
-<li><a href="#_example_3">10.8.2. Example</a></li>
+<li><a href="#_structure_definition_3">11.8.1. Structure definition</a></li>
+<li><a href="#_example_3">11.8.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_event">10.9. Event</a>
+<li><a href="#_event">11.9. Event</a>
 <ul class="sectlevel3">
-<li><a href="#_fields">10.9.1. Fields</a></li>
-<li><a href="#_event_types">10.9.2. Event types</a></li>
+<li><a href="#_fields">11.9.1. Fields</a></li>
+<li><a href="#_event_types">11.9.2. Event types</a></li>
 </ul>
 </li>
-<li><a href="#_profile">10.10. Profile</a>
+<li><a href="#_profile">11.10. Profile</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition_4">10.10.1. Structure definition</a></li>
-<li><a href="#_example_4">10.10.2. Example</a></li>
+<li><a href="#_structure_definition_4">11.10.1. Structure definition</a></li>
+<li><a href="#_example_4">11.10.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_persona">10.11. Persona</a>
+<li><a href="#_persona">11.11. Persona</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition_5">10.11.1. Structure definition</a></li>
-<li><a href="#_example_5">10.11.2. Example</a></li>
+<li><a href="#_structure_definition_5">11.11.1. Structure definition</a></li>
+<li><a href="#_example_5">11.11.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_consent">10.12. Consent</a>
+<li><a href="#_consent">11.12. Consent</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition_6">10.12.1. Structure definition</a></li>
-<li><a href="#_example_6">10.12.2. Example</a></li>
+<li><a href="#_structure_definition_6">11.12.1. Structure definition</a></li>
+<li><a href="#_example_6">11.12.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_session">10.13. Session</a>
+<li><a href="#_session">11.13. Session</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition_7">10.13.1. Structure definition</a></li>
-<li><a href="#_example_7">10.13.2. Example</a></li>
+<li><a href="#_structure_definition_7">11.13.1. Structure definition</a></li>
+<li><a href="#_example_7">11.13.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_segment">10.14. Segment</a>
+<li><a href="#_segment">11.14. Segment</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition_8">10.14.1. Structure definition</a></li>
-<li><a href="#_example_8">10.14.2. Example</a></li>
+<li><a href="#_structure_definition_8">11.14.1. Structure definition</a></li>
+<li><a href="#_example_8">11.14.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_condition">10.15. Condition</a>
+<li><a href="#_condition">11.15. Condition</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition_9">10.15.1. Structure definition</a></li>
-<li><a href="#_example_9">10.15.2. Example</a></li>
+<li><a href="#_structure_definition_9">11.15.1. Structure definition</a></li>
+<li><a href="#_example_9">11.15.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_rule">10.16. Rule</a>
+<li><a href="#_rule">11.16. Rule</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition_10">10.16.1. Structure definition</a></li>
-<li><a href="#_example_10">10.16.2. Example</a></li>
+<li><a href="#_structure_definition_10">11.16.1. Structure definition</a></li>
+<li><a href="#_example_10">11.16.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_action">10.17. Action</a>
+<li><a href="#_action">11.17. Action</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition_11">10.17.1. Structure definition</a></li>
-<li><a href="#_example_11">10.17.2. Example</a></li>
+<li><a href="#_structure_definition_11">11.17.1. Structure definition</a></li>
+<li><a href="#_example_11">11.17.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_list">10.18. List</a>
+<li><a href="#_list">11.18. List</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition_12">10.18.1. Structure definition</a></li>
-<li><a href="#_example_12">10.18.2. Example</a></li>
+<li><a href="#_structure_definition_12">11.18.1. Structure definition</a></li>
+<li><a href="#_example_12">11.18.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_goal">10.19. Goal</a>
+<li><a href="#_goal">11.19. Goal</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition_13">10.19.1. Structure definition</a></li>
-<li><a href="#_example_13">10.19.2. Example</a></li>
+<li><a href="#_structure_definition_13">11.19.1. Structure definition</a></li>
+<li><a href="#_example_13">11.19.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_campaign">10.20. Campaign</a>
+<li><a href="#_campaign">11.20. Campaign</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition_14">10.20.1. Structure definition</a></li>
-<li><a href="#_example_14">10.20.2. Example</a></li>
+<li><a href="#_structure_definition_14">11.20.1. Structure definition</a></li>
+<li><a href="#_example_14">11.20.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_scoring_plan">10.21. Scoring plan</a>
+<li><a href="#_scoring_plan">11.21. Scoring plan</a>
 <ul class="sectlevel3">
-<li><a href="#_structure_definition_15">10.21.1. Structure definition</a></li>
-<li><a href="#_example_15">10.21.2. Example</a></li>
+<li><a href="#_structure_definition_15">11.21.1. Structure definition</a></li>
+<li><a href="#_example_15">11.21.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_built_in_event_types">10.22. Built-in Event types</a>
+<li><a href="#_built_in_event_types">11.22. Built-in Event types</a>
 <ul class="sectlevel3">
-<li><a href="#_login_event_type">10.22.1. Login event type</a></li>
-<li><a href="#_view_event_type">10.22.2. View event type</a></li>
-<li><a href="#_form_event_type">10.22.3. Form event type</a></li>
-<li><a href="#_update_properties_event_type">10.22.4. Update properties event 
type</a></li>
-<li><a href="#_identify_event_type">10.22.5. Identify event type</a></li>
-<li><a href="#_session_created_event_type">10.22.6. Session created event 
type</a></li>
-<li><a href="#_goal_event_type">10.22.7. Goal event type</a></li>
-<li><a href="#_modify_consent_event_type">10.22.8. Modify consent event 
type</a></li>
+<li><a href="#_login_event_type">11.22.1. Login event type</a></li>
+<li><a href="#_view_event_type">11.22.2. View event type</a></li>
+<li><a href="#_form_event_type">11.22.3. Form event type</a></li>
+<li><a href="#_update_properties_event_type">11.22.4. Update properties event 
type</a></li>
+<li><a href="#_identify_event_type">11.22.5. Identify event type</a></li>
+<li><a href="#_session_created_event_type">11.22.6. Session created event 
type</a></li>
+<li><a href="#_goal_event_type">11.22.7. Goal event type</a></li>
+<li><a href="#_modify_consent_event_type">11.22.8. Modify consent event 
type</a></li>
 </ul>
 </li>
-<li><a href="#_built_in_condition_types">10.23. Built-in condition types</a>
+<li><a href="#_built_in_condition_types">11.23. Built-in condition types</a>
 <ul class="sectlevel3">
-<li><a href="#_existing_condition_type_descriptors">10.23.1. Existing 
condition type descriptors</a></li>
+<li><a href="#_existing_condition_type_descriptors">11.23.1. Existing 
condition type descriptors</a></li>
 </ul>
 </li>
-<li><a href="#_built_in_action_types">10.24. Built-in action types</a>
+<li><a href="#_built_in_action_types">11.24. Built-in action types</a>
 <ul class="sectlevel3">
-<li><a href="#_existing_action_types_descriptors">10.24.1. Existing action 
types descriptors</a></li>
+<li><a href="#_existing_action_types_descriptors">11.24.1. Existing action 
types descriptors</a></li>
 </ul>
 </li>
-<li><a href="#_updating_events_using_the_context_servlet">10.25. Updating 
Events Using the Context Servlet</a>
+<li><a href="#_updating_events_using_the_context_servlet">11.25. Updating 
Events Using the Context Servlet</a>
 <ul class="sectlevel3">
-<li><a href="#_solution">10.25.1. Solution</a></li>
-<li><a href="#_defining_rules">10.25.2. Defining Rules</a></li>
+<li><a href="#_solution">11.25.1. Solution</a></li>
+<li><a href="#_defining_rules">11.25.2. Defining Rules</a></li>
 </ul>
 </li>
 </ul>
 </li>
-<li><a href="#_integration_samples">11. Integration samples</a>
+<li><a href="#_integration_samples">12. Integration samples</a>
 <ul class="sectlevel2">
-<li><a href="#_samples">11.1. Samples</a></li>
-<li><a href="#_login_sample">11.2. Login sample</a>
+<li><a href="#_samples">12.1. Samples</a></li>
+<li><a href="#_login_sample">12.2. Login sample</a>
 <ul class="sectlevel3">
-<li><a href="#_warning">11.2.1. Warning !</a></li>
-<li><a href="#_installing_the_samples">11.2.2. Installing the samples</a></li>
+<li><a href="#_warning">12.2.1. Warning !</a></li>
+<li><a href="#_installing_the_samples">12.2.2. Installing the samples</a></li>
 </ul>
 </li>
-<li><a href="#_twitter_sample">11.3. Twitter sample</a>
+<li><a href="#_twitter_sample">12.3. Twitter sample</a>
 <ul class="sectlevel3">
-<li><a href="#_overview">11.3.1. Overview</a></li>
-<li><a href="#_interacting_with_the_context_server">11.3.2. Interacting with 
the context server</a></li>
-<li><a 
href="#_retrieving_context_information_from_unomi_using_the_context_servlet">11.3.3.
 Retrieving context information from Unomi using the context servlet</a></li>
+<li><a href="#_overview">12.3.1. Overview</a></li>
+<li><a href="#_interacting_with_the_context_server">12.3.2. Interacting with 
the context server</a></li>
+<li><a 
href="#_retrieving_context_information_from_unomi_using_the_context_servlet">12.3.3.
 Retrieving context information from Unomi using the context servlet</a></li>
 </ul>
 </li>
-<li><a href="#_example_24">11.4. Example</a>
+<li><a href="#_example_24">12.4. Example</a>
 <ul class="sectlevel3">
-<li><a href="#_html_page">11.4.1. HTML page</a></li>
-<li><a href="#_javascript">11.4.2. Javascript</a></li>
+<li><a href="#_html_page">12.4.1. HTML page</a></li>
+<li><a href="#_javascript">12.4.2. Javascript</a></li>
 </ul>
 </li>
-<li><a href="#_conclusion">11.5. Conclusion</a></li>
-<li><a href="#_annex">11.6. Annex</a></li>
-<li><a href="#_weather_update_sample">11.7. Weather update sample</a></li>
+<li><a href="#_conclusion">12.5. Conclusion</a></li>
+<li><a href="#_annex">12.6. Annex</a></li>
+<li><a href="#_weather_update_sample">12.7. Weather update sample</a></li>
 </ul>
 </li>
-<li><a href="#_connectors">12. Connectors</a>
+<li><a href="#_connectors">13. Connectors</a>
 <ul class="sectlevel2">
-<li><a href="#_connectors_2">12.1. Connectors</a>
+<li><a href="#_connectors_2">13.1. Connectors</a>
 <ul class="sectlevel3">
-<li><a href="#_call_for_contributors">12.1.1. Call for contributors</a></li>
+<li><a href="#_call_for_contributors">13.1.1. Call for contributors</a></li>
 </ul>
 </li>
-<li><a href="#_salesforce_connector">12.2. Salesforce Connector</a>
+<li><a href="#_salesforce_connector">13.2. Salesforce Connector</a>
 <ul class="sectlevel3">
-<li><a href="#_getting_started_2">12.2.1. Getting started</a></li>
-<li><a href="#_properties">12.2.2. Properties</a></li>
-<li><a 
href="#_hot_deploying_updates_to_the_salesforce_connector_for_developers">12.2.3.
 Hot-deploying updates to the Salesforce connector (for developers)</a></li>
-<li><a href="#_using_the_salesforce_workbench_for_testing_rest_api">12.2.4. 
Using the Salesforce Workbench for testing REST API</a></li>
-<li><a href="#_setting_up_streaming_push_queries">12.2.5. Setting up Streaming 
Push queries</a></li>
-<li><a href="#_executing_the_unit_tests">12.2.6. Executing the unit 
tests</a></li>
+<li><a href="#_getting_started">13.2.1. Getting started</a></li>
+<li><a href="#_properties">13.2.2. Properties</a></li>
+<li><a 
href="#_hot_deploying_updates_to_the_salesforce_connector_for_developers">13.2.3.
 Hot-deploying updates to the Salesforce connector (for developers)</a></li>
+<li><a href="#_using_the_salesforce_workbench_for_testing_rest_api">13.2.4. 
Using the Salesforce Workbench for testing REST API</a></li>
+<li><a href="#_setting_up_streaming_push_queries">13.2.5. Setting up Streaming 
Push queries</a></li>
+<li><a href="#_executing_the_unit_tests">13.2.6. Executing the unit 
tests</a></li>
 </ul>
 </li>
-<li><a href="#_mailchimp_connector">12.3. MailChimp Connector</a>
+<li><a href="#_mailchimp_connector">13.3. MailChimp Connector</a>
 <ul class="sectlevel3">
-<li><a href="#_getting_started_3">12.3.1. Getting started</a></li>
+<li><a href="#_getting_started_2">13.3.1. Getting started</a></li>
 </ul>
 </li>
 </ul>
 </li>
-<li><a href="#_developers">13. Developers</a>
+<li><a href="#_developers">14. Developers</a>
 <ul class="sectlevel2">
-<li><a href="#_building">13.1. Building</a>
+<li><a href="#_building">14.1. Building</a>
+<ul class="sectlevel3">
+<li><a href="#_initial_setup">14.1.1. Initial Setup</a></li>
+<li><a href="#_building_2">14.1.2. Building</a></li>
+<li><a href="#_installing_an_elasticsearch_server">14.1.3. Installing an 
ElasticSearch server</a></li>
+<li><a href="#_deploying_the_generated_binary_package">14.1.4. Deploying the 
generated binary package</a></li>
+<li><a href="#_deploying_into_an_existing_karaf_server">14.1.5. Deploying into 
an existing Karaf server</a></li>
+<li><a href="#_jdk_selection_on_mac_os_x">14.1.6. JDK Selection on Mac OS 
X</a></li>
+<li><a href="#_running_the_integration_tests">14.1.7. Running the integration 
tests</a></li>
+<li><a href="#_testing_with_an_example_page">14.1.8. Testing with an example 
page</a></li>
+</ul>
+</li>
+<li><a href="#_ssh_shell_commands">14.2. SSH Shell Commands</a>
 <ul class="sectlevel3">
-<li><a href="#_initial_setup">13.1.1. Initial Setup</a></li>
-<li><a href="#_building_2">13.1.2. Building</a></li>
-<li><a href="#_installing_an_elasticsearch_server">13.1.3. Installing an 
ElasticSearch server</a></li>
-<li><a href="#_deploying_the_generated_binary_package">13.1.4. Deploying the 
generated binary package</a></li>
-<li><a href="#_deploying_into_an_existing_karaf_server">13.1.5. Deploying into 
an existing Karaf server</a></li>
-<li><a href="#_jdk_selection_on_mac_os_x">13.1.6. JDK Selection on Mac OS 
X</a></li>
-<li><a href="#_running_the_integration_tests">13.1.7. Running the integration 
tests</a></li>
-<li><a href="#_testing_with_an_example_page">13.1.8. Testing with an example 
page</a></li>
-</ul>
-</li>
-<li><a href="#_ssh_shell_commands">13.2. SSH Shell Commands</a>
-<ul class="sectlevel3">
-<li><a href="#_using_the_shell">13.2.1. Using the shell</a></li>
-<li><a href="#_lifecycle_commands">13.2.2. Lifecycle commands</a></li>
-<li><a href="#_runtime_commands">13.2.3. Runtime commands</a></li>
-</ul>
-</li>
-<li><a href="#_writing_plugins">13.3. Writing Plugins</a></li>
-<li><a href="#_types_vs_instances">13.4. Types vs. instances</a></li>
-<li><a href="#_plugin_structure">13.5. Plugin structure</a></li>
-<li><a href="#_extension_points">13.6. Extension points</a>
-<ul class="sectlevel3">
-<li><a href="#_actiontype">13.6.1. ActionType</a></li>
-<li><a href="#_conditiontype">13.6.2. ConditionType</a></li>
-<li><a href="#_persona_2">13.6.3. Persona</a></li>
-<li><a href="#_propertymergestrategytype">13.6.4. 
PropertyMergeStrategyType</a></li>
-<li><a href="#_propertytype">13.6.5. PropertyType</a></li>
-<li><a href="#_rule_2">13.6.6. Rule</a></li>
-<li><a href="#_scoring">13.6.7. Scoring</a></li>
-<li><a href="#_segments">13.6.8. Segments</a></li>
-<li><a href="#_tag">13.6.9. Tag</a></li>
-<li><a href="#_valuetype">13.6.10. ValueType</a></li>
-</ul>
-</li>
-<li><a href="#_custom_plugins">13.7. Custom plugins</a>
-<ul class="sectlevel3">
-<li><a href="#_creating_a_plugin">13.7.1. Creating a plugin</a></li>
-<li><a href="#_deployment_and_custom_definition">13.7.2. Deployment and custom 
definition</a></li>
-<li><a href="#_predefined_segments">13.7.3. Predefined segments</a></li>
-<li><a href="#_predefined_rules">13.7.4. Predefined rules</a></li>
-<li><a href="#_predefined_properties">13.7.5. Predefined properties</a></li>
-<li><a href="#_predefined_child_conditions">13.7.6. Predefined child 
conditions</a></li>
-<li><a href="#_predefined_personas">13.7.7. Predefined personas</a></li>
-<li><a href="#_custom_action_types">13.7.8. Custom action types</a></li>
-<li><a href="#_custom_condition_types">13.7.9. Custom condition types</a></li>
+<li><a href="#_using_the_shell">14.2.1. Using the shell</a></li>
+<li><a href="#_lifecycle_commands">14.2.2. Lifecycle commands</a></li>
+<li><a href="#_runtime_commands">14.2.3. Runtime commands</a></li>
 </ul>
 </li>
-<li><a href="#_migration_patches">13.8. Migration patches</a></li>
+<li><a href="#_writing_plugins">14.3. Writing Plugins</a></li>
+<li><a href="#_types_vs_instances">14.4. Types vs. instances</a></li>
+<li><a href="#_plugin_structure">14.5. Plugin structure</a></li>
+<li><a href="#_extension_points">14.6. Extension points</a>
+<ul class="sectlevel3">
+<li><a href="#_actiontype">14.6.1. ActionType</a></li>
+<li><a href="#_conditiontype">14.6.2. ConditionType</a></li>
+<li><a href="#_persona_2">14.6.3. Persona</a></li>
+<li><a href="#_propertymergestrategytype">14.6.4. 
PropertyMergeStrategyType</a></li>
+<li><a href="#_propertytype">14.6.5. PropertyType</a></li>
+<li><a href="#_rule_2">14.6.6. Rule</a></li>
+<li><a href="#_scoring">14.6.7. Scoring</a></li>
+<li><a href="#_segments">14.6.8. Segments</a></li>
+<li><a href="#_tag">14.6.9. Tag</a></li>
+<li><a href="#_valuetype">14.6.10. ValueType</a></li>
+</ul>
+</li>
+<li><a href="#_custom_plugins">14.7. Custom plugins</a>
+<ul class="sectlevel3">
+<li><a href="#_creating_a_plugin">14.7.1. Creating a plugin</a></li>
+<li><a href="#_deployment_and_custom_definition">14.7.2. Deployment and custom 
definition</a></li>
+<li><a href="#_predefined_segments">14.7.3. Predefined segments</a></li>
+<li><a href="#_predefined_rules">14.7.4. Predefined rules</a></li>
+<li><a href="#_predefined_properties">14.7.5. Predefined properties</a></li>
+<li><a href="#_predefined_child_conditions">14.7.6. Predefined child 
conditions</a></li>
+<li><a href="#_predefined_personas">14.7.7. Predefined personas</a></li>
+<li><a href="#_custom_action_types">14.7.8. Custom action types</a></li>
+<li><a href="#_custom_condition_types">14.7.9. Custom condition types</a></li>
+</ul>
+</li>
+<li><a href="#_migration_patches">14.8. Migration patches</a></li>
 </ul>
 </li>
 </ul>
@@ -462,14 +482,8 @@ make sure you are using the proper versi
 <div class="ulist">
 <ul>
 <li>
-<p>Connect to <a href="http://localhost:8181"; 
class="bare">http://localhost:8181</a> to try our some live examples (such as 
the web tracker)</p>
-</li>
-<li>
 <p>Trying our integration <a href="#_samples">samples page</a></p>
 </li>
-<li>
-<p>Learning more about the <a href="#_web_tracker">web tracker</a></p>
-</li>
 </ul>
 </div>
 </div>
@@ -1127,463 +1141,12 @@ to send additional events.</p>
 <p>You can find more <a href="#_useful_apache_unomi_urls">useful Apache Unomi 
URLs</a> that can be used in the same way as the above examples.</p>
 </li>
 <li>
-<p>You may want to know integrate the provided <a href="#_web_tracker">web 
tracker</a> into your web site.</p>
-</li>
-<li>
 <p>Read the <a href="#_twitter_sample">Twitter sample</a> documentation that 
contains a detailed example of how to integrate with Apache Unomi.</p>
 </li>
 </ul>
 </div>
 </div>
 </div>
-<div class="sect2">
-<h3 id="_web_tracker">2.4. Web Tracker</h3>
-<div class="paragraph">
-<p>This extension is providing the web tracker to start collecting visitors 
data on your website.
-The tracker is implemented as an integration of <a 
href="https://github.com/segmentio/analytics.js";>analytics.js</a> for Unomi.</p>
-</div>
-<div class="sect3">
-<h4 id="_getting_started">2.4.1. Getting started</h4>
-<div class="paragraph">
-<p>Extension can be tested at : <code><a 
href="http://localhost:8181/tracker/index.html"; 
class="bare">http://localhost:8181/tracker/index.html</a></code></p>
-</div>
-<div class="paragraph">
-<p>In your page include unomiOptions and include code snippet from 
<code>snippet.min.js</code> :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>&lt;script type="text/javascript"&gt;
-        var unomiOption = {
-            scope: 'realEstateManager',
-            url: 'http://localhost:8181'
-        };
-        window.unomiTracker||(window.unomiTracker={}),function(){function 
e(e){for(unomiTracker.initialize({"Apache 
Unomi":unomiOption});n.length&gt;0;){var 
r=n.shift(),t=r.shift();unomiTracker[t]&amp;&amp;unomiTracker[t].apply(unomiTracker,r)}}for(var
 
n=[],r=["trackSubmit","trackClick","trackLink","trackForm","initialize","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on","personalize"],t=0;t&lt;r.length;t++){var
 i=r[t];window.unomiTracker[i]=function(e){return function(){var 
r=Array.prototype.slice.call(arguments);return 
r.unshift(e),n.push(r),window.unomiTracker}}(i)}unomiTracker.load=function(){var
 
n=document.createElement("script");n.type="text/javascript",n.async=!0,n.src=unomiOption.url+"/tracker/unomi-tracker.min.js",n.addEventListener?n.addEventListener("load",function(n){"function"==typeof
 
e&amp;&amp;e(n)},!1):n.onreadystatechange=function(){"complete"!==this.readyState&amp;&amp;"loaded"!==this.readyState||e(window.event)};var
 r=
 
document.getElementsByTagName("script")[0];r.parentNode.insertBefore(n,r)},document.addEventListener("DOMContentLoaded",unomiTracker.load),unomiTracker.page()}();
-&lt;/script&gt;</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p><code>window.unomiTracker</code> can be used to send additional events when 
needed.</p>
-</div>
-<div class="paragraph">
-<p>Check analytics.js API <a 
href="https://segment.com/docs/sources/website/analytics.js/";>here</a>.
-All methods can be used on <code>unomiTracker</code> object, although not all 
event types are supported by Unomi intergation.</p>
-</div>
-</div>
-<div class="sect3">
-<h4 id="_how_to_contribute">2.4.2. How to contribute</h4>
-<div class="paragraph">
-<p>The source code is in the folder javascript with a package.json, the file 
to update is <code>analytics.js-integration-apache-unomi.js</code> apply your 
modification in this file then use the command <code>yarn build</code> to 
compile a new JS file.
-Then you can use the test page to try your changes <code><a 
href="http://localhost:8181/tracker/index.html"; 
class="bare">http://localhost:8181/tracker/index.html</a></code>.</p>
-</div>
-</div>
-<div class="sect3">
-<h4 id="_tracking_page_views">2.4.3. Tracking page views</h4>
-<div class="paragraph">
-<p>In the initialize call, the tracker will generate an implicit page view 
event, which by default will be populated with
-the following information:</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code class="language-javascript" 
data-lang="javascript">    window.digitalData.page = window.digitalData.page || 
{
-        path: location.pathname + location.hash,
-        pageInfo: {
-            pageName: document.title,
-            pageID : location.pathname + location.hash,
-            pagePath : location.pathname + location.hash,
-            destinationURL: location.href
-        }
-    }</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>Now if you want to provide your own custom page information for the initial 
page view, you can simply do it like this:</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code class="language-`javascript" 
data-lang="`javascript">    unomiTracker.initialize({
-            scope: 'myScope',
-            url: 'http://unomi:8181', // we use an empty URL to make it 
relative to this page.
-            initialPageProperties: {
-                path: path,
-                pageInfo: {
-                    destinationURL: location.href,
-                    tags: ["tag1", "tag2", "tag3"],
-                    categories: ["category1", "category2", "category3"]
-                },
-                interests: {
-                    "interest1": 1,
-                    "interest2": 2,
-                    "interest3": 3
-                }
-            }
-        });</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>`</p>
-</div>
-<div class="paragraph">
-<p>Also note that the FIRST call to unomiTracker.page() will be IGNORED 
because of this initial page view.This is the
-way that the Analytics.js library handles it.So make sure you are aware of 
this when calling it.This is to avoid having
-two page views on a single call and to be compatible with old versions that 
did use the explicit call.</p>
-</div>
-<div class="paragraph">
-<p>By default the script will track page views, but maybe you want to take 
control over this mechanism of add page views
-to a single page application.In order to generate a page view programmatically 
from Javascript you can use code similar
-to this :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>    &lt;script type="text/javascript"&gt;
-        // This is an example of how to provide more details page properties 
to the view event. This can be useful
-        // in the case of an SPA that wants to provide information about a 
view that has metadata such as categories,
-        // tags or interests.
-        path = location.pathname + location.hash;
-        properties = {
-            path: path,
-            pageInfo: {
-                destinationURL: location.href,
-                tags : [ "tag1", "tag2", "tag3"],
-                categories : ["category1", "category2", "category3"],
-            },
-            interests : {
-                "interest1" : 1,
-                "interest2" : 2,
-                "interest3" : 3
-            }
-        };
-        console.log(properties);
-        // this will trigger a second page view for the same page (the first 
page view is in the tracker snippet).
-        window.unomiTracker.page(properties);
-    &lt;/script&gt;</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>Here is a more detail view of what you may include in the pageInfo object 
:</p>
-</div>
-<table class="tableblock frame-all grid-all stretch">
-<caption class="title">Table 1. PageInfo Properties</caption>
-<colgroup>
-<col style="width: 50%;">
-<col style="width: 50%;">
-</colgroup>
-<thead>
-<tr>
-<th class="tableblock halign-left valign-top">Name</th>
-<th class="tableblock halign-left valign-top">Description</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td class="tableblock halign-left valign-top"><p 
class="tableblock">pageID</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">A unique 
identifier in string format for the page. Default value : page path</p></td>
-</tr>
-<tr>
-<td class="tableblock halign-left valign-top"><p 
class="tableblock">pageName</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">A 
user-displayed name for the page. Default value : page title</p></td>
-</tr>
-<tr>
-<td class="tableblock halign-left valign-top"><p 
class="tableblock">pagePath</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">The path 
of the page, stored by Unomi. This value should be the same as the one passed 
in the <code>page</code> property of the
-object passed to the unomiTracker call. Default value : page path</p></td>
-</tr>
-<tr>
-<td class="tableblock halign-left valign-top"><p 
class="tableblock">destinationURL</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">The full 
URL for the page view. This doesn&#8217;t have to be a real existing URL it 
could be an internal SPA route. Default value : page URL</p></td>
-</tr>
-<tr>
-<td class="tableblock halign-left valign-top"><p 
class="tableblock">referringURL</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">The 
referringURL also known as the previous URL of the page/screen viewed. Default 
value : page referrer URL</p></td>
-</tr>
-<tr>
-<td class="tableblock halign-left valign-top"><p 
class="tableblock">tags</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">A String 
array of tag identifiers. For example <code>['tag1', 'tag2', 
'tag3']</code></p></td>
-</tr>
-<tr>
-<td class="tableblock halign-left valign-top"><p 
class="tableblock">categories</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">A String 
array of category identifiers. For example <code>['category1', 'category2', 
'category3']</code></p></td>
-</tr>
-</tbody>
-</table>
-<div class="paragraph">
-<p>The <code>interests</code> object is basically list of interests with 
"weights" attached to them.These interests will be accumulated
-in Apache Unomi on profiles to indicate growing interest over time for 
specific topics.These are freely defined and
-will be accepted by Apache Unomi without needing to declare them previously 
anywhere (the same is true for tags and
-categories).</p>
-</div>
-</div>
-<div class="sect3">
-<h4 id="_tracking_form_submissions">2.4.4. Tracking form submissions</h4>
-<div class="paragraph">
-<p>Using the web tracker you can also track form submissions. In order to do 
this a few steps are required to get a form&#8217;s
-submission to be tracked and then its form values to be sent as events to 
Apache Unomi. Finally setting up a rule to
-react to the incoming event will help use the form values to perform any 
action that is desired.</p>
-</div>
-<div class="paragraph">
-<p>Let&#8217;s look at a concrete example. Before we get started you should 
know that this example is already available to
-directly test in Apache Unomi at the following URL :</p>
-</div>
-<div class="literalblock">
-<div class="content">
-<pre>http://localhost:8181/tracker</pre>
-</div>
-</div>
-<div class="paragraph">
-<p>Simply modify the form values and click submit and it will perform all the 
steps we are describing below.</p>
-</div>
-<div class="paragraph">
-<p>So here is the form we want to track :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>&lt;form id="testFormTracking" action="#" 
name="testFormTracking"&gt;
-    &lt;label for="firstName"&gt;First name&lt;/label&gt;
-    &lt;input type="text" id="firstName" name="firstName" value="John"/&gt;
-
-    &lt;label for="lastName"&gt;Last name&lt;/label&gt;
-    &lt;input type="text" id="lastName" name="lastName" value="Doe"/&gt;
-
-    &lt;label for="email"&gt;Email&lt;/label&gt;
-    &lt;input type="email" id="email" name="email" 
value="[email protected]"/&gt;
-
-    &lt;input type="submit" name="submitButton" value="Submit"/&gt;
-&lt;/form&gt;</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>As you can see it&#8217;s composed of three fields - firstName, lastName 
and email - as well as a submit button. In order to
-track it we can add directly under the following snippet :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>&lt;script type="text/javascript"&gt;
-    window.addEventListener("load", function () {
-        var form = document.getElementById('testFormTracking');
-        unomiTracker.trackForm(form, 'formSubmitted', {formName: form.name});
-    });
-&lt;/script&gt;</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>What this snippet does is retrieve the form using its element ID and then 
uses the unomiTracker to track form submissions.
-Be careful to always use in the form event name a string that starts with 
<code>form</code> in order for the event to be sent back
-to Unomi. Also the form name is also a mandatory parameter that will be passed 
to Unomi inside a event of type <code>form</code> under
-the <code>target.itemId</code> property name.</p>
-</div>
-<div class="paragraph">
-<p>Here is an example of the event that gets sent back to Apache Unomi:</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>{
-  "itemId" : "cd627012-963e-4bb5-97f0-480990b41254",
-  "itemType" : "event",
-  "scope" : "realEstateManager",
-  "version" : 1,
-  "eventType" : "form",
-  "sessionId" : "aaad09aa-88c2-67bd-b106-5a47ded43ead",
-  "profileId" : "48563fd0-6319-4260-8dba-ae421beba26f",
-  "timeStamp" : "2018-11-23T16:32:26Z",
-  "properties" : {
-    "firstName" : "John",
-    "lastName" : "Doe",
-    "email" : "[email protected]",
-    "submitButton" : "Submit"
-  },
-  "source" : {
-    "itemId" : "/tracker/",
-    "itemType" : "page",
-    "scope" : "realEstateManager",
-    "version" : null,
-    "properties" : {
-      "pageInfo" : {
-        "destinationURL" : 
"http://localhost:8181/tracker/?firstName=Bill&amp;lastName=Gates&amp;email=bgates%40microsoft.com";,
-        "pageID" : "/tracker/",
-        "pagePath" : "/tracker/",
-        "pageName" : "Apache Unomi Web Tracker Test Page",
-        "referringURL" : 
"http://localhost:8181/tracker/?firstName=John&amp;lastName=Doe&amp;email=johndoe%40acme.com";
-      },
-      "attributes" : [ ],
-      "consentTypes" : [ ],
-      "interests" : { }
-    }
-  },
-  "target" : {
-    "itemId" : "testFormTracking",
-    "itemType" : "form",
-    "scope" : "realEstateManager",
-    "version" : null,
-    "properties" : { }
-  },
-  "persistent" : true
-}</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>You can see in this event that the form values are sent as properties of 
the event itself, while the form name is sent
-as the <code>target.itemId</code></p>
-</div>
-<div class="paragraph">
-<p>While setting up form tracking, it can be very useful to use the Apache 
Unomi Karaf SSH shell commands : <code>event-tail</code>
-and <code>event-view</code> to check if you are properly receiving the form 
submission events and that they contain the expected
-data. If not, check your tracking code for any errors.</p>
-</div>
-<div class="paragraph">
-<p>Now that the data is properly sent using an event to Apache Unomi, we must 
still use it to perform some kind of actions.
-Using rules, we could do anything from updating the profile to sending the 
data to a third-party server (using a custom-
-developped action of course). In this example we will illustrate how to update 
the profile.</p>
-</div>
-<div class="paragraph">
-<p>In order to do so we will deploy a rule that will copy data coming from the 
event into a profile. But we will need to
-map the form field names to profile names, and this can be done using the 
<code>setPropertyAction</code> that&#8217;s available out of the
-box in the Apache Unomi server.</p>
-</div>
-<div class="paragraph">
-<p>There are two ways to register rules : either by building a custom OSGi 
bundle plugin or using the REST API to directly
-send a JSON representation of the rule to be saved. We will in this example 
use the CURL shell command to make a call to
-the REST API.</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>curl -X POST -k -u karaf:karaf 
https://localhost:9443/cxs/rules \
-  --header "Content-Type: application/json" \
--d @- &lt;&lt; EOF
-{
-  "itemId": "form-mapping-example",
-  "itemType": "rule",
-  "linkedItems": null,
-  "raiseEventOnlyOnceForProfile": false,
-  "raiseEventOnlyOnceForSession": false,
-  "priority": -1,
-  "metadata": {
-    "id": "form-mapping-example",
-    "name": "Example Form Mapping",
-    "description": "An example of how to map event properties to profile 
properties",
-    "scope": "realEstateManager",
-    "tags": [],
-    "enabled": true,
-    "missingPlugins": false,
-    "hidden": false,
-    "readOnly": false
-  },
-  "condition": {
-    "type": "formEventCondition",
-    "parameterValues": {
-      "formId": "testFormTracking",
-      "pagePath" : "/tracker/"
-    }
-  },
-  "actions": [
-    {
-      "type": "setPropertyAction",
-      "parameterValues": {
-        "setPropertyName": "properties(firstName)",
-        "setPropertyValue": "eventProperty::properties(firstName)",
-        "setPropertyStrategy": "alwaysSet"
-      }
-    },
-    {
-      "type": "setPropertyAction",
-      "parameterValues": {
-        "setPropertyName": "properties(lastName)",
-        "setPropertyValue": "eventProperty::properties(lastName)",
-        "setPropertyStrategy": "alwaysSet"
-      }
-    },
-    {
-      "type": "setPropertyAction",
-      "parameterValues": {
-        "setPropertyName": "properties(email)",
-        "setPropertyValue": "eventProperty::properties(email)",
-        "setPropertyStrategy": "alwaysSet"
-      }
-    }
-  ]
-}
-EOF</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>As you can see in this request, we have a few parameters that need 
explaining:</p>
-</div>
-<div class="ulist">
-<ul>
-<li>
-<p><code>-k</code> is used to accept any certificate as we are in this example 
using a default Apache Unomi server configuration that
-comes with its predefined HTTPS certificates</p>
-</li>
-<li>
-<p><code>-u karaf:karaf</code> is the default username/password for 
authenticating to the REST API. To change this value you should
-edit the `etc/users.properties`file and it is required to modify this login 
before going to production.</p>
-</li>
-</ul>
-</div>
-<div class="paragraph">
-<p>Finally the rule itself should be pretty self-explanatory but there are a 
few important things to note :</p>
-</div>
-<div class="ulist">
-<ul>
-<li>
-<p>the <code>itemId</code> and <code>metadata.id</code> values should be the 
same</p>
-</li>
-<li>
-<p>the <code>scope</code> should be the same as the scope that was setup in 
the tracker initialization</p>
-</li>
-<li>
-<p>the <code>formId</code> parameter must have the form name value</p>
-</li>
-<li>
-<p>the <code>pagePath</code> should be the pagePath passed through the event 
(if you&#8217;re not sure of its value, you could either using
-network debugging in the browser or use the <code>event-tail</code> and 
<code>event-view</code> commands in the Apache Unomi Karaf SSH shell).</p>
-</li>
-<li>
-<p>the setPropertyAction may be repeated as many times as desired to copy the 
values from the event to the profile. Note that
-the <code>setPropertyName</code> will define the property to set on the 
profile and the <code>setPropertyValue</code> will define where the
-value is coming from. In this example the name and the value are the same but 
that is no way a requirement. It could
-even be possible to using multiple <code>setPropertyAction</code> instances to 
copy the same event property into different profile
-properties.</p>
-</li>
-</ul>
-</div>
-<div class="paragraph">
-<p>To check if your rule is properly deployed you can use the following SSH 
shell command :</p>
-</div>
-<div class="paragraph">
-<p><code>unomi:rule-view form-mapping-example</code></p>
-</div>
-<div class="paragraph">
-<p>The parameter is the <code>itemId</code> of the rule. If you want to see 
all the rules deployed in the system you can use the
-command :</p>
-</div>
-<div class="paragraph">
-<p><code>unomi:rule-list 1000</code></p>
-</div>
-<div class="paragraph">
-<p>The <code>1000</code> parameter is the limit of number of objects to 
retrieve. As the number of rules can grow quickly in an Apache
-Unomi instance, it is recommended to put this value a bit high to make sure 
you get the full list of rules.</p>
-</div>
-<div class="paragraph">
-<p>Once the rule is in place, try submitting the form with some values and 
check that the profile is properly updated. One
-recommend way of doing this is to use the <code>event-tail</code> command that 
will output something like this :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>ID                                  |Type         
 |Session                             |Profile                             
|Timestamp                    |Scope          |Persi|
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-cef09b89-6b99-4e4f-a99c-a4159a66b42b|form          
|aaad09aa-88c2-67bd-b106-5a47ded43ead|48563fd0-6319-4260-8dba-ae421beba26f|Fri 
Nov 23 17:52:33 CET 2018 |realEstateManag|true |</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>You can directly see the profile that is being used, so you can then simply 
use the</p>
-</div>
-<div class="paragraph">
-<p><code>unomi:profile-view 48563fd0-6319-4260-8dba-ae421beba26f</code></p>
-</div>
-<div class="paragraph">
-<p>command to see a JSON dump of the profile and check that the form values 
have been properly positioned.</p>
-</div>
-</div>
-</div>
 </div>
 </div>
 <div class="sect1">
@@ -2085,7 +1648,7 @@ org.apache.unomi.security.personalizatio
 <p>Placed right before the function, the “@Action” annotation contains a 
set of parameter detailing how the action should be triggered.</p>
 </div>
 <table class="tableblock frame-all grid-all stretch">
-<caption class="title">Table 2. @Action annotation</caption>
+<caption class="title">Table 1. @Action annotation</caption>
 <colgroup>
 <col style="width: 25%;">
 <col style="width: 25%;">
@@ -2622,15 +2185,562 @@ of the ElasticSearch server(s). But if y
 </div>
 </div>
 <div class="sect1">
-<h2 id="_migrations">4. Migrations</h2>
+<h2 id="_json_schemas">4. JSON schemas</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="_introduction_2">4.1. Introduction</h3>
+<div class="sect3">
+<h4 id="_what_is_a_json_schema">4.1.1. What is a JSON Schema</h4>
+<div class="paragraph">
+<p><a href="https://json-schema.org/specification.html";>JSON Schema</a> is a 
powerful standard for validating the structure of JSON data.
+Described as a JSON object, a JSON schema file contains format, types, 
patterns, and more.
+Used against JSON data, a JSON schema validates that the data is compatible 
with the specified schema.</p>
+</div>
+<div class="paragraph">
+<p>Example of a basic JSON schema that validates that the path property is a 
string property:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+    "$id":"https://unomi.apache.org/schemas/json/example/1-0-0";,
+    "$schema":"https://json-schema.org/draft/2019-09/schema";,
+    "title":"Example of a basic schema",
+    "type":"object",
+    "properties":{
+        "path":{
+            "type":"string",
+            "$comment":"Example of a property."
+        }
+    }
+}</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+    "path": "example/of/path" //Is valid
+}</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+    "path": 100  // Is not valid
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Apache Unomi is using json-schema-validator to integrate JSON schema.
+The library and its source code is available at: <a 
href="https://github.com/networknt/json-schema-validator";>https://github.com/networknt/json-schema-validator</a>,
 you can refer to the feature’s pom.xml available at <a 
href="https://github.com/apache/unomi/blob/master/extensions/json-schema/services/pom.xml#L35";>json-schema/service/pom.xml</a>
 to identify which version of the library is currently integrated.</p>
+</div>
+<div class="paragraph">
+<p>You can discover and play with JSON schema using online tools such as <a 
href="https://www.jsonschemavalidator.net/";>JSON Schema Validator</a>.
+Such tools allow you to validate a schema against JSON data (such as the 
example above), and can point to particular errors.
+More details about JSON schema are available on the official specification’s 
website: <a 
href="https://json-schema.org/specification.html";>https://json-schema.org/specification.html</a></p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_key_concepts">4.1.2. Key concepts</h4>
+<div class="paragraph">
+<p>This section details concepts that are important to understand in order to 
use JSON schema validation with Apache Unomi.</p>
+</div>
+<div class="sect4">
+<h5 id="_id_keyword">$id keyword</h5>
+<div class="paragraph">
+<p>The <strong>$id</strong> keyword:</p>
+</div>
+<div class="paragraph">
+<p>Each schema in Apache Unomi should have a <strong>$id</strong>, the 
<strong>$id</strong> value is an URI which will be used to retrieve the schema 
and must be unique.</p>
+</div>
+<div class="paragraph">
+<p>Example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+    "$id":"https://unomi.apache.org/schemas/json/example/1-0-0";
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_ref_keyword">$ref keyword</h5>
+<div class="paragraph">
+<p>The <strong>$ref</strong> keyword allows you to reference another JSON 
schema by its <strong>$id</strong> keyword.
+It’s possible to separate complex structures or repetitive parts of schema 
into other small files and use <strong>$ref</strong> to include them into 
several json schemas.</p>
+</div>
+<div class="paragraph">
+<p>Example with a person and an address:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+    "$id": "https://example.com/schemas/address";,
+    "type": "object",
+    "properties": {
+        "street_address": { "type": "string" },
+        "city": { "type": "string" },
+        "state": { "type": "string" }
+    }
+}</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+    "type": "object",
+    "properties": {
+        "first_name":{ "type": "string" },
+        "last_name": { "type": "string" },
+        "shipping_address": {
+            "$ref": "https://example.com/schemas/address";
+        },
+        "billing_address": {
+            "$ref": "https://example.com/schemas/address";
+        }
+    }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>More details about <strong>$ref</strong> can be found in the 
specifications: <a 
href="https://json-schema.org/understanding-json-schema/structuring.html#ref";>https://json-schema.org/understanding-json-schema/structuring.html#ref</a></p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_allof_keyword">allOf keyword</h5>
+<div class="paragraph">
+<p>The allOf keyword is an array of fields which allows schema composition.
+The data will be valid against a schema if the data are valid against all of 
the given subschemas in the allOf part and are valid against the properties 
defined in the schema.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+    "$id": "https://unomi.apache.org/schemas/json/example/1-0-0";,
+    "$schema": "https://json-schema.org/draft/2019-09/schema";,
+    "type": "object",
+    "allOf": [
+        {
+            "type": "object",
+            "properties": {
+                "fromAllOf": {
+                    "type": "integer",
+                    "$comment": "Example of allOf."
+                }
+            }
+        }
+    ],
+    "properties": {
+        "myProperty": {
+            "type": "string",
+            "$comment": "Example of a property."
+        }
+    }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Valid JSON:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+    "myProperty": "My property",
+    "fromAllOf" : 10
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Invalid JSON:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+    "myProperty": "My property",
+    "fromAllOf" : "My value"
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>It’s also possible to use a reference <strong>$ref</strong> in the 
<strong>allOf</strong> keyword to reference another schema.</p>
+</div>
+<div class="paragraph">
+<p>In Unomi, there is an example of using <strong>$ref</strong> in the 
<strong>allOf</strong> keyword to validate the properties which are defined in 
the event schema.
+This schema contains properties common to all events.
+It’s done in the the view event schema.
+The file can be found on github: <a 
href="https://github.com/apache/unomi/blob/master/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/view/view.json#L13";>view.json</a>
+More details about allOf can be found in the specifications: <a 
href="https://json-schema.org/understanding-json-schema/reference/combining.html#allof";>https://json-schema.org/understanding-json-schema/reference/combining.html#allof</a></p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_unevaluatedproperties_keyword">unevaluatedProperties keyword</h5>
+<div class="paragraph">
+<p>The <strong>unevaluatedProperties</strong> keyword is useful for schema 
composition as well as enforcing stricter schemas.
+This keyword is similar to <strong>additionalProperties</strong> except that 
it can recognize properties declared in sub schemas.
+When setting the <strong>unevaluatedProperties</strong> value to 
<strong>false</strong>, the properties which are not present in the properties 
part and are not present in the sub schemas will be considered as invalid.</p>
+</div>
+<div class="paragraph">
+<p>Example with the following schema:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+    "$id": "https://unomi.apache.org/schemas/json/example/1-0-0";,
+    "$schema": "https://json-schema.org/draft/2019-09/schema";,
+    "type": "object",
+    "allOf": [
+        {
+            "$ref": "https://unomi.apache.org/schemas/json/subschema/1-0-0";
+        }
+    ],
+    "properties": {
+        "myProperty": {
+            "type": "string",
+            "$comment": "Example of a property."
+        }
+    },
+    "unevaluatedProperties": false
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Sub schema:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+    "$id": "https://unomi.apache.org/schemas/json/subschema/1-0-0";,
+    "$schema": "https://json-schema.org/draft/2019-09/schema";,
+    "type": "object",
+    "properties": {
+        "fromAllOf": {
+            "type": "string",
+            "$comment": "Example of allOf."
+        }
+    }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>With the following data, the validation will fail because the property 
<strong>myNewProperty</strong> is not defined neither the 
<strong>properties</strong> part nor the <strong>allOf</strong> part.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+    "myProperty": "My property",
+    "fromAllOf" : 10,
+    "myNewProperty": "another one" //Not valid
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_how_are_json_schema_used_in_unomi">4.1.3. How are JSON Schema used in 
Unomi</h4>
+<div class="paragraph">
+<p>JSON Schema is used in Unomi to validate the data coming from the two 
public endpoints <strong>/contextRequest</strong> and 
<strong>/eventCollector</strong>.
+Both endpoints have a custom deserializer which will begin by validating the 
payload of the request, then will filter invalid events present in this payload.
+If an event is not valid it will not be processed by the system.
+The internal events are not validated by JSON schema as they are not sent 
through the public endpoints.</p>
+</div>
+<div class="paragraph">
+<p>In Unomi, each event type must have an associated JSON schema.
+To validate an event, Unomi will search for a schema in which the target of 
the schema is <strong>events</strong>, and with the name of the schema matching 
the event type.</p>
+</div>
+<div class="paragraph">
+<p>A custom keyword named <strong>self</strong> has to be present in the JSON 
schemas to store the information related to each schema.
+The following example is the <strong>self</strong> part of the view event JSON 
schema.
+Having the target set to <strong>events</strong> and the name set to 
<strong>view</strong>, this schema will be used to validate the events of type 
<strong>view</strong>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>…
+"self":{
+    "vendor":"org.apache.unomi",
+    "target" : "events",
+    "name": "view",
+    "format":"jsonschema",
+    "version":"1-0-0"
+},
+…</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Link to the schema on github: <a 
href="https://github.com/apache/unomi/blob/master/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/view/view.json";>view.json</a>.</p>
+</div>
+<div class="paragraph">
+<p>A set of predefined schema are present in Unomi, these schemas can be found 
under the folder : <a 
href="https://github.com/apache/unomi/tree/master/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas";>extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas</a>.</p>
+</div>
+<div class="paragraph">
+<p>These schemas will be loaded in memory at startup.
+Each schema where the <strong>target</strong> value is set to 
<strong>events</strong>, will be used to validate events.
+The others are simply used as part of JSON schema or can be used in additional 
JSON schemas.</p>
+</div>
+<div class="paragraph">
+<p>It’s possible to add JSON schemas to validate your own event by using the 
API, the explanations to manage JSON schema through the API are
+in the <a href="#_create_update_a_json_schema_to_validate_an_event">Create / 
update a JSON schema to validate an event</a> section.</p>
+</div>
+<div class="paragraph">
+<p>Contrary to the predefined schemas, the schemas added through the API will 
be persisted in Elasticsearch in the jsonSchema index.
+Schemas persisted in Elasticsearch do not require a restart of the platform to 
reflect changes.</p>
+</div>
+<div class="paragraph">
+<p>Process of creation of schemas:</p>
+</div>
+<div class="imageblock text-center">
+<div class="content">
+<img src="images/process-creation-schema.png" alt="process creation schema">
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_json_schema_api">4.2. JSON schema API</h3>
+<div class="paragraph">
+<p>The JSON schema endpoints are private, so the user has to be authenticated 
to manage the JSON schema in Unomi.</p>
+</div>
+<div class="sect3">
+<h4 id="_list_existing_schemas">4.2.1. List existing schemas</h4>
+<div class="paragraph">
+<p>The REST endpoint GET <code>{{url}}/cxs/jsonSchema</code> allows to get all 
ids of available schemas and subschemas.</p>
+</div>
+<div class="paragraph">
+<p>List of predefined schemas:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>[
+    
"https://unomi.apache.org/schemas/json/events/modifyConsent/properties/1-0-0";,
+    "https://unomi.apache.org/schemas/json/item/1-0-0";,
+    "https://unomi.apache.org/schemas/json/events/login/1-0-0";,
+    "https://unomi.apache.org/schemas/json/events/modifyConsent/1-0-0";,
+    "https://unomi.apache.org/schemas/json/consentType/1-0-0";,
+    "https://unomi.apache.org/schemas/json/items/page/properties/1-0-0";,
+    
"https://unomi.apache.org/schemas/json/items/page/properties/attributes/1-0-0";,
+    "https://unomi.apache.org/schemas/json/events/incrementInterest/1-0-0";,
+    
"https://unomi.apache.org/schemas/json/events/view/flattenProperties/1-0-0";,
+    "https://unomi.apache.org/schemas/json/interests/1-0-0";,
+    "https://unomi.apache.org/schemas/json/items/site/1-0-0";,
+    
"https://unomi.apache.org/schemas/json/items/page/properties/pageInfo/1-0-0";,
+    "https://unomi.apache.org/schemas/json/rest/requestIds/1-0-0";,
+    "https://unomi.apache.org/schemas/json/rest/eventscollectorrequest/1-0-0";,
+    "https://unomi.apache.org/schemas/json/events/view/properties/1-0-0";,
+    "https://unomi.apache.org/schemas/json/items/page/1-0-0";,
+    "https://unomi.apache.org/schemas/json/URLParameters/1-0-0";,
+    "https://unomi.apache.org/schemas/json/event/1-0-0";,
+    "https://unomi.apache.org/schemas/json/timestampeditem/1-0-0";,
+    "https://unomi.apache.org/schemas/json/events/updateProperties/1-0-0";,
+    "https://unomi.apache.org/schemas/json/consent/1-0-0";,
+    
"https://unomi.apache.org/schemas/json/events/incrementInterest/flattenProperties/1-0-0";,
+    "https://unomi.apache.org/schemas/json/events/view/1-0-0";
+]</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Custom schemas will also be present in this list once added.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_read_a_schema">4.2.2. Read a schema</h4>
+<div class="paragraph">
+<p>It’s possible to get a schema by its id by calling the endpoint 
<code>POST {{url}}/cxs/jsonSchema/query</code> with the id of the schema in the 
payload of the query.</p>
+</div>
+<div class="paragraph">
+<p>Example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl --location --request POST 
'http://localhost:8181/cxs/jsonSchema/query' \
+-u 'karaf:karaf'
+--header 'Content-Type: text/plain' \
+--header 'Cookie: context-profile-id=0f2fbca8-c242-4e6d-a439-d65fcbf0f0a8' \
+--data-raw 'https://unomi.apache.org/schemas/json/event/1-0-0'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_create_update_a_json_schema_to_validate_an_event">4.2.3. Create / 
update a JSON schema to validate an event</h4>
+<div class="paragraph">
+<p>It’s possible to add or update JSON schema by calling the endpoint 
<code>POST {{url}}/cxs/jsonSchema</code> with the JSON schema in the payload of 
the request.
+If the JSON schema exists it will be updated with the new one.</p>
+</div>
+<div class="paragraph">
+<p>Example of creation:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl --location --request POST 
'http://localhost:8181/cxs/jsonSchema' \
+-u 'karaf:karaf' \
+--header 'Content-Type: application/json' \
+--header 'Cookie: context-profile-id=0f2fbca8-c242-4e6d-a439-d65fcbf0f0a8' \
+--data-raw '{
+    "$id": "https://vendor.test.com/schemas/json/events/dummy/1-0-0";,
+    "$schema": "https://json-schema.org/draft/2019-09/schema";,
+    "self": {
+        "vendor": "com.vendor.test",
+        "name": "dummy",
+        "format": "jsonschema",
+        "target": "events",
+        "version": "1-0-0"
+    },
+    "title": "DummyEvent",
+    "type": "object",
+    "allOf": [
+        {
+            "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0";
+        }
+    ],
+    "properties": {
+        "properties": {
+            "$ref": 
"https://vendor.test.com/schemas/json/events/dummy/properties/1-0-0";
+        }
+    },
+    "unevaluatedProperties": false
+}'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_deleting_a_schema">4.2.4. Deleting a schema</h4>
+<div class="paragraph">
+<p>To delete a schema, call the endpoint <code>POST 
{{url}}/cxs/jsonSchema/delete</code>  with the id of the schema into the 
payload of the request</p>
+</div>
+<div class="paragraph">
+<p>Example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl --location --request POST 
'http://localhost:8181/cxs/jsonSchema/delete' \
+-u 'karaf:karaf' \
+--header 'Content-Type: text/plain' \
+--header 'Cookie: context-profile-id=0f2fbca8-c242-4e6d-a439-d65fcbf0f0a8' \
+--data-raw 
'https://vendor.test.com/schemas/json/events/dummy/1-0-0'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_error_management">4.2.5. Error Management</h4>
+<div class="paragraph">
+<p>When calling an endpoint with invalid data, such as an invalid value for 
the <strong>sessionId</strong> property in the contextRequest object or 
eventCollectorRequest object, the server would respond with a 400 error code 
and the message <strong>Request rejected by the server because: Invalid 
received data</strong>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_details_on_invalid_events">4.2.6. Details on invalid events</h4>
+<div class="paragraph">
+<p>If it’s an event which is incorrect the server will continue to process 
the request but will exclude the invalid events.
+Running Apache Unomi with the logs in debug level will add to the logs the 
reason why events are rejected.
+You can set the log level of the class validating the events to debug by using 
the following karaf command:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>log:set DEBUG 
org.apache.unomi.schema.impl.SchemaServiceImpl</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_extend_an_existing_schema">4.3. Extend an existing schema</h3>
+<div class="sect3">
+<h4 id="_when_a_extension_is_needed">4.3.1. When a extension is needed?</h4>
+<div class="paragraph">
+<p>Apache Unomi provides predefined schemas to validate some known events such 
as a view event.</p>
+</div>
+<div class="paragraph">
+<p>The Apache Unomi JSON schemas are designed to consider invalid any 
properties which are not defined in the JSON schema.
+So if an unknown property is part of the event, the event will be considered 
as invalid.</p>
+</div>
+<div class="paragraph">
+<p>This means that if your events include additional properties, you will need 
extensions to describe these.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_understanding_how_extensions_are_merged_in_unomi">4.3.2. 
Understanding how extensions are merged in unomi</h4>
+<div class="paragraph">
+<p>An extension schema is a JSON schema whose id will be overridden and be 
defined by a keyword named <strong>extends</strong> in the 
<strong>self</strong> part of the extension.</p>
+</div>
+<div class="paragraph">
+<p>When sending an extension through the API, it will be persisted in 
Elasticsearch then will be merged to the targeted schema.</p>
+</div>
+<div class="paragraph">
+<p>What does “merge a schema” mean?
+The merge will simply add in the <strong>allOf</strong> keyword of the 
targeted schema a reference to the extensions.
+It means that to be valid, an event should be valid against the base schema 
and against the ones added in the <strong>allOf</strong>.</p>
+</div>
+<div class="paragraph">
+<p>Example of an extension to allow to add a new property in the view event 
properties:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+    "$id": "https://vendor.test.com/schemas/json/events/dummy/extension/1-0-0";,
+    "$schema": "https://json-schema.org/draft/2019-09/schema";,
+    "self":{
+        "vendor":"com.vendor.test",
+        "name":"dummyExtension",
+        "format":"jsonschema",
+        "extends": 
"https://unomi.apache.org/schemas/json/events/view/properties/1-0-0";,
+        "version":"1-0-0"
+    },
+    "title": "DummyEventExtension",
+    "type": "object",
+    "properties": {
+        "myNewProp": {
+            "type": "string"
+        }
+    }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>When validating the events of type view, the extension will be added to the 
schema with the id 
<strong>https://unomi.apache.org/schemas/json/events/view/properties/1-0-0</strong>
 like the following:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>"allOf": [{
+    "$ref": "https://vendor.test.com/schemas/json/events/dummy/extension/1-0-0";
+}]</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>With this extension the property <strong>myNewProp</strong> can now be 
added to the event.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>…
+"properties": {
+    "myNewProp" : "newValue"
+},
+…</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Process when adding extension:</p>
+</div>
+<div class="imageblock text-center">
+<div class="content">
+<img src="images/process-creation-extension.png" alt="process creation 
extension">
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_how_to_add_an_extension_through_the_api">4.3.3. How to add an 
extension through the API</h4>
+<div class="paragraph">
+<p>Since an extension is also a JSON schema, it is possible to add extensions 
by calling the endpoint to add a JSON schema.
+By calling <code>POST {{url}}/cxs/jsonSchema</code> with the JSON schema in 
the payload of the request, the extension will be persisted and will be merged 
to the targeted schema.</p>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_migrations">5. Migrations</h2>
 <div class="sectionbody">
 <div class="paragraph">
 <p>This section contains information and steps to migrate between major Unomi 
versions.</p>
 </div>
 <div class="sect2">
-<h3 id="_from_version_1_4_to_1_5">4.1. From version 1.4 to 1.5</h3>
+<h3 id="_from_version_1_4_to_1_5">5.1. From version 1.4 to 1.5</h3>
 <div class="sect3">
-<h4 id="_data_model_and_elasticsearch_7">4.1.1. Data model and ElasticSearch 
7</h4>
+<h4 id="_data_model_and_elasticsearch_7">5.1.1. Data model and ElasticSearch 
7</h4>
 <div class="paragraph">
 <p>Since Apache Unomi version 1.5.0 we decided to upgrade the supported 
ElasticSearch version to the latest 7.4.2.</p>
 </div>
@@ -2645,7 +2755,7 @@ of the ElasticSearch server(s). But if y
 </div>
 </div>
 <div class="sect3">
-<h4 id="_api_changes">4.1.2. API changes</h4>
+<h4 id="_api_changes">5.1.2. API changes</h4>
 <div class="paragraph">
 <p>To be able to handle the multiple indices the Persistence API implementation
 (<a 
href="https://github.com/apache/unomi/blob/9f1bab437fd93826dc54d318ed00d3b2e3161437/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java";>ElasticSearchPersistenceServiceImpl</a>)
@@ -2685,7 +2795,7 @@ Previously named: <code>geonames</code>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_migration_steps">4.1.3. Migration steps</h4>
+<h4 id="_migration_steps">5.1.3. Migration steps</h4>
 <div class="paragraph">
 <p>In order to migrate the data from ElasticSearch 5 to 7, Unomi provides a 
migration tool that is directly integrated.</p>
 </div>
@@ -2816,7 +2926,7 @@ the profiles:</p>
 </div>
 </div>
 <div class="sect2">
-<h3 
id="_important_changes_in_public_servlets_since_version_1_5_5_and_2_0_0">4.2. 
Important changes in public servlets since version 1.5.5 and 2.0.0</h3>
+<h3 
id="_important_changes_in_public_servlets_since_version_1_5_5_and_2_0_0">5.2. 
Important changes in public servlets since version 1.5.5 and 2.0.0</h3>
 <div class="paragraph">
 <p>What used to be dedicated servlets are now part of the REST endpoints.
 Prior to version 1.5.5 the following servlets were used:</p>
@@ -2858,7 +2968,7 @@ to update your client applications.</p>
 </div>
 </div>
 <div class="sect1">
-<h2 id="_queries_and_aggregations">5. Queries and aggregations</h2>
+<h2 id="_queries_and_aggregations">6. Queries and aggregations</h2>
 <div class="sectionbody">
 <div class="paragraph">
 <p>Apache Unomi contains a <code>query</code> endpoint that is quite powerful. 
It provides ways to perform queries that can quickly
@@ -2868,7 +2978,7 @@ get result counts, apply metrics such as
 <p>In this section we will show examples of requests that may be built using 
this API.</p>
 </div>
 <div class="sect2">
-<h3 id="_query_counts">5.1. Query counts</h3>
+<h3 id="_query_counts">6.1. Query counts</h3>
 <div class="paragraph">
 <p>Query counts are highly optimized queries that will count the number of 
objects that match a certain condition without
 retrieving the results. This can be used for example to quickly figure out how 
many objects will match a given condition
@@ -2923,7 +3033,7 @@ EOF</code></pre>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_metrics">5.2. Metrics</h3>
+<h3 id="_metrics">6.2. Metrics</h3>
 <div class="paragraph">
 <p>Metric queries make it possible to apply functions to the resulting 
property. The supported metrics are:</p>
 </div>
@@ -2985,7 +3095,7 @@ EOF</code></pre>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_aggregations">5.3. Aggregations</h3>
+<h3 id="_aggregations">6.3. Aggregations</h3>
 <div class="paragraph">
 <p>Aggregations are a very powerful way to build queries in Apache Unomi that 
will collect and aggregate data by filtering
 on certain conditions.</p>
@@ -2997,7 +3107,7 @@ on certain conditions.</p>
 - a condition (used to filter the data set that will be aggregated)</p>
 </div>
 <div class="sect3">
-<h4 id="_aggregation_types">5.3.1. Aggregation types</h4>
+<h4 id="_aggregation_types">6.3.1. Aggregation types</h4>
 <div class="paragraph">
 <p>Aggregations may be of different types. They are listed here below.</p>
 </div>
@@ -3235,14 +3345,14 @@ EOF</code></pre>
 </div>
 </div>
 <div class="sect1">
-<h2 id="_profile_import_export">6. Profile import &amp; export</h2>
+<h2 id="_profile_import_export">7. Profile import &amp; export</h2>
 <div class="sectionbody">
 <div class="paragraph">
 <p>The profile import and export feature in Apache Unomi is based on 
configurations and consumes or produces CSV files that
 contain profiles to be imported and exported.</p>
 </div>
 <div class="sect2">
-<h3 id="_importing_profiles">6.1. Importing profiles</h3>
+<h3 id="_importing_profiles">7.1. Importing profiles</h3>
 <div class="paragraph">
 <p>Only <code>ftp</code>, <code>sftp</code>, <code>ftps</code> and 
<code>file</code> are supported in the source path. For example:</p>
 </div>
@@ -3302,7 +3412,7 @@ ftps://USER@HOST?password=PASSWORD&amp;f
 </ul>
 </div>
 <div class="sect3">
-<h4 id="_import_api">6.1.1. Import API</h4>
+<h4 id="_import_api">7.1.1. Import API</h4>
 <div class="paragraph">
 <p>Apache Unomi provides REST endpoints to manage import configurations:</p>
 </div>
@@ -3377,7 +3487,7 @@ ftps://USER@HOST?password=PASSWORD&amp;f
 </div>
 </div>
 <div class="sect2">
-<h3 id="_exporting_profiles">6.2. Exporting profiles</h3>
+<h3 id="_exporting_profiles">7.2. Exporting profiles</h3>
 <div class="paragraph">
 <p>Only <code>ftp</code>, <code>sftp</code>, <code>ftps</code> and `file 
are supported in the source path. For example:</p>
 </div>
@@ -3398,7 +3508,7 @@ per file.</p>
 <p>See <a href="http://camel.apache.org/ftp.html and 
http://camel.apache.org/file2.html to"; 
class="bare">http://camel.apache.org/ftp.html and 
http://camel.apache.org/file2.html to</a> build more complex destination 
path.</p>
 </div>
 <div class="sect3">
-<h4 id="_export_api">6.2.1. Export API</h4>
+<h4 id="_export_api">7.2.1. Export API</h4>
 <div class="paragraph">
 <p>Apache Unomi provides REST endpoints to manage export configurations:</p>
 </div>
@@ -3466,7 +3576,7 @@ per file.</p>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_configuration_in_details">6.3. Configuration in details</h3>
+<h3 id="_configuration_in_details">7.3. Configuration in details</h3>
 <div class="paragraph">
 <p>First configuration you need to change would be the configuration type of 
your import / export feature (code name
 router) in the <code>etc/unomi.custom.system.properties</code> file (creating 
it if necessary):</p>
@@ -3560,17 +3670,17 @@ org.apache.unomi.router.config.allowedEn
 </div>
 </div>
 <div class="sect1">
-<h2 id="_consent_management">7. Consent management</h2>
+<h2 id="_consent_management">8. Consent management</h2>
 <div class="sectionbody">
 <div class="sect2">
-<h3 id="_consent_api">7.1. Consent API</h3>
+<h3 id="_consent_api">8.1. Consent API</h3>
 <div class="paragraph">
 <p>Starting with Apache Unomi 1.3, a new API for consent management is now 
available. This API
 is designed to be able to store/retrieve/update visitor consents in order to 
comply with new
 privacy regulations such as the <a 
href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation";>GDPR</a>.</p>
 </div>
 <div class="sect3">
-<h4 id="_profiles_with_consents">7.1.1. Profiles with consents</h4>
+<h4 id="_profiles_with_consents">8.1.1. Profiles with consents</h4>
 <div class="paragraph">
 <p>Visitor profiles now contain a new Consent object that contains the 
following information:</p>
 </div>
@@ -3645,7 +3755,7 @@ EOF</code></pre>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_consent_type_definitions">7.1.2. Consent type definitions</h4>
+<h4 id="_consent_type_definitions">8.1.2. Consent type definitions</h4>
 <div class="paragraph">
 <p>Apache Unomi does not manage consent definitions, it leaves that to an 
external system (for example a CMS) so that it
 can handle user-facing UIs to create, update, internationalize and present 
consent definitions to end users.</p>
@@ -3656,7 +3766,7 @@ consent type.</p>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_creating_update_a_visitor_consent">7.1.3. Creating / update a visitor 
consent</h4>
+<h4 id="_creating_update_a_visitor_consent">8.1.3. Creating / update a visitor 
consent</h4>
 <div class="paragraph">
 <p>A new built-in event type called "modifyConsent" can be sent to Apache 
Unomi to update a consent for the current
 profile.</p>
@@ -3739,7 +3849,7 @@ EOF</code></pre>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_how_it_works_internally">7.1.4. How it works (internally)</h4>
+<h4 id="_how_it_works_internally">8.1.4. How it works (internally)</h4>
 <div class="paragraph">
 <p>Upon receiving this event, Apache Unomi will trigger the modifyAnyConsent 
rule that has the following definition:</p>
 </div>
@@ -3782,14 +3892,14 @@ EOF</code></pre>
 </div>
 </div>
 <div class="sect1">
-<h2 id="_privacy_management">8. Privacy management</h2>
+<h2 id="_privacy_management">9. Privacy management</h2>
 <div class="sectionbody">
 <div class="paragraph">
 <p>Apache Unomi provides an endpoint to manage visitor privacy. You will find 
in this section information about what it
 includes as well as how to use it.</p>
 </div>
 <div class="sect2">
-<h3 id="_setting_up_access_to_the_privacy_endpoint">8.1. Setting up access to 
the privacy endpoint</h3>
+<h3 id="_setting_up_access_to_the_privacy_endpoint">9.1. Setting up access to 
the privacy endpoint</h3>
 <div class="paragraph">
 <p>The privacy endpoint is a bit special, because despite being protected by 
basic authentication as the rest of the REST
 API is is actually designed to be available to end-users.</p>
@@ -3815,7 +3925,7 @@ geographic location)</p>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_anonymizing_a_profile">8.2. Anonymizing a profile</h3>
+<h3 id="_anonymizing_a_profile">9.2. Anonymizing a profile</h3>
 <div class="paragraph">
 <p>It is possible to anonymize a profile, meaning it will remove all 
"identifying" property values from the profile.
 Basically all properties with the tag 
<code>personalIdentifierProperties</code> will be purged from the profile.</p>
@@ -3834,7 +3944,7 @@ and <code>ASCOPE</code> must be replaced
 </div>
 </div>
 <div class="sect2">
-<h3 id="_downloading_profile_data">8.3. Downloading profile data</h3>
+<h3 id="_downloading_profile_data">9.3. Downloading profile data</h3>
 <div class="paragraph">
 <p>It is possible to download the profile data of a user. This will only 
download the profile for a user using the
 specified ID as a cookie value.</p>
@@ -3855,7 +3965,7 @@ IDs.</p>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_deleting_a_profile">8.4. Deleting a profile</h3>
+<h3 id="_deleting_a_profile">9.4. Deleting a profile</h3>
 <div class="paragraph">
 <p>It is possible to delete a profile, but this works a little differently 
than you might expect. In all cases the data
 contained in the profile will be completely erased. If the 
<code>withData</code> optional flag is set to true, all past event and
@@ -3872,7 +3982,7 @@ and the <code>withData</code> specifies
 </div>
 </div>
 <div class="sect2">
-<h3 id="_related">8.5. Related</h3>
+<h3 id="_related">9.5. Related</h3>
 <div class="paragraph">
 <p>You might also be interested in the <a href="#_consent_api">Consent API</a> 
section that describe how to manage profile consents.</p>
 </div>
@@ -3880,10 +3990,10 @@ and the <code>withData</code> specifies
 </div>
 </div>
 <div class="sect1">
-<h2 id="_cluster_setup">9. Cluster setup</h2>
+<h2 id="_cluster_setup">10. Cluster setup</h2>
 <div class="sectionbody">
 <div class="sect2">
-<h3 id="_cluster_setup_2">9.1. Cluster setup</h3>
+<h3 id="_cluster_setup_2">10.1. Cluster setup</h3>
 <div class="paragraph">
 <p>Apache Karaf relies on Apache Karaf Cellar, which in turn uses Hazelcast to 
discover and configure its cluster.</p>
 </div>
@@ -3924,10 +4034,10 @@ placeholders in the hazelcast.xml file i
 </div>
 </div>
 <div class="sect1">
-<h2 id="_reference">10. Reference</h2>
+<h2 id="_reference">11. Reference</h2>
 <div class="sectionbody">
 <div class="sect2">
-<h3 id="_useful_apache_unomi_urls">10.1. Useful Apache Unomi URLs</h3>
+<h3 id="_useful_apache_unomi_urls">11.1. Useful Apache Unomi URLs</h3>
 <div class="paragraph">
 <p>In this section we will list some useful URLs that can be used to quickly 
access parts of Apache Unomi that can help
 you understand or diagnose what is going on in the system.</p>
@@ -3944,7 +4054,7 @@ results as the returned JSON is not beau
 <p>Important : all URLs are relative to the private Apache Unomi URL, by 
default: <a href="https://localhost:9443"; 
class="bare">https://localhost:9443</a></p>
 </div>
 <table class="tableblock frame-all grid-all stretch">
-<caption class="title">Table 3. Useful URLs</caption>
+<caption class="title">Table 2. Useful URLs</caption>
 <colgroup>
 <col style="width: 33.3333%;">
 <col style="width: 33.3333%;">
@@ -4025,12 +4135,12 @@ where PROFILE_ID is a profile identifier
 </table>
 </div>
 <div class="sect2">
-<h3 id="_how_profile_tracking_works">10.2. How profile tracking works</h3>
+<h3 id="_how_profile_tracking_works">11.2. How profile tracking works</h3>
 <div class="paragraph">
 <p>In this section you will learn how Apache Unomi keeps track of visitors.</p>
 </div>
 <div class="sect3">
-<h4 id="_steps">10.2.1. Steps</h4>
+<h4 id="_steps">11.2.1. Steps</h4>
 <div class="olist arabic">
 <ol class="arabic">
 <li>
@@ -4070,7 +4180,7 @@ forcing.</p>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_context_request_flow">10.3. Context Request Flow</h3>
+<h3 id="_context_request_flow">11.3. Context Request Flow</h3>
 <div class="paragraph">
 <p>Here is an overview of how Unomi processes incoming requests to the 
<code>ContextServlet</code>.</p>
 </div>
@@ -4081,7 +4191,7 @@ forcing.</p>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_data_model_overview">10.4. Data Model Overview</h3>
+<h3 id="_data_model_overview">11.4. Data Model Overview</h3>
 <div class="paragraph">
 <p>Apache Unomi gathers information about users actions, information that is 
processed and stored by Unomi services.
 The collected information can then be used to personalize content, derive 
insights on user behavior, categorize the
@@ -4101,7 +4211,7 @@ There are other classes that are less ce
 </div>
 </div>
 <div class="sect2">
-<h3 id="_scope">10.5. Scope</h3>
+<h3 id="_scope">11.5. Scope</h3>
 <div class="paragraph">
 <p>Scopes are not actually an object in the system, but simply unique strings 
that are used to "classify" objects.
 For example, when using scopes with a web content management system, a scope 
could be associated with a site identifier or even a host name.</p>
@@ -4114,7 +4224,7 @@ For example, when using scopes with a we
 </blockquote>
 </div>
 <div class="sect3">
-<h4 id="_example">10.5.1. Example</h4>
+<h4 id="_example">11.5.1. Example</h4>
 <div class="paragraph">
 <p>In the following example, the scope uses the unique identifier of a web 
site called “digitall”.</p>
 </div>
@@ -4130,7 +4240,7 @@ For example, when using scopes with a we
 </div>
 </div>
 <div class="sect2">
-<h3 id="_item">10.6. Item</h3>
+<h3 id="_item">11.6. Item</h3>
 <div class="paragraph">
 <p>Unomi structures the information it collects using the concept of 
<code>Item</code> which provides the base information (an identifier and a 
type) the context server needs to process and store the data.
 Items are persisted according to their type (structure) and identifier 
(identity).
@@ -4155,7 +4265,7 @@ Scopes allow clients accessing the conte
 It contains the following fields, that are inherited by other objects that 
inherit from it.</p>
 </div>
 <div class="sect3">
-<h4 id="_structure_definition">10.6.1. Structure definition</h4>
+<h4 id="_structure_definition">11.6.1. Structure definition</h4>
 <div class="paragraph">
 <p>Inherits all the fields from: n/a</p>
 </div>
@@ -4193,13 +4303,13 @@ It contains the following fields, that a
 </div>
 </div>
 <div class="sect2">
-<h3 id="_metadata">10.7. Metadata</h3>
+<h3 id="_metadata">11.7. Metadata</h3>
 <div class="paragraph">
 <p>The Metadata object is an object that contains additional information about 
an object.
 It is usually associated with an Item object (see MetadataItem below).</p>
 </div>
 <div class="sect3">
-<h4 id="_structure_definition_2">10.7.1. Structure definition</h4>
+<h4 id="_structure_definition_2">11.7.1. Structure definition</h4>
 <div class="paragraph">
 <p>Inherits all the fields from: n/a</p>
 </div>

[... 1177 lines stripped ...]

Reply via email to