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/07/29 16:58:53 UTC

svn commit: r1863957 [2/2] - in /unomi/website/manual: 1_1_x/index.html 1_2_x/index.html 1_3_x/index.html latest/images/unomi-rule-engine.png latest/index.html

Modified: unomi/website/manual/latest/index.html
URL: http://svn.apache.org/viewvc/unomi/website/manual/latest/index.html?rev=1863957&r1=1863956&r2=1863957&view=diff
==============================================================================
--- unomi/website/manual/latest/index.html (original)
+++ unomi/website/manual/latest/index.html Mon Jul 29 16:58:53 2019
@@ -29,7 +29,14 @@
 <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>
+<li><a href="#_segments">2.5. Segments</a></li>
+<li><a href="#_conditions">2.6. Conditions</a></li>
+<li><a href="#_rules">2.7. Rules</a>
+<ul class="sectlevel3">
+<li><a href="#_actions">2.7.1. Actions</a></li>
+</ul>
+</li>
+<li><a href="#_request_flow">2.8. Request flow</a></li>
 </ul>
 </li>
 <li><a href="#_first_steps_with_apache_unomi">3. First steps with Apache Unomi</a>
@@ -40,42 +47,59 @@
 <li><a href="#_running_unomi">3.1.2. Running Unomi</a></li>
 </ul>
 </li>
-<li><a href="#_request_examples">3.2. Request examples</a>
+<li><a href="#_recipes">3.2. Recipes</a>
+<ul class="sectlevel3">
+<li><a href="#_introduction">3.2.1. Introduction</a></li>
+<li><a href="#_how_to_read_a_profile">3.2.2. How to read a profile</a></li>
+<li><a href="#_how_to_update_a_profile_from_the_public_internet">3.2.3. How to update a profile from the public internet</a></li>
+<li><a href="#_how_to_search_for_profile_events">3.2.4. How to search for profile events</a></li>
+<li><a href="#_how_to_create_a_new_rule">3.2.5. How to create a new rule</a></li>
+<li><a href="#_how_to_search_for_profiles">3.2.6. How to search for profiles</a></li>
+<li><a href="#_getting_updating_consents">3.2.7. Getting / updating consents</a></li>
+<li><a href="#_how_to_send_a_login_event_to_unomi">3.2.8. How to send a login event to Unomi</a></li>
+</ul>
+</li>
+<li><a href="#_request_examples">3.3. Request examples</a>
+<ul class="sectlevel3">
+<li><a href="#_retrieving_your_first_context">3.3.1. Retrieving your first context</a></li>
+<li><a href="#_retrieving_a_context_as_a_json_object">3.3.2. Retrieving a context as a JSON object.</a></li>
+<li><a href="#_accessing_profile_properties_in_a_context">3.3.3. Accessing profile properties in a context</a></li>
+<li><a href="#_sending_events_using_the_context_servlet">3.3.4. Sending events using the context servlet</a></li>
+<li><a href="#_sending_events_using_the_eventcollector_servlet">3.3.5. Sending events using the eventcollector servlet</a></li>
+<li><a href="#_where_to_go_from_here">3.3.6. Where to go from here</a></li>
+</ul>
+</li>
+<li><a href="#_web_tracker">3.4. Web Tracker</a>
 <ul class="sectlevel3">
-<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>
+<li><a href="#_getting_started">3.4.1. Getting started</a></li>
+<li><a href="#_how_to_contribute">3.4.2. How to contribute</a></li>
+<li><a href="#_tracking_page_views">3.4.3. Tracking page views</a></li>
+<li><a href="#_tracking_form_submissions">3.4.4. Tracking form submissions</a></li>
 </ul>
 </li>
-<li><a href="#_web_tracker">3.3. Web Tracker</a>
+<li><a href="#_configuration">3.5. Configuration</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>
+<li><a href="#_centralized_configuration">3.5.1. Centralized configuration</a></li>
+<li><a href="#_changing_the_default_configuration_using_environment_variables_i_e_docker_configuration">3.5.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.5.3. Changing the default configuration using property files</a></li>
+<li><a href="#_secured_events_configuration">3.5.4. Secured events configuration</a></li>
+<li><a href="#_installing_the_maxmind_geoiplite2_ip_lookup_database">3.5.5. Installing the MaxMind GeoIPLite2 IP lookup database</a></li>
+<li><a href="#_installing_geonames_database">3.5.6. Installing Geonames database</a></li>
+<li><a href="#_rest_api_security">3.5.7. REST API Security</a></li>
+<li><a href="#_automatic_profile_merging">3.5.8. Automatic profile merging</a></li>
+<li><a href="#_securing_a_production_environment">3.5.9. Securing a production environment</a></li>
+<li><a href="#_integrating_with_an_apache_http_web_server">3.5.10. Integrating with an Apache HTTP web server</a></li>
+<li><a href="#_changing_the_default_tracking_location">3.5.11. Changing the default tracking location</a></li>
+<li><a href="#_apache_karaf_ssh_console">3.5.12. Apache Karaf SSH Console</a></li>
+<li><a href="#_elasticsearch_x_pack_support">3.5.13. ElasticSearch X-Pack Support</a></li>
 </ul>
 </li>
-<li><a href="#_configuration">3.4. Configuration</a>
+<li><a href="#_useful_apache_unomi_urls">3.6. Useful Apache Unomi URLs</a></li>
+<li><a href="#_how_profile_tracking_works">3.7. How profile tracking works</a>
 <ul class="sectlevel3">
-<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>
+<li><a href="#_steps">3.7.1. Steps</a></li>
 </ul>
 </li>
-<li><a href="#_useful_apache_unomi_urls">3.5. Useful Apache Unomi URLs</a></li>
 </ul>
 </li>
 <li><a href="#_consent_management">4. Consent management</a>
@@ -90,121 +114,144 @@
 </li>
 </ul>
 </li>
-<li><a href="#_cluster_setup">5. Cluster setup</a>
+<li><a href="#_privacy_management">5. Privacy management</a>
+<ul class="sectlevel3">
+<li><a href="#_setting_up_access_to_the_privacy_endpoint">5.1. Setting up access to the privacy endpoint</a></li>
+<li><a href="#_anonymizing_a_profile">5.2. Anonymizing a profile</a></li>
+<li><a href="#_downloading_profile_data">5.3. Downloading profile data</a></li>
+<li><a href="#_deleting_a_profile">5.4. Deleting a profile</a></li>
+<li><a href="#_related">5.5. Related</a></li>
+</ul>
+</li>
+<li><a href="#_cluster_setup">6. Cluster setup</a>
+<ul class="sectlevel2">
+<li><a href="#_cluster_setup_2">6.1. Cluster setup</a></li>
+</ul>
+</li>
+<li><a href="#_reference">7. Reference</a>
 <ul class="sectlevel2">
-<li><a href="#_cluster_setup_2">5.1. Cluster setup</a></li>
+<li><a href="#_built_in_conditions">7.1. Built-in conditions</a>
+<ul class="sectlevel3">
+<li><a href="#_existing_condition_descriptors">7.1.1. Existing condition descriptors</a></li>
+</ul>
+</li>
+<li><a href="#_built_in_actions">7.2. Built-in actions</a>
+<ul class="sectlevel3">
+<li><a href="#_existing_actions_descriptors">7.2.1. Existing actions descriptors</a></li>
+</ul>
+</li>
 </ul>
 </li>
-<li><a href="#_integration_samples">6. Integration samples</a>
+<li><a href="#_integration_samples">8. 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>
+<li><a href="#_samples">8.1. Samples</a></li>
+<li><a href="#_login_sample">8.2. Login sample</a>
 <ul class="sectlevel3">
-<li><a href="#_warning">6.2.1. Warning !</a></li>
-<li><a href="#_installing_the_samples">6.2.2. Installing the samples</a></li>
+<li><a href="#_warning">8.2.1. Warning !</a></li>
+<li><a href="#_installing_the_samples">8.2.2. Installing the samples</a></li>
 </ul>
 </li>
-<li><a href="#_twitter_sample">6.3. Twitter sample</a>
+<li><a href="#_twitter_sample">8.3. Twitter sample</a>
 <ul class="sectlevel3">
-<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>
+<li><a href="#_overview">8.3.1. Overview</a></li>
+<li><a href="#_interacting_with_the_context_server">8.3.2. Interacting with the context server</a></li>
+<li><a href="#_retrieving_context_information_from_unomi_using_the_context_servlet">8.3.3. Retrieving context information from Unomi using the context servlet</a></li>
 </ul>
 </li>
-<li><a href="#_example">6.4. Example</a>
+<li><a href="#_example">8.4. Example</a>
 <ul class="sectlevel3">
-<li><a href="#_html_page">6.4.1. HTML page</a></li>
-<li><a href="#_javascript">6.4.2. Javascript</a></li>
+<li><a href="#_html_page">8.4.1. HTML page</a></li>
+<li><a href="#_javascript">8.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>
+<li><a href="#_conclusion">8.5. Conclusion</a></li>
+<li><a href="#_annex">8.6. Annex</a></li>
+<li><a href="#_weather_update_sample">8.7. Weather update sample</a></li>
 </ul>
 </li>
-<li><a href="#_connectors">7. Connectors</a>
+<li><a href="#_connectors">9. Connectors</a>
 <ul class="sectlevel2">
-<li><a href="#_connectors_2">7.1. Connectors</a>
+<li><a href="#_connectors_2">9.1. Connectors</a>
 <ul class="sectlevel3">
-<li><a href="#_call_for_contributors">7.1.1. Call for contributors</a></li>
+<li><a href="#_call_for_contributors">9.1.1. Call for contributors</a></li>
 </ul>
 </li>
-<li><a href="#_salesforce_connector">7.2. Salesforce Connector</a>
+<li><a href="#_salesforce_connector">9.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>
+<li><a href="#_getting_started_2">9.2.1. Getting started</a></li>
+<li><a href="#_properties">9.2.2. Properties</a></li>
+<li><a href="#_hot_deploying_updates_to_the_salesforce_connector_for_developers">9.2.3. Hot-deploying updates to the Salesforce connector (for developers)</a></li>
+<li><a href="#_using_the_salesforce_workbench_for_testing_rest_api">9.2.4. Using the Salesforce Workbench for testing REST API</a></li>
+<li><a href="#_setting_up_streaming_push_queries">9.2.5. Setting up Streaming Push queries</a></li>
+<li><a href="#_executing_the_unit_tests">9.2.6. Executing the unit tests</a></li>
 </ul>
 </li>
-<li><a href="#_mailchimp_connector">7.3. MailChimp Connector</a>
+<li><a href="#_mailchimp_connector">9.3. MailChimp Connector</a>
 <ul class="sectlevel3">
-<li><a href="#_getting_started_3">7.3.1. Getting started</a></li>
+<li><a href="#_getting_started_3">9.3.1. Getting started</a></li>
 </ul>
 </li>
 </ul>
 </li>
-<li><a href="#_developers">8. Developers</a>
+<li><a href="#_developers">10. Developers</a>
 <ul class="sectlevel2">
-<li><a href="#_building">8.1. Building</a>
+<li><a href="#_building">10.1. Building</a>
 <ul class="sectlevel3">
-<li><a href="#_initial_setup">8.1.1. Initial Setup</a></li>
-<li><a href="#_building_2">8.1.2. Building</a></li>
-<li><a href="#_installing_an_elasticsearch_server">8.1.3. Installing an ElasticSearch server</a></li>
-<li><a href="#_deploying_the_generated_binary_package">8.1.4. Deploying the generated binary package</a></li>
-<li><a href="#_deploying_into_an_existing_karaf_server">8.1.5. Deploying into an existing Karaf server</a></li>
-<li><a href="#_jdk_selection_on_mac_os_x">8.1.6. JDK Selection on Mac OS X</a></li>
-<li><a href="#_running_the_integration_tests">8.1.7. Running the integration tests</a></li>
-<li><a href="#_running_the_performance_tests">8.1.8. Running the performance tests</a></li>
-<li><a href="#_testing_with_an_example_page">8.1.9. Testing with an example page</a></li>
+<li><a href="#_initial_setup">10.1.1. Initial Setup</a></li>
+<li><a href="#_building_2">10.1.2. Building</a></li>
+<li><a href="#_installing_an_elasticsearch_server">10.1.3. Installing an ElasticSearch server</a></li>
+<li><a href="#_deploying_the_generated_binary_package">10.1.4. Deploying the generated binary package</a></li>
+<li><a href="#_deploying_into_an_existing_karaf_server">10.1.5. Deploying into an existing Karaf server</a></li>
+<li><a href="#_jdk_selection_on_mac_os_x">10.1.6. JDK Selection on Mac OS X</a></li>
+<li><a href="#_running_the_integration_tests">10.1.7. Running the integration tests</a></li>
+<li><a href="#_running_the_performance_tests">10.1.8. Running the performance tests</a></li>
+<li><a href="#_testing_with_an_example_page">10.1.9. Testing with an example page</a></li>
 </ul>
 </li>
-<li><a href="#_ssh_shell_commands">8.2. SSH Shell Commands</a>
+<li><a href="#_ssh_shell_commands">10.2. SSH Shell Commands</a>
 <ul class="sectlevel3">
-<li><a href="#_using_the_shell">8.2.1. Using the shell</a></li>
-<li><a href="#_lifecycle_commands">8.2.2. Lifecycle commands</a></li>
-<li><a href="#_runtime_commands">8.2.3. Runtime commands</a></li>
+<li><a href="#_using_the_shell">10.2.1. Using the shell</a></li>
+<li><a href="#_lifecycle_commands">10.2.2. Lifecycle commands</a></li>
+<li><a href="#_runtime_commands">10.2.3. Runtime commands</a></li>
 </ul>
 </li>
-<li><a href="#_types_vs_instances">8.3. Types vs. instances</a></li>
-<li><a href="#_plugin_structure">8.4. Plugin structure</a></li>
-<li><a href="#_extension_points">8.5. Extension points</a>
+<li><a href="#_types_vs_instances">10.3. Types vs. instances</a></li>
+<li><a href="#_plugin_structure">10.4. Plugin structure</a></li>
+<li><a href="#_extension_points">10.5. Extension points</a>
 <ul class="sectlevel3">
-<li><a href="#_actiontype">8.5.1. ActionType</a></li>
-<li><a href="#_conditiontype">8.5.2. ConditionType</a></li>
-<li><a href="#_persona">8.5.3. Persona</a></li>
-<li><a href="#_propertymergestrategytype">8.5.4. PropertyMergeStrategyType</a></li>
-<li><a href="#_propertytype">8.5.5. PropertyType</a></li>
-<li><a href="#_rule">8.5.6. Rule</a></li>
-<li><a href="#_scoring">8.5.7. Scoring</a></li>
-<li><a href="#_segments">8.5.8. Segments</a></li>
-<li><a href="#_tag">8.5.9. Tag</a></li>
-<li><a href="#_valuetype">8.5.10. ValueType</a></li>
+<li><a href="#_actiontype">10.5.1. ActionType</a></li>
+<li><a href="#_conditiontype">10.5.2. ConditionType</a></li>
+<li><a href="#_persona">10.5.3. Persona</a></li>
+<li><a href="#_propertymergestrategytype">10.5.4. PropertyMergeStrategyType</a></li>
+<li><a href="#_propertytype">10.5.5. PropertyType</a></li>
+<li><a href="#_rule">10.5.6. Rule</a></li>
+<li><a href="#_scoring">10.5.7. Scoring</a></li>
+<li><a href="#_segments_2">10.5.8. Segments</a></li>
+<li><a href="#_tag">10.5.9. Tag</a></li>
+<li><a href="#_valuetype">10.5.10. ValueType</a></li>
 </ul>
 </li>
-<li><a href="#_other_unomi_entities">8.6. Other Unomi entities</a>
+<li><a href="#_other_unomi_entities">10.6. Other Unomi entities</a>
 <ul class="sectlevel3">
-<li><a href="#_userlist">8.6.1. UserList</a></li>
-<li><a href="#_goal">8.6.2. Goal</a></li>
-<li><a href="#_campaign">8.6.3. Campaign</a></li>
+<li><a href="#_userlist">10.6.1. UserList</a></li>
+<li><a href="#_goal">10.6.2. Goal</a></li>
+<li><a href="#_campaign">10.6.3. Campaign</a></li>
 </ul>
 </li>
-<li><a href="#_custom_extensions">8.7. Custom extensions</a>
+<li><a href="#_custom_extensions">10.7. Custom extensions</a>
 <ul class="sectlevel3">
-<li><a href="#_creating_an_extension">8.7.1. Creating an extension</a></li>
-<li><a href="#_deployment_and_custom_definition">8.7.2. Deployment and custom definition</a></li>
-<li><a href="#_predefined_segments">8.7.3. Predefined segments</a></li>
-<li><a href="#_predefined_rules">8.7.4. Predefined rules</a></li>
-<li><a href="#_predefined_properties">8.7.5. Predefined properties</a></li>
-<li><a href="#_predefined_child_conditions">8.7.6. Predefined child conditions</a></li>
-<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="#_creating_an_extension">10.7.1. Creating an extension</a></li>
+<li><a href="#_deployment_and_custom_definition">10.7.2. Deployment and custom definition</a></li>
+<li><a href="#_predefined_segments">10.7.3. Predefined segments</a></li>
+<li><a href="#_predefined_rules">10.7.4. Predefined rules</a></li>
+<li><a href="#_predefined_properties">10.7.5. Predefined properties</a></li>
+<li><a href="#_predefined_child_conditions">10.7.6. Predefined child conditions</a></li>
+<li><a href="#_predefined_personas">10.7.7. Predefined personas</a></li>
+<li><a href="#_custom_actions">10.7.8. Custom actions</a></li>
+<li><a href="#_custom_conditions">10.7.9. Custom conditions</a></li>
 </ul>
 </li>
-<li><a href="#_migration_patches">8.8. Migration patches</a></li>
+<li><a href="#_migration_patches">10.8. Migration patches</a></li>
 </ul>
 </li>
 </ul>
@@ -267,21 +314,33 @@ make sure you are using the proper versi
 <h2 id="_concepts">2. Concepts</h2>
 <div class="sectionbody">
 <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 user profiles into segments along user-definable dimensions or acted upon by algorithms.</p>
+<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 user
+profiles into segments along user-definable dimensions or acted upon by algorithms.</p>
 </div>
 <div class="sect2">
 <h3 id="_items_and_types">2.1. Items and types</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). This base structure can be extended, if needed, using properties in the form of key-value pairs.</p>
+<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). This base structure can be extended, if needed, using properties in the
+form of key-value pairs.</p>
 </div>
 <div class="paragraph">
-<p>These properties are further defined by the <code>Item</code>’s type definition which explicits the <code>Item</code>’s structure and semantics. By defining new types, users specify which properties (including the type of values they accept) are available to items of that specific type.</p>
+<p>These properties are further defined by the <code>Item</code>’s type definition which explicits the <code>Item</code>’s structure and
+semantics. By defining new types, users specify which properties (including the type of values they accept) are
+available to items of that specific type.</p>
 </div>
 <div class="paragraph">
-<p>Unomi defines default value types: <code>date</code>, <code>email</code>, <code>integer</code> and <code>string</code>, all pretty self-explanatory. While you can think of these value types as "primitive" types, it is possible to extend Unomi by providing additional value types.</p>
+<p>Unomi defines default value types: <code>date</code>, <code>email</code>, <code>integer</code> and <code>string</code>, all pretty self-explanatory. While you can
+think of these value types as "primitive" types, it is possible to extend Unomi by providing additional value types.</p>
 </div>
 <div class="paragraph">
-<p>Additionally, most items are also associated to a scope, which is a concept that Unomi uses to group together related items. A given scope is represented in Unomi by a simple string identifier and usually represents an application or set of applications from which Unomi gathers data, depending on the desired analysis granularity. In the context of web sites, a scope could, for example, represent a site or family of related sites being analyzed. Scopes allow clients accessing the context server to filter data to only see relevant data.</p>
+<p>Additionally, most items are also associated to a scope, which is a concept that Unomi uses to group together related
+items. A given scope is represented in Unomi by a simple string identifier and usually represents an application or set
+of applications from which Unomi gathers data, depending on the desired analysis granularity. In the context of web
+sites, a scope could, for example, represent a site or family of related sites being analyzed. Scopes allow clients
+accessing the context server to filter data to only see relevant data.</p>
 </div>
 <div class="paragraph">
 <p><em>Base <code>Item</code> structure:</em></p>
@@ -297,7 +356,11 @@ make sure you are using the proper versi
 </div>
 </div>
 <div class="paragraph">
-<p>Some types can be dynamically defined at runtime by calling to the REST API while other extensions are done via Unomi plugins. Part of extending Unomi, therefore, is a matter of defining new types and specifying which kind of Unomi entity (e.g. profiles) they can be affected to. For example, the following JSON document can be passed to Unomi to declare a new property type identified (and named) <code>tweetNb</code>, tagged with the <code>social</code> tag, targeting profiles and using the <code>integer</code> value type.</p>
+<p>Some types can be dynamically defined at runtime by calling to the REST API while other extensions are done via Unomi
+plugins. Part of extending Unomi, therefore, is a matter of defining new types and specifying which kind of Unomi
+entity (e.g. profiles) they can be affected to. For example, the following JSON document can be passed to Unomi to
+declare a new property type identified (and named) <code>tweetNb</code>, tagged with the <code>social</code> tag, targeting profiles and
+using the <code>integer</code> value type.</p>
 </div>
 <div class="paragraph">
 <p><em>Example JSON type definition:</em></p>
@@ -328,7 +391,10 @@ make sure you are using the proper versi
 <div class="sect2">
 <h3 id="_events">2.2. Events</h3>
 <div class="paragraph">
-<p>Users' actions are conveyed from clients to the context server using events. Of course, the required information depends on what is collected and users' interactions with the observed systems but events minimally provide a type, a scope and source and target items. Additionally, events are timestamped. Conceptually, an event can be seen as a sentence, the event&#8217;s type being the verb, the source the subject and the target the object.</p>
+<p>Users' actions are conveyed from clients to the context server using events. Of course, the required information
+depends on what is collected and users' interactions with the observed systems but events minimally provide a type, a
+scope and source and target items. Additionally, events are timestamped. Conceptually, an event can be seen as a
+sentence, the event&#8217;s type being the verb, the source the subject and the target the object.</p>
 </div>
 <div class="paragraph">
 <p><em>Event structure:</em></p>
@@ -345,10 +411,14 @@ make sure you are using the proper versi
 </div>
 </div>
 <div class="paragraph">
-<p>Source and target can be any Unomi item but are not limited to them. In particular, as long as they can be described using properties and Unomi’s type mechanism and can be processed either natively or via extension plugins, source and target can represent just about anything. Events can also be triggered as part of Unomi’s internal processes for example when a rule is triggered.</p>
+<p>Source and target can be any Unomi item but are not limited to them. In particular, as long as they can be described
+using properties and Unomi’s type mechanism and can be processed either natively or via extension plugins, source and
+target can represent just about anything. Events can also be triggered as part of Unomi’s internal processes for example
+when a rule is triggered.</p>
 </div>
 <div class="paragraph">
-<p>Events are sent to Unomi from client applications using the JSON format and a typical page view event from a web site could look something like the following:</p>
+<p>Events are sent to Unomi from client applications using the JSON format and a typical page view event from a web site
+could look something like the following:</p>
 </div>
 <div class="paragraph">
 <p><em>Example page view event:</em></p>
@@ -387,23 +457,229 @@ make sure you are using the proper versi
 <div class="sect2">
 <h3 id="_profiles">2.3. Profiles</h3>
 <div class="paragraph">
-<p>By processing events, Unomi progressively builds a picture of who the user is and how they behave. This knowledge is embedded in <code>Profile</code> object. A profile is an <code>Item</code> with any number of properties and optional segments and scores. Unomi provides default properties to cover common data (name, last name, age, email, etc.) as well as default segments to categorize users. Unomi users are, however, free and even encouraged to create additional properties and segments to better suit their needs.</p>
+<p>By processing events, Unomi progressively builds a picture of who the user is and how they behave. This knowledge is
+embedded in <code>Profile</code> object. A profile is an <code>Item</code> with any number of properties and optional segments and scores.
+Unomi provides default properties to cover common data (name, last name, age, email, etc.) as well as default segments
+to categorize users. Unomi users are, however, free and even encouraged to create additional properties and segments to
+better suit their needs.</p>
+</div>
+<div class="paragraph">
+<p>Contrary to other Unomi items, profiles are not part of a scope since we want to be able to track the associated user
+across applications. For this reason, data collected for a given profile in a specific scope is still available to any
+scoped item that accesses the profile information.</p>
+</div>
+<div class="paragraph">
+<p>It is interesting to note that there is not necessarily a one to one mapping between users and profiles as users can be
+captured across applications and different observation contexts. As identifying information might not be available in
+all contexts in which data is collected, resolving profiles to a single physical user can become complex because
+physical users are not observed directly. Rather, their portrait is progressively patched together and made clearer as
+Unomi captures more and more traces of their actions. Unomi will merge related profiles as soon as collected data
+permits positive association between distinct profiles, usually as a result of the user performing some identifying
+action in a context where the user hadn’t already been positively identified.</p>
 </div>
+</div>
+<div class="sect2">
+<h3 id="_sessions">2.4. Sessions</h3>
 <div class="paragraph">
-<p>Contrary to other Unomi items, profiles are not part of a scope since we want to be able to track the associated user across applications. For this reason, data collected for a given profile in a specific scope is still available to any scoped item that accesses the profile information.</p>
+<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="_segments">2.5. Segments</h3>
 <div class="paragraph">
-<p>It is interesting to note that there is not necessarily a one to one mapping between users and profiles as users can be captured across applications and different observation contexts. As identifying information might not be available in all contexts in which data is collected, resolving profiles to a single physical user can become complex because physical users are not observed directly. Rather, their portrait is progressively patched together and made clearer as Unomi captures more and more traces of their actions. Unomi will merge related profiles as soon as collected data permits positive association between distinct profiles, usually as a result of the user performing some identifying action in a context where the user hadn’t already been positively identified.</p>
+<p>Segments are used to group profiles together, and are based on conditions that are executed on profiles to determine if
+they are part of a segment or not. This also means that a profile may enter or leave a segment based on changes in their
+properties, making segments a highly dynamic concept.</p>
+</div>
+<div class="paragraph">
+<p>Here is an example of a simple segment definition registered using the REST API:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl -X POST http://localhost:8181/cxs/segments \
+--user karaf:karaf \
+-H "Content-Type: application/json" \
+-d @- &lt;&lt;'EOF'
+{
+  "metadata": {
+    "id": "leads",
+    "name": "Leads",
+    "scope": "systemscope",
+    "description": "You can customize the list below by editing the leads segment.",
+    "readOnly":true
+  },
+  "condition": {
+    "type": "booleanCondition",
+    "parameterValues": {
+      "operator" : "and",
+      "subConditions": [
+        {
+          "type": "profilePropertyCondition",
+          "parameterValues": {
+            "propertyName": "properties.leadAssignedTo",
+            "comparisonOperator": "exists"
+          }
+        }
+      ]
+    }
+  }
+}
+EOF</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>For more details on the conditions and how they are structured using conditions, see the next section.</p>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_sessions">2.4. Sessions</h3>
+<h3 id="_conditions">2.6. Conditions</h3>
+<div class="paragraph">
+<p>Conditions are a very useful notion inside of Apache Unomi, as they are used as the basis for multiple other objects.
+Conditions may be used as parts of:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Segments</p>
+</li>
+<li>
+<p>Rules</p>
+</li>
+<li>
+<p>Queries</p>
+</li>
+<li>
+<p>Campaigns</p>
+</li>
+<li>
+<p>Goals</p>
+</li>
+<li>
+<p>Profile filters</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>A condition is composed of two basic elements:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>a condition type identifier</p>
+</li>
+<li>
+<p>a list of parameter values for the condition, that can be of any type, and in some cases may include sub-conditions</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>A condition type identifier is a string that contains a unique identifier for a condition type. Example condition types
+may include <code>booleanCondition</code>, <code>eventTypeCondition</code>, <code>eventPropertyCondition</code>, and so on. Plugins may implement new
+condition types that may implement any logic that may be needed. The parameter values are simply lists of objects that
+may be used to configure the condition. In the case of a <code>booleanCondition</code> for example one of the parameter values will
+be an <code>operator</code> that will contain values such as <code>and</code> or <code>or</code> and a second parameter value called <code>subConditions</code>
+that contains a list of conditions to evaluate with that operator. The result of a condition is always a boolean
+value of true or false.</p>
+</div>
+<div class="paragraph">
+<p>Apache Unomi provides quite a lot of built-in condition types, including boolean types that make it possible to
+compose conditions using operators such as <code>and</code>, <code>or</code> or <code>not</code>. Composition is an essential element of building more
+complex conditions.</p>
+</div>
+<div class="paragraph">
+<p>Here is an example of a complex condition:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-json" data-lang="json">{
+  "condition": {
+    "type": "booleanCondition",
+    "parameterValues": {
+      "operator":"or",
+      "subConditions":[
+        {
+          "type": "eventTypeCondition",
+          "parameterValues": {
+            "eventTypeId": "sessionCreated"
+          }
+        },
+        {
+          "type": "eventTypeCondition",
+          "parameterValues": {
+            "eventTypeId": "sessionReassigned"
+          }
+        }
+      ]
+    }
+  }
+}</code></pre>
+</div>
+</div>
 <div class="paragraph">
-<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>
+<p>As we can see in the above example we use the boolean <code>or</code> condition to check if the event type is of type <code>sessionCreated</code>
+or <code>sessionReassigned</code>.</p>
+</div>
+<div class="paragraph">
+<p>For a more complete list of available conditions, see the <a href="#_built_in_conditions">Built-in conditions</a> reference section.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_rules">2.7. Rules</h3>
+<div class="imageblock">
+<div class="content">
+<img src="images/unomi-rule-engine.png" alt="Unomi Rule Engine">
+</div>
+</div>
+<div class="paragraph">
+<p>Apache Unomi has a built-in rule engine that is one of the most important components of its architecture. Every time
+an event is received by the server, it is evaluated against all the rules and the ones matching the incoming event will
+be executed. You can think of a rule as a structure that looks like this:</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>when
+    conditions
+then
+    actions</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Basically when a rule is evaluated, all the conditions in the <code>when</code> part are evaluated and if the result matches
+(meaning it evaluates to <code>true</code>) then the actions will be executed in sequence.</p>
+</div>
+<div class="paragraph">
+<p>The real power of Apache Unomi comes from the fact that <code>conditions</code> and <code>actions</code> are fully pluggeable and that plugins
+may implement new conditions and/or actions to perform any task. You can imagine conditions checking incoming event data
+against third-party systems or even against authentication systesm, and actions actually pulling or pushing data to third-party
+systems.</p>
+</div>
+<div class="paragraph">
+<p>For example the Salesforce CRM connector is simply a set of actions that pull and push data into the CRM. It is then
+just a matter of setting up the proper rules with the proper conditions to determine when and how the data will be
+pulled or pushed into the third-party system.</p>
+</div>
+<div class="sect3">
+<h4 id="_actions">2.7.1. Actions</h4>
+<div class="paragraph">
+<p>Actions are executed by rules in a sequence, and an action is only executed once the previous action has finished
+executing. If an action generates an exception, it will be logged and the execution sequence will continue unless in the
+case of a Runtime exception (such as a NullPointerException).</p>
+</div>
+<div class="paragraph">
+<p>Actions are implemented as Java classes, and as such may perform any kind of tasks that may include calling web hooks,
+setting profile properties, extracting data from the incoming request (such as resolving location from an IP address),
+or even pulling and/or pushing data to third-party systems such as a CRM server.</p>
+</div>
+<div class="paragraph">
+<p>Apache Unomi also comes with built-in actions. You may find the list of built-in actions in the <a href="#_built_in_actions">Built-in actions</a> section.</p>
+</div>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_request_flow">2.5. Request flow</h3>
+<h3 id="_request_flow">2.8. Request flow</h3>
 <div class="paragraph">
 <p>Here is an overview of how Unomi processes incoming requests to the <code>ContextServlet</code>.</p>
 </div>
@@ -415,58 +691,467 @@ make sure you are using the proper versi
 </div>
 </div>
 </div>
-<div class="sect1">
-<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="sect1">
+<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>
+</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.
+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">
+<h4 id="_running_unomi">3.1.2. Running Unomi</h4>
+<div class="sect4">
+<h5 id="_start_unomi">Start Unomi</h5>
+<div class="paragraph">
+<p>Start Unomi according to the <a href="#_5-min-quickstart">5 minute quick start</a> or by compiling using the building <a href="building-and-deploying.html#Deploying_the_generated_package">instructions</a>. Once you have Karaf running,
+ you should wait until you see the following messages on the Karaf console:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>Initializing user list service endpoint...
+Initializing geonames service endpoint...
+Initializing segment service endpoint...
+Initializing scoring service endpoint...
+Initializing campaigns service endpoint...
+Initializing rule service endpoint...
+Initializing profile service endpoint...
+Initializing cluster service endpoint...</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<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>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_recipes">3.2. Recipes</h3>
+<div class="sect3">
+<h4 id="_introduction">3.2.1. Introduction</h4>
+<div class="paragraph">
+<p>In this section of the documentation we provide quick recipes focused on helping you achieve a specific result with
+Apache Unomi.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_how_to_read_a_profile">3.2.2. How to read a profile</h4>
+<div class="paragraph">
+<p>The simplest way to retrieve profile data for the current profile is to simply send a request to the /context.json
+endpoint. However you will need to send a body along with that request. Here&#8217;s an example:</p>
+</div>
+<div class="paragraph">
+<p>Here is an example that will retrieve all the session and profile properties.</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"
+    },
+    "requiredProfileProperties":["*"],
+    "requiredSessionProperties":["*"],
+    "requireSegments":true
+}
+EOF</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <code>requiredProfileProperties</code> and <code>requiredSessionProperties</code> are properties that take an array of property names
+that should be retrieved. In this case we use the wildcard character '*' to say we want to retrieve all the available
+properties. The structure of the JSON object that you should send is a JSON-serialized version of the <a href="http://unomi.incubator.apache.org/unomi-api/apidocs/org/apache/unomi/api/ContextRequest.html">ContextRequest</a>
+Java class.</p>
+</div>
+<div class="paragraph">
+<p>Note that it is also possible to access a profile&#8217;s data through the /cxs/profiles/ endpoint but that really should be
+reserved to administrative purposes. All public accesses should always use the /context.json endpoint for consistency
+and security.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_how_to_update_a_profile_from_the_public_internet">3.2.3. How to update a profile from the public internet</h4>
+<div class="paragraph">
+<p>Before we get into how to update a profile directly from a request coming from the public internet, we&#8217;ll quickly talk
+first about how NOT to do it, because we often see users using the following anti-patterns.</p>
+</div>
+<div class="sect4">
+<h5 id="_how_not_to_update_a_profile_from_the_public_internet">How NOT to update a profile from the public internet</h5>
+<div class="paragraph">
+<p>Please avoid using the /cxs/profile endpoint. This endpoint was initially the only way to update a profile but it has
+multiple issues:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>it requires authenticated access. The temptation can be great to use this endpoint because it is simple to access
+but the risk is that developers might include the credentials to access it in non-secure parts of code such as
+client-side code. Since there is no difference between this endpoint and any other administration-focused endpoints,
+attackers could easily re-use stolen credentials to wreak havock on the whole platform.</p>
+</li>
+<li>
+<p>No history of profile modifications is kept: this can be a problem for multiple reasons: you might want to keep an
+trail of profile modifications, or even a history of profile values in case you want to understand how a profile
+property was modified.</p>
+</li>
+<li>
+<p>Even when protected using some kind of proxy, potentially the whole profile properties might be modified, including
+ones that you might not want to be overriden.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_recommended_ways_to_update_a_profile">Recommended ways to update a profile</h5>
+<div class="paragraph">
+<p>Instead you can use the following solutions to update profiles:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>(Preferred) Use you own custom event(s) to send data you want to be inserted in a profile, and use rules to map the
+event data to the profile. This is simpler than it sounds, as usually all it requires is setting up a simple rule and
+you&#8217;re ready to update profiles using events. This is also the safest way to update a profile because if you design your
+events to be as specific as possible to your needs, only the data that you specified will be copied to the profile,
+making sure that even in the case an attacker tries to send more data using your custom event it will simply be ignored.</p>
+</li>
+<li>
+<p>Use the protected built-in "updateProperties" event. This event is designed to be used for administrative purposes
+only. Again, prefer the custom events solution because as this is a protected event it will require sending the Unomi
+key as a request header, and as Unomi only supports a single key for the moment it could be problematic if the key is
+intercepted. But at least by using an event you will get the benefits of auditing and historical property modification
+tracing.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Let&#8217;s go into more detail about the preferred way to update a profile. Let&#8217;s consider the following example of a rule:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl -X POST http://localhost:8181/cxs/rules \
+--user karaf:karaf \
+-H "Content-Type: application/json" \
+-d @- &lt;&lt;'EOF'
+{
+  "metadata": {
+    "id": "setContactInfo",
+    "name": "Copy the received contact info to the current profile",
+    "description": "Copies the contact info received in a custom event called 'contactInfoSubmitted' to the current profile"
+  },
+  "raiseEventOnlyOnceForSession": false,
+  "condition": {
+    "type": "eventTypeCondition",
+    "parameterValues": {
+      "eventTypeId": "contactInfoSubmitted"
+    }
+  },
+  "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>What this rule does is that it listen for a custom event (events don&#8217;t need any registration, you can simply start
+sending them to Apache Unomi whenever you like) of type 'contactInfoSubmitted' and it will search for properties called
+'firstName', 'lastName' and 'email' and copy them over to the profile with corresponding property names. You could of
+course change any of the property names to find your needs. For example you might want to prefix the profile properties
+with the source of the event, such as 'mobileApp:firstName'.</p>
+</div>
+<div class="paragraph">
+<p>You could then simply send the <code>contactInfoSubmitted</code> event using a request similar to this one:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl -X POST http://localhost:8181/eventcollector \
+-H "Content-Type: application/json" \
+-d @- &lt;&lt;'EOF'
+{
+    "sessionId" : "1234",
+    "events":[
+        {
+            "eventType":"contactInfoSubmitted",
+            "scope": "example",
+            "source":{
+                "itemType": "site",
+                "scope":"example",
+                "itemId": "mysite"
+            },
+            "target":{
+                "itemType":"form",
+                "scope":"example",
+                "itemId":"contactForm",
+            },
+            "properties" : {
+              "firstName" : "John",
+              "lastName" : "Doe",
+              "email" : "john.doe@acme.com"
+            }
+        }
+    ]
+}
+EOF</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_how_to_search_for_profile_events">3.2.4. How to search for profile events</h4>
+<div class="paragraph">
+<p>Sometimes you want to retrieve events for a known profile. You will need to provide a query in the body of the request
+that looks something like this (and <a href="https://unomi.incubator.apache.org/rest-api-doc/#1768188821">documentation is available in the REST API</a>) :</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl -X POST http://localhost:8181/cxs/event/search \
+--user karaf:karaf \
+-H "Content-Type: application/json" \
+-d @- &lt;&lt;'EOF'
+{ "offset" : 0,
+  "limit" : 20,
+  "condition" : {
+    "type": "eventPropertyCondition",
+    "parameterValues" : {
+      "propertyName" : "profileId",
+      "comparisonOperator" : "equals",
+      "propertyValue" : "PROFILE_ID"
+    }
+  }
+}
+EOF</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where PROFILE_ID is a profile identifier. This will indeed retrieve all the events for a given profile.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_how_to_create_a_new_rule">3.2.5. How to create a new rule</h4>
+<div class="paragraph">
+<p>There are basically two ways to create a new rule :</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Using the REST API</p>
+</li>
+<li>
+<p>Packaging it as a predefined rule in a plugin</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>In both cases the JSON structure for the rule will be exactly the same, and in most scenarios it will be more
+interesting to use the REST API to create and manipulate rules, as they don&#8217;t require any development or deployments
+on the Apache Unomi server.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl -X POST http://localhost:8181/cxs/rules \
+--user karaf:karaf \
+-H "Content-Type: application/json" \
+-d @- &lt;&lt;'EOF'
+{
+  "metadata": {
+    "id": "exampleEventCopy",
+    "name": "Example Copy Event to Profile",
+    "description": "Copy event properties to profile properties"
+  },
+  "condition": {
+      "type": "eventTypeCondition",
+      "parameterValues": {
+        "eventTypeId" : "myEvent"
+      }
+  },
+  "actions": [
+    {
+      "parameterValues": {
+      },
+      "type": "allEventToProfilePropertiesAction"
+    }
+  ]
+}
+EOF</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above rule will be executed if the incoming event is of type <code>myEvent</code> and will simply copy all the properties
+contained in the event to the current profile.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_how_to_search_for_profiles">3.2.6. How to search for profiles</h4>
+<div class="paragraph">
+<p>In order to search for profiles you will have to use the /cxs/profiles/search endpoint that requires a Query JSON
+structure. Here&#8217;s an example of a profile search with a Query object:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl -X POST http://localhost:8181/cxs/rules \
+--user karaf:karaf \
+-H "Content-Type: application/json" \
+-d @- &lt;&lt;'EOF'
+{
+  "text" : "unomi",
+  "offset" : 0,
+  "limit" : 10,
+  "sortby" : "properties.lastName:asc,properties.firstName:desc",
+  "condition" : {
+    "type" : "booleanCondition",
+    "parameterValues" : {
+      "operator" : "and",
+      "subConditions" : [
+        {
+          "type": "profilePropertyCondition",
+          "parameterValues": {
+            "propertyName": "properties.leadAssignedTo",
+            "comparisonOperator": "exists"
+          }
+        },
+        {
+          "type": "profilePropertyCondition",
+          "parameterValues": {
+            "propertyName": "properties.lastName",
+            "comparisonOperator": "exists"
+          }
+        },
+      ]
+    }
+  }
+}
+EOF</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>In the above example, you search for all the profiles that have the <code>leadAssignedTo</code> and <code>lastName</code> properties and that
+have the <code>unomi</code> value anywhere in their profile property values. You are also specifying that you only want 10 results
+beginning at offset 0. The results will be also sorted in alphabetical order for the <code>lastName</code> property value, and then
+by reverse alphabetical order for the <code>firstName</code> property value.</p>
+</div>
+<div class="paragraph">
+<p>As you can see, queries can be quite complex. Please remember that the more complex the more resources it will consume
+on the server and potentially this could affect performance.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_getting_updating_consents">3.2.7. Getting / updating consents</h4>
+<div class="paragraph">
+<p>You can find information on how to retrieve or create/update consents in the <a href="#_consent_api">Consent API</a> section.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_how_to_send_a_login_event_to_unomi">3.2.8. How to send a login event to Unomi</h4>
+<div class="paragraph">
+<p>Tracking logins must be done carefully with Unomi. A login event is considered a "privileged" event and therefore for
+not be initiated from the public internet. Ideally user authentication should always be validated by a trusted third-
+party even if it is a well-known social platform such as Facebook or Twitter. Basically what should NEVER be done:</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Login to a social platform</p>
+</li>
+<li>
+<p>Call back to the originating page</p>
+</li>
+<li>
+<p>Send a login event to Unomi from the page originating the login in step 1</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>The problem with this, is that any attacker could simply directly call step 3 without any kind of security. Instead the
+flow should look something like this:</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Login to a social platform</p>
+</li>
+<li>
+<p>Call back to a special secured system that performs an server-to-server call to send the login event to Apache
+Unomi using the Unomi key.</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>For simplicity reasons, in our login example, the first method is used, but it really should never be done like this
+in production because of the aforementioned security issues. The second method, although a little more involved, is
+much preferred.</p>
+</div>
 <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>When sending a login event, you can setup a rule that can check a profile property to see if profiles can be merged on an
+universal identifier such as an email address.</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.
-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>
+<p>In our login sample we provide an example of such a rule. You can find it here:</p>
 </div>
+<div class="paragraph">
+<p><a href="https://github.com/apache/unomi/blob/master/samples/login-integration/src/main/resources/META-INF/cxs/rules/exampleLogin.json" class="bare">https://github.com/apache/unomi/blob/master/samples/login-integration/src/main/resources/META-INF/cxs/rules/exampleLogin.json</a></p>
 </div>
-<div class="sect3">
-<h4 id="_running_unomi">3.1.2. Running Unomi</h4>
-<div class="sect4">
-<h5 id="_start_unomi">Start Unomi</h5>
 <div class="paragraph">
-<p>Start Unomi according to the <a href="#_5-min-quickstart">5 minute quick start</a> or by compiling using the building <a href="building-and-deploying.html#Deploying_the_generated_package">instructions</a>. Once you have Karaf running,
- you should wait until you see the following messages on the Karaf console:</p>
+<p>As you can see in this rule, we call an action called :</p>
 </div>
-<div class="listingblock">
+<div class="literalblock">
 <div class="content">
-<pre class="highlight"><code>Initializing user list service endpoint...
-Initializing geonames service endpoint...
-Initializing segment service endpoint...
-Initializing scoring service endpoint...
-Initializing campaigns service endpoint...
-Initializing rule service endpoint...
-Initializing profile service endpoint...
-Initializing cluster service endpoint...</code></pre>
-</div>
+<pre>mergeProfilesOnPropertyAction</pre>
 </div>
-<div class="paragraph">
-<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>
+<p>with as a parameter value the name of the property on which to perform the merge (the email). What this means is that
+upon successful login using an email, Unomi will look for other profiles that have the same email and merge them into
+a single profile. Because of the merge, this should only be done for authenticated profiles, otherwise this could be a
+security issue since it could be a way to load data from other profiles by merging their data !</p>
 </div>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_request_examples">3.2. Request examples</h3>
+<h3 id="_request_examples">3.3. Request examples</h3>
 <div class="sect3">
-<h4 id="_retrieving_your_first_context">3.2.1. Retrieving your first context</h4>
+<h4 id="_retrieving_your_first_context">3.3.1. Retrieving your first context</h4>
 <div class="paragraph">
 <p>You can retrieve a context using curl like this :</p>
 </div>
@@ -482,7 +1167,7 @@ events using the cxs.collectEvents() fun
 </div>
 </div>
 <div class="sect3">
-<h4 id="_retrieving_a_context_as_a_json_object">3.2.2. Retrieving a context as a JSON object.</h4>
+<h4 id="_retrieving_a_context_as_a_json_object">3.3.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>
@@ -493,7 +1178,7 @@ events using the cxs.collectEvents() fun
 </div>
 </div>
 <div class="sect3">
-<h4 id="_accessing_profile_properties_in_a_context">3.2.3. Accessing profile properties in a context</h4>
+<h4 id="_accessing_profile_properties_in_a_context">3.3.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
@@ -528,7 +1213,7 @@ Java class.</p>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_sending_events_using_the_context_servlet">3.2.4. Sending events using the context servlet</h4>
+<h4 id="_sending_events_using_the_context_servlet">3.3.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>
@@ -577,17 +1262,18 @@ to send events in a network optimal way
 </div>
 </div>
 <div class="sect3">
-<h4 id="_sending_events_using_the_eventcollector_servlet">3.2.5. Sending events using the eventcollector servlet</h4>
+<h4 id="_sending_events_using_the_eventcollector_servlet">3.3.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 -X POST http://localhost:8181/context.json?sessionId=1234 \
+<pre class="highlight"><code>curl -X POST http://localhost:8181/eventcollector \
 -H "Content-Type: application/json" \
 -d @- &lt;&lt;'EOF'
 {
+    "sessionId" : "1234",
     "events":[
         {
             "eventType":"view",
@@ -619,7 +1305,7 @@ to send additional events.</p>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_where_to_go_from_here">3.2.6. Where to go from here</h4>
+<h4 id="_where_to_go_from_here">3.3.6. Where to go from here</h4>
 <div class="ulist">
 <ul>
 <li>
@@ -636,13 +1322,13 @@ to send additional events.</p>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_web_tracker">3.3. Web Tracker</h3>
+<h3 id="_web_tracker">3.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">3.3.1. Getting started</h4>
+<h4 id="_getting_started">3.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>
@@ -669,14 +1355,14 @@ All methods can be used on <code>unomiTr
 </div>
 </div>
 <div class="sect3">
-<h4 id="_how_to_contribute">3.3.2. How to contribute</h4>
+<h4 id="_how_to_contribute">3.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">3.3.3. Tracking page views</h4>
+<h4 id="_tracking_page_views">3.4.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
@@ -763,7 +1449,7 @@ categories).</p>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_tracking_form_submissions">3.3.4. Tracking form submissions</h4>
+<h4 id="_tracking_form_submissions">3.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
@@ -1035,9 +1721,9 @@ cef09b89-6b99-4e4f-a99c-a4159a66b42b|for
 </div>
 </div>
 <div class="sect2">
-<h3 id="_configuration">3.4. Configuration</h3>
+<h3 id="_configuration">3.5. Configuration</h3>
 <div class="sect3">
-<h4 id="_centralized_configuration">3.4.1. Centralized configuration</h4>
+<h4 id="_centralized_configuration">3.5.1. Centralized configuration</h4>
 <div class="paragraph">
 <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>
@@ -1063,7 +1749,7 @@ the values in the <code>$MY_KARAF_HOME/e
 </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>
+<h4 id="_changing_the_default_configuration_using_environment_variables_i_e_docker_configuration">3.5.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>
@@ -1081,7 +1767,7 @@ 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>
+<h4 id="_changing_the_default_configuration_using_property_files">3.5.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>
@@ -1128,7 +1814,7 @@ org.apache.unomi.elasticsearch.addresses
 </div>
 </div>
 <div class="sect3">
-<h4 id="_secured_events_configuration">3.4.4. Secured events configuration</h4>
+<h4 id="_secured_events_configuration">3.5.4. Secured events configuration</h4>
 <div class="paragraph">
 <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>
@@ -1220,7 +1906,7 @@ thirdparty.provider1.allowedEvents=login
 </div>
 </div>
 <div class="sect3">
-<h4 id="_installing_the_maxmind_geoiplite2_ip_lookup_database">3.4.5. Installing the MaxMind GeoIPLite2 IP lookup database</h4>
+<h4 id="_installing_the_maxmind_geoiplite2_ip_lookup_database">3.5.5. Installing the MaxMind GeoIPLite2 IP lookup database</h4>
 <div class="paragraph">
 <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 :
@@ -1231,7 +1917,7 @@ The GeoLite2 database can be downloaded
 </div>
 </div>
 <div class="sect3">
-<h4 id="_installing_geonames_database">3.4.6. Installing Geonames database</h4>
+<h4 id="_installing_geonames_database">3.5.6. Installing Geonames database</h4>
 <div class="paragraph">
 <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>
@@ -1249,7 +1935,7 @@ At the end, you should have about 4 mill
 </div>
 </div>
 <div class="sect3">
-<h4 id="_rest_api_security">3.4.7. REST API Security</h4>
+<h4 id="_rest_api_security">3.5.7. REST API Security</h4>
 <div class="paragraph">
 <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>
@@ -1282,7 +1968,7 @@ org.ops4j.pax.web.ssl.keypassword=${env:
 </div>
 </div>
 <div class="sect3">
-<h4 id="_automatic_profile_merging">3.4.8. Automatic profile merging</h4>
+<h4 id="_automatic_profile_merging">3.5.8. Automatic profile merging</h4>
 <div class="paragraph">
 <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
@@ -1301,7 +1987,7 @@ Upon sending one of the events, all matc
 </div>
 </div>
 <div class="sect3">
-<h4 id="_securing_a_production_environment">3.4.9. Securing a production environment</h4>
+<h4 id="_securing_a_production_environment">3.5.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>
@@ -1411,7 +2097,7 @@ a proxy, and use it to filter any commun
 </div>
 </div>
 <div class="sect3">
-<h4 id="_integrating_with_an_apache_http_web_server">3.4.10. Integrating with an Apache HTTP web server</h4>
+<h4 id="_integrating_with_an_apache_http_web_server">3.5.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>
@@ -1509,7 +2195,7 @@ ProxyPassReverse / http://localhost:8181
 </div>
 </div>
 <div class="sect3">
-<h4 id="_changing_the_default_tracking_location">3.4.11. Changing the default tracking location</h4>
+<h4 id="_changing_the_default_tracking_location">3.5.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 modify the default location settings using the
@@ -1537,7 +2223,7 @@ org.apache.unomi.ip.default.longitude=${
 </div>
 </div>
 <div class="sect3">
-<h4 id="_apache_karaf_ssh_console">3.4.12. Apache Karaf SSH Console</h4>
+<h4 id="_apache_karaf_ssh_console">3.5.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>
@@ -1553,7 +2239,7 @@ shell commands in the "Shell commands" s
 </div>
 </div>
 <div class="sect3">
-<h4 id="_elasticsearch_x_pack_support">3.4.13. ElasticSearch X-Pack Support</h4>
+<h4 id="_elasticsearch_x_pack_support">3.5.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>
@@ -1648,7 +2334,7 @@ as in the following example:</p>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_useful_apache_unomi_urls">3.5. Useful Apache Unomi URLs</h3>
+<h3 id="_useful_apache_unomi_urls">3.6. 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>
@@ -1745,6 +2431,51 @@ where PROFILE_ID is a profile identifier
 </tbody>
 </table>
 </div>
+<div class="sect2">
+<h3 id="_how_profile_tracking_works">3.7. 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">3.7.1. Steps</h4>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>A visitor comes to a website</p>
+</li>
+<li>
+<p>The web server resolves a previous request session ID if it exists, or if it doesn&#8217;t it create a new sessionID</p>
+</li>
+<li>
+<p>A request to Apache Unomi&#8217;s /context.json servlet is made passing the web server session ID as a query parameter</p>
+</li>
+<li>
+<p>Unomi uses the sessionID and tries to load an existing session, if none is found a new session is created with the
+ID passed by the web server</p>
+</li>
+<li>
+<p>If a session was found, the profile ID is extracted from the session and if it not found, Unomi looks for a cookie
+called <code>context-profile-id</code> to read the profileID. If no profileID is found or if the session didn&#8217;t exist, a new
+profile ID is created by Apache Unomi</p>
+</li>
+<li>
+<p>If the profile ID existed, the corresponding profile is loaded by Apache Unomi, otherwise a new profile is created</p>
+</li>
+<li>
+<p>If events were passed along with the request to the context.json endpoint, they are processed against the profile</p>
+</li>
+<li>
+<p>The updated profile is sent back as a response to the context.json request. Along with the response</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>It is important to note that the profileID is always server-generated. Injecting a custom cookie with a non-valid
+profile ID will result in failure to load the profile. Profile ID are UUIDs, which make them (pretty) safe from brute-
+forcing.</p>
+</div>
+</div>
+</div>
 </div>
 </div>
 <div class="sect1">
@@ -1970,10 +2701,108 @@ EOF</code></pre>
 </div>
 </div>
 <div class="sect1">
-<h2 id="_cluster_setup">5. Cluster setup</h2>
+<h2 id="_privacy_management">5. 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="sect3">
+<h4 id="_setting_up_access_to_the_privacy_endpoint">5.1. Setting up access to the privacy endpoint</h4>
+<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>
+</div>
+<div class="paragraph">
+<p>So in effect it should usually be proxied so that public internet users can access the endpoint but the proxy should
+also check if the profile ID wasn&#8217;t manipulated in some way.</p>
+</div>
+<div class="paragraph">
+<p>Apache Unomi doesn&#8217;t provide (for the moment) such a proxy, but basically it should do the following:</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>check for potential attack activity (could be based on IDS policies or even rate detection), and at the minimum check
+that the profile ID cookie seems authentic (for example by checking that it is often coming from the same IP or the same
+geographic location)</p>
+</li>
+<li>
+<p>proxy to /cxs/privacy</p>
+</li>
+</ol>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_anonymizing_a_profile">5.2. Anonymizing a profile</h4>
+<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>
+</div>
+<div class="paragraph">
+<p>Here&#8217;s an example of a request to anonymize a profile:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl -X POST http://localhost:8181/cxs/profiles/{profileID}/anonymize?scope=ASCOPE</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>{profileID}</code> must be replaced by the actual identifier of a profile
+and <code>ASCOPE</code> must be replaced by a scope identifier.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_downloading_profile_data">5.3. Downloading profile data</h4>
+<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>
+</div>
+<div class="paragraph">
+<p>Warning: this operation can also be sensitive so it would be better to protected with a proxy that can perform some
+validation on the requests to make sure no one is trying to download a profile using some kind of "guessing" of profile
+IDs.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl -X GET http://localhost:8181/client/myprofile.[json,csv,yaml,text] \
+--cookie "context-profile-id=PROFILE-ID"</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>PROFILE-ID</code> is the profile identifier for which to download the profile.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_deleting_a_profile">5.4. Deleting a profile</h4>
+<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
+session data will also be detached from the current profile and anonymized.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl -X DELETE http://localhost:8181/cxs/profiles/{profileID}?withData=false --user karaf:karaf</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>{profileID}</code> must be replaced by the actual identifier of a profile
+and the <code>withData</code> specifies whether the data associated with the profile must be anonymized or not</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_related">5.5. Related</h4>
+<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>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_cluster_setup">6. Cluster setup</h2>
 <div class="sectionbody">
 <div class="sect2">
-<h3 id="_cluster_setup_2">5.1. Cluster setup</h3>
+<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.</p>
 </div>
@@ -2014,10 +2843,201 @@ placeholders in the hazelcast.xml file i
 </div>
 </div>
 <div class="sect1">
-<h2 id="_integration_samples">6. Integration samples</h2>
+<h2 id="_reference">7. Reference</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="_built_in_conditions">7.1. Built-in conditions</h3>
+<div class="paragraph">
+<p>Apache Unomi comes with an extensive collection of built-in conditions. Instead of detailing them one by one you will
+find here an overview of what a JSON condition descriptor looks like:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-json" data-lang="json">{
+  "metadata": {
+    "id": "booleanCondition",
+    "name": "booleanCondition",
+    "description": "",
+    "systemTags": [
+      "profileTags",
+      "logical",
+      "condition",
+      "profileCondition",
+      "eventCondition",
+      "sessionCondition",
+      "sourceEventCondition"
+    ],
+    "readOnly": true
+  },
+  "conditionEvaluator": "booleanConditionEvaluator",
+  "queryBuilder": "booleanConditionESQueryBuilder",
+  "parameters": [
+    {
+      "id": "operator",
+      "type": "String",
+      "multivalued": false,
+      "defaultValue": "and"
+    },
+    {
+      "id": "subConditions",
+      "type": "Condition",
+      "multivalued": true
+    }
+  ]
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Note that conditions have two important identifiers:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>conditionEvaluator</p>
+</li>
+<li>
+<p>queryBuilder</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>This is because conditions can either be used to build queries or to evaluate a condition in real time. When implementing
+a new condition type, both implementations much be provided. Here&#8217;s an example an OSGi Blueprint registration for the
+above condition descriptor:</p>
+</div>
+<div class="paragraph">
+<p>From <a href="https://github.com/apache/unomi/blob/master/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml" class="bare">https://github.com/apache/unomi/blob/master/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml</a></p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-xml" data-lang="xml">...
+    &lt;service
+            interface="org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder"&gt;
+        &lt;service-properties&gt;
+            &lt;entry key="queryBuilderId" value="booleanConditionESQueryBuilder"/&gt;
+        &lt;/service-properties&gt;
+        &lt;bean class="org.apache.unomi.plugins.baseplugin.conditions.BooleanConditionESQueryBuilder"/&gt;
+    &lt;/service&gt;
+...
+    &lt;!-- Condition evaluators --&gt;
+    &lt;service interface="org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator"&gt;
+        &lt;service-properties&gt;
+            &lt;entry key="conditionEvaluatorId" value="booleanConditionEvaluator"/&gt;
+        &lt;/service-properties&gt;
+        &lt;bean class="org.apache.unomi.plugins.baseplugin.conditions.BooleanConditionEvaluator"/&gt;
+    &lt;/service&gt;
+...</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>As you can see two Java classes are used to build a single condition. You don&#8217;t need to understand all these details in
+order to use conditions, but this might be interesting to know if you&#8217;re interested in building your own condition
+implementations. For more details on building your own custom plugins/extensions, please refer to the corresponding
+sections.</p>
+</div>
+<div class="sect3">
+<h4 id="_existing_condition_descriptors">7.1.1. Existing condition descriptors</h4>
+<div class="paragraph">
+<p>Here is a non-exhaustive list of conditions built into Apache Unomi. Feel free to browse the source code if you want to
+discover more. But the list below should get you started with the most useful conditions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><a href="https://github.com/apache/unomi/tree/master/plugins/baseplugin/src/main/resources/META-INF/cxs/conditions" class="bare">https://github.com/apache/unomi/tree/master/plugins/baseplugin/src/main/resources/META-INF/cxs/conditions</a></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Of course it is also possible to build your own custom conditions by developing custom Unomi plugins/extensions.</p>
+</div>
+<div class="paragraph">
+<p>You will also note that some conditions can re-use a <code>parentCondition</code>. This is a way to inherit from another condition
+type to make them more specific.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_built_in_actions">7.2. Built-in actions</h3>
+<div class="paragraph">
+<p>Unomi comes with quite a lot of built-in actions. Instead of detailing them one by one you will find here an overview of
+what an action descriptor looks like:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-json" data-lang="json">{
+  "metadata": {
+    "id": "UNIQUE_IDENTIFIER_STRING",
+    "name": "DISPLAYABLE_ACTION_NAME",
+    "description": "DISPLAYABLE_ACTION_DESCRIPTION",
+    "systemTags": [
+      "profileTags",
+      "event",
+      "availableToEndUser",
+      "allowMultipleInstances"
+    ],
+    "readOnly": true
+  },
+  "actionExecutor": "ACTION_EXECUTOR_ID",
+  "parameters": [
+     ... parameters specific to each action ...
+  ]
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The ACTION_EXECUTOR_ID points to a OSGi Blueprint parameter that is defined when implementing the action in a plugin.
+Here&#8217;s an example of such a registration:</p>
+</div>
+<div class="paragraph">
+<p>From <a href="https://github.com/apache/unomi/blob/master/plugins/mail/src/main/resources/OSGI-INF/blueprint/blueprint.xml" class="bare">https://github.com/apache/unomi/blob/master/plugins/mail/src/main/resources/OSGI-INF/blueprint/blueprint.xml</a></p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-xml" data-lang="xml">    &lt;bean id="sendMailActionImpl" class="org.apache.unomi.plugins.mail.actions.SendMailAction"&gt;
+       &lt;!-- ... bean properties ... --&gt;
+    &lt;/bean&gt;
+    &lt;service id="sendMailAction" ref="sendMailActionImpl" interface="org.apache.unomi.api.actions.ActionExecutor"&gt;
+        &lt;service-properties&gt;
+            &lt;entry key="actionExecutorId" value="sendMail"/&gt;
+        &lt;/service-properties&gt;
+    &lt;/service&gt;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>In the above example the ACTION_EXECUTOR_ID is <code>sendMail</code></p>
+</div>
+<div class="sect3">
+<h4 id="_existing_actions_descriptors">7.2.1. Existing actions descriptors</h4>
+<div class="paragraph">
+<p>Here is a non-exhaustive list of actions built into Apache Unomi. Feel free to browse the source code if you want to
+discover more. But the list below should get you started with the most useful actions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><a href="https://github.com/apache/unomi/tree/master/plugins/baseplugin/src/main/resources/META-INF/cxs/actions" class="bare">https://github.com/apache/unomi/tree/master/plugins/baseplugin/src/main/resources/META-INF/cxs/actions</a></p>
+</li>
+<li>
+<p><a href="https://github.com/apache/unomi/tree/master/plugins/request/src/main/resources/META-INF/cxs/actions" class="bare">https://github.com/apache/unomi/tree/master/plugins/request/src/main/resources/META-INF/cxs/actions</a></p>
+</li>
+<li>
+<p><a href="https://github.com/apache/unomi/tree/master/plugins/mail/src/main/resources/META-INF/cxs/actions" class="bare">https://github.com/apache/unomi/tree/master/plugins/mail/src/main/resources/META-INF/cxs/actions</a></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Of course it is also possible to build your own custom actions by developing custom Unomi plugins/extensions.</p>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_integration_samples">8. Integration samples</h2>
 <div class="sectionbody">
 <div class="sect2">
-<h3 id="_samples">6.1. Samples</h3>
+<h3 id="_samples">8.1. Samples</h3>
 <div class="paragraph">
 <p>Apache Unomi provides the following samples:</p>
 </div>
@@ -2033,12 +3053,12 @@ placeholders in the hazelcast.xml file i
 </div>
 </div>
 <div class="sect2">
-<h3 id="_login_sample">6.2. Login sample</h3>
+<h3 id="_login_sample">8.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">6.2.1. Warning !</h4>
+<h4 id="_warning">8.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>
@@ -2049,7 +3069,7 @@ only be sent if the user has authenticat
 </div>
 </div>
 <div class="sect3">
-<h4 id="_installing_the_samples">6.2.2. Installing the samples</h4>
+<h4 id="_installing_the_samples">8.2.2. Installing the samples</h4>
 <div class="paragraph">
 <p>Login into the Unomi Karaf SSH shell using something like this :</p>
 </div>
@@ -2096,9 +3116,9 @@ only be sent if the user has authenticat
 </div>
 </div>
 <div class="sect2">
-<h3 id="_twitter_sample">6.3. Twitter sample</h3>
+<h3 id="_twitter_sample">8.3. Twitter sample</h3>
 <div class="sect3">
-<h4 id="_overview">6.3.1. Overview</h4>
+<h4 id="_overview">8.3.1. Overview</h4>
 <div class="paragraph">

[... 525 lines stripped ...]