Modified: unomi/website/manual/latest/index.html URL: http://svn.apache.org/viewvc/unomi/website/manual/latest/index.html?rev=1868532&r1=1868531&r2=1868532&view=diff ============================================================================== --- unomi/website/manual/latest/index.html (original) +++ unomi/website/manual/latest/index.html Thu Oct 17 05:10:27 2019 @@ -102,156 +102,182 @@ </li> </ul> </li> -<li><a href="#_consent_management">4. Consent management</a> +<li><a href="#_queries_and_aggregations">4. Queries and aggregations</a> <ul class="sectlevel2"> -<li><a href="#_consent_api">4.1. Consent API</a> +<li><a href="#_query_counts">4.1. Query counts</a></li> +<li><a href="#_metrics">4.2. Metrics</a></li> +<li><a href="#_aggregations">4.3. Aggregations</a> <ul class="sectlevel3"> -<li><a href="#_profiles_with_consents">4.1.1. Profiles with consents</a></li> -<li><a href="#_consent_type_definitions">4.1.2. Consent type definitions</a></li> -<li><a href="#_creating_update_a_visitor_consent">4.1.3. Creating / update a visitor consent</a></li> -<li><a href="#_how_it_works_internally">4.1.4. How it works (internally)</a></li> +<li><a href="#_aggregation_types">4.3.1. Aggregation types</a></li> </ul> </li> </ul> </li> -<li><a href="#_privacy_management">5. Privacy management</a> +<li><a href="#_profile_import_export">5. Profile import & export</a> +<ul class="sectlevel2"> +<li><a href="#_importing_profiles">5.1. Importing profiles</a> +<ul class="sectlevel3"> +<li><a href="#_import_api">5.1.1. Import API</a></li> +</ul> +</li> +<li><a href="#_exporting_profiles">5.2. Exporting profiles</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> +<li><a href="#_export_api">5.2.1. Export API</a></li> </ul> </li> -<li><a href="#_cluster_setup">6. Cluster setup</a> +<li><a href="#_configuration_in_details">5.3. Configuration in details</a></li> +</ul> +</li> +<li><a href="#_consent_management">6. Consent management</a> <ul class="sectlevel2"> -<li><a href="#_cluster_setup_2">6.1. Cluster setup</a></li> +<li><a href="#_consent_api">6.1. Consent API</a> +<ul class="sectlevel3"> +<li><a href="#_profiles_with_consents">6.1.1. Profiles with consents</a></li> +<li><a href="#_consent_type_definitions">6.1.2. Consent type definitions</a></li> +<li><a href="#_creating_update_a_visitor_consent">6.1.3. Creating / update a visitor consent</a></li> +<li><a href="#_how_it_works_internally">6.1.4. How it works (internally)</a></li> </ul> </li> -<li><a href="#_reference">7. Reference</a> +</ul> +</li> +<li><a href="#_privacy_management">7. Privacy management</a> +<ul class="sectlevel3"> +<li><a href="#_setting_up_access_to_the_privacy_endpoint">7.1. Setting up access to the privacy endpoint</a></li> +<li><a href="#_anonymizing_a_profile">7.2. Anonymizing a profile</a></li> +<li><a href="#_downloading_profile_data">7.3. Downloading profile data</a></li> +<li><a href="#_deleting_a_profile">7.4. Deleting a profile</a></li> +<li><a href="#_related">7.5. Related</a></li> +</ul> +</li> +<li><a href="#_cluster_setup">8. Cluster setup</a> <ul class="sectlevel2"> -<li><a href="#_built_in_conditions">7.1. Built-in conditions</a> +<li><a href="#_cluster_setup_2">8.1. Cluster setup</a></li> +</ul> +</li> +<li><a href="#_reference">9. Reference</a> +<ul class="sectlevel2"> +<li><a href="#_built_in_conditions">9.1. Built-in conditions</a> <ul class="sectlevel3"> -<li><a href="#_existing_condition_descriptors">7.1.1. Existing condition descriptors</a></li> +<li><a href="#_existing_condition_descriptors">9.1.1. Existing condition descriptors</a></li> </ul> </li> -<li><a href="#_built_in_actions">7.2. Built-in actions</a> +<li><a href="#_built_in_actions">9.2. Built-in actions</a> <ul class="sectlevel3"> -<li><a href="#_existing_actions_descriptors">7.2.1. Existing actions descriptors</a></li> +<li><a href="#_existing_actions_descriptors">9.2.1. Existing actions descriptors</a></li> </ul> </li> </ul> </li> -<li><a href="#_integration_samples">8. Integration samples</a> +<li><a href="#_integration_samples">10. Integration samples</a> <ul class="sectlevel2"> -<li><a href="#_samples">8.1. Samples</a></li> -<li><a href="#_login_sample">8.2. Login sample</a> +<li><a href="#_samples">10.1. Samples</a></li> +<li><a href="#_login_sample">10.2. Login sample</a> <ul class="sectlevel3"> -<li><a href="#_warning">8.2.1. Warning !</a></li> -<li><a href="#_installing_the_samples">8.2.2. Installing the samples</a></li> +<li><a href="#_warning">10.2.1. Warning !</a></li> +<li><a href="#_installing_the_samples">10.2.2. Installing the samples</a></li> </ul> </li> -<li><a href="#_twitter_sample">8.3. Twitter sample</a> +<li><a href="#_twitter_sample">10.3. Twitter sample</a> <ul class="sectlevel3"> -<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> +<li><a href="#_overview">10.3.1. Overview</a></li> +<li><a href="#_interacting_with_the_context_server">10.3.2. Interacting with the context server</a></li> +<li><a href="#_retrieving_context_information_from_unomi_using_the_context_servlet">10.3.3. Retrieving context information from Unomi using the context servlet</a></li> </ul> </li> -<li><a href="#_example">8.4. Example</a> +<li><a href="#_example">10.4. Example</a> <ul class="sectlevel3"> -<li><a href="#_html_page">8.4.1. HTML page</a></li> -<li><a href="#_javascript">8.4.2. Javascript</a></li> +<li><a href="#_html_page">10.4.1. HTML page</a></li> +<li><a href="#_javascript">10.4.2. Javascript</a></li> </ul> </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> +<li><a href="#_conclusion">10.5. Conclusion</a></li> +<li><a href="#_annex">10.6. Annex</a></li> +<li><a href="#_weather_update_sample">10.7. Weather update sample</a></li> </ul> </li> -<li><a href="#_connectors">9. Connectors</a> +<li><a href="#_connectors">11. Connectors</a> <ul class="sectlevel2"> -<li><a href="#_connectors_2">9.1. Connectors</a> +<li><a href="#_connectors_2">11.1. Connectors</a> <ul class="sectlevel3"> -<li><a href="#_call_for_contributors">9.1.1. Call for contributors</a></li> +<li><a href="#_call_for_contributors">11.1.1. Call for contributors</a></li> </ul> </li> -<li><a href="#_salesforce_connector">9.2. Salesforce Connector</a> +<li><a href="#_salesforce_connector">11.2. Salesforce Connector</a> <ul class="sectlevel3"> -<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> +<li><a href="#_getting_started_2">11.2.1. Getting started</a></li> +<li><a href="#_properties">11.2.2. Properties</a></li> +<li><a href="#_hot_deploying_updates_to_the_salesforce_connector_for_developers">11.2.3. Hot-deploying updates to the Salesforce connector (for developers)</a></li> +<li><a href="#_using_the_salesforce_workbench_for_testing_rest_api">11.2.4. Using the Salesforce Workbench for testing REST API</a></li> +<li><a href="#_setting_up_streaming_push_queries">11.2.5. Setting up Streaming Push queries</a></li> +<li><a href="#_executing_the_unit_tests">11.2.6. Executing the unit tests</a></li> </ul> </li> -<li><a href="#_mailchimp_connector">9.3. MailChimp Connector</a> +<li><a href="#_mailchimp_connector">11.3. MailChimp Connector</a> <ul class="sectlevel3"> -<li><a href="#_getting_started_3">9.3.1. Getting started</a></li> +<li><a href="#_getting_started_3">11.3.1. Getting started</a></li> </ul> </li> </ul> </li> -<li><a href="#_developers">10. Developers</a> +<li><a href="#_developers">12. Developers</a> <ul class="sectlevel2"> -<li><a href="#_building">10.1. Building</a> +<li><a href="#_building">12.1. Building</a> <ul class="sectlevel3"> -<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> +<li><a href="#_initial_setup">12.1.1. Initial Setup</a></li> +<li><a href="#_building_2">12.1.2. Building</a></li> +<li><a href="#_installing_an_elasticsearch_server">12.1.3. Installing an ElasticSearch server</a></li> +<li><a href="#_deploying_the_generated_binary_package">12.1.4. Deploying the generated binary package</a></li> +<li><a href="#_deploying_into_an_existing_karaf_server">12.1.5. Deploying into an existing Karaf server</a></li> +<li><a href="#_jdk_selection_on_mac_os_x">12.1.6. JDK Selection on Mac OS X</a></li> +<li><a href="#_running_the_integration_tests">12.1.7. Running the integration tests</a></li> +<li><a href="#_running_the_performance_tests">12.1.8. Running the performance tests</a></li> +<li><a href="#_testing_with_an_example_page">12.1.9. Testing with an example page</a></li> </ul> </li> -<li><a href="#_ssh_shell_commands">10.2. SSH Shell Commands</a> +<li><a href="#_ssh_shell_commands">12.2. SSH Shell Commands</a> <ul class="sectlevel3"> -<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> +<li><a href="#_using_the_shell">12.2.1. Using the shell</a></li> +<li><a href="#_lifecycle_commands">12.2.2. Lifecycle commands</a></li> +<li><a href="#_runtime_commands">12.2.3. Runtime commands</a></li> </ul> </li> -<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> +<li><a href="#_types_vs_instances">12.3. Types vs. instances</a></li> +<li><a href="#_plugin_structure">12.4. Plugin structure</a></li> +<li><a href="#_extension_points">12.5. Extension points</a> <ul class="sectlevel3"> -<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> +<li><a href="#_actiontype">12.5.1. ActionType</a></li> +<li><a href="#_conditiontype">12.5.2. ConditionType</a></li> +<li><a href="#_persona">12.5.3. Persona</a></li> +<li><a href="#_propertymergestrategytype">12.5.4. PropertyMergeStrategyType</a></li> +<li><a href="#_propertytype">12.5.5. PropertyType</a></li> +<li><a href="#_rule">12.5.6. Rule</a></li> +<li><a href="#_scoring">12.5.7. Scoring</a></li> +<li><a href="#_segments_2">12.5.8. Segments</a></li> +<li><a href="#_tag">12.5.9. Tag</a></li> +<li><a href="#_valuetype">12.5.10. ValueType</a></li> </ul> </li> -<li><a href="#_other_unomi_entities">10.6. Other Unomi entities</a> +<li><a href="#_other_unomi_entities">12.6. Other Unomi entities</a> <ul class="sectlevel3"> -<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> +<li><a href="#_userlist">12.6.1. UserList</a></li> +<li><a href="#_goal">12.6.2. Goal</a></li> +<li><a href="#_campaign">12.6.3. Campaign</a></li> </ul> </li> -<li><a href="#_custom_extensions">10.7. Custom extensions</a> +<li><a href="#_custom_extensions">12.7. Custom extensions</a> <ul class="sectlevel3"> -<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> +<li><a href="#_creating_an_extension">12.7.1. Creating an extension</a></li> +<li><a href="#_deployment_and_custom_definition">12.7.2. Deployment and custom definition</a></li> +<li><a href="#_predefined_segments">12.7.3. Predefined segments</a></li> +<li><a href="#_predefined_rules">12.7.4. Predefined rules</a></li> +<li><a href="#_predefined_properties">12.7.5. Predefined properties</a></li> +<li><a href="#_predefined_child_conditions">12.7.6. Predefined child conditions</a></li> +<li><a href="#_predefined_personas">12.7.7. Predefined personas</a></li> +<li><a href="#_custom_actions">12.7.8. Custom actions</a></li> +<li><a href="#_custom_conditions">12.7.9. Custom conditions</a></li> </ul> </li> -<li><a href="#_migration_patches">10.8. Migration patches</a></li> +<li><a href="#_migration_patches">12.8. Migration patches</a></li> </ul> </li> </ul> @@ -262,7 +288,7 @@ <div class="sectionbody"> <div class="imageblock" style="text-align: center"> <div class="content"> -<img src="images/incubator-logo.png" alt="incubator logo"> +<img src="images/asf_logo_url.png" alt="asf logo url"> </div> </div> </div> @@ -286,7 +312,7 @@ JAVA_HOME variable <a href="https://docs <p>4) Launch ElasticSearch using : <code>bin/elasticsearch</code></p> </div> <div class="paragraph"> -<p>5) Download Apache Unomi here : <a href="http://unomi.incubator.apache.org/download.html" class="bare">http://unomi.incubator.apache.org/download.html</a></p> +<p>5) Download Apache Unomi here : <a href="https://unomi.apache.org/download.html" class="bare">https://unomi.apache.org/download.html</a></p> </div> <div class="paragraph"> <p>6) Start it using : <code>./bin/karaf</code></p> @@ -778,7 +804,7 @@ EOF</code></pre> <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> +properties. The structure of the JSON object that you should send is a JSON-serialized version of the <a href="http://unomi.apache.org/unomi-api/apidocs/org/apache/unomi/api/ContextRequest.html">ContextRequest</a> Java class.</p> </div> <div class="paragraph"> @@ -923,7 +949,7 @@ with the source of the event, such as 'm "target":{ "itemType":"form", "scope":"example", - "itemId":"contactForm", + "itemId":"contactForm" }, "properties" : { "firstName" : "John", @@ -942,11 +968,11 @@ EOF</code></pre> <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> +that looks something like this (and <a href="https://unomi.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 \ +<pre class="highlight"><code>curl -X POST http://localhost:8181/cxs/events/search \ --user karaf:karaf \ -H "Content-Type: application/json" \ -d @- <<'EOF' @@ -1030,7 +1056,7 @@ structure. Here’s an example of a </div> <div class="listingblock"> <div class="content"> -<pre class="highlight"><code>curl -X POST http://localhost:8181/cxs/rules \ +<pre class="highlight"><code>curl -X POST http://localhost:8181/cxs/profiles/search \ --user karaf:karaf \ -H "Content-Type: application/json" \ -d @- <<'EOF' @@ -1057,7 +1083,7 @@ structure. Here’s an example of a "propertyName": "properties.lastName", "comparisonOperator": "exists" } - }, + } ] } } @@ -1208,7 +1234,7 @@ EOF</code></pre> <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> +properties. The structure of the JSON object that you should send is a JSON-serialized version of the <a href="http://unomi.apache.org/unomi-api/apidocs/org/apache/unomi/api/ContextRequest.html">ContextRequest</a> Java class.</p> </div> </div> @@ -1755,7 +1781,7 @@ the values in the <code>$MY_KARAF_HOME/e Apache Unomi inside a Docker container. You can find the list of all the environment variable names in the following file:</p> </div> <div class="paragraph"> -<p><a href="https://github.com/apache/incubator-unomi/blob/master/package/src/main/resources/etc/custom.system.properties" class="bare">https://github.com/apache/incubator-unomi/blob/master/package/src/main/resources/etc/custom.system.properties</a></p> +<p><a href="https://github.com/apache/unomi/blob/master/package/src/main/resources/etc/custom.system.properties" class="bare">https://github.com/apache/unomi/blob/master/package/src/main/resources/etc/custom.system.properties</a></p> </div> <div class="paragraph"> <p>If you are using Docker Container, simply pass the environment variables on the docker command line or if you are using @@ -2398,13 +2424,13 @@ results as the returned JSON is not beau <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">/cxs/profiles/sessions/SESSION_ID/events</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">GET</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Listing events for a session. This query can have additional such as eventTypes, q (query), offset, size, sort. See the <a href="https://unomi.incubator.apache.org/rest-api-doc/#1019321624">related +<td class="tableblock halign-left valign-top"><p class="tableblock">Listing events for a session. This query can have additional such as eventTypes, q (query), offset, size, sort. See the <a href="https://unomi.apache.org/rest-api-doc/#1019321624">related section in the REST API</a> for details.</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">/cxs/events/search</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">POST</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Listing events for a 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>) : +<td class="tableblock halign-left valign-top"><p class="tableblock">Listing events for a profile. You will need to provide a query in the body of the request that looks something like this (and <a href="https://unomi.apache.org/rest-api-doc/#1768188821">documentation is available in the REST API</a>) : { "offset" : 0, "limit" : 20, "condition" : { @@ -2479,17 +2505,719 @@ forcing.</p> </div> </div> <div class="sect1"> -<h2 id="_consent_management">4. Consent management</h2> +<h2 id="_queries_and_aggregations">4. Queries and aggregations</h2> +<div class="sectionbody"> +<div class="paragraph"> +<p>Apache Unomi contains a <code>query</code> endpoint that is quite powerful. It provides ways to perform queries that can quickly +get result counts, apply metrics such as sum/min/max/avg or even use powerful aggregations.</p> +</div> +<div class="paragraph"> +<p>In this section we will show examples of requests that may be built using this API.</p> +</div> +<div class="sect2"> +<h3 id="_query_counts">4.1. Query counts</h3> +<div class="paragraph"> +<p>Query counts are highly optimized queries that will count the number of objects that match a certain condition without +retrieving the results. This can be used for example to quickly figure out how many objects will match a given condition +before actually retrieving the results. It uses ElasticSearch/Lucene optimizations to avoid the cost of loading all the +resulting objects.</p> +</div> +<div class="paragraph"> +<p>Here’s an example of a query:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="highlight"><code class="language-bash" data-lang="bash">curl -X POST http://localhost:8181/cxs/query/profile/count \ +--user karaf:karaf \ +-H "Content-Type: application/json" \ +-d @- <<'EOF' +{ + "parameterValues": { + "subConditions": [ + { + "type": "profilePropertyCondition", + "parameterValues": { + "propertyName": "systemProperties.isAnonymousProfile", + "comparisonOperator": "missing" + } + }, + { + "type": "profilePropertyCondition", + "parameterValues": { + "propertyName": "properties.nbOfVisits", + "comparisonOperator": "equals", + "propertyValueInteger": 1 + } + } + ], + "operator": "and" + }, + "type": "booleanCondition" +} +EOF</code></pre> +</div> +</div> +<div class="paragraph"> +<p>The above result will return the profile count of all the profiles</p> +</div> +<div class="paragraph"> +<p>Result will be something like this:</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>2084</pre> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_metrics">4.2. Metrics</h3> +<div class="paragraph"> +<p>Metric queries make it possible to apply functions to the resulting property. The supported metrics are:</p> +</div> +<div class="ulist"> +<ul> +<li> +<p>sum</p> +</li> +<li> +<p>avg</p> +</li> +<li> +<p>min</p> +</li> +<li> +<p>max</p> +</li> +</ul> +</div> +<div class="paragraph"> +<p>It is also possible to request more than one metric in a single request by concatenating them with a "/" in the URL. +Here’s an example request that uses the <code>sum</code> and <code>avg</code> metrics:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="highlight"><code>curl -X POST http://localhost:8181/cxs/query/session/profile.properties.nbOfVisits/sum/avg \ +--user karaf:karaf \ +-H "Content-Type: application/json" \ +-d @- <<'EOF' +{ + "parameterValues": { + "subConditions": [ + { + "type": "sessionPropertyCondition", + "parameterValues": { + "comparisonOperator": "equals", + "propertyName": "scope", + "propertyValue": "digitall" + } + } + ], + "operator": "and" + }, + "type": "booleanCondition" +} +EOF</code></pre> +</div> +</div> +<div class="paragraph"> +<p>The result will look something like this:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="highlight"><code class="language-json" data-lang="json">{ + "_avg":1.0, + "_sum":9.0 +}</code></pre> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_aggregations">4.3. Aggregations</h3> +<div class="paragraph"> +<p>Aggregations are a very powerful way to build queries in Apache Unomi that will collect and aggregate data by filtering +on certain conditions.</p> +</div> +<div class="paragraph"> +<p>Aggregations are composed of : +- an object type and a property on which to aggregate +- an aggregation setup (how data will be aggregated, by date, by numeric range, date range or ip range) +- a condition (used to filter the data set that will be aggregated)</p> +</div> +<div class="sect3"> +<h4 id="_aggregation_types">4.3.1. Aggregation types</h4> +<div class="paragraph"> +<p>Aggregations may be of different types. They are listed here below.</p> +</div> +<div class="sect4"> +<h5 id="_date">Date</h5> +<div class="paragraph"> +<p>Date aggregations make it possible to automatically generate "buckets" by time periods. For more information about the +format, it is directly inherited from ElasticSearch and you may find it here: <a href="https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-aggregations-bucket-datehistogram-aggregation.html" class="bare">https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-aggregations-bucket-datehistogram-aggregation.html</a></p> +</div> +<div class="paragraph"> +<p>Here’s an example of a request to retrieve a histogram of by day of all the session that have been create by newcomers (nbOfVisits=1)</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="highlight"><code>curl -X POST http://localhost:8181/cxs/query/session/timeStamp \ +--user karaf:karaf \ +-H "Content-Type: application/json" \ +-d @- <<'EOF' +{ + "aggregate": { + "type": "date", + "parameters": { + "interval": "1d", + "format": "yyyy-MM-dd" + } + }, + "condition": { + "type": "booleanCondition", + "parameterValues": { + "operator": "and", + "subConditions": [ + { + "type": "sessionPropertyCondition", + "parameterValues": { + "propertyName": "scope", + "comparisonOperator": "equals", + "propertyValue": "acme" + } + }, + { + "type": "sessionPropertyCondition", + "parameterValues": { + "propertyName": "profile.properties.nbOfVisits", + "comparisonOperator": "equals", + "propertyValueInteger": 1 + } + } + ] + } + } +} +EOF</code></pre> +</div> +</div> +<div class="paragraph"> +<p>The above request will produce a similar that looks like this:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="highlight"><code class="language-json" data-lang="json">{ + "_all": 8062, + "_filtered": 4085, + "2018-10-02": 3, + "2018-10-03": 17, + "2018-10-04": 18, + "2018-10-05": 19, + "2018-10-06": 23, + "2018-10-07": 18, + "2018-10-08": 20 +}</code></pre> +</div> +</div> +<div class="paragraph"> +<p>You can see that we retrieve the count of newcomers aggregated by day.</p> +</div> +</div> +<div class="sect4"> +<h5 id="_date_range">Date range</h5> +<div class="paragraph"> +<p>Date ranges make it possible to "bucket" dates, for example to regroup profiles by their birth date as in the example +below:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="highlight"><code class="language-shell script" data-lang="shell script">curl -X POST http://localhost:8181/cxs/query/profile/properties.birthDate \ +--user karaf:karaf \ +-H "Content-Type: application/json" \ +-d @- <<'EOF' +{ + "aggregate": { + "property": "properties.birthDate", + "type": "dateRange", + "dateRanges": [ + { + "key": "After 2009", + "from": "now-10y/y", + "to": null + }, + { + "key": "Between 1999 and 2009", + "from": "now-20y/y", + "to": "now-10y/y" + }, + { + "key": "Between 1989 and 1999", + "from": "now-30y/y", + "to": "now-20y/y" + }, + { + "key": "Between 1979 and 1989", + "from": "now-40y/y", + "to": "now-30y/y" + }, + { + "key": "Between 1969 and 1979", + "from": "now-50y/y", + "to": "now-40y/y" + }, + { + "key": "Before 1969", + "from": null, + "to": "now-50y/y" + } + ] + }, + "condition": { + "type": "matchAllCondition", + "parameterValues": {} + } +} +EOF</code></pre> +</div> +</div> +<div class="paragraph"> +<p>The resulting JSON response will look something like this:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="highlight"><code class="language-json" data-lang="json">{ + "_all":4095, + "_filtered":4095, + "Before 1969":2517, + "Between 1969 and 1979":353, + "Between 1979 and 1989":336, + "Between 1989 and 1999":337, + "Between 1999 and 2009":35, + "After 2009":0, + "_missing":517 +}</code></pre> +</div> +</div> +<div class="paragraph"> +<p>You can find more information about the date range formats here: <a href="https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-aggregations-bucket-daterange-aggregation.html" class="bare">https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-aggregations-bucket-daterange-aggregation.html</a></p> +</div> +</div> +<div class="sect4"> +<h5 id="_numeric_range">Numeric range</h5> +<div class="paragraph"> +<p>Numeric ranges make it possible to use "buckets" for the various ranges you want to classify.</p> +</div> +<div class="paragraph"> +<p>Here’s an example of a using numeric range to regroup profiles by number of visits:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="highlight"><code class="language-shell script" data-lang="shell script">curl -X POST http://localhost:8181/cxs/query/profile/properties.nbOfVisits \ +--user karaf:karaf \ +-H "Content-Type: application/json" \ +-d @- <<'EOF' +{ + "aggregate": { + "property": "properties.nbOfVisits", + "type": "numericRange", + "numericRanges": [ + { + "key": "Less than 5", + "from": null, + "to": 5 + }, + { + "key": "Between 5 and 10", + "from": 5, + "to": 10 + }, + { + "key": "Between 10 and 20", + "from": 10, + "to": 20 + }, + { + "key": "Between 20 and 40", + "from": 20, + "to": 40 + }, + { + "key": "Between 40 and 80", + "from": 40, + "to": 80 + }, + { + "key": "Greater than 100", + "from": 100, + "to": null + } + ] + }, + "condition": { + "type": "matchAllCondition", + "parameterValues": {} + } +} +EOF</code></pre> +</div> +</div> +<div class="paragraph"> +<p>This will produce an output that looks like this:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="highlight"><code class="language-json" data-lang="json">{ + "_all":4095, + "_filtered":4095, + "Less than 5":3855, + "Between 5 and 10":233, + "Between 10 and 20":7, + "Between 20 and 40":0, + "Between 40 and 80":0, + "Greater than 100":0 +}</code></pre> +</div> +</div> +</div> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_profile_import_export">5. Profile import & export</h2> +<div class="sectionbody"> +<div class="paragraph"> +<p>The profile import and export feature in Apache Unomi is based on configurations and consumes or produces CSV files that +contain profiles to be imported and exported.</p> +</div> +<div class="sect2"> +<h3 id="_importing_profiles">5.1. Importing profiles</h3> +<div class="paragraph"> +<p>Only <code>ftp</code>, <code>sftp</code>, <code>ftps</code> and <code>file</code> are supported in the source path. For example:</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>file:///tmp/?fileName=profiles.csv&move=.done&consumer.delay=25s</pre> +</div> +</div> +<div class="paragraph"> +<p>Where:</p> +</div> +<div class="ulist"> +<ul> +<li> +<p><code>fileName</code> Can be a pattern, for example <code>include=.*.csv</code> instead of <code>fileName=…​</code> to consume all CSV files. +By default the processed files are moved to <code>.camel</code> folder you can change it using the <code>move</code> option.</p> +</li> +<li> +<p><code>consumer.delay</code> Is the frequency of polling in milliseconds. For example, 20000 milliseconds is 20 seconds. This +frequency can also be 20s. Other possible format are: 2h30m10s = 2 hours and 30 minutes and 10 seconds.</p> +</li> +</ul> +</div> +<div class="paragraph"> +<p>See <a href="http://camel.apache.org/ftp.html" class="bare">http://camel.apache.org/ftp.html</a> and <a href="http://camel.apache.org/file2.html" class="bare">http://camel.apache.org/file2.html</a> to build more complex source path. Also be +careful with FTP configuration as most servers no longer support plain text FTP and you should use SFTP or FTPS +instead, but they are a little more difficult to configure properly. It is recommended to test the connection with an +FTP client first before setting up these source paths to ensure that everything works properly. Also on FTP +connections most servers require PASSIVE mode so you can specify that in the path using the <code>passiveMode=true</code> parameter.</p> +</div> +<div class="paragraph"> +<p>Here are some examples of FTPS and SFTP source paths:</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>sftp://USER@HOST/PATH?password=PASSWORD&include=.*.csv +ftps://USER@HOST?password=PASSWORD&fileName=profiles.csv&passiveMode=true</pre> +</div> +</div> +<div class="paragraph"> +<p>Where:</p> +</div> +<div class="ulist"> +<ul> +<li> +<p><code>USER</code> is the user name of the SFTP/FTPS user account to login with</p> +</li> +<li> +<p><code>PASSWORD</code> is the password for the user account</p> +</li> +<li> +<p><code>HOST</code> is the host name (or IP address) of the host server that provides the SFTP / FTPS server</p> +</li> +<li> +<p><code>PATH</code> is a path to a directory inside the user’s account where the file will be retrieved.</p> +</li> +</ul> +</div> +<div class="sect3"> +<h4 id="_import_api">5.1.1. Import API</h4> +<div class="paragraph"> +<p>Apache Unomi provides REST endpoints to manage import configurations:</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre> GET /cxs/importConfiguration + GET /cxs/importConfiguration/{configId} + POST /cxs/importConfiguration + DELETE /cxs/importConfiguration/{configId}</pre> +</div> +</div> +<div class="paragraph"> +<p>This is how a oneshot import configuration looks like:</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>{ + "itemId": "importConfigId", + "itemType": "importConfig", + "name": "Import Config Sample", + "description": "Sample description", + "configType": "oneshot", //Config type can be 'oneshot' or 'recurrent' + "properties": { + "mapping": { + "email": 0, //<Apache Unomi Property Id> : <Column Index In the CSV> + "firstName": 2, + ... + } + }, + "columnSeparator": ",", //Character used to separate columns + "lineSeparator": "\\n", //Character used to separate lines (\n or \r) + "multiValueSeparator": ";", //Character used to separate values for multivalued columns + "multiValueDelimiter": "[]", //Character used to wrap values for multivalued columns + "status": "SUCCESS", //Status of last execution + "executions": [ //(RETURN) Last executions by default only last 5 are returned + ... + ], + "mergingProperty": "email", //Apache Unomi Property Id used to check duplicates + "overwriteExistingProfiles": true, //Overwrite profiles that have duplicates + "propertiesToOverwrite": "firstName, lastName, ...", //If last is set to true, which property to overwrite, 'null' means overwrite all + "hasHeader": true, //CSV file to import contains a header line + "hasDeleteColumn": false //CSV file to import doesn't contain a TO DELETE column (if it contains, will be the last column) +}</pre> +</div> +</div> +<div class="paragraph"> +<p>A recurrent import configuration is similar to the previous one with some specific information to add to the JSON like:</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>{ + ... + "configType": "recurrent", + "properties": { + "source": "ftp://USER@SERVER[:PORT]/PATH?password=xxx&fileName=profiles.csv&move=.done&consumer.delay=20000", + // Only 'ftp', 'sftp', 'ftps' and 'file' are supported in the 'source' path + // eg. file:///tmp/?fileName=profiles.csv&move=.done&consumer.delay=25s + // 'fileName' can be a pattern eg 'include=.*.csv' instead of 'fileName=...' to consume all CSV files + // By default the processed files are moved to '.camel' folder you can change it using the 'move' option + // 'consumer.delay' is the frequency of polling. '20000' (in milliseconds) means 20 seconds. Can be also '20s' + // Other possible format are: '2h30m10s' = 2 hours and 30 minutes and 10 seconds + "mapping": { + ... + } + }, + ... + "active": true, //If true the polling will start according to the 'source' configured above + ... +}</pre> +</div> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_exporting_profiles">5.2. Exporting profiles</h3> +<div class="paragraph"> +<p>Only <code>ftp</code>, <code>sftp</code>, <code>ftps</code> and `file are supported in the source path. For example:</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>file:///tmp/?fileName=profiles-export-${date:now:yyyyMMddHHmm}.csv&fileExist=Append) +sftp://USER@HOST/PATH?password=PASSWORD&binary=true&fileName=profiles-export-${date:now:yyyyMMddHHmm}.csv&fileExist=Append +ftps://USER@HOST?password=PASSWORD&binary=true&fileName=profiles-export-${date:now:yyyyMMddHHmm}.csv&fileExist=Append&passiveMode=true</pre> +</div> +</div> +<div class="paragraph"> +<p>As you can see in the examples above, you can inject variables in the produced file name <code>${date:now:yyyyMMddHHmm}</code> is +the current date formatted with the pattern <code>yyyyMMddHHmm</code>. <code>fileExist</code> option put as <code>Append</code> will tell the file writer +to append to the same file for each execution of the export configuration. You cam omit this option to write a profile +per file.</p> +</div> +<div class="paragraph"> +<p>See <a href="http://camel.apache.org/ftp.html and http://camel.apache.org/file2.html to" class="bare">http://camel.apache.org/ftp.html and http://camel.apache.org/file2.html to</a> build more complex destination path.</p> +</div> +<div class="sect3"> +<h4 id="_export_api">5.2.1. Export API</h4> +<div class="paragraph"> +<p>Apache Unomi provides REST endpoints to manage export configurations:</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre> GET /cxs/exportConfiguration + GET /cxs/exportConfiguration/{configId} + POST /cxs/exportConfiguration + DELETE /cxs/exportConfiguration/{configId}</pre> +</div> +</div> +<div class="paragraph"> +<p>This is how a oneshot export configuration looks like:</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>{ + "itemId": "exportConfigId", + "itemType": "exportConfig", + "name": "Export configuration sample", + "description": "Sample description", + "configType": "oneshot", + "properties": { + "period": "2m30s", + "segment": "contacts", + "mapping": { + "0": "firstName", + "1": "lastName", + ... + } + }, + "columnSeparator": ",", + "lineSeparator": "\\n", + "multiValueSeparator": ";", + "multiValueDelimiter": "[]", + "status": "RUNNING", + "executions": [ + ... + ] +}</pre> +</div> +</div> +<div class="paragraph"> +<p>A recurrent export configuration is similar to the previous one with some specific information to add to the JSON like:</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>{ + ... + "configType": "recurrent", + "properties": { + "destination": "sftp://USER@SERVER:PORT/PATH?password=XXX&fileName=profiles-export-${date:now:yyyyMMddHHmm}.csv&fileExist=Append", + "period": "2m30s", //Same as 'consumer.delay' option in the import source path + "segment": "contacts", //Segment ID to use to collect profiles to export + "mapping": { + ... + } + }, + ... + "active": true, //If true the configuration will start polling upon save until the user deactivate it + ... +}</pre> +</div> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_configuration_in_details">5.3. Configuration in details</h3> +<div class="paragraph"> +<p>First configuration you need to change would be the configuration type of your import / export feature (code name +router) in the <code>etc/unomi.custom.system.properties</code> file (creating it if necessary):</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>#Configuration Type values {'nobroker', 'kafka'} +org.apache.unomi.router.config.type=nobroker</pre> +</div> +</div> +<div class="paragraph"> +<p>By default the feature is configured (as above) to use no external broker,  which means to handle import/export data it +will use in memory queues (In the same JVM as Apache Unomi). If you are clustering Apache Unomi, most important thing +to know about this type of configuration is that each Apache Unomi will handle the import/export task by itself without +the help of other nodes (No Load-Distribution).</p> +</div> +<div class="paragraph"> +<p>Changing this property to kafka means you have to provide the Apache Kafka configuration, and in the opposite of the +nobroker option import/export data will be handled using an external broker (Apache Kafka), this will lighten the burden +on the Apache Unomi machines.</p> +</div> +<div class="paragraph"> +<p>You may use several Apache Kafka instance, 1 per N Apache Unomi nodes for better application scaling.</p> +</div> +<div class="paragraph"> +<p>To enable using Apache Kafka you need to configure the feature as follows:</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>#Configuration Type values {'nobroker', 'kafka'} +org.apache.unomi.router.config.type=kafka</pre> +</div> +</div> +<div class="paragraph"> +<p>Uncomment and update Kafka settings to use Kafka as a broker</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>#Kafka +org.apache.unomi.router.kafka.host=localhost +org.apache.unomi.router.kafka.port=9092 +org.apache.unomi.router.kafka.import.topic=import-deposit +org.apache.unomi.router.kafka.export.topic=export-deposit +org.apache.unomi.router.kafka.import.groupId=unomi-import-group +org.apache.unomi.router.kafka.export.groupId=unomi-import-group +org.apache.unomi.router.kafka.consumerCount=10 +org.apache.unomi.router.kafka.autoCommit=true</pre> +</div> +</div> +<div class="paragraph"> +<p>There is couple of properties you may want to change to fit your needs, one of them is the <strong>import.oneshot.uploadDir which</strong> +will tell Apache Unomi where to store temporarily the CSV files to import in Oneshot mode, it’s a technical property +to allow the choice of the convenient disk space where to store the files to be imported. It defaults to the following path +under the Apache Unomi Karaf (It is recommended to change the path to a more convenient one).</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>#Import One Shot upload directory +org.apache.unomi.router.import.oneshot.uploadDir=${karaf.data}/tmp/unomi_oneshot_import_configs/</pre> +</div> +</div> +<div class="paragraph"> +<p>Next two properties are max sizes for executions history and error reports, for some reason you don’t want Apache Unomi +to report all the executions history and error reports generated by the executions of an import/export configuration. +To change this you have to change the default values of these properties.</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>#Import/Export executions history size +org.apache.unomi.router.executionsHistory.size=5</pre> +</div> +</div> +<div class="literalblock"> +<div class="content"> +<pre>#errors report size +org.apache.unomi.router.executions.error.report.size=200</pre> +</div> +</div> +<div class="paragraph"> +<p>Final one is about the allowed endpoints you can use when building the source or destionation path, as mentioned above +we can have a path of type <code>file</code>, <code>ftp</code>, <code>ftps</code>, <code>sftp</code>. You can make it less if you want to omit some endpoints (eg. +you don’t want to permit the use of non secure FTP).</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>#Allowed source endpoints +org.apache.unomi.router.config.allowedEndpoints=file,ftp,sftp,ftps</pre> +</div> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_consent_management">6. Consent management</h2> <div class="sectionbody"> <div class="sect2"> -<h3 id="_consent_api">4.1. Consent API</h3> +<h3 id="_consent_api">6.1. Consent API</h3> <div class="paragraph"> <p>Starting with Apache Unomi 1.3, a new API for consent management is now available. This API is designed to be able to store/retrieve/update visitor consents in order to comply with new privacy regulations such as the <a href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation">GDPR</a>.</p> </div> <div class="sect3"> -<h4 id="_profiles_with_consents">4.1.1. Profiles with consents</h4> +<h4 id="_profiles_with_consents">6.1.1. Profiles with consents</h4> <div class="paragraph"> <p>Visitor profiles now contain a new Consent object that contains the following information:</p> </div> @@ -2564,7 +3292,7 @@ EOF</code></pre> </div> </div> <div class="sect3"> -<h4 id="_consent_type_definitions">4.1.2. Consent type definitions</h4> +<h4 id="_consent_type_definitions">6.1.2. Consent type definitions</h4> <div class="paragraph"> <p>Apache Unomi does not manage consent definitions, it leaves that to an external system (for example a CMS) so that it can handle user-facing UIs to create, update, internationalize and present consent definitions to end users.</p> @@ -2575,7 +3303,7 @@ consent type.</p> </div> </div> <div class="sect3"> -<h4 id="_creating_update_a_visitor_consent">4.1.3. Creating / update a visitor consent</h4> +<h4 id="_creating_update_a_visitor_consent">6.1.3. Creating / update a visitor consent</h4> <div class="paragraph"> <p>A new built-in event type called "modifyConsent" can be sent to Apache Unomi to update a consent for the current profile.</p> @@ -2658,7 +3386,7 @@ EOF</code></pre> </div> </div> <div class="sect3"> -<h4 id="_how_it_works_internally">4.1.4. How it works (internally)</h4> +<h4 id="_how_it_works_internally">6.1.4. How it works (internally)</h4> <div class="paragraph"> <p>Upon receiving this event, Apache Unomi will trigger the modifyAnyConsent rule that has the following definition:</p> </div> @@ -2691,7 +3419,7 @@ EOF</code></pre> </div> <div class="paragraph"> <p>As we can see this rule is pretty simple it will simply execute the modifyConsentAction that is implemented by the -<a href="https://github.com/apache/incubator-unomi/blob/9f1bab437fd93826dc54d318ed00d3b2e3161437/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/ModifyConsentAction.java">ModifyConsentAction Java class</a></p> +<a href="https://github.com/apache/unomi/blob/9f1bab437fd93826dc54d318ed00d3b2e3161437/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/ModifyConsentAction.java">ModifyConsentAction Java class</a></p> </div> <div class="paragraph"> <p>This class will update the current visitor profile to add/update/revoke any consents that are included in the event.</p> @@ -2701,14 +3429,14 @@ EOF</code></pre> </div> </div> <div class="sect1"> -<h2 id="_privacy_management">5. Privacy management</h2> +<h2 id="_privacy_management">7. 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> +<h4 id="_setting_up_access_to_the_privacy_endpoint">7.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> @@ -2734,7 +3462,7 @@ geographic location)</p> </div> </div> <div class="sect3"> -<h4 id="_anonymizing_a_profile">5.2. Anonymizing a profile</h4> +<h4 id="_anonymizing_a_profile">7.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> @@ -2753,7 +3481,7 @@ and <code>ASCOPE</code> must be replaced </div> </div> <div class="sect3"> -<h4 id="_downloading_profile_data">5.3. Downloading profile data</h4> +<h4 id="_downloading_profile_data">7.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> @@ -2774,7 +3502,7 @@ IDs.</p> </div> </div> <div class="sect3"> -<h4 id="_deleting_a_profile">5.4. Deleting a profile</h4> +<h4 id="_deleting_a_profile">7.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 @@ -2791,7 +3519,7 @@ and the <code>withData</code> specifies </div> </div> <div class="sect3"> -<h4 id="_related">5.5. Related</h4> +<h4 id="_related">7.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> @@ -2799,10 +3527,10 @@ and the <code>withData</code> specifies </div> </div> <div class="sect1"> -<h2 id="_cluster_setup">6. Cluster setup</h2> +<h2 id="_cluster_setup">8. Cluster setup</h2> <div class="sectionbody"> <div class="sect2"> -<h3 id="_cluster_setup_2">6.1. Cluster setup</h3> +<h3 id="_cluster_setup_2">8.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> @@ -2843,10 +3571,10 @@ placeholders in the hazelcast.xml file i </div> </div> <div class="sect1"> -<h2 id="_reference">7. Reference</h2> +<h2 id="_reference">9. Reference</h2> <div class="sectionbody"> <div class="sect2"> -<h3 id="_built_in_conditions">7.1. Built-in conditions</h3> +<h3 id="_built_in_conditions">9.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> @@ -2936,7 +3664,7 @@ implementations. For more details on bui sections.</p> </div> <div class="sect3"> -<h4 id="_existing_condition_descriptors">7.1.1. Existing condition descriptors</h4> +<h4 id="_existing_condition_descriptors">9.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> @@ -2958,7 +3686,7 @@ type to make them more specific.</p> </div> </div> <div class="sect2"> -<h3 id="_built_in_actions">7.2. Built-in actions</h3> +<h3 id="_built_in_actions">9.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> @@ -3008,7 +3736,7 @@ Here’s an example of such a regist <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> +<h4 id="_existing_actions_descriptors">9.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> @@ -3034,10 +3762,10 @@ discover more. But the list below should </div> </div> <div class="sect1"> -<h2 id="_integration_samples">8. Integration samples</h2> +<h2 id="_integration_samples">10. Integration samples</h2> <div class="sectionbody"> <div class="sect2"> -<h3 id="_samples">8.1. Samples</h3> +<h3 id="_samples">10.1. Samples</h3> <div class="paragraph"> <p>Apache Unomi provides the following samples:</p> </div> @@ -3053,12 +3781,12 @@ discover more. But the list below should </div> </div> <div class="sect2"> -<h3 id="_login_sample">8.2. Login sample</h3> +<h3 id="_login_sample">10.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">8.2.1. Warning !</h4> +<h4 id="_warning">10.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> @@ -3069,7 +3797,7 @@ only be sent if the user has authenticat </div> </div> <div class="sect3"> -<h4 id="_installing_the_samples">8.2.2. Installing the samples</h4> +<h4 id="_installing_the_samples">10.2.2. Installing the samples</h4> <div class="paragraph"> <p>Login into the Unomi Karaf SSH shell using something like this :</p> </div> @@ -3116,9 +3844,9 @@ only be sent if the user has authenticat </div> </div> <div class="sect2"> -<h3 id="_twitter_sample">8.3. Twitter sample</h3> +<h3 id="_twitter_sample">10.3. Twitter sample</h3> <div class="sect3"> -<h4 id="_overview">8.3.1. Overview</h4> +<h4 id="_overview">10.3.1. Overview</h4> <div class="paragraph"> <p>We will examine how a simple HTML page can interact with Unomi to enrich a user’s profile. The use case we will follow is a rather simple one: we use a Twitter button to record the number of times the visitor tweeted (as a <code>tweetNb</code> profile @@ -3167,7 +3895,7 @@ mvn clean install</code></pre> </div> </div> <div class="sect3"> -<h4 id="_interacting_with_the_context_server">8.3.2. Interacting with the context server</h4> +<h4 id="_interacting_with_the_context_server">10.3.2. Interacting with the context server</h4> <div class="paragraph"> <p>There are essentially two modalities to interact with the context server, reflecting different types of Unomi users: context server clients and context server integrators.</p> </div> @@ -3182,7 +3910,7 @@ mvn clean install</code></pre> </div> </div> <div class="sect3"> -<h4 id="_retrieving_context_information_from_unomi_using_the_context_servlet">8.3.3. Retrieving context information from Unomi using the context servlet</h4> +<h4 id="_retrieving_context_information_from_unomi_using_the_context_servlet">10.3.3. Retrieving context information from Unomi using the context servlet</h4> <div class="paragraph"> <p>Unomi provides two ways to retrieve context: either as a pure JSON object containing strictly context information or as a couple of JSON objects augmented with javascript functions that can be used to interact with the Unomi server using the <code><context server base URL>/context.json</code> or <code><context server base URL>/context.js</code> URLs, respectively.</p> </div> @@ -3230,18 +3958,18 @@ information about the context for the cu </div> </div> <div class="sect2"> -<h3 id="_example">8.4. Example</h3> +<h3 id="_example">10.4. Example</h3> <div class="sect3"> -<h4 id="_html_page">8.4.1. HTML page</h4> +<h4 id="_html_page">10.4.1. HTML page</h4> <div class="paragraph"> -<p>The code for the HTML page with our Tweet button can be found at <a href="https://github.com/apache/incubator-unomi/blob/master/wab/src/main/webapp/index.html">https://github.com/apache/incubator-unomi/blob/master/wab/src/main/webapp/index.html</a>.</p> +<p>The code for the HTML page with our Tweet button can be found at <a href="https://github.com/apache/unomi/blob/master/wab/src/main/webapp/index.html">https://github.com/apache/unomi/blob/master/wab/src/main/webapp/index.html</a>.</p> </div> <div class="paragraph"> <p>This HTML page is fairly straightforward: we create a tweet button using the Twitter API while a Javascript script performs the actual logic.</p> </div> </div> <div class="sect3"> -<h4 id="_javascript">8.4.2. Javascript</h4> +<h4 id="_javascript">10.4.2. Javascript</h4> <div class="paragraph"> <p>Globally, the script loads both the twitter widget and the initial context asynchronously (as shown previously). This is accomplished using fairly standard javascript code and we won’t look at it here. Using the Twitter API, we react to the <code>tweet</code> event and call the Unomi server to update the user’s profile with the required information, triggering a custom <code>tweetEvent</code> event. This is accomplished using a <code>contextRequest</code> function which is an extended version of a classic <code>AJAX</code> request:</p> </div> @@ -3432,17 +4160,17 @@ var source = { <div class="paragraph"> <p>In order to react to <code>tweetEvent</code> events, we will define a new Unomi rule since this is exactly what Unomi rules are supposed to do. Rules are guarded by conditions and if these conditions match, the associated set of actions will be executed. In our case, we want our new - <a href="https://github.com/apache/incubator-unomi/blob/master/samples/tweet-button-plugin/src/main/resources/META-INF/cxs/rules/incrementTweetNumber.json"><code>incrementTweetNumber</code></a> rule to only react to <code>tweetEvent</code> events and + <a href="https://github.com/apache/unomi/blob/master/samples/tweet-button-plugin/src/main/resources/META-INF/cxs/rules/incrementTweetNumber.json"><code>incrementTweetNumber</code></a> rule to only react to <code>tweetEvent</code> events and we want it to perform the profile update accordingly: create the property types for our custom properties if they don’t exist and update them. To do so, we will create a custom - <a href="https://github.com/apache/incubator-unomi/blob/master/samples/tweet-button-plugin/src/main/resources/META-INF/cxs/actions/incrementTweetNumberAction.json"><code>incrementTweetNumberAction</code></a> action that will be triggered any time our rule matches. An action is some custom code that is deployed in the context server and can access the + <a href="https://github.com/apache/unomi/blob/master/samples/tweet-button-plugin/src/main/resources/META-INF/cxs/actions/incrementTweetNumberAction.json"><code>incrementTweetNumberAction</code></a> action that will be triggered any time our rule matches. An action is some custom code that is deployed in the context server and can access the Unomi API to perform what it is that it needs to do.</p> </div> </div> <div class="sect4"> <h5 id="_rule_definition">Rule definition</h5> <div class="paragraph"> -<p>Let’s look at how our custom <a href="https://github.com/apache/incubator-unomi/blob/master/samples/tweet-button-plugin/src/main/resources/META-INF/cxs/rules/incrementTweetNumber.json"><code>incrementTweetNumber</code></a> rule is defined:</p> +<p>Let’s look at how our custom <a href="https://github.com/apache/unomi/blob/master/samples/tweet-button-plugin/src/main/resources/META-INF/cxs/rules/incrementTweetNumber.json"><code>incrementTweetNumber</code></a> rule is defined:</p> </div> <div class="listingblock"> <div class="content"> @@ -3487,7 +4215,7 @@ var source = { <div class="sect4"> <h5 id="_action_definition">Action definition</h5> <div class="paragraph"> -<p>Let’s now look at our custom <a href="https://github.com/apache/incubator-unomi/blob/master/samples/tweet-button-plugin/src/main/resources/META-INF/cxs/actions/incrementTweetNumberAction.json"><code>incrementTweetNumberAction</code></a> action type definition:</p> +<p>Let’s now look at our custom <a href="https://github.com/apache/unomi/blob/master/samples/tweet-button-plugin/src/main/resources/META-INF/cxs/actions/incrementTweetNumberAction.json"><code>incrementTweetNumberAction</code></a> action type definition:</p> </div> <div class="listingblock"> <div class="content"> @@ -3511,7 +4239,7 @@ var source = { <div class="sect4"> <h5 id="_action_executor_definition">Action executor definition</h5> <div class="paragraph"> -<p>The action executor references the actual implementation of the action as defined in our <a href="https://github.com/apache/incubator-unomi/blob/master/samples/tweet-button-plugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml">blueprint definition</a>:</p> +<p>The action executor references the actual implementation of the action as defined in our <a href="https://github.com/apache/unomi/blob/master/samples/tweet-button-plugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml">blueprint definition</a>:</p> </div> <div class="listingblock"> <div class="content"> @@ -3540,7 +4268,7 @@ var source = { <div class="sect4"> <h5 id="_action_executor_implementation">Action executor implementation</h5> <div class="paragraph"> -<p>Our action executor definition specifies that the bean providing the service is implemented in the <a href="https://github.com/apache/incubator-unomi/blob/master/samples/tweet-button-plugin/src/main/java/org/apache/unomi/samples/tweet_button_plugin/actions/IncrementTweetNumberAction.java"><code>org.apache.unomi.samples.tweet_button_plugin.actions +<p>Our action executor definition specifies that the bean providing the service is implemented in the <a href="https://github.com/apache/unomi/blob/master/samples/tweet-button-plugin/src/main/java/org/apache/unomi/samples/tweet_button_plugin/actions/IncrementTweetNumberAction.java"><code>org.apache.unomi.samples.tweet_button_plugin.actions .IncrementTweetNumberAction</code></a> class. This class implements the Unomi <code>ActionExecutor</code> interface which provides a single <code>int execute(Action action, Event event)</code> method: the executor gets the action instance to execute along with the event that triggered it, performs its work and returns an integer status corresponding to what happened as defined by public constants of the <code>EventService</code> interface of Unomi: <code>NO_CHANGE</code>, <code>SESSION_UPDATED</code> or <code>PROFILE_UPDATED</code>.</p> </div> <div class="paragraph"> @@ -3614,13 +4342,13 @@ return EventService.PROFILE_UPDATED;</co </div> </div> <div class="sect2"> -<h3 id="_conclusion">8.5. Conclusion</h3> +<h3 id="_conclusion">10.5. Conclusion</h3> <div class="paragraph"> <p>We have seen a simple example how to interact with Unomi using a combination of client-side code and Unomi plugin. Hopefully, this provided an introduction to the power of what Unomi can do and how it can be extended to suit your needs.</p> </div> </div> <div class="sect2"> -<h3 id="_annex">8.6. Annex</h3> +<h3 id="_annex">10.6. Annex</h3> <div class="paragraph"> <p>Here is an overview of how Unomi processes incoming requests to the <code>ContextServlet</code>.</p> </div> @@ -3631,16 +4359,16 @@ return EventService.PROFILE_UPDATED;</co </div> </div> <div class="sect2"> -<h3 id="_weather_update_sample">8.7. Weather update sample</h3> +<h3 id="_weather_update_sample">10.7. Weather update sample</h3> </div> </div> </div> <div class="sect1"> -<h2 id="_connectors">9. Connectors</h2> +<h2 id="_connectors">11. Connectors</h2> <div class="sectionbody"> <div class="sect2"> -<h3 id="_connectors_2">9.1. Connectors</h3> +<h3 id="_connectors_2">11.1. Connectors</h3> <div class="paragraph"> <p>Apache Unomi provides the following connectors:</p> </div> @@ -3655,7 +4383,7 @@ return EventService.PROFILE_UPDATED;</co </ul> </div> <div class="sect3"> -<h4 id="_call_for_contributors">9.1.1. Call for contributors</h4> +<h4 id="_call_for_contributors">11.1.1. Call for contributors</h4> <div class="paragraph"> <p>We are looking for help with the development of additional connectors. Any contribution (large or small) is more than welcome. Feel free to discuss this in our <a href="http://unomi.apache.org/community.html" target="_blank" rel="noopener">mailing list</a>.</p> @@ -3663,13 +4391,13 @@ welcome. Feel free to discuss this in ou </div> </div> <div class="sect2"> -<h3 id="_salesforce_connector">9.2. Salesforce Connector</h3> +<h3 id="_salesforce_connector">11.2. Salesforce Connector</h3> <div class="paragraph"> <p>This connectors makes it possible to push and pull data to/from the Salesforce CRM. It can copy information between Apache Unomi profiles and Salesforce Leads.</p> </div> <div class="sect3"> -<h4 id="_getting_started_2">9.2.1. Getting started</h4> +<h4 id="_getting_started_2">11.2.1. Getting started</h4> <div class="sect4"> <h5 id="_salesforce_account_setup">Salesforce account setup</h5> <div class="olist arabic"> @@ -3753,8 +4481,8 @@ If this is not the case or you prefer to <p>Deploy into Apache Unomi using the following commands from the Apache Karaf shell:</p> <div class="listingblock"> <div class="content"> -<pre class="highlight"><code>feature:repo-add mvn:org.apache.unomi/unomi-salesforce-connectors-karaf-kar/${project.version}/xml/features -feature:install unomi-salesforce-connectors-karaf-kar</code></pre> +<pre class="highlight"><code>feature:repo-add mvn:org.apache.unomi/unomi-salesforce-connector-karaf-kar/${project.version}/xml/features +feature:install unomi-salesforce-connector-karaf-kar</code></pre> </div> </div> </li> @@ -3812,7 +4540,7 @@ find more information about rules in the </div> </div> <div class="sect3"> -<h4 id="_properties">9.2.2. Properties</h4> +<h4 id="_properties">11.2.2. Properties</h4> <div class="paragraph"> <p>To define how Salesforce attributes will be mapped to Marketing Factory profile properties, edit the following entry using the pattern below :</p> </div> @@ -3832,7 +4560,7 @@ An identifier needs to be set as well. T </div> </div> <div class="sect3"> -<h4 id="_hot_deploying_updates_to_the_salesforce_connector_for_developers">9.2.3. Hot-deploying updates to the Salesforce connector (for developers)</h4> +<h4 id="_hot_deploying_updates_to_the_salesforce_connector_for_developers">11.2.3. Hot-deploying updates to the Salesforce connector (for developers)</h4> <div class="paragraph"> <p>If you followed all the steps in the Getting Started section, you can upgrade the Salesforce connectors by using the following steps:</p> </div> @@ -3842,7 +4570,7 @@ An identifier needs to be set as well. T <p>Compile the connectors using:</p> <div class="listingblock"> <div class="content"> -<pre class="highlight"><code>cd extensions/salesforce-connectors +<pre class="highlight"><code>cd extensions/salesforce-connector mvn clean install</code></pre> </div> </div> @@ -3860,8 +4588,8 @@ mvn clean install</code></pre> <div class="listingblock"> <div class="content"> <pre class="highlight"><code>feature:repo-refresh -feature:uninstall unomi-salesforce-connectors-karaf-feature -feature:install unomi-salesforce-connectors-karaf-feature</code></pre> +feature:uninstall unomi-salesforce-connector-karaf-feature +feature:install unomi-salesforce-connector-karaf-feature</code></pre> </div> </div> </li> @@ -3880,7 +4608,7 @@ feature:install unomi-salesforce-connect </div> </div> <div class="sect3"> -<h4 id="_using_the_salesforce_workbench_for_testing_rest_api">9.2.4. Using the Salesforce Workbench for testing REST API</h4> +<h4 id="_using_the_salesforce_workbench_for_testing_rest_api">11.2.4. Using the Salesforce Workbench for testing REST API</h4> <div class="paragraph"> <p>The Salesforce Workbench contains a REST API Explorer that is very useful to test requests. You may find it here :</p> </div> @@ -3891,7 +4619,7 @@ feature:install unomi-salesforce-connect </div> </div> <div class="sect3"> -<h4 id="_setting_up_streaming_push_queries">9.2.5. Setting up Streaming Push queries</h4> +<h4 id="_setting_up_streaming_push_queries">11.2.5. Setting up Streaming Push queries</h4> <div class="paragraph"> <p>Using the Salesforce Workbench, you can setting streaming push queries (Queries->Streaming push topics) such as the following example:</p> @@ -3904,7 +4632,7 @@ Query : SELECT Id,FirstName,LastName,Ema </div> </div> <div class="sect3"> -<h4 id="_executing_the_unit_tests">9.2.6. Executing the unit tests</h4> +<h4 id="_executing_the_unit_tests">11.2.6. Executing the unit tests</h4> <div class="paragraph"> <p>Before running the tests, make sure you have completed all the steps above, including the streaming push queries setup.</p> </div> @@ -3945,7 +4673,7 @@ sfdc.consumer.secret=CONNECTED_APP_SECRE </div> <div class="listingblock"> <div class="content"> -<pre class="highlight"><code>cd extensions/salesforce-connectors +<pre class="highlight"><code>cd extensions/salesforce-connector mvn clean install -DsfdcProperties=../test.properties</code></pre> </div> </div> @@ -3955,7 +4683,7 @@ mvn clean install -DsfdcProperties=../te </div> </div> <div class="sect2"> -<h3 id="_mailchimp_connector">9.3. MailChimp Connector</h3> +<h3 id="_mailchimp_connector">11.3. MailChimp Connector</h3> <div class="paragraph"> <p>This extension has 3 actions:</p> </div> @@ -3973,7 +4701,7 @@ mvn clean install -DsfdcProperties=../te </ul> </div> <div class="sect3"> -<h4 id="_getting_started_3">9.3.1. Getting started</h4> +<h4 id="_getting_started_3">11.3.1. Getting started</h4> <div class="olist arabic"> <ol class="arabic"> <li> @@ -4085,12 +4813,12 @@ The mapping can’t be use with mult </div> </div> <div class="sect1"> -<h2 id="_developers">10. Developers</h2> +<h2 id="_developers">12. Developers</h2> <div class="sectionbody"> <div class="sect2"> -<h3 id="_building">10.1. Building</h3> +<h3 id="_building">12.1. Building</h3> <div class="sect3"> -<h4 id="_initial_setup">10.1.1. Initial Setup</h4> +<h4 id="_initial_setup">12.1.1. Initial Setup</h4> <div class="olist arabic"> <ol class="arabic"> <li> @@ -4111,11 +4839,11 @@ the MVN_HOME/bin directory.</p> </div> </div> <div class="sect3"> -<h4 id="_building_2">10.1.2. Building</h4> +<h4 id="_building_2">12.1.2. Building</h4> <div class="olist arabic"> <ol class="arabic"> <li> -<p>Get the code: <code>git clone <a href="https://git-wip-us.apache.org/repos/asf/incubator-unomi.git" class="bare">https://git-wip-us.apache.org/repos/asf/incubator-unomi.git</a></code></p> +<p>Get the code: <code>git clone <a href="https://github.com/apache/unomi.git" class="bare">https://github.com/apache/unomi.git</a></code></p> </li> <li> <p>Change to the top level directory of Apache Unomi source distribution.</p> @@ -4148,7 +4876,7 @@ the MVN_HOME/bin directory.</p> </div> </div> <div class="sect3"> -<h4 id="_installing_an_elasticsearch_server">10.1.3. Installing an ElasticSearch server</h4> +<h4 id="_installing_an_elasticsearch_server">12.1.3. Installing an ElasticSearch server</h4> <div class="paragraph"> <p>Starting with version 1.2, Apache Unomi no longer embeds an ElasticSearch server as this is no longer supported by the developers of ElasticSearch. Therefore you will need to install a standalone ElasticSearch using the following steps:</p> @@ -4189,7 +4917,7 @@ bin\elasticsearch.bat (Windows)</code></ </div> </div> <div class="sect3"> -<h4 id="_deploying_the_generated_binary_package">10.1.4. Deploying the generated binary package</h4> +<h4 id="_deploying_the_generated_binary_package">12.1.4. Deploying the generated binary package</h4> <div class="paragraph"> <p>The "package" sub-project generates a pre-configured Apache Karaf installation that is the simplest way to get started. Simply uncompress the package/target/unomi-VERSION.tar.gz (for Linux or Mac OS X) or @@ -4222,7 +4950,7 @@ shell command:</p> </div> </div> <div class="sect3"> -<h4 id="_deploying_into_an_existing_karaf_server">10.1.5. Deploying into an existing Karaf server</h4> +<h4 id="_deploying_into_an_existing_karaf_server">12.1.5. Deploying into an existing Karaf server</h4> <div class="paragraph"> <p>This is only needed if you didn’t use the generated package. Also, this is the preferred way to install a development environment if you intend to re-deploy the context server KAR iteratively.</p> @@ -4269,7 +4997,7 @@ files (at the end of the file):</p> </div> </div> <div class="sect3"> -<h4 id="_jdk_selection_on_mac_os_x">10.1.6. JDK Selection on Mac OS X</h4> +<h4 id="_jdk_selection_on_mac_os_x">12.1.6. JDK Selection on Mac OS X</h4> <div class="paragraph"> <p>You might need to select the JDK to run the tests in the itests subproject. In order to do so you can list the installed JDKs with the following command :</p> @@ -4322,7 +5050,7 @@ Java HotSpot(TM) 64-Bit Server VM (build </div> </div> <div class="sect3"> -<h4 id="_running_the_integration_tests">10.1.7. Running the integration tests</h4> +<h4 id="_running_the_integration_tests">12.1.7. Running the integration tests</h4> <div class="paragraph"> <p>The integration tests are not executed by default to make build time minimal, but it is recommended to run the integration tests at least once before using the server to make sure that everything is ok in the build. Another way @@ -4342,7 +5070,7 @@ to use these tests is to run them from a </div> </div> <div class="sect3"> -<h4 id="_running_the_performance_tests">10.1.8. Running the performance tests</h4> +<h4 id="_running_the_performance_tests">12.1.8. Running the performance tests</h4> <div class="paragraph"> <p>Performance tests are based on Gatling. You need to have a running context server or cluster of servers before executing the tests.</p> @@ -4365,7 +5093,7 @@ contains the URLs of all your cluster no </div> </div> <div class="sect3"> -<h4 id="_testing_with_an_example_page">10.1.9. Testing with an example page</h4> +<h4 id="_testing_with_an_example_page">12.1.9. Testing with an example page</h4> <div class="paragraph"> <p>A default test page is provided at the following URL:</p> </div> @@ -4382,7 +5110,7 @@ doesn’t yet save the context back </div> </div> <div class="sect2"> -<h3 id="_ssh_shell_commands">10.2. SSH Shell Commands</h3> +<h3 id="_ssh_shell_commands">12.2. SSH Shell Commands</h3> <div class="paragraph"> <p>Apache Unomi provides its own Apache Karaf Shell commands to make it easy to control the application lifecycle or perform queries or modifications on the internal state of the system.</p> @@ -4392,7 +5120,7 @@ lifecycle or perform queries or modifica autocompletion to list all the commands available.</p> </div> <div class="sect3"> -<h4 id="_using_the_shell">10.2.1. Using the shell</h4> +<h4 id="_using_the_shell">12.2.1. Using the shell</h4> <div class="paragraph"> <p>You can connect to the Apache Karaf SSH Shell using the following command:</p> </div> @@ -4438,7 +5166,7 @@ ARGUMENTS </div> </div> <div class="sect3"> -<h4 id="_lifecycle_commands">10.2.2. Lifecycle commands</h4> +<h4 id="_lifecycle_commands">12.2.2. Lifecycle commands</h4> <div class="paragraph"> <p>The commands control the lifecycle of the Apache Unomi server and are used to migrate, start or stop the server.</p> </div> @@ -4481,7 +5209,7 @@ ARGUMENTS </table> </div> <div class="sect3"> -<h4 id="_runtime_commands">10.2.3. Runtime commands</h4> +<h4 id="_runtime_commands">12.2.3. Runtime commands</h4> <div class="paragraph"> <p>These commands are available once the application is running. If an argument is between brackets [] it means it is optional.</p> </div> @@ -4513,6 +5241,12 @@ value of rules registered in the server. <td class="tableblock halign-left valign-top"><p class="tableblock">Dumps a single rule in JSON. The rule-id argument can be retrieved from the <code>rule-list</code> command output.</p></td> </tr> <tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">rule-remove</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">rule-id</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">Removes a single rule from Apache Unomi. The <code>rule-id</code> argument can be retrieved from the <code>rule-list</code> command output. +Warning: no confirmation is asked, be careful with this command.</p></td> +</tr> +<tr> <td class="tableblock halign-left valign-top"><p class="tableblock">rule-reset-stats</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">n/a</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Resets the rule statistics. This is notably useful when trying to understand rule performance and impact</p></td> @@ -4545,6 +5279,18 @@ created, EXECUTE means the rule’s <td class="tableblock halign-left valign-top"><p class="tableblock">Dumps a single event in JSON. The <code>event-id</code> can be retrieved from the event-tail command output.</p></td> </tr> <tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">event-list</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">[max-entries] [--csv]</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">List the last events processed by Apache Unomi. The <code>max-entries</code> parameter can be used to control how many events are +displayed (default is 100). The <code>--csv</code> argument is used to output the list as a CSV list instead of an ASCII table.</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">event-search</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">profile-id [event-type] [max-entries]</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">This command makes it possible to search for the last events by <code>profile-id</code> and by <code>event-type</code>. A <code>max-entries</code> +parameter (with a default value of 100) is also accepted to control the number of results returned by the search.</p></td> +</tr> +<tr> <td class="tableblock halign-left valign-top"><p class="tableblock">action-list</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">[--csv]</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Lists all the rule actions registered in the Apache Unomi server. This command is useful when developing plugins to @@ -4576,10 +5322,14 @@ check that everything is properly regist <td class="tableblock halign-left valign-top"><p class="tableblock">Dumps a single profile in JSON. The profile-id argument can be retrieved from the <code>profile-list</code> command output.</p></td> </tr> <tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">profile-remove</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">profile-id</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">Removes a profile identified by <code>profile-id</code> argument. Warning: no confirmation is asked so be careful with this command!</p></td> +</tr> +<tr> <td class="tableblock halign-left valign-top"><p class="tableblock">segment-list</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">[--csv]</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Lists all the segments registered in the Apache Unomi server. If you add the "--csv" option the list will be output - as a CSV formatted table</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">Lists all the segments registered in the Apache Unomi server. If you add the "--csv" option the list will be output as a CSV formatted table</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">segment-view</p></td> @@ -4587,6 +5337,12 @@ check that everything is properly regist <td class="tableblock halign-left valign-top"><p class="tableblock">Dumps a single segment in JSON. The segment-id argument can be retrieved from the <code>segment-list</code> command output.</p></td> </tr> <tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">segment-remove</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">segment-id</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">Removes a single segment identified by the <code>segment-id</code> argument. Warning: no confirmation is asked so be careful with +this command!</p></td> +</tr> +<tr> <td class="tableblock halign-left valign-top"><p class="tableblock">session-list</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">[--csv]</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Lists the last 10 sessions by last event date. If you add the "--csv" option the list will be output @@ -4603,7 +5359,19 @@ check that everything is properly regist <td class="tableblock halign-left valign-top"><p class="tableblock">[bundleId] [type] [fileName]</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">This command can be used to force redeployment of definitions from bundles. By default existing definitions will not be overriden unless they come from SNAPSHOT bundles. Using this command you can override this mechanism. Here are some -examples of using this command: <code>unomi:deploy-definition 175 rule *</code> will redeploy all the rules provided by bundle with id 175. If you launch the command without any arguments you will get prompts for what you want to deploy from which bundle</p></td> +examples of using this command: <code>unomi:deploy-definition 175 rule *</code> will redeploy all the rules provided by bundle with +id 175. If you launch the command without any arguments you will get prompts for what you want to deploy from which bundle. +If you want to deploy all the definitions of a bundle you can also use wildcards such as in the following example: <code>deploy-definition 175 * *</code>. +It is also possible to give no argument to this command and it will then interactively request the definitions you want +to deploy.</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">undeploy-definition</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">[bundleId] [type] [fileName]</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">This command does the opposite of the <code>deploy-definition</code> command and works exactly the same way in terms of arguments +and interactive mode except that it undeploys definitions instead of deploying them. This command can be very useful when +working on a plugin. For example to remove all the definitions deployed by a plugin you can simply use the following +command: <code>undeploy-definition BUNDLE_ID * *</code> when <code>BUNDLE_ID</code> is the identifier of the bundle that contains your plugin.</p></td> </tr> </tbody> </table> @@ -4613,7 +5381,7 @@ examples of using this command: <code>un </div> </div> <div class="sect2"> -<h3 id="_types_vs_instances">10.3. Types vs. instances</h3> +<h3 id="_types_vs_instances">12.3. Types vs. instances</h3> <div class="paragraph"> <p>Several extension points in Unomi rely on the concept of type: the extension defines a prototype for what the actual items will be once parameterized with values known only at runtime. This is similar to the concept of classes in @@ -4622,7 +5390,7 @@ be provided at runtime, that are then in </div> </div> <div class="sect2"> -<h3 id="_plugin_structure">10.4. Plugin structure</h3> +<h3 id="_plugin_structure">12.4. Plugin structure</h3> <div class="paragraph"> <p>Being built on top of Apache Karaf, Unomi leverages OSGi to support plugins. A Unomi plugin is, thus, an OSGi bundle specifying some specific metadata to tell Unomi the kind of entities it provides. A plugin can provide the @@ -4704,78 +5472,78 @@ while some more involved plugins provide </div> </div> <div class="sect2"> -<h3 id="_extension_points">10.5. Extension points</h3> +<h3 id="_extension_points">12.5. Extension points</h3> <div class="sect3"> -<h4 id="_actiontype">10.5.1. ActionType</h4> +<h4 id="_actiontype">12.5.1. ActionType</h4> <div class="paragraph"> <p><code>ActionType`s define new actions that can be used as consequences of Rules being triggered. When a rule triggers, it creates new actions based on the event data and the rule internal processes, providing values for parameters defined in the associated `ActionType</code>. Example actions include: âSet user property x to value yâ or âSend a message to service xâ.</p> </div> </div> <div class="sect3"> -<h4 id="_conditiontype">10.5.2. ConditionType</h4> +<h4 id="_conditiontype">12.5.2. ConditionType</h4> <div class="paragraph"> <p>`ConditionType`s define new conditions that can be applied to items (for example to decide whether a rule needs to be triggered or if a profile is considered as taking part in a campaign) or to perform queries against the stored Unomi data. They may be implemented in Java when attempting to define a particularly complex test or one that can better be optimized by coding it. They may also be defined as combination of other conditions. A simple condition could be: âUser is maleâ, while a more generic condition with parameters may test whether a given property has a specific value: âUser property x has value yâ.</p> </div> </div> <div class="sect3"> -<h4 id="_persona">10.5.3. Persona</h4> +<h4 id="_persona">12.5.3. Persona</h4> <div class="paragraph"> <p>A persona is a "virtual" profile used to represent categories of profiles, and may also be used to test how a personalized experience would look like using this virtual profile. A persona can define predefined properties and sessions. Persona definition make it possible to âemulateâ a certain type of profile, e.g : US visitor, non-US visitor, etc.</p> </div> </div> <div class="sect3"> -<h4 id="_propertymergestrategytype">10.5.4. PropertyMergeStrategyType</h4> +<h4 id="_propertymergestrategytype">12.5.4. PropertyMergeStrategyType</h4> <div class="paragraph"> <p>A strategy to resolve how to merge properties when merging profile together.</p> </div> </div> <div class="sect3"> -<h4 id="_propertytype">10.5.5. PropertyType</h4> +<h4 id="_propertytype">12.5.5. PropertyType</h4> <div class="paragraph"> <p>Definition for a profile or session property, specifying how possible values are constrained, if the value is multi-valued (a vector of values as opposed to a scalar value). `PropertyType`s can also be categorized using systemTags or file system structure, using sub-directories to organize definition files.</p> </div> </div> <div class="sect3"> -<h4 id="_rule">10.5.6. Rule</h4>
[... 183 lines stripped ...]