You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@unomi.apache.org by sh...@apache.org on 2019/05/12 09:36:19 UTC

svn commit: r1859135 [2/2] - in /unomi/website/manual: 1_1_x/index.html 1_2_x/index.html 1_3_x/index.html latest/index.html

Modified: unomi/website/manual/latest/index.html
URL: http://svn.apache.org/viewvc/unomi/website/manual/latest/index.html?rev=1859135&r1=1859134&r2=1859135&view=diff
==============================================================================
--- unomi/website/manual/latest/index.html (original)
+++ unomi/website/manual/latest/index.html Sun May 12 09:36:18 2019
@@ -19,7 +19,7 @@
 <div id="toctitle">Table of Contents</div>
 <ul class="sectlevel1">
 <li><a href="#_quick_start">1. Quick start</a>
-<ul class="sectlevel3">
+<ul class="sectlevel2">
 <li><a href="#_five_minutes_quickstart">1.1. Five Minutes QuickStart</a></li>
 </ul>
 </li>
@@ -29,104 +29,119 @@
 <li><a href="#_events">2.2. Events</a></li>
 <li><a href="#_profiles">2.3. Profiles</a></li>
 <li><a href="#_sessions">2.4. Sessions</a></li>
+<li><a href="#_request_flow">2.5. Request flow</a></li>
 </ul>
 </li>
-<li><a href="#_setup">3. Setup</a>
+<li><a href="#_first_steps_with_apache_unomi">3. First steps with Apache Unomi</a>
 <ul class="sectlevel2">
 <li><a href="#_getting_started_with_unomi">3.1. Getting started with Unomi</a>
 <ul class="sectlevel3">
 <li><a href="#_prerequisites">3.1.1. Prerequisites</a></li>
 <li><a href="#_running_unomi">3.1.2. Running Unomi</a></li>
-<li><a href="#_web_tracker">3.1.3. Web Tracker</a></li>
 </ul>
 </li>
-<li><a href="#_configuration">3.2. Configuration</a>
+<li><a href="#_request_examples">3.2. Request examples</a>
 <ul class="sectlevel3">
-<li><a href="#_changing_the_default_configuration">3.2.1. Changing the default configuration</a></li>
-<li><a href="#_secured_events_configuration">3.2.2. Secured events configuration</a></li>
-<li><a href="#_installing_the_maxmind_geoiplite2_ip_lookup_database">3.2.3. Installing the MaxMind GeoIPLite2 IP lookup database</a></li>
-<li><a href="#_installing_geonames_database">3.2.4. Installing Geonames database</a></li>
-<li><a href="#_rest_api_security">3.2.5. REST API Security</a></li>
-<li><a href="#_automatic_profile_merging">3.2.6. Automatic profile merging</a></li>
-<li><a href="#_securing_a_production_environment">3.2.7. Securing a production environment</a></li>
-<li><a href="#_integrating_with_an_apache_http_web_server">3.2.8. Integrating with an Apache HTTP web server</a></li>
-<li><a href="#_changing_the_default_tracking_location">3.2.9. Changing the default tracking location</a></li>
-<li><a href="#_apache_karaf_ssh_console">3.2.10. Apache Karaf SSH Console</a></li>
-<li><a href="#_elasticsearch_x_pack_support">3.2.11. ElasticSearch X-Pack Support</a></li>
-<li><a href="#_useful_apache_unomi_urls">3.2.12. Useful Apache Unomi URLs</a></li>
+<li><a href="#_retrieving_your_first_context">3.2.1. Retrieving your first context</a></li>
+<li><a href="#_retrieving_a_context_as_a_json_object">3.2.2. Retrieving a context as a JSON object.</a></li>
+<li><a href="#_accessing_profile_properties_in_a_context">3.2.3. Accessing profile properties in a context</a></li>
+<li><a href="#_sending_events_using_the_context_servlet">3.2.4. Sending events using the context servlet</a></li>
+<li><a href="#_sending_events_using_the_eventcollector_servlet">3.2.5. Sending events using the eventcollector servlet</a></li>
+<li><a href="#_where_to_go_from_here">3.2.6. Where to go from here</a></li>
 </ul>
 </li>
+<li><a href="#_web_tracker">3.3. Web Tracker</a>
+<ul class="sectlevel3">
+<li><a href="#_getting_started">3.3.1. Getting started</a></li>
+<li><a href="#_how_to_contribute">3.3.2. How to contribute</a></li>
+<li><a href="#_tracking_page_views">3.3.3. Tracking page views</a></li>
+<li><a href="#_tracking_form_submissions">3.3.4. Tracking form submissions</a></li>
 </ul>
 </li>
-<li><a href="#_integration_samples">4. Integration samples</a>
-<ul class="sectlevel2">
-<li><a href="#_samples">4.1. Samples</a></li>
-<li><a href="#_login_sample">4.2. Login sample</a>
+<li><a href="#_configuration">3.4. Configuration</a>
 <ul class="sectlevel3">
-<li><a href="#_warning">4.2.1. Warning !</a></li>
-<li><a href="#_installing_the_samples">4.2.2. Installing the samples</a></li>
+<li><a href="#_centralized_configuration">3.4.1. Centralized configuration</a></li>
+<li><a href="#_changing_the_default_configuration_using_environment_variables_i_e_docker_configuration">3.4.2. Changing the default configuration using environment variables (i.e. Docker configuration)</a></li>
+<li><a href="#_changing_the_default_configuration_using_property_files">3.4.3. Changing the default configuration using property files</a></li>
+<li><a href="#_secured_events_configuration">3.4.4. Secured events configuration</a></li>
+<li><a href="#_installing_the_maxmind_geoiplite2_ip_lookup_database">3.4.5. Installing the MaxMind GeoIPLite2 IP lookup database</a></li>
+<li><a href="#_installing_geonames_database">3.4.6. Installing Geonames database</a></li>
+<li><a href="#_rest_api_security">3.4.7. REST API Security</a></li>
+<li><a href="#_automatic_profile_merging">3.4.8. Automatic profile merging</a></li>
+<li><a href="#_securing_a_production_environment">3.4.9. Securing a production environment</a></li>
+<li><a href="#_integrating_with_an_apache_http_web_server">3.4.10. Integrating with an Apache HTTP web server</a></li>
+<li><a href="#_changing_the_default_tracking_location">3.4.11. Changing the default tracking location</a></li>
+<li><a href="#_apache_karaf_ssh_console">3.4.12. Apache Karaf SSH Console</a></li>
+<li><a href="#_elasticsearch_x_pack_support">3.4.13. ElasticSearch X-Pack Support</a></li>
 </ul>
 </li>
-<li><a href="#_twitter_sample">4.3. Twitter sample</a>
-<ul class="sectlevel3">
-<li><a href="#_overview">4.3.1. Overview</a></li>
-<li><a href="#_interacting_with_the_context_server">4.3.2. Interacting with the context server</a></li>
-<li><a href="#_retrieving_context_information_from_unomi_using_the_context_servlet">4.3.3. Retrieving context information from Unomi using the context servlet</a></li>
+<li><a href="#_useful_apache_unomi_urls">3.5. Useful Apache Unomi URLs</a></li>
 </ul>
 </li>
-<li><a href="#_example">4.4. Example</a>
+<li><a href="#_consent_management">4. Consent management</a>
+<ul class="sectlevel2">
+<li><a href="#_consent_api">4.1. Consent API</a>
 <ul class="sectlevel3">
-<li><a href="#_html_page">4.4.1. HTML page</a></li>
-<li><a href="#_javascript">4.4.2. Javascript</a></li>
+<li><a href="#_profiles_with_consents">4.1.1. Profiles with consents</a></li>
+<li><a href="#_consent_type_definitions">4.1.2. Consent type definitions</a></li>
+<li><a href="#_creating_update_a_visitor_consent">4.1.3. Creating / update a visitor consent</a></li>
+<li><a href="#_how_it_works_internally">4.1.4. How it works (internally)</a></li>
 </ul>
 </li>
-<li><a href="#_conclusion">4.5. Conclusion</a></li>
-<li><a href="#_annex">4.6. Annex</a></li>
-<li><a href="#_weather_update_sample">4.7. Weather update sample</a></li>
 </ul>
 </li>
-<li><a href="#_connectors">5. Connectors</a>
+<li><a href="#_cluster_setup">5. Cluster setup</a>
 <ul class="sectlevel2">
-<li><a href="#_connectors_2">5.1. Connectors</a>
+<li><a href="#_cluster_setup_2">5.1. Cluster setup</a></li>
+</ul>
+</li>
+<li><a href="#_integration_samples">6. Integration samples</a>
+<ul class="sectlevel2">
+<li><a href="#_samples">6.1. Samples</a></li>
+<li><a href="#_login_sample">6.2. Login sample</a>
 <ul class="sectlevel3">
-<li><a href="#_call_for_contributors">5.1.1. Call for contributors</a></li>
+<li><a href="#_warning">6.2.1. Warning !</a></li>
+<li><a href="#_installing_the_samples">6.2.2. Installing the samples</a></li>
 </ul>
 </li>
-<li><a href="#_salesforce_connector">5.2. Salesforce Connector</a>
+<li><a href="#_twitter_sample">6.3. Twitter sample</a>
 <ul class="sectlevel3">
-<li><a href="#_getting_started_2">5.2.1. Getting started</a></li>
-<li><a href="#_properties">5.2.2. Properties</a></li>
-<li><a href="#_hot_deploying_updates_to_the_salesforce_connector_for_developers">5.2.3. Hot-deploying updates to the Salesforce connector (for developers)</a></li>
-<li><a href="#_using_the_salesforce_workbench_for_testing_rest_api">5.2.4. Using the Salesforce Workbench for testing REST API</a></li>
-<li><a href="#_setting_up_streaming_push_queries">5.2.5. Setting up Streaming Push queries</a></li>
-<li><a href="#_executing_the_unit_tests">5.2.6. Executing the unit tests</a></li>
+<li><a href="#_overview">6.3.1. Overview</a></li>
+<li><a href="#_interacting_with_the_context_server">6.3.2. Interacting with the context server</a></li>
+<li><a href="#_retrieving_context_information_from_unomi_using_the_context_servlet">6.3.3. Retrieving context information from Unomi using the context servlet</a></li>
 </ul>
 </li>
-<li><a href="#_mailchimp_connector">5.3. MailChimp Connector</a>
+<li><a href="#_example">6.4. Example</a>
 <ul class="sectlevel3">
-<li><a href="#_getting_started_3">5.3.1. Getting started</a></li>
+<li><a href="#_html_page">6.4.1. HTML page</a></li>
+<li><a href="#_javascript">6.4.2. Javascript</a></li>
 </ul>
 </li>
+<li><a href="#_conclusion">6.5. Conclusion</a></li>
+<li><a href="#_annex">6.6. Annex</a></li>
+<li><a href="#_weather_update_sample">6.7. Weather update sample</a></li>
 </ul>
 </li>
-<li><a href="#_cluster_setup">6. Cluster setup</a>
+<li><a href="#_connectors">7. Connectors</a>
 <ul class="sectlevel2">
-<li><a href="#_cluster_setup_2">6.1. Cluster setup</a>
+<li><a href="#_connectors_2">7.1. Connectors</a>
 <ul class="sectlevel3">
-<li><a href="#_2_nodes_configuration">6.1.1. 2 nodes configuration</a></li>
-<li><a href="#_3_nodes_configuration">6.1.2. 3 nodes configuration</a></li>
+<li><a href="#_call_for_contributors">7.1.1. Call for contributors</a></li>
 </ul>
 </li>
+<li><a href="#_salesforce_connector">7.2. Salesforce Connector</a>
+<ul class="sectlevel3">
+<li><a href="#_getting_started_2">7.2.1. Getting started</a></li>
+<li><a href="#_properties">7.2.2. Properties</a></li>
+<li><a href="#_hot_deploying_updates_to_the_salesforce_connector_for_developers">7.2.3. Hot-deploying updates to the Salesforce connector (for developers)</a></li>
+<li><a href="#_using_the_salesforce_workbench_for_testing_rest_api">7.2.4. Using the Salesforce Workbench for testing REST API</a></li>
+<li><a href="#_setting_up_streaming_push_queries">7.2.5. Setting up Streaming Push queries</a></li>
+<li><a href="#_executing_the_unit_tests">7.2.6. Executing the unit tests</a></li>
 </ul>
 </li>
-<li><a href="#_consent_api">7. Consent API</a>
-<ul class="sectlevel2">
-<li><a href="#_consent_api_2">7.1. Consent API</a>
+<li><a href="#_mailchimp_connector">7.3. MailChimp Connector</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="#_getting_started_3">7.3.1. Getting started</a></li>
 </ul>
 </li>
 </ul>
@@ -187,9 +202,9 @@
 <li><a href="#_predefined_personas">8.7.7. Predefined personas</a></li>
 <li><a href="#_custom_actions">8.7.8. Custom actions</a></li>
 <li><a href="#_custom_conditions">8.7.9. Custom conditions</a></li>
-<li><a href="#_migration_patches">8.7.10. Migration patches</a></li>
 </ul>
 </li>
+<li><a href="#_migration_patches">8.8. Migration patches</a></li>
 </ul>
 </li>
 </ul>
@@ -208,8 +223,8 @@
 <div class="sect1">
 <h2 id="_quick_start">1. Quick start</h2>
 <div class="sectionbody">
-<div class="sect3">
-<h4 id="_five_minutes_quickstart">1.1. Five Minutes QuickStart</h4>
+<div class="sect2">
+<h3 id="_five_minutes_quickstart">1.1. Five Minutes QuickStart</h3>
 <div class="paragraph">
 <p>1) Install JDK 8 (<a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" class="bare">http://www.oracle.com/technetwork/java/javase/downloads/index.html</a>) and make sure you set the
 JAVA_HOME variable <a href="https://docs.oracle.com/cd/E19182-01/820-7851/inst_cli_jdk_javahome_t/" class="bare">https://docs.oracle.com/cd/E19182-01/820-7851/inst_cli_jdk_javahome_t/</a></p>
@@ -387,20 +402,34 @@ make sure you are using the proper versi
 <p>A session represents a time-bounded interaction between a user (via their associated profile) and a Unomi-enabled application. A session represents the sequence of actions the user performed during its duration. For this reason, events are associated with the session during which they occurred. In the context of web applications, sessions are usually linked to HTTP sessions.</p>
 </div>
 </div>
+<div class="sect2">
+<h3 id="_request_flow">2.5. Request flow</h3>
+<div class="paragraph">
+<p>Here is an overview of how Unomi processes incoming requests to the <code>ContextServlet</code>.</p>
+</div>
+<div class="imageblock">
+<div class="content">
+<img src="images/unomi-request.png" alt="Unomi request overview">
+</div>
+</div>
+</div>
 </div>
 </div>
 <div class="sect1">
-<h2 id="_setup">3. Setup</h2>
+<h2 id="_first_steps_with_apache_unomi">3. First steps with Apache Unomi</h2>
 <div class="sectionbody">
 <div class="sect2">
 <h3 id="_getting_started_with_unomi">3.1. Getting started with Unomi</h3>
 <div class="paragraph">
-<p>We will first get you up and running with an example. We will then lift the corner of the cover somewhat and explain in greater details what just happened.</p>
+<p>We will first get you up and running with an example. We will then lift the corner of the cover somewhat and explain
+in greater details what just happened.</p>
 </div>
 <div class="sect3">
 <h4 id="_prerequisites">3.1.1. Prerequisites</h4>
 <div class="paragraph">
-<p>This document assumes that you are already familiar with Unomi&#8217;s <a href="#_concepts">concepts</a>. On the technical side, we also assume working knowledge of <a href="https://git-scm.com/">git</a> to be able to retrieve the code for Unomi and the example. Additionnally, you will require a working Java 7 or above install. Refer to <a href="http://www.oracle.com/technetwork/java/javase/">http://www.oracle.com/technetwork/java/javase/</a> for details on how to download and install Java SE 7 or greater.</p>
+<p>This document assumes that you are already familiar with Unomi&#8217;s <a href="#_concepts">concepts</a>. On the technical side, we
+also assume working knowledge of <a href="https://git-scm.com/">git</a> to be able to retrieve the code for Unomi and the example.
+Additionally, you will require a working Java 7 or above install. Refer to <a href="http://www.oracle.com/technetwork/java/javase/">http://www.oracle.com/technetwork/java/javase/</a> for details on how to download and install Java SE 7 or greater.</p>
 </div>
 </div>
 <div class="sect3">
@@ -427,11 +456,17 @@ Initializing cluster service endpoint...
 <p>This indicates that all the Unomi services are started and ready to react to requests. You can then open a browser and go to <code><a href="http://localhost:8181/cxs" class="bare">http://localhost:8181/cxs</a></code> to see the list of
 available RESTful services or retrieve an initial context at <code><a href="http://localhost:8181/context.json" class="bare">http://localhost:8181/context.json</a></code> (which isn&#8217;t very useful at this point).</p>
 </div>
+<div class="paragraph">
+<p>Now that your service is up and running you can go look at the <a href="#_request-examples">request examples</a> to learn basic
+requests you can do once your server is up and running.</p>
 </div>
-<div class="sect4">
-<h5 id="_request_examples">Request examples</h5>
-<div class="sect5">
-<h6 id="_retrieving_your_first_context">Retrieving your first context</h6>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_request_examples">3.2. Request examples</h3>
+<div class="sect3">
+<h4 id="_retrieving_your_first_context">3.2.1. Retrieving your first context</h4>
 <div class="paragraph">
 <p>You can retrieve a context using curl like this :</p>
 </div>
@@ -446,8 +481,8 @@ profile, segments, scores as well as fun
 events using the cxs.collectEvents() function).</p>
 </div>
 </div>
-<div class="sect5">
-<h6 id="_retrieving_a_context_as_a_json_object">Retrieving a context as a JSON object.</h6>
+<div class="sect3">
+<h4 id="_retrieving_a_context_as_a_json_object">3.2.2. Retrieving a context as a JSON object.</h4>
 <div class="paragraph">
 <p>If you prefer to retrieve a pure JSON object, you can simply use a request formed like this:</p>
 </div>
@@ -457,8 +492,8 @@ events using the cxs.collectEvents() fun
 </div>
 </div>
 </div>
-<div class="sect5">
-<h6 id="_accessing_profile_properties_in_a_context">Accessing profile properties in a context</h6>
+<div class="sect3">
+<h4 id="_accessing_profile_properties_in_a_context">3.2.3. Accessing profile properties in a context</h4>
 <div class="paragraph">
 <p>By default, in order to optimize the amount of data sent over the network, Apache Unomi will not send the content of
 the profile or session properties. If you need this data, you must send a JSON object to configure the resulting output
@@ -469,7 +504,20 @@ of the context.js(on) servlet.</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>curl -H "Content-Type: application/json" -X POST -d '{"source":{"itemId":"homepage","itemType":"page","scope":"example"},"requiredProfileProperties":["*"],"requiredSessionProperties":["*"],"requireSegments":true}' http://localhost:8181/context.json?sessionId=1234</code></pre>
+<pre class="highlight"><code>curl -X POST http://localhost:8181/context.json?sessionId=1234 \
+-H "Content-Type: application/json" \
+-d @- &lt;&lt;'EOF'
+{
+    "source": {
+        "itemId":"homepage",
+        "itemType":"page",
+        "scope":"example"
+    },
+    "requiredProfileProperties":["*"],
+    "requiredSessionProperties":["*"],
+    "requireSegments":true
+}
+EOF</code></pre>
 </div>
 </div>
 <div class="paragraph">
@@ -479,15 +527,46 @@ properties. The structure of the JSON ob
 Java class.</p>
 </div>
 </div>
-<div class="sect5">
-<h6 id="_sending_events_using_the_context_servlet">Sending events using the context servlet</h6>
+<div class="sect3">
+<h4 id="_sending_events_using_the_context_servlet">3.2.4. Sending events using the context servlet</h4>
 <div class="paragraph">
 <p>At the same time as you are retrieving the context, you can also directly send events in the ContextRequest object as
 illustrated in the following example:</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>curl -H "Content-Type: application/json" -X POST -d '{"source":{"itemId":"homepage","itemType":"page","scope":"example"},"events":[{"eventType":"view","scope": "example","source":{"itemType": "site","scope":"example","itemId": "mysite"},"target":{"itemType":"page","scope":"example","itemId":"homepage","properties":{"pageInfo":{"referringURL":""}}}}]}' http://localhost:8181/context.json?sessionId=1234</code></pre>
+<pre class="highlight"><code>curl -X POST http://localhost:8181/context.json?sessionId=1234 \
+-H "Content-Type: application/json" \
+-d @- &lt;&lt;'EOF'
+{
+    "source":{
+        "itemId":"homepage",
+        "itemType":"page",
+        "scope":"example"
+    },
+    "events":[
+        {
+            "eventType":"view",
+            "scope": "example",
+            "source":{
+                "itemType": "site",
+                "scope":"example",
+                "itemId": "mysite"
+            },
+            "target":{
+                "itemType":"page",
+                "scope":"example",
+                "itemId":"homepage",
+                "properties":{
+                    "pageInfo":{
+                        "referringURL":""
+                    }
+                }
+            }
+        }
+    ]
+}
+EOF</code></pre>
 </div>
 </div>
 <div class="paragraph">
@@ -497,15 +576,41 @@ finished loading you could either do a s
 to send events in a network optimal way you can use the eventcollector servlet (see below).</p>
 </div>
 </div>
-<div class="sect5">
-<h6 id="_sending_events_using_the_eventcollector_servlet">Sending events using the eventcollector servlet</h6>
+<div class="sect3">
+<h4 id="_sending_events_using_the_eventcollector_servlet">3.2.5. Sending events using the eventcollector servlet</h4>
 <div class="paragraph">
 <p>If you only need to send events without retrieving a context, you should use the eventcollector servlet that is optimized
 respond quickly and minimize network traffic. Here is an example of using this servlet:</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>curl -H "Content-Type: application/json" -X POST -d '{"events":[{"eventType":"view","scope": "example","source":{"itemType": "site","scope":"example","itemId": "mysite"},"target":{"itemType":"page","scope":"example","itemId":"homepage","properties":{"pageInfo":{"referringURL":""}}}}]}' http://localhost:8181/eventcollector?sessionId=1234</code></pre>
+<pre class="highlight"><code>curl -X POST http://localhost:8181/context.json?sessionId=1234 \
+-H "Content-Type: application/json" \
+-d @- &lt;&lt;'EOF'
+{
+    "events":[
+        {
+            "eventType":"view",
+            "scope": "example",
+            "source":{
+                "itemType": "site",
+                "scope":"example",
+                "itemId": "mysite"
+            },
+            "target":{
+                "itemType":"page",
+                "scope":"example",
+                "itemId":"homepage",
+                "properties":{
+                    "pageInfo":{
+                        "referringURL":""
+                    }
+                }
+            }
+        }
+    ]
+}
+EOF</code></pre>
 </div>
 </div>
 <div class="paragraph">
@@ -513,26 +618,31 @@ respond quickly and minimize network tra
 to send additional events.</p>
 </div>
 </div>
-</div>
-<div class="sect4">
-<h5 id="_where_to_go_from_here">Where to go from here</h5>
+<div class="sect3">
+<h4 id="_where_to_go_from_here">3.2.6. Where to go from here</h4>
 <div class="ulist">
 <ul>
 <li>
+<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="sect3">
-<h4 id="_web_tracker">3.1.3. Web Tracker</h4>
+<div class="sect2">
+<h3 id="_web_tracker">3.3. 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="sect4">
-<h5 id="_getting_started">Getting started</h5>
+<div class="sect3">
+<h4 id="_getting_started">3.3.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>
@@ -558,15 +668,15 @@ The tracker is implemented as an integra
 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="sect4">
-<h5 id="_how_to_contribute">How to contribute</h5>
+<div class="sect3">
+<h4 id="_how_to_contribute">3.3.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="sect4">
-<h5 id="_tracking_page_views">Tracking page views</h5>
+<div class="sect3">
+<h4 id="_tracking_page_views">3.3.3. Tracking page views</h4>
 <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
@@ -585,7 +695,6 @@ to this :</p>
                 destinationURL: location.href,
                 tags : [ "tag1", "tag2", "tag3"],
                 categories : ["category1", "category2", "category3"],
-                language : "en"
             },
             interests : {
                 "interest1" : 1,
@@ -637,10 +746,6 @@ object passed to the unomiTracker call.
 <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">language</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">An identifier (usually a locale for such as en_US or fr_CH) for the language</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>
@@ -657,8 +762,8 @@ will be accepted by Apache Unomi without
 categories).</p>
 </div>
 </div>
-<div class="sect4">
-<h5 id="_tracking_form_submissions">Tracking form submissions</h5>
+<div class="sect3">
+<h4 id="_tracking_form_submissions">3.3.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
@@ -929,16 +1034,65 @@ cef09b89-6b99-4e4f-a99c-a4159a66b42b|for
 </div>
 </div>
 </div>
-</div>
 <div class="sect2">
-<h3 id="_configuration">3.2. Configuration</h3>
+<h3 id="_configuration">3.4. Configuration</h3>
 <div class="sect3">
-<h4 id="_changing_the_default_configuration">3.2.1. Changing the default configuration</h4>
+<h4 id="_centralized_configuration">3.4.1. Centralized configuration</h4>
 <div class="paragraph">
-<p>If you want to change the default configuration, you can perform any modification you want in the $MY_KARAF_HOME/etc directory.</p>
+<p>Apache Unomi uses a centralized configuration file that contains both system properties and configuration properties.
+These settings are then fed to the OSGi and other configuration files using placeholder that look something like this:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>contextserver.publicAddress=${org.apache.unomi.cluster.public.address:-http://localhost:8181}
+contextserver.internalAddress=${org.apache.unomi.cluster.internal.address:-https://localhost:9443}</code></pre>
+</div>
 </div>
 <div class="paragraph">
-<p>If you want to change the HTTP ports that the server is listening on, you will need to add/change the following lines in the $MY_KARAF_HOME/etc/custom.properties file:</p>
+<p>Default values are stored in a file called <code>$MY_KARAF_HOME/etc/custom.system.properties</code> but you should never modify
+this file directly, as an override mechanism is available. Simply create a file called:</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>unomi.custom.system.properties</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>and put your own property values in their to override the defaults OR you can use environment variables to also override
+the values in the <code>$MY_KARAF_HOME/etc/custom.system.properties</code>. See the next section for more information about that.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_changing_the_default_configuration_using_environment_variables_i_e_docker_configuration">3.4.2. Changing the default configuration using environment variables (i.e. Docker configuration)</h4>
+<div class="paragraph">
+<p>You might want to use environment variables to change the default system configuration, especially if you intend to run
+Apache Unomi inside a Docker container. You can find the list of all the environment variable names in the following file:</p>
+</div>
+<div class="paragraph">
+<p><a href="https://github.com/apache/incubator-unomi/blob/master/package/src/main/resources/etc/custom.system.properties" class="bare">https://github.com/apache/incubator-unomi/blob/master/package/src/main/resources/etc/custom.system.properties</a></p>
+</div>
+<div class="paragraph">
+<p>If you are using Docker Container, simply pass the environment variables on the docker command line or if you are using
+Docker Compose you can put the environment variables in the docker-compose.yml file.</p>
+</div>
+<div class="paragraph">
+<p>If you want to "save" the environment values in a file, you can use the <code>bin/setenv(.bat)</code> to setup the environment
+variables you want to use.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_changing_the_default_configuration_using_property_files">3.4.3. Changing the default configuration using property files</h4>
+<div class="paragraph">
+<p>If you want to change the default configuration using property files instead of environment variables, you can perform
+any modification you want in the <code>$MY_KARAF_HOME/etc/unomi.custom.system.properties</code> file.</p>
+</div>
+<div class="paragraph">
+<p>By default this file does not exist and is designed to be a file that will contain only your custom modifications to the
+default configuration.</p>
+</div>
+<div class="paragraph">
+<p>For example, if you want to change the HTTP ports that the server is listening on, you will need to create the
+following lines in the $MY_KARAF_HOME/etc/unomi.custom.system.properties (and create it if you haven&#8217;t yet) file:</p>
 </div>
 <div class="listingblock">
 <div class="content">
@@ -947,58 +1101,114 @@ org.osgi.service.http.port=8181</code></
 </div>
 </div>
 <div class="paragraph">
-<p>If you change these ports, also make sure you adjust the following file in the cluster configuration.</p>
-</div>
-<div class="paragraph">
-<p>The context server configuration is kept in the $MY_KARAF_HOME/etc/org.apache.unomi.cluster.cfg . It defines the
-addresses where it can be found :</p>
+<p>If you change these ports, also make sure you adjust the following settings in the same file :</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>contextserver.publicAddress=https://localhost:9443
-contextserver.internalAddress=http://127.0.0.1:8181</code></pre>
+<pre class="highlight"><code>org.apache.unomi.cluster.public.address=http://localhost:8181
+org.apache.unomi.cluster.internal.address=https://localhost:9443</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>If you need to specify an Elasticsearch cluster name, or a host and port that are different than the default,
+<p>If you need to specify an ElasticSearch cluster name, or a host and port that are different than the default,
 it is recommended to do this BEFORE you start the server for the first time, or you will loose all the data
 you have stored previously.</p>
 </div>
 <div class="paragraph">
-<p>To change these settings, you will need to modify a file called</p>
+<p>You can use the following properties for the ElasticSearch configuration</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>$MY_KARAF_HOME/etc/org.apache.unomi.persistence.elasticsearch.cfg</code></pre>
+<pre class="highlight"><code>org.apache.unomi.elasticsearch.cluster.name=contextElasticSearch
+# The elasticsearch.adresses may be a comma seperated list of host names and ports such as
+# hostA:9300,hostB:9300
+# Note: the port number must be repeated for each host.
+org.apache.unomi.elasticsearch.addresses=localhost:9300</code></pre>
 </div>
 </div>
+</div>
+<div class="sect3">
+<h4 id="_secured_events_configuration">3.4.4. Secured events configuration</h4>
 <div class="paragraph">
-<p>with the following contents:</p>
+<p>Apache Unomi secures some events by default. It comes out of the box with a default configuration that you can adjust
+by using the centralized configuration file override in <code>$MY_KARAF_HOME/etc/unomi.custom.system.properties</code></p>
 </div>
-<div class="listingblock">
+<div class="paragraph">
+<p>You can find the default configuration in the following file:</p>
+</div>
+<div class="literalblock">
 <div class="content">
-<pre class="highlight"><code>cluster.name=contextElasticSearch
-# The elasticSearchAddresses may be a comma seperated list of host names and ports such as
-# hostA:9300,hostB:9300
-# Note: the port number must be repeated for each host.
-elasticSearchAddresses=localhost:9300
-index.name=context</code></pre>
+<pre>$MY_KARAF_HOME/etc/custom.system.properties</pre>
 </div>
 </div>
+<div class="paragraph">
+<p>The properties start with the prefix : <code>org.apache.unomi.thirdparty.*</code> and here are the default values :</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>org.apache.unomi.thirdparty.provider1.key=${env:UNOMI_THIRDPARTY_PROVIDER1_KEY:-670c26d1cc413346c3b2fd9ce65dab41}
+org.apache.unomi.thirdparty.provider1.ipAddresses=${env:UNOMI_THIRDPARTY_PROVIDER1_IPADDRESSES:-127.0.0.1,::1}
+org.apache.unomi.thirdparty.provider1.allowedEvents=${env:UNOMI_THIRDPARTY_PROVIDER1_ALLOWEDEVENTS:-login,updateProperties}</pre>
+</div>
 </div>
-<div class="sect3">
-<h4 id="_secured_events_configuration">3.2.2. Secured events configuration</h4>
 <div class="paragraph">
-<p>Unomi secures some events by default. You can find the default configuration in the following file (created after the
-first server startup):</p>
+<p>The events set in allowedEvents will be secured and will only be accepted if the call comes from the specified IP
+address, and if the secret-key is passed in the X-Unomi-Peer HTTP request header. The "env:" part means that it will
+attempt to read an environment variable by that name, and if it&#8217;s not found it will default to the value after the ":-"
+marker.</p>
 </div>
-<div class="listingblock">
+<div class="paragraph">
+<p>It is now also possible to use IP address ranges instead of having to list all valid IP addresses for event sources. This
+is very useful when working in cluster deployments where servers may be added or removed dynamically. In order to support
+this Apache Unomi uses a library called <a href="https://seancfoley.github.io/IPAddress/#_Toc525135541">IPAddress</a> that supports
+IP ranges and subnets. Here is an example of how to setup a range:</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>org.apache.unomi.thirdparty.provider1.ipAddresses=${env:UNOMI_THIRDPARTY_PROVIDER1_IPADDRESSES:-192.168.1.1-100,::1}</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above configuration will allow a range of IP addresses between 192.168.1.1 and 192.168.1.100 as well as the IPv6
+loopback.</p>
+</div>
+<div class="paragraph">
+<p>Here&#8217;s another example using the subnet format:</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>org.apache.unomi.thirdparty.provider1.ipAddresses=${env:UNOMI_THIRDPARTY_PROVIDER1_IPADDRESSES:-1.2.0.0/16,::1}</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above configuration will allow all addresses starting with 1.2 as well as the IPv6 loopback address.</p>
+</div>
+<div class="paragraph">
+<p>Wildcards may also be used:</p>
+</div>
+<div class="literalblock">
 <div class="content">
-<pre class="highlight"><code>$MY_KARAF_HOME/etc/org.apache.unomi.thirdparty.cfg</code></pre>
+<pre>org.apache.unomi.thirdparty.provider1.ipAddresses=${env:UNOMI_THIRDPARTY_PROVIDER1_IPADDRESSES:-1.2.*.*,::1}</pre>
 </div>
 </div>
 <div class="paragraph">
-<p>Ususally, login events, which operate on profiles and do merge on protected properties, must be secured. For each
+<p>The above configuration is exactly the same as the previous one.</p>
+</div>
+<div class="paragraph">
+<p>More advanced ranges and subnets can be used as well, please refer to the <a href="https://seancfoley.github.io/IPAddress">IPAddress</a> library documentation for details on
+how to format them.</p>
+</div>
+<div class="paragraph">
+<p>If you want to add another provider you will need to add them manually in the following file (and make sure you maintain
+the changes when upgrading) :</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>$MY_KARAF_HOME/etc/org.apache.unomi.thirdparty.cfg</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Usually, login events, which operate on profiles and do merge on protected properties, must be secured. For each
 trusted third party server, you need to add these 3 lines :</p>
 </div>
 <div class="listingblock">
@@ -1008,15 +1218,11 @@ thirdparty.provider1.ipAddresses=127.0.0
 thirdparty.provider1.allowedEvents=login,updateProperties</code></pre>
 </div>
 </div>
-<div class="paragraph">
-<p>The events set in allowedEvents will be secured and will only be accepted if the call comes from the specified IP
-address, and if the secret-key is passed in the X-Unomi-Peer header.</p>
-</div>
 </div>
 <div class="sect3">
-<h4 id="_installing_the_maxmind_geoiplite2_ip_lookup_database">3.2.3. Installing the MaxMind GeoIPLite2 IP lookup database</h4>
+<h4 id="_installing_the_maxmind_geoiplite2_ip_lookup_database">3.4.5. Installing the MaxMind GeoIPLite2 IP lookup database</h4>
 <div class="paragraph">
-<p>The Context Server requires an IP database in order to resolve IP addresses to user location.
+<p>Apache Unomi requires an IP database in order to resolve IP addresses to user location.
 The GeoLite2 database can be downloaded from MaxMind here :
 <a href="http://dev.maxmind.com/geoip/geoip2/geolite2/">http://dev.maxmind.com/geoip/geoip2/geolite2/</a></p>
 </div>
@@ -1025,9 +1231,9 @@ The GeoLite2 database can be downloaded
 </div>
 </div>
 <div class="sect3">
-<h4 id="_installing_geonames_database">3.2.4. Installing Geonames database</h4>
+<h4 id="_installing_geonames_database">3.4.6. Installing Geonames database</h4>
 <div class="paragraph">
-<p>Context server includes a geocoding service based on the geonames database ( <a href="http://www.geonames.org/">http://www.geonames.org/</a> ). It can be
+<p>Apache Unomi includes a geocoding service based on the geonames database ( <a href="http://www.geonames.org/">http://www.geonames.org/</a> ). It can be
 used to create conditions on countries or cities.</p>
 </div>
 <div class="paragraph">
@@ -1036,15 +1242,16 @@ used to create conditions on countries o
 </div>
 <div class="paragraph">
 <p>Download it and put it in the "etc" directory, without unzipping it.
-Edit $MY_KARAF_HOME/etc/org.apache.unomi.geonames.cfg and set request.geonamesDatabase.forceImport to true, import should start right away.
+Edit <code>$MY_KARAF_HOME/etc/unomi.custom.system.properties</code> and set <code>org.apache.unomi.geonames.forceImport</code> to true,
+import should start right away.
 Otherwise, import should start at the next startup. Import runs in background, but can take about 15 minutes.
 At the end, you should have about 4 million entries in the geonames index.</p>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_rest_api_security">3.2.5. REST API Security</h4>
+<h4 id="_rest_api_security">3.4.7. REST API Security</h4>
 <div class="paragraph">
-<p>The Context Server REST API is protected using JAAS authentication and using Basic or Digest HTTP auth.
+<p>The Apache Unomi Context Server REST API is protected using JAAS authentication and using Basic or Digest HTTP auth.
 By default, the login/password for the REST API full administrative access is "karaf/karaf".</p>
 </div>
 <div class="paragraph">
@@ -1057,32 +1264,27 @@ By default, the login/password for the R
 <p><a href="http://wiki.eclipse.org/Jetty/Howto/Configure_SSL">http://wiki.eclipse.org/Jetty/Howto/Configure_SSL</a></p>
 </div>
 <div class="paragraph">
-<p>Update the keystore and certificate password in $MY_KARAF_HOME/etc/custom.properties file :</p>
+<p>Update the keystore and certificate password in $MY_KARAF_HOME/etc/unomi.custom.system.properties file :</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>    org.osgi.service.http.secure.enabled = true
-    org.ops4j.pax.web.ssl.keystore=${karaf.etc}/keystore
-    org.ops4j.pax.web.ssl.password=changeme
-    org.ops4j.pax.web.ssl.keypassword=changeme
-    org.osgi.service.http.port.secure=9443</code></pre>
+<pre class="highlight"><code>org.ops4j.pax.web.ssl.keystore=${env:UNOMI_SSL_KEYSTORE:-${karaf.etc}/keystore}
+org.ops4j.pax.web.ssl.password=${env:UNOMI_SSL_PASSWORD:-changeme}
+org.ops4j.pax.web.ssl.keypassword=${env:UNOMI_SSL_KEYPASSWORD:-changeme}</code></pre>
 </div>
 </div>
 <div class="paragraph">
 <p>You should now have SSL setup on Karaf with your certificate, and you can test it by trying to access it on port 9443.</p>
 </div>
-<div class="olist arabic">
-<ol class="arabic">
-<li>
-<p>Changing the default Karaf password can be done by modifying the etc/users.properties file</p>
-</li>
-</ol>
+<div class="paragraph">
+<p>Changing the default Karaf password can be done by modifying the <code>org.apache.unomi.security.root.password</code> in the
+<code>$MY_KARAF_HOME/etc/unomi.custom.system.properties</code> file</p>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_automatic_profile_merging">3.2.6. Automatic profile merging</h4>
+<h4 id="_automatic_profile_merging">3.4.8. Automatic profile merging</h4>
 <div class="paragraph">
-<p>The context server is capable of merging profiles based on a common property value. In order to use this, you must
+<p>Apache Unomi is capable of merging profiles based on a common property value. In order to use this, you must
 add the MergeProfileOnPropertyAction to a rule (such as a login rule for example), and configure it with the name
  of the property that will be used to identify the profiles to be merged. An example could be the "email" property,
  meaning that if two (or more) profiles are found to have the same value for the "email" property they will be merged
@@ -1099,7 +1301,7 @@ Upon sending one of the events, all matc
 </div>
 </div>
 <div class="sect3">
-<h4 id="_securing_a_production_environment">3.2.7. Securing a production environment</h4>
+<h4 id="_securing_a_production_environment">3.4.9. Securing a production environment</h4>
 <div class="paragraph">
 <p>Before going live with a project, you should <em>absolutely</em> read the following section that will help you setup a proper
 secure environment for running your context server.</p>
@@ -1125,7 +1327,7 @@ application-level firewall you should on
 <p>All other ports should not be accessible to the world.</p>
 </div>
 <div class="paragraph">
-<p>For your Context Server client applications (such as the Jahia CMS), you will need to make the following ports
+<p>For your Apache Unomi client applications (such as the Jahia CMS), you will need to make the following ports
 accessible :</p>
 </div>
 <div class="listingblock">
@@ -1135,7 +1337,7 @@ accessible :</p>
 </div>
 </div>
 <div class="paragraph">
-<p>The context server actually requires HTTP Basic Auth for access to the Context Server administration REST API, so it is
+<p>The Apache Unomi actually requires HTTP Basic Auth for access to the Context Server administration REST API, so it is
 highly recommended that you design your client applications to use the HTTPS port for accessing the REST API.</p>
 </div>
 <div class="paragraph">
@@ -1158,12 +1360,23 @@ documentation for here :</p>
 </div>
 </div>
 <div class="paragraph">
-<p>You should really change this default username/password as soon as possible. To do so, simply modify the following
-file :</p>
+<p>You should really change this default username/password as soon as possible. Changing the default Karaf password can be
+done by modifying the <code>org.apache.unomi.security.root.password</code> in the <code>$MY_KARAF_HOME/etc/unomi.custom.system.properties</code> file</p>
 </div>
-<div class="listingblock">
+<div class="paragraph">
+<p>Or if you want to also change the user name you could modify the following file :</p>
+</div>
+<div class="literalblock">
 <div class="content">
-<pre class="highlight"><code>$MY_KARAF_HOME/etc/users.properties</code></pre>
+<pre>$MY_KARAF_HOME/etc/users.properties</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>But you will also need to change the following property in the $MY_KARAF_HOME/etc/unomi.custom.system.properties :</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>karaf.local.user = karaf</pre>
 </div>
 </div>
 <div class="paragraph">
@@ -1198,23 +1411,24 @@ a proxy, and use it to filter any commun
 </div>
 </div>
 <div class="sect3">
-<h4 id="_integrating_with_an_apache_http_web_server">3.2.8. Integrating with an Apache HTTP web server</h4>
+<h4 id="_integrating_with_an_apache_http_web_server">3.4.10. Integrating with an Apache HTTP web server</h4>
 <div class="paragraph">
 <p>If you want to setup an Apache HTTP web server in from of Apache Unomi, here is an example configuration using
 mod_proxy.</p>
 </div>
 <div class="paragraph">
-<p>In your Unomi package directory, in /etc/org.apache.unomi.cluster.cfg for unomi.apache.org</p>
+<p>In your Unomi package directory, in $MY_KARAF_HOME/etc/unomi.custom.system.properties setup the public address for
+the hostname <code>unomi.apache.org</code>:</p>
 </div>
 <div class="paragraph">
-<p>contextserver.publicAddress=https://unomi.apache.org/
- contextserver.internalAddress=http://192.168.1.1:8181</p>
+<p>org.apache.unomi.cluster.public.address=https://unomi.apache.org/
+org.apache.unomi.cluster.internal.address=http://192.168.1.1:8181</p>
 </div>
 <div class="paragraph">
-<p>and you will also need to change the contextserver.domain in the /etc/org.apache.unomi.web.cfg file</p>
+<p>and you will also need to change the cookie domain in the same file:</p>
 </div>
 <div class="paragraph">
-<p>contextserver.domain=apache.org</p>
+<p>org.apache.unomi.profile.cookie.domain=apache.org</p>
 </div>
 <div class="paragraph">
 <p>Main virtual host config:</p>
@@ -1295,30 +1509,27 @@ ProxyPassReverse / http://localhost:8181
 </div>
 </div>
 <div class="sect3">
-<h4 id="_changing_the_default_tracking_location">3.2.9. Changing the default tracking location</h4>
+<h4 id="_changing_the_default_tracking_location">3.4.11. Changing the default tracking location</h4>
 <div class="paragraph">
 <p>When performing localhost requests to Apache Unomi, a default location will be used to insert values into the session
-to make the location-based personalization still work. You can find the default location settings in the file :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>org.apache.unomi.plugins.request.cfg</code></pre>
-</div>
+to make the location-based personalization still work. You can modify the default location settings using the
+centralized configuration file (<code>$MY_KARAF_HOME/etc/unomi.custom.system.properties</code>).</p>
 </div>
 <div class="paragraph">
-<p>that contains the following default settings:</p>
+<p>Here are the default values for the location settings :</p>
 </div>
 <div class="listingblock">
 <div class="content">
 <pre class="highlight"><code># The following settings represent the default position that is used for localhost requests
-defaultSessionCountryCode=CH
-defaultSessionCountryName=Switzerland
-defaultSessionCity=Geneva
-defaultSessionAdminSubDiv1=2660645
-defaultSessionAdminSubDiv2=6458783
-defaultSessionIsp=Cablecom
-defaultLatitude=46.1884341
-defaultLongitude=6.1282508</code></pre>
+org.apache.unomi.ip.database.location=${env:UNOMI_IP_DB:-${karaf.etc}/GeoLite2-City.mmdb}
+org.apache.unomi.ip.default.countryCode=${env:UNOMI_IP_DEFAULT_COUNTRYCODE:-CH}
+org.apache.unomi.ip.default.countryName=${env:UNOMI_IP_DEFAULT_COUNTRYNAME:-Switzerland}
+org.apache.unomi.ip.default.city=${env:UNOMI_IP_DEFAULT_CITY:-Geneva}
+org.apache.unomi.ip.default.subdiv1=${env:UNOMI_IP_DEFAULT_SUBDIV1:-2660645}
+org.apache.unomi.ip.default.subdiv2=${env:UNOMI_IP_DEFAULT_SUBDIV2:-6458783}
+org.apache.unomi.ip.default.isp=${env:UNOMI_IP_DEFAULT_ISP:-Cablecom}
+org.apache.unomi.ip.default.latitude=${env:UNOMI_IP_DEFAULT_LATITUDE:-46.1884341}
+org.apache.unomi.ip.default.longitude=${env:UNOMI_IP_DEFAULT_LONGITUDE:-6.1282508}</code></pre>
 </div>
 </div>
 <div class="paragraph">
@@ -1326,7 +1537,7 @@ defaultLongitude=6.1282508</code></pre>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_apache_karaf_ssh_console">3.2.10. Apache Karaf SSH Console</h4>
+<h4 id="_apache_karaf_ssh_console">3.4.12. Apache Karaf SSH Console</h4>
 <div class="paragraph">
 <p>The Apache Karaf SSH console is available inside Apache Unomi, but the port has been changed from the default value of
 8101 to 8102 to avoid conflicts with other Karaf-based products. So to connect to the SSH console you should use:</p>
@@ -1337,11 +1548,12 @@ defaultLongitude=6.1282508</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>or the user/password you have setup to protect the system if you have changed it.</p>
+<p>or the user/password you have setup to protect the system if you have changed it. You can find the list of Apache Unomi
+shell commands in the "Shell commands" section of the documentation.</p>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_elasticsearch_x_pack_support">3.2.11. ElasticSearch X-Pack Support</h4>
+<h4 id="_elasticsearch_x_pack_support">3.4.13. ElasticSearch X-Pack Support</h4>
 <div class="paragraph">
 <p>It is now possible to use X-Pack to connect to ElasticSearch. However, for licensing reasons this is not provided out
 of the box. Here is the procedure to install X-Pack with Apache Unomi:</p>
@@ -1434,8 +1646,9 @@ as in the following example:</p>
 </div>
 </div>
 </div>
-<div class="sect3">
-<h4 id="_useful_apache_unomi_urls">3.2.12. Useful Apache Unomi URLs</h4>
+</div>
+<div class="sect2">
+<h3 id="_useful_apache_unomi_urls">3.5. 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>
@@ -1534,12 +1747,277 @@ where PROFILE_ID is a profile identifier
 </div>
 </div>
 </div>
+<div class="sect1">
+<h2 id="_consent_management">4. Consent management</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="_consent_api">4.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">4.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>
+<div class="ulist">
+<ul>
+<li>
+<p>a scope</p>
+</li>
+<li>
+<p>a type identifier for the consent. This can be any key to reference a consent. Note that Unomi does not manage consent
+definitions, it only stores/retrieves consents for each profile based on this type</p>
+</li>
+<li>
+<p>a status : GRANT, DENY or REVOKED</p>
+</li>
+<li>
+<p>a status date (the date at which the status was updated)</p>
+</li>
+<li>
+<p>a revocation date, in order to comply with GDPR this is usually set at two years</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Consents are stored as a sub-structure inside a profile. To retrieve the consents of a profile
+you can simply retrieve a profile with the following request:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl -X POST http://localhost:8181/context.json?sessionId=1234 \
+-H "Content-Type: application/json" \
+-d @- &lt;&lt;'EOF'
+{
+    "source": {
+        "itemId":"homepage",
+        "itemType":"page",
+        "scope":"example"
+    }
+}
+EOF</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Here is an example of a response with a Profile with a consent attached to it:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+    "profileId": "18afb5e3-48cf-4f8b-96c4-854cfaadf889",
+    "sessionId": "1234",
+    "profileProperties": null,
+    "sessionProperties": null,
+    "profileSegments": null,
+    "filteringResults": null,
+    "personalizations": null,
+    "trackedConditions": [],
+    "anonymousBrowsing": false,
+    "consents": {
+        "example/newsletter": {
+            "scope": "example",
+            "typeIdentifier": "newsletter",
+            "status": "GRANTED",
+            "statusDate": "2018-05-22T09:27:09Z",
+            "revokeDate": "2020-05-21T09:27:09Z"
+        }
+    }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>It is of course possible to have multiple consents defined for a single visitor profile.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_consent_type_definitions">4.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>
+</div>
+<div class="paragraph">
+<p>The only thing that is import to Apache Unomi to manage visitor consents is a globally unique key, that is called the
+consent type.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_creating_update_a_visitor_consent">4.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>
+</div>
+<div class="paragraph">
+<p>Here is an example of such an event:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+  "events": [
+    {
+      "scope": "example",
+      "eventType": "modifyConsent",
+      "source": {
+        "itemType": "page",
+        "scope": "example",
+        "itemId": "anItemId"
+      },
+      "target": {
+        "itemType": "anyType",
+        "scope": "example",
+        "itemId": "anyItemId"
+      },
+      "properties": {
+        "consent": {
+          "typeIdentifier": "newsletter",
+          "scope": "example",
+          "status": "GRANTED",
+          "statusDate": "2018-05-22T09:27:09.473Z",
+          "revokeDate": "2020-05-21T09:27:09.473Z"
+        }
+      }
+    }
+  ]
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>You could send it using the following curl request:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl -X POST http://localhost:8181/context.json?sessionId=1234 \
+-H "Content-Type: application/json" \
+-d @- &lt;&lt;'EOF'
+{
+    "source":{
+        "itemId":"homepage",
+        "itemType":"page",
+        "scope":"example"
+    },
+    "events": [
+        {
+            "scope":"example",
+            "eventType":"modifyConsent",
+            "source":{
+                "itemType":"page",
+                "scope":"example",
+                "itemId":"anItemId"
+            },
+            "target":{
+                "itemType":"anyType",
+                "scope":"example",
+                "itemId":"anyItemId"},
+            "properties":{
+                "consent":{
+                    "typeIdentifier":"newsletter",
+                    "scope":"example",
+                    "status":"GRANTED",
+                    "statusDate":"2018-05-22T09:27:09.473Z",
+                    "revokeDate":"2020-05-21T09:27:09.473Z"
+                }
+            }
+        }
+    ]
+}
+EOF</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_how_it_works_internally">4.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>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>{
+  "metadata" : {
+    "id": "modifyAnyConsent",
+    "name": "Modify any consent",
+    "description" : "Modify any consent and sets the consent in the profile",
+    "readOnly":true
+  },
+
+  "condition" : {
+    "type": "modifyAnyConsentEventCondition",
+    "parameterValues": {
+    }
+  },
+
+  "actions" : [
+    {
+      "type": "modifyConsentAction",
+      "parameterValues": {
+      }
+    }
+  ]
+
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>As we can see this rule is pretty simple it will simply execute the modifyConsentAction that is implemented by the
+<a href="https://github.com/apache/incubator-unomi/blob/9f1bab437fd93826dc54d318ed00d3b2e3161437/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/ModifyConsentAction.java">ModifyConsentAction Java class</a></p>
+</div>
+<div class="paragraph">
+<p>This class will update the current visitor profile to add/update/revoke any consents that are included in the event.</p>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_cluster_setup">5. Cluster setup</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="_cluster_setup_2">5.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>
+<div class="paragraph">
+<p>You can control most of the important clustering settings through the centralized configuration file at</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>etc/unomi.custom.system.properties</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>And notably using the following properties:</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>org.apache.unomi.hazelcast.group.name=${env:UNOMI_HAZELCAST_GROUP_NAME:-cellar}
+org.apache.unomi.hazelcast.group.password=${env:UNOMI_HAZELCAST_GROUP_PASSWORD:-pass}
+# This list can be comma separated and use ranges such as 192.168.1.0-7,192.168.1.21
+org.apache.unomi.hazelcast.tcp-ip.members=${env:UNOMI_HAZELCAST_TCPIP_MEMBERS:-127.0.0.1}
+org.apache.unomi.hazelcast.tcp-ip.interface=${env:UNOMI_HAZELCAST_TCPIP_INTERFACE:-127.0.0.1}
+org.apache.unomi.hazelcast.network.port=${env:UNOMI_HAZELCAST_NETWORK_PORT:-5701}</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>If you need more fine-grained control over the Hazelcast configuration you could also edit the following file:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>etc/hazelcast.xml</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Note that it would be best to keep all configuration in the centralized custom configuration, for example by adding
+placeholders in the hazelcast.xml file if need be and adding the properties to the centralized configuration file.</p>
+</div>
+</div>
+</div>
 </div>
 <div class="sect1">
-<h2 id="_integration_samples">4. Integration samples</h2>
+<h2 id="_integration_samples">6. Integration samples</h2>
 <div class="sectionbody">
 <div class="sect2">
-<h3 id="_samples">4.1. Samples</h3>
+<h3 id="_samples">6.1. Samples</h3>
 <div class="paragraph">
 <p>Apache Unomi provides the following samples:</p>
 </div>
@@ -1555,12 +2033,12 @@ where PROFILE_ID is a profile identifier
 </div>
 </div>
 <div class="sect2">
-<h3 id="_login_sample">4.2. Login sample</h3>
+<h3 id="_login_sample">6.2. Login sample</h3>
 <div class="paragraph">
 <p>This samples is an example of what is involved in integrated a login with Apache Unomi.</p>
 </div>
 <div class="sect3">
-<h4 id="_warning">4.2.1. Warning !</h4>
+<h4 id="_warning">6.2.1. Warning !</h4>
 <div class="paragraph">
 <p>The example code uses client-side Javascript code to send the login event. This is only
 done this way for the sake of samples simplicity but if should NEVER BE DONE THIS WAY in real cases.</p>
@@ -1571,7 +2049,7 @@ only be sent if the user has authenticat
 </div>
 </div>
 <div class="sect3">
-<h4 id="_installing_the_samples">4.2.2. Installing the samples</h4>
+<h4 id="_installing_the_samples">6.2.2. Installing the samples</h4>
 <div class="paragraph">
 <p>Login into the Unomi Karaf SSH shell using something like this :</p>
 </div>
@@ -1618,9 +2096,9 @@ only be sent if the user has authenticat
 </div>
 </div>
 <div class="sect2">
-<h3 id="_twitter_sample">4.3. Twitter sample</h3>
+<h3 id="_twitter_sample">6.3. Twitter sample</h3>
 <div class="sect3">
-<h4 id="_overview">4.3.1. Overview</h4>
+<h4 id="_overview">6.3.1. Overview</h4>
 <div class="paragraph">
 <p>We will examine how a simple HTML page can interact with Unomi to enrich a user&#8217;s profile. The use case we will follow
 is a rather simple one: we use a Twitter button to record the number of times the visitor tweeted (as a <code>tweetNb</code> profile
@@ -1669,7 +2147,7 @@ mvn clean install</code></pre>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_interacting_with_the_context_server">4.3.2. Interacting with the context server</h4>
+<h4 id="_interacting_with_the_context_server">6.3.2. Interacting with the context server</h4>
 <div class="paragraph">
 <p>There are essentially two modalities to interact with the context server, reflecting different types of Unomi users: context server clients and context server integrators.</p>
 </div>
@@ -1684,7 +2162,7 @@ mvn clean install</code></pre>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_retrieving_context_information_from_unomi_using_the_context_servlet">4.3.3. Retrieving context information from Unomi using the context servlet</h4>
+<h4 id="_retrieving_context_information_from_unomi_using_the_context_servlet">6.3.3. Retrieving context information from Unomi using the context servlet</h4>
 <div class="paragraph">
 <p>Unomi provides two ways to retrieve context: either as a pure JSON object containing strictly context information or as a couple of JSON objects augmented with javascript functions that can be used to interact with the Unomi server using the <code>&lt;context server base URL&gt;/context.json</code> or <code>&lt;context server base URL&gt;/context.js</code> URLs, respectively.</p>
 </div>
@@ -1732,9 +2210,9 @@ information about the context for the cu
 </div>
 </div>
 <div class="sect2">
-<h3 id="_example">4.4. Example</h3>
+<h3 id="_example">6.4. Example</h3>
 <div class="sect3">
-<h4 id="_html_page">4.4.1. HTML page</h4>
+<h4 id="_html_page">6.4.1. HTML page</h4>
 <div class="paragraph">
 <p>The code for the HTML page with our Tweet button can be found at <a href="https://github.com/apache/incubator-unomi/blob/master/wab/src/main/webapp/index.html">https://github.com/apache/incubator-unomi/blob/master/wab/src/main/webapp/index.html</a>.</p>
 </div>
@@ -1743,7 +2221,7 @@ information about the context for the cu
 </div>
 </div>
 <div class="sect3">
-<h4 id="_javascript">4.4.2. Javascript</h4>
+<h4 id="_javascript">6.4.2. Javascript</h4>
 <div class="paragraph">
 <p>Globally, the script loads both the twitter widget and the initial context asynchronously (as shown previously). This is accomplished using fairly standard javascript code and we won&#8217;t look at it here. Using the Twitter API, we react to the <code>tweet</code> event and call the Unomi server to update the user&#8217;s profile with the required information, triggering a custom <code>tweetEvent</code> event. This is accomplished using a <code>contextRequest</code> function which is an extended version of a classic <code>AJAX</code> request:</p>
 </div>
@@ -2116,29 +2594,33 @@ return EventService.PROFILE_UPDATED;</co
 </div>
 </div>
 <div class="sect2">
-<h3 id="_conclusion">4.5. Conclusion</h3>
+<h3 id="_conclusion">6.5. Conclusion</h3>
 <div class="paragraph">
 <p>We have seen a simple example how to interact with Unomi using a combination of client-side code and Unomi plugin. Hopefully, this provided an introduction to the power of what Unomi can do and how it can be extended to suit your needs.</p>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_annex">4.6. Annex</h3>
+<h3 id="_annex">6.6. Annex</h3>
 <div class="paragraph">
-<p>Here is an overview of how Unomi processes incoming requests to the <code>ContextServlet</code>.
-image: images/unomi-request.png[Unomi request overview]</p>
+<p>Here is an overview of how Unomi processes incoming requests to the <code>ContextServlet</code>.</p>
+</div>
+<div class="imageblock">
+<div class="content">
+<img src="images/unomi-request.png" alt="Unomi request overview">
+</div>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_weather_update_sample">4.7. Weather update sample</h3>
+<h3 id="_weather_update_sample">6.7. Weather update sample</h3>
 
 </div>
 </div>
 </div>
 <div class="sect1">
-<h2 id="_connectors">5. Connectors</h2>
+<h2 id="_connectors">7. Connectors</h2>
 <div class="sectionbody">
 <div class="sect2">
-<h3 id="_connectors_2">5.1. Connectors</h3>
+<h3 id="_connectors_2">7.1. Connectors</h3>
 <div class="paragraph">
 <p>Apache Unomi provides the following connectors:</p>
 </div>
@@ -2153,7 +2635,7 @@ image: images/unomi-request.png[Unomi re
 </ul>
 </div>
 <div class="sect3">
-<h4 id="_call_for_contributors">5.1.1. Call for contributors</h4>
+<h4 id="_call_for_contributors">7.1.1. Call for contributors</h4>
 <div class="paragraph">
 <p>We are looking for help with the development of additional connectors. Any contribution (large or small) is more than
 welcome. Feel free to discuss this in our <a href="http://unomi.apache.org/community.html" target="_blank" rel="noopener">mailing list</a>.</p>
@@ -2161,13 +2643,13 @@ welcome. Feel free to discuss this in ou
 </div>
 </div>
 <div class="sect2">
-<h3 id="_salesforce_connector">5.2. Salesforce Connector</h3>
+<h3 id="_salesforce_connector">7.2. Salesforce Connector</h3>
 <div class="paragraph">
 <p>This connectors makes it possible to push and pull data to/from the Salesforce CRM. It can copy information between
 Apache Unomi profiles and Salesforce Leads.</p>
 </div>
 <div class="sect3">
-<h4 id="_getting_started_2">5.2.1. Getting started</h4>
+<h4 id="_getting_started_2">7.2.1. Getting started</h4>
 <div class="sect4">
 <h5 id="_salesforce_account_setup">Salesforce account setup</h5>
 <div class="olist arabic">
@@ -2216,15 +2698,15 @@ with the security token.</p>
 <div class="olist arabic">
 <ol class="arabic">
 <li>
-<p>You are now ready to configure the Apache Unomi Salesforce Connector. In the etc/org.apache.unomi.sfdc.cfg file
-change the following settings:</p>
+<p>You are now ready to configure the Apache Unomi Salesforce Connector. In the etc/unomi.custom.system.properties file
+add/change the following settings:</p>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>sfdc.user.username=YOUR_USER_NAME
-sfdc.user.password=YOUR_PASSWORD
-sfdc.user.securityToken=YOUR_USER_SECURITY_TOKEN
-sfdc.consumer.key=CONNECTED_APP_CONSUMER_KEY
-sfdc.consumer.secret=CONNECTED_APP_SECRET</code></pre>
+<pre class="highlight"><code>org.apache.unomi.sfdc.user.username=${env:UNOMI_SFDC_USER_USERNAME:-}
+org.apache.unomi.sfdc.user.password=${env:UNOMI_SFDC_USER_PASSWORD:-}
+org.apache.unomi.sfdc.user.securityToken=${env:UNOMI_SFDC_USER_SECURITYTOKEN:-}
+org.apache.unomi.sfdc.consumer.key=${env:UNOMI_SFDC_CONSUMER_KEY:-}
+org.apache.unomi.sfdc.consumer.secret=${env:UNOMI_SFDC_CONSUMER_SECRET:-}</code></pre>
 </div>
 </div>
 </li>
@@ -2310,13 +2792,13 @@ find more information about rules in the
 </div>
 </div>
 <div class="sect3">
-<h4 id="_properties">5.2.2. Properties</h4>
+<h4 id="_properties">7.2.2. Properties</h4>
 <div class="paragraph">
 <p>To define how Salesforce attributes will be mapped to Marketing Factory profile properties, edit the following entry using the pattern below :</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>sfdc.fields.mappings=myMarketingFactoryProperty1&lt;=&gt;mySFDCAttribute1,myMarketingFactoryProperty2&lt;=&gt;mySFDCAttribute2</code></pre>
+<pre class="highlight"><code>org.apache.unomi.sfdc.fields.mappings=${env:UNOMI_SFDC_FIELDS_MAPPINGS:-email&lt;=&gt;Email,firstName&lt;=&gt;FirstName,lastName&lt;=&gt;LastName,company&lt;=&gt;Company,phoneNumber&lt;=&gt;Phone,jobTitle&lt;=&gt;Title,city&lt;=&gt;City,zipCode&lt;=&gt;PostalCode,address&lt;=&gt;Street,sfdcStatus&lt;=&gt;Status,sfdcRating&lt;=&gt;Rating}</code></pre>
 </div>
 </div>
 <div class="paragraph">
@@ -2325,12 +2807,12 @@ An identifier needs to be set as well. T
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>sfdc.fields.mappings.identifier=email&lt;=&gt;Email</code></pre>
+<pre class="highlight"><code>org.apache.unomi.sfdc.fields.mappings.identifier=${env:UNOMI_SFDC_FIELDS_MAPPINGS_IDENTIFIER:-email&lt;=&gt;Email}</code></pre>
 </div>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_hot_deploying_updates_to_the_salesforce_connector_for_developers">5.2.3. Hot-deploying updates to the Salesforce connector (for developers)</h4>
+<h4 id="_hot_deploying_updates_to_the_salesforce_connector_for_developers">7.2.3. Hot-deploying updates to the Salesforce connector (for developers)</h4>
 <div class="paragraph">
 <p>If you followed all the steps in the Getting Started section, you can upgrade the Salesforce connectors by using the following steps:</p>
 </div>
@@ -2378,7 +2860,7 @@ feature:install unomi-salesforce-connect
 </div>
 </div>
 <div class="sect3">
-<h4 id="_using_the_salesforce_workbench_for_testing_rest_api">5.2.4. Using the Salesforce Workbench for testing REST API</h4>
+<h4 id="_using_the_salesforce_workbench_for_testing_rest_api">7.2.4. Using the Salesforce Workbench for testing REST API</h4>
 <div class="paragraph">
 <p>The Salesforce Workbench contains a REST API Explorer that is very useful to test requests. You may find it here :</p>
 </div>
@@ -2389,7 +2871,7 @@ feature:install unomi-salesforce-connect
 </div>
 </div>
 <div class="sect3">
-<h4 id="_setting_up_streaming_push_queries">5.2.5. Setting up Streaming Push queries</h4>
+<h4 id="_setting_up_streaming_push_queries">7.2.5. Setting up Streaming Push queries</h4>
 <div class="paragraph">
 <p>Using the Salesforce Workbench, you can setting streaming push queries (Queries-&gt;Streaming push topics) such as the
 following example:</p>
@@ -2402,7 +2884,7 @@ Query : SELECT Id,FirstName,LastName,Ema
 </div>
 </div>
 <div class="sect3">
-<h4 id="_executing_the_unit_tests">5.2.6. Executing the unit tests</h4>
+<h4 id="_executing_the_unit_tests">7.2.6. Executing the unit tests</h4>
 <div class="paragraph">
 <p>Before running the tests, make sure you have completed all the steps above, including the streaming push queries setup.</p>
 </div>
@@ -2453,7 +2935,7 @@ mvn clean install -DsfdcProperties=../te
 </div>
 </div>
 <div class="sect2">
-<h3 id="_mailchimp_connector">5.3. MailChimp Connector</h3>
+<h3 id="_mailchimp_connector">7.3. MailChimp Connector</h3>
 <div class="paragraph">
 <p>This extension has 3 actions:</p>
 </div>
@@ -2471,7 +2953,7 @@ mvn clean install -DsfdcProperties=../te
 </ul>
 </div>
 <div class="sect3">
-<h4 id="_getting_started_3">5.3.1. Getting started</h4>
+<h4 id="_getting_started_3">7.3.1. Getting started</h4>
 <div class="olist arabic">
 <ol class="arabic">
 <li>
@@ -2481,11 +2963,11 @@ mvn clean install -DsfdcProperties=../te
 <p>Generate a new API Key, or get the default: <a href="https://usX.admin.mailchimp.com/account/api/" class="bare">https://usX.admin.mailchimp.com/account/api/</a></p>
 </li>
 <li>
-<p>Configure the MailChimp Connector Basic in the <code>etc/org.apache.unomi.mailchimpconnector.cfg</code> file change the following settings:</p>
+<p>Configure the MailChimp Connector Basic in the <code>etc/unomi.custom.system.properties</code> file and add/change the following settings:</p>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>    mailChimpConnector.apiKey=YOUR_APIKEY
-    mailChimpConnector.url.subDomain=YOUR_SUB_DOMAIN  (exemple: https://usX.admin.mailchimp.com/account/api/, the X is the SUB_DOMAIN)</code></pre>
+<pre class="highlight"><code>org.apache.unomi.mailchimp.apiKey=${env:UNOMI_MAILCHIMP_APIKEY:-yourApiKey}
+org.apache.unomi.mailchimp.url.subDomain=${env:UNOMI_MAILCHIMP_URL_SUBDOMAIN:-us16}</code></pre>
 </div>
 </div>
 </li>
@@ -2500,10 +2982,10 @@ The mapping can&#8217;t be use with mult
 </div>
 </div>
 <div class="paragraph">
-<p>Then in the cfg file <code>mailChimpConnector.list.merge-fields.activate={Boolean} if you like to activate the mapping feature.</code></p>
+<p>Then in the cfg file <code>org.apache.unomi.mailchimp.list.merge-fields.activate={Boolean} if you like to activate the mapping feature.</code></p>
 </div>
 <div class="paragraph">
-<p>This is the property to configure for the mapping, the format is as shown. <code>mailChimpConnector.list.merge-fields.mapping={Apache Unomi property ID}&lt;&#8658;{MailChimp Tag name}</code></p>
+<p>This is the property to configure for the mapping, the format is as shown. <code>org.apache.unomi.mailchimp.list.merge-fields.mapping={Apache Unomi property ID}&lt;&#8658;{MailChimp Tag name}</code></p>
 </div>
 <div class="admonitionblock note">
 <table>
@@ -2583,258 +3065,6 @@ The mapping can&#8217;t be use with mult
 </div>
 </div>
 <div class="sect1">
-<h2 id="_cluster_setup">6. Cluster setup</h2>
-<div class="sectionbody">
-<div class="sect2">
-<h3 id="_cluster_setup_2">6.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.
-You just need to install multiple context servers on the same network, and then (optionally) change the Hazelcast
- configuration in the following file :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>etc/hazelcast.xml</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>All nodes on the same network, sharing the same cluster name will be part of the same cluster.</p>
-</div>
-<div class="paragraph">
-<p>For the actual ElasticSearch configuration however, this must be done using the following file:</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>etc/org.apache.unomi.persistence.elasticsearch.cfg</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>Depending on the cluster size, you will want to adjust the following parameters to make sure your setup is optimal in
-terms of performance and safety.</p>
-</div>
-<div class="sect3">
-<h4 id="_2_nodes_configuration">6.1.1. 2 nodes configuration</h4>
-<div class="paragraph">
-<p>One node dedicated to context server, 1 node for elasticsearch storage.</p>
-</div>
-<div class="paragraph">
-<p>Node A :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>numberOfReplicas=0
-monthlyIndex.numberOfReplicas=0</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>Node B :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>numberOfReplicas=0
-monthlyIndex.numberOfReplicas=0</code></pre>
-</div>
-</div>
-</div>
-<div class="sect3">
-<h4 id="_3_nodes_configuration">6.1.2. 3 nodes configuration</h4>
-<div class="paragraph">
-<p>One node dedicated to context server, 2 nodes for elasticsearch storage with fault-tolerance</p>
-</div>
-<div class="paragraph">
-<p>Node A :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>numberOfReplicas=1
-monthlyIndex.numberOfReplicas=1</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>Node B :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>numberOfReplicas=1
-monthlyIndex.numberOfReplicas=1</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>Node C :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>numberOfReplicas=1
-monthlyIndex.numberOfReplicas=1</code></pre>
-</div>
-</div>
-</div>
-</div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_consent_api">7. Consent API</h2>
-<div class="sectionbody">
-<div class="sect2">
-<h3 id="_consent_api_2">7.1. Consent API</h3>
-<div class="paragraph">
-<p>Starting with Apache Unomi 1.3 (still in development), 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>
-<div class="paragraph">
-<p>Visitor profiles now contain a new Consent object that contains the following information:</p>
-</div>
-<div class="ulist">
-<ul>
-<li>
-<p>a scope</p>
-</li>
-<li>
-<p>a type identifier for the consent. This can be any key to reference a consent. Note that Unomi does not manage consent
-definitions, it only stores/retrieves consents for each profile based on this type</p>
-</li>
-<li>
-<p>a status : GRANT, DENY or REVOKED</p>
-</li>
-<li>
-<p>a status date (the date at which the status was updated)</p>
-</li>
-<li>
-<p>a revocation date, in order to comply with GDPR this is usually set at two years</p>
-</li>
-</ul>
-</div>
-<div class="paragraph">
-<p>Here is an example of a Profile with a consent attached to it:</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>{
-    "profileId": "8cbe380f-57bb-419d-97bf-24bf30178550",
-    "sessionId": "0d755f4e-154a-45c8-9169-e852e1d706d9",
-    "consents": {
-        "example/newsletter": {
-            "scope": "example",
-            "typeIdentifier": "newsletter",
-            "status": "GRANTED",
-            "statusDate": "2018-05-22T09:44:33Z",
-            "revokeDate": "2020-05-21T09:44:33Z"
-        }
-    }
-}</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>It is of course possible to have multiple consents defined for a single visitor profile.</p>
-</div>
-</div>
-<div class="sect3">
-<h4 id="_consent_type_definitions">7.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>
-</div>
-<div class="paragraph">
-<p>The only thing that is import to Apache Unomi to manage visitor consents is a globally unique key, that is called the
-consent type.</p>
-</div>
-</div>
-<div class="sect3">
-<h4 id="_creating_update_a_visitor_consent">7.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>
-</div>
-<div class="paragraph">
-<p>Here is an example of such an event:</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>{
-  "events": [
-    {
-      "scope": "example",
-      "eventType": "modifyConsent",
-      "source": {
-        "itemType": "page",
-        "scope": "example",
-        "itemId": "anItemId"
-      },
-      "target": {
-        "itemType": "anyType",
-        "scope": "example",
-        "itemId": "anyItemId"
-      },
-      "properties": {
-        "consent": {
-          "typeIdentifier": "newsletter",
-          "scope": "example",
-          "status": "GRANTED",
-          "statusDate": "2018-05-22T09:27:09.473Z",
-          "revokeDate": "2020-05-21T09:27:09.473Z"
-        }
-      }
-    }
-  ]
-}</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>You could send it using the following curl request:</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>curl -H "Content-Type: application/json" -X POST -d '{"source":{"itemId":"homepage","itemType":"page","scope":"example"},"events":[{"scope":"example","eventType":"modifyConsent","source":{"itemType":"page","scope":"example","itemId":"anItemId"},"target":{"itemType":"anyType","scope":"example","itemId":"anyItemId"},"properties":{"consent":{"typeIdentifier":"newsletter","scope":"example","status":"GRANTED","statusDate":"2018-05-22T09:27:09.473Z","revokeDate":"2020-05-21T09:27:09.473Z"}}}]}' http://localhost:8181/context.json?sessionId=1234</code></pre>
-</div>
-</div>
-</div>
-<div class="sect3">
-<h4 id="_how_it_works_internally">7.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>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>{
-  "metadata" : {
-    "id": "modifyAnyConsent",
-    "name": "Modify any consent",
-    "description" : "Modify any consent and sets the consent in the profile",
-    "readOnly":true
-  },
-
-  "condition" : {
-    "type": "modifyAnyConsentEventCondition",
-    "parameterValues": {
-    }
-  },
-
-  "actions" : [
-    {
-      "type": "modifyConsentAction",
-      "parameterValues": {
-      }
-    }
-  ]
-
-}</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>As we can see this rule is pretty simple it will simply execute the modifyConsentAction that is implemented by the
-<a href="https://github.com/apache/incubator-unomi/blob/9f1bab437fd93826dc54d318ed00d3b2e3161437/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/ModifyConsentAction.java">ModifyConsentAction Java class</a></p>
-</div>
-<div class="paragraph">
-<p>This class will update the current visitor profile to add/update/revoke any consents that are included in the event.</p>
-</div>
-</div>
-</div>
-</div>
-</div>
-<div class="sect1">
 <h2 id="_developers">8. Developers</h2>
 <div class="sectionbody">
 <div class="sect2">
@@ -3365,13 +3595,19 @@ examples of using this command: <code>un
 <div class="sect2">
 <h3 id="_types_vs_instances">8.3. Types vs. instances</h3>
 <div class="paragraph">
-<p>Several extension points in Unomi rely on the concept of type: the extension defines a prototype for what the actual items will be once parameterized with values known only at runtime. This is similar to the concept of classes in object-oriented programming: types define classes, providing the expected structure and which fields are expected to be provided at runtime, that are then instantiated when needed with actual values.</p>
+<p>Several extension points in Unomi rely on the concept of type: the extension defines a prototype for what the actual
+items will be once parameterized with values known only at runtime. This is similar to the concept of classes in
+object-oriented programming: types define classes, providing the expected structure and which fields are expected to
+be provided at runtime, that are then instantiated when needed with actual values.</p>
 </div>
 </div>
 <div class="sect2">
 <h3 id="_plugin_structure">8.4. Plugin structure</h3>
 <div class="paragraph">
-<p>Being built on top of Apache Karaf, Unomi leverages OSGi to support plugins. A Unomi plugin is, thus, an OSGi bundle specifying some specific metadata to tell Unomi the kind of entities it provides. A plugin can provide the following entities to extend Unomi, each with its associated definition (as a JSON file), located in a specific spot within the <code>META-INF/cxs/</code> directory of the bundle JAR file:</p>
+<p>Being built on top of Apache Karaf, Unomi leverages OSGi to support plugins. A Unomi plugin is, thus, an OSGi
+bundle specifying some specific metadata to tell Unomi the kind of entities it provides. A plugin can provide the
+following entities to extend Unomi, each with its associated definition (as a JSON file), located in a specific spot
+within the <code>META-INF/cxs/</code> directory of the bundle JAR file:</p>
 </div>
 <table class="tableblock frame-all grid-all stretch">
 <colgroup>
@@ -3424,7 +3660,8 @@ examples of using this command: <code>un
 </tbody>
 </table>
 <div class="paragraph">
-<p><a href="http://aries.apache.org/modules/blueprint.html">Blueprint</a> is used to declare what the plugin provides and inject any required dependency. The Blueprint file is located, as usual, at <code>OSGI-INF/blueprint/blueprint.xml</code> in the bundle JAR file.</p>
+<p><a href="http://aries.apache.org/modules/blueprint.html">Blueprint</a> is used to declare what the plugin provides and inject
+any required dependency. The Blueprint file is located, as usual, at <code>OSGI-INF/blueprint/blueprint.xml</code> in the bundle JAR file.</p>
 </div>
 <div class="paragraph">
 <p>The plugin otherwise follows a regular maven project layout and should depend on the Unomi API maven artifact:</p>
@@ -3439,7 +3676,8 @@ examples of using this command: <code>un
 </div>
 </div>
 <div class="paragraph">
-<p>Some plugins consists only of JSON definitions that are used to instantiate the appropriate structures at runtime while some more involved plugins provide code that extends Unomi in deeper ways.</p>
+<p>Some plugins consists only of JSON definitions that are used to instantiate the appropriate structures at runtime
+while some more involved plugins provide code that extends Unomi in deeper ways.</p>
 </div>
 <div class="paragraph">
 <p>In both cases, plugins can provide more that one type of extension. For example, a plugin could provide both `ActionType`s and `ConditionType`s.</p>
@@ -3983,8 +4221,9 @@ definition file.</p>
 </ul>
 </div>
 </div>
-<div class="sect3">
-<h4 id="_migration_patches">8.7.10. Migration patches</h4>
+</div>
+<div class="sect2">
+<h3 id="_migration_patches">8.8. Migration patches</h3>
 <div class="paragraph">
 <p>You may provide patches on any predefined items by simply adding a JSON file in :</p>
 </div>
@@ -4114,10 +4353,9 @@ They allow to modify an item, that would
 </div>
 </div>
 </div>
-</div>
 <div id="footer">
 <div id="footer-text">
-Last updated 2018-11-26 14:15:18 CET
+Last updated 2019-05-12 10:06:20 CEST
 </div>
 </div>
 </body>