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....@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 ...]

Reply via email to