Added: unomi/website/manual/latest/images/profile-alias-example.png
URL: 
http://svn.apache.org/viewvc/unomi/website/manual/latest/images/profile-alias-example.png?rev=1905673&view=auto
==============================================================================
Binary file - no diff available.

Propchange: unomi/website/manual/latest/images/profile-alias-example.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: unomi/website/manual/latest/images/profile-alias-external-ids.png
URL: 
http://svn.apache.org/viewvc/unomi/website/manual/latest/images/profile-alias-external-ids.png?rev=1905673&view=auto
==============================================================================
Binary file - no diff available.

Propchange: unomi/website/manual/latest/images/profile-alias-external-ids.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: unomi/website/manual/latest/images/profile-alias-overview.png
URL: 
http://svn.apache.org/viewvc/unomi/website/manual/latest/images/profile-alias-overview.png?rev=1905673&view=auto
==============================================================================
Binary file - no diff available.

Propchange: unomi/website/manual/latest/images/profile-alias-overview.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: unomi/website/manual/latest/index.html
URL: 
http://svn.apache.org/viewvc/unomi/website/manual/latest/index.html?rev=1905673&r1=1905672&r2=1905673&view=diff
==============================================================================
--- unomi/website/manual/latest/index.html (original)
+++ unomi/website/manual/latest/index.html Thu Dec  1 15:35:33 2022
@@ -22,13 +22,14 @@
 <ul class="sectlevel2">
 <li><a href="#_whats_new_in_apache_unomi_2_0">1.1. What&#8217;s new in Apache 
Unomi 2.0</a>
 <ul class="sectlevel3">
-<li><a href="#_scopes_declarations_are_now_required">1.1.1. Scopes 
declarations are now required</a></li>
-<li><a href="#_json_schemas">1.1.2. JSON Schemas</a></li>
-<li><a href="#_updated_data_model">1.1.3. Updated data model</a></li>
-<li><a href="#_new_web_tracker">1.1.4. New Web Tracker</a></li>
-<li><a href="#_graphql_api_beta">1.1.5. GraphQL API - beta</a></li>
-<li><a href="#_migrate_from_unomi_1_x">1.1.6. Migrate from Unomi 1.x</a></li>
-<li><a href="#_elasticsearch_compatibility">1.1.7. Elasticsearch 
compatibility</a></li>
+<li><a href="#_introducing_profiles_aliases">1.1.1. Introducing profiles 
aliases</a></li>
+<li><a href="#_scopes_declarations_are_now_required">1.1.2. Scopes 
declarations are now required</a></li>
+<li><a href="#_json_schemas">1.1.3. JSON Schemas</a></li>
+<li><a href="#_updated_data_model">1.1.4. Updated data model</a></li>
+<li><a href="#_new_web_tracker">1.1.5. New Web Tracker</a></li>
+<li><a href="#_graphql_api_beta">1.1.6. GraphQL API - beta</a></li>
+<li><a href="#_migrate_from_unomi_1_x">1.1.7. Migrate from Unomi 1.x</a></li>
+<li><a href="#_elasticsearch_compatibility">1.1.8. Elasticsearch 
compatibility</a></li>
 </ul>
 </li>
 </ul>
@@ -71,6 +72,7 @@
 <li><a href="#_how_to_search_for_profiles">3.1.7. How to search for 
profiles</a></li>
 <li><a href="#_getting_updating_consents">3.1.8. Getting / updating 
consents</a></li>
 <li><a href="#_how_to_send_a_login_event_to_unomi">3.1.9. How to send a login 
event to Unomi</a></li>
+<li><a href="#_what_profile_aliases_are_and_how_to_use_them">3.1.10. What 
profile aliases are and how to use them</a></li>
 </ul>
 </li>
 <li><a href="#_request_examples">3.2. Request examples</a>
@@ -245,7 +247,7 @@
 <li><a href="#_data_model_overview">13.4. Data Model Overview</a></li>
 <li><a href="#_scope">13.5. Scope</a>
 <ul class="sectlevel3">
-<li><a href="#_example">13.5.1. Example</a></li>
+<li><a href="#_example_2">13.5.1. Example</a></li>
 </ul>
 </li>
 <li><a href="#_item">13.6. Item</a>
@@ -256,13 +258,13 @@
 <li><a href="#_metadata">13.7. Metadata</a>
 <ul class="sectlevel3">
 <li><a href="#_structure_definition_2">13.7.1. Structure definition</a></li>
-<li><a href="#_example_2">13.7.2. Example</a></li>
+<li><a href="#_example_3">13.7.2. Example</a></li>
 </ul>
 </li>
 <li><a href="#_metadataitem">13.8. MetadataItem</a>
 <ul class="sectlevel3">
 <li><a href="#_structure_definition_3">13.8.1. Structure definition</a></li>
-<li><a href="#_example_3">13.8.2. Example</a></li>
+<li><a href="#_example_4">13.8.2. Example</a></li>
 </ul>
 </li>
 <li><a href="#_event">13.9. Event</a>
@@ -274,109 +276,115 @@
 <li><a href="#_profile">13.10. Profile</a>
 <ul class="sectlevel3">
 <li><a href="#_structure_definition_4">13.10.1. Structure definition</a></li>
-<li><a href="#_example_4">13.10.2. Example</a></li>
+<li><a href="#_example_5">13.10.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_persona">13.11. Persona</a>
+<li><a href="#_profile_aliases">13.11. Profile aliases</a>
 <ul class="sectlevel3">
 <li><a href="#_structure_definition_5">13.11.1. Structure definition</a></li>
-<li><a href="#_example_5">13.11.2. Example</a></li>
+<li><a href="#_example_6">13.11.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_consent">13.12. Consent</a>
+<li><a href="#_persona">13.12. Persona</a>
 <ul class="sectlevel3">
 <li><a href="#_structure_definition_6">13.12.1. Structure definition</a></li>
-<li><a href="#_example_6">13.12.2. Example</a></li>
+<li><a href="#_example_7">13.12.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_session">13.13. Session</a>
+<li><a href="#_consent">13.13. Consent</a>
 <ul class="sectlevel3">
 <li><a href="#_structure_definition_7">13.13.1. Structure definition</a></li>
-<li><a href="#_example_7">13.13.2. Example</a></li>
+<li><a href="#_example_8">13.13.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_segment">13.14. Segment</a>
+<li><a href="#_session">13.14. Session</a>
 <ul class="sectlevel3">
 <li><a href="#_structure_definition_8">13.14.1. Structure definition</a></li>
-<li><a href="#_example_8">13.14.2. Example</a></li>
+<li><a href="#_example_9">13.14.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_condition">13.15. Condition</a>
+<li><a href="#_segment">13.15. Segment</a>
 <ul class="sectlevel3">
 <li><a href="#_structure_definition_9">13.15.1. Structure definition</a></li>
-<li><a href="#_example_9">13.15.2. Example</a></li>
+<li><a href="#_example_10">13.15.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_rule">13.16. Rule</a>
+<li><a href="#_condition">13.16. Condition</a>
 <ul class="sectlevel3">
 <li><a href="#_structure_definition_10">13.16.1. Structure definition</a></li>
-<li><a href="#_example_10">13.16.2. Example</a></li>
+<li><a href="#_example_11">13.16.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_action">13.17. Action</a>
+<li><a href="#_rule">13.17. Rule</a>
 <ul class="sectlevel3">
 <li><a href="#_structure_definition_11">13.17.1. Structure definition</a></li>
-<li><a href="#_example_11">13.17.2. Example</a></li>
+<li><a href="#_example_12">13.17.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_list">13.18. List</a>
+<li><a href="#_action">13.18. Action</a>
 <ul class="sectlevel3">
 <li><a href="#_structure_definition_12">13.18.1. Structure definition</a></li>
-<li><a href="#_example_12">13.18.2. Example</a></li>
+<li><a href="#_example_13">13.18.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_goal">13.19. Goal</a>
+<li><a href="#_list">13.19. List</a>
 <ul class="sectlevel3">
 <li><a href="#_structure_definition_13">13.19.1. Structure definition</a></li>
-<li><a href="#_example_13">13.19.2. Example</a></li>
+<li><a href="#_example_14">13.19.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_campaign">13.20. Campaign</a>
+<li><a href="#_goal">13.20. Goal</a>
 <ul class="sectlevel3">
 <li><a href="#_structure_definition_14">13.20.1. Structure definition</a></li>
-<li><a href="#_example_14">13.20.2. Example</a></li>
+<li><a href="#_example_15">13.20.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_scoring_plan">13.21. Scoring plan</a>
+<li><a href="#_campaign">13.21. Campaign</a>
 <ul class="sectlevel3">
 <li><a href="#_structure_definition_15">13.21.1. Structure definition</a></li>
-<li><a href="#_example_15">13.21.2. Example</a></li>
+<li><a href="#_example_16">13.21.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_built_in_event_types">13.22. Built-in Event types</a>
+<li><a href="#_scoring_plan">13.22. Scoring plan</a>
 <ul class="sectlevel3">
-<li><a href="#_login_event_type">13.22.1. Login event type</a></li>
-<li><a href="#_view_event_type">13.22.2. View event type</a></li>
-<li><a href="#_form_event_type">13.22.3. Form event type</a></li>
-<li><a href="#_update_properties_event_type">13.22.4. Update properties event 
type</a></li>
-<li><a href="#_identify_event_type">13.22.5. Identify event type</a></li>
-<li><a href="#_session_created_event_type">13.22.6. Session created event 
type</a></li>
-<li><a href="#_goal_event_type">13.22.7. Goal event type</a></li>
-<li><a href="#_modify_consent_event_type">13.22.8. Modify consent event 
type</a></li>
+<li><a href="#_structure_definition_16">13.22.1. Structure definition</a></li>
+<li><a href="#_example_17">13.22.2. Example</a></li>
 </ul>
 </li>
-<li><a href="#_built_in_condition_types">13.23. Built-in condition types</a>
+<li><a href="#_built_in_event_types">13.23. Built-in Event types</a>
 <ul class="sectlevel3">
-<li><a href="#_existing_condition_type_descriptors">13.23.1. Existing 
condition type descriptors</a></li>
+<li><a href="#_login_event_type">13.23.1. Login event type</a></li>
+<li><a href="#_view_event_type">13.23.2. View event type</a></li>
+<li><a href="#_form_event_type">13.23.3. Form event type</a></li>
+<li><a href="#_update_properties_event_type">13.23.4. Update properties event 
type</a></li>
+<li><a href="#_identify_event_type">13.23.5. Identify event type</a></li>
+<li><a href="#_session_created_event_type">13.23.6. Session created event 
type</a></li>
+<li><a href="#_goal_event_type">13.23.7. Goal event type</a></li>
+<li><a href="#_modify_consent_event_type">13.23.8. Modify consent event 
type</a></li>
 </ul>
 </li>
-<li><a href="#_built_in_action_types">13.24. Built-in action types</a>
+<li><a href="#_built_in_condition_types">13.24. Built-in condition types</a>
 <ul class="sectlevel3">
-<li><a href="#_existing_action_types_descriptors">13.24.1. Existing action 
types descriptors</a></li>
+<li><a href="#_existing_condition_type_descriptors">13.24.1. Existing 
condition type descriptors</a></li>
 </ul>
 </li>
-<li><a href="#_updating_events_using_the_context_servlet">13.25. Updating 
Events Using the Context Servlet</a>
+<li><a href="#_built_in_action_types">13.25. Built-in action types</a>
 <ul class="sectlevel3">
-<li><a href="#_solution">13.25.1. Solution</a></li>
-<li><a href="#_defining_rules">13.25.2. Defining Rules</a></li>
+<li><a href="#_existing_action_types_descriptors">13.25.1. Existing action 
types descriptors</a></li>
 </ul>
 </li>
-<li><a href="#_unomi_web_tracker_reference">13.26. Unomi Web Tracker 
reference</a>
+<li><a href="#_updating_events_using_the_context_servlet">13.26. Updating 
Events Using the Context Servlet</a>
 <ul class="sectlevel3">
-<li><a href="#_custom_events">13.26.1. Custom events</a></li>
-<li><a href="#_integrating_with_tag_managers">13.26.2. Integrating with tag 
managers</a></li>
-<li><a href="#_cookiesession_handling">13.26.3. Cookie/session 
handling</a></li>
-<li><a href="#_javascript_api">13.26.4. JavaScript API</a></li>
+<li><a href="#_solution">13.26.1. Solution</a></li>
+<li><a href="#_defining_rules">13.26.2. Defining Rules</a></li>
+</ul>
+</li>
+<li><a href="#_unomi_web_tracker_reference">13.27. Unomi Web Tracker 
reference</a>
+<ul class="sectlevel3">
+<li><a href="#_custom_events">13.27.1. Custom events</a></li>
+<li><a href="#_integrating_with_tag_managers">13.27.2. Integrating with tag 
managers</a></li>
+<li><a href="#_cookiesession_handling">13.27.3. Cookie/session 
handling</a></li>
+<li><a href="#_javascript_api">13.27.4. JavaScript API</a></li>
 </ul>
 </li>
 </ul>
@@ -397,7 +405,7 @@
 <li><a 
href="#_retrieving_context_information_from_unomi_using_the_context_servlet">14.3.3.
 Retrieving context information from Unomi using the context servlet</a></li>
 </ul>
 </li>
-<li><a href="#_example_24">14.4. Example</a>
+<li><a href="#_example_26">14.4. Example</a>
 <ul class="sectlevel3">
 <li><a href="#_html_page">14.4.1. HTML page</a></li>
 <li><a href="#_javascript">14.4.2. Javascript</a></li>
@@ -505,14 +513,22 @@
 <div class="sect2">
 <h3 id="_whats_new_in_apache_unomi_2_0">1.1. What&#8217;s new in Apache Unomi 
2.0</h3>
 <div class="paragraph">
-<p>Apache Unomi 2 is a new release focused on improving core functionalities 
and robustness of the product.
-The introduction of tighter data validation with JSON Schemas required some 
changes in the product data model, which presented an opportunity for 
noticeable improvements in the overall performance.</p>
+<p>Apache Unomi 2 is a new release focused on improving core functionalities 
and robustness of the product.</p>
+</div>
+<div class="paragraph">
+<p>The introduction of tighter data validation with JSON Schemas required some 
changes in the product data model, which presented an opportunity for 
noticeable improvements in the overall performance.</p>
 </div>
 <div class="paragraph">
 <p>This new release also introduces a first (beta) version of the Unomi 
GraphQL API.</p>
 </div>
 <div class="sect3">
-<h4 id="_scopes_declarations_are_now_required">1.1.1. Scopes declarations are 
now required</h4>
+<h4 id="_introducing_profiles_aliases">1.1.1. Introducing profiles aliases</h4>
+<div class="paragraph">
+<p>Profiles may now have alias IDs, which is a new way to reference profiles 
using multiple IDs. The Unomi ID still exists, but a new index with aliases can 
reference a single Unomi profile. This enables more flexible integrations with 
external systems, as well as provide more flexible and reliable merging 
mechanisms. A new REST API makes it easy to define, update and remove aliases 
for profiles. You can read more about <a 
href="#_what_profile_aliases_are_and_how_to_use_them">profile aliases 
here</a>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_scopes_declarations_are_now_required">1.1.2. Scopes declarations are 
now required</h4>
 <div class="paragraph">
 <p>Scopes declarations are now required in Unomi 2. When submitting an event 
and specifying a scope,
 that scope must already be declared on the platform.</p>
@@ -536,7 +552,7 @@ that scope must already be declared on t
 </div>
 </div>
 <div class="sect3">
-<h4 id="_json_schemas">1.1.2. JSON Schemas</h4>
+<h4 id="_json_schemas">1.1.3. JSON Schemas</h4>
 <div class="paragraph">
 <p>Apache Unomi 2 introduces support for <a 
href="https://json-schema.org/specification.html";>JSON Schema</a> for all of 
its publicly exposed endpoints.
 Data received by Apache Unomi 2 will first be validated against a known schema 
to make sure it complies with an expected payload.
@@ -550,7 +566,7 @@ If the received payload does not match a
 </div>
 </div>
 <div class="sect3">
-<h4 id="_updated_data_model">1.1.3. Updated data model</h4>
+<h4 id="_updated_data_model">1.1.4. Updated data model</h4>
 <div class="paragraph">
 <p>The introduction of JSON schema required us to modify Apache Unomi data 
model, One of the key differences is the removal of open maps.</p>
 </div>
@@ -645,21 +661,23 @@ stored as flattened and will not create
 </div>
 </div>
 <div class="paragraph">
-<p>If using the default Apache 1.x data model, our Unomi 2 migration process 
will handle the data model changes for you.
-If you are using custom events/objects, please refer to the detailed migration 
guide for more details.</p>
+<p>If using the default Apache 1.x data model, our Unomi 2 migration process 
will handle the data model changes for you.</p>
+</div>
+<div class="paragraph">
+<p>If you are using custom events/objects, please refer to the detailed <a 
href="#_migration_overview">migration guide</a> for more details.</p>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_new_web_tracker">1.1.4. New Web Tracker</h4>
+<h4 id="_new_web_tracker">1.1.5. New Web Tracker</h4>
 <div class="paragraph">
 <p>Apache Unomi 2.0 Web Tracker, located in 
<code>extensions/web-tracker/</code> has been completely rewritten. It is no 
longer based on an external library and is fully self-sufficient. It is based 
on an external contribution that has been used in production on many sites.</p>
 </div>
 <div class="paragraph">
-<p>You can find more information about the new web tracker here: [TODO ADD 
LINK]</p>
+<p>You can find more information about the <a 
href="#_unomi_web_tracking_tutorial">new web tracker here</a>.</p>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_graphql_api_beta">1.1.5. GraphQL API - beta</h4>
+<h4 id="_graphql_api_beta">1.1.6. GraphQL API - beta</h4>
 <div class="paragraph">
 <p>Apache Unomi 2.0 sees the introduction of a new (beta) GraphQL API.
 Available behind a feature flag (the API disabled by default), the GraphQL API 
is available for you to play with.</p>
@@ -672,7 +690,7 @@ Available behind a feature flag (the API
 </div>
 </div>
 <div class="sect3">
-<h4 id="_migrate_from_unomi_1_x">1.1.6. Migrate from Unomi 1.x</h4>
+<h4 id="_migrate_from_unomi_1_x">1.1.7. Migrate from Unomi 1.x</h4>
 <div class="paragraph">
 <p>To facilitate migration we prepared a set of scripts that will 
automatically handle the migration of your data from Apache Unomi 1.5+ to 
Apache Unomi 2.0.</p>
 </div>
@@ -686,7 +704,7 @@ More details about migration (incl. of c
 </div>
 </div>
 <div class="sect3">
-<h4 id="_elasticsearch_compatibility">1.1.7. Elasticsearch compatibility</h4>
+<h4 id="_elasticsearch_compatibility">1.1.8. Elasticsearch compatibility</h4>
 <div class="paragraph">
 <p>We currently recommend using Elasticsearch 7.17.5 with Apache Unomi 2.0,
 this ensure you are on a recent version that is not impacted by the log4j 
vulnerabilities (fixed in Elasticsearch 7.16.3).</p>
@@ -866,22 +884,25 @@ requests you can do once your server is
 <div class="paragraph">
 <p>In this tutorial we will guide through the basic steps of getting started 
with a web tracking project. You will see how to integrate the built-in web 
tracker with an existing web site and what this enables.</p>
 </div>
+<div class="paragraph">
+<p>If you prefer to use existing HTML and Javascript rather than building your 
own, all the code we feature in this tutorial is extracted from our tracker 
sample which is available here: <a 
href="https://github.com/apache/unomi/blob/master/extensions/web-tracker/wab/src/main/webapp/index.html";
 
class="bare">https://github.com/apache/unomi/blob/master/extensions/web-tracker/wab/src/main/webapp/index.html</a>
 . However you will still need to use the REST API calls to create the scope 
and rule to make it all work.</p>
+</div>
 <div class="sect3">
 <h4 id="_installing_the_web_tracker_in_a_web_page">2.4.1. Installing the web 
tracker in a web page</h4>
 <div class="paragraph">
 <p>Using the built-in tracker is pretty simple, simply add the following code 
to your HTML page :</p>
 </div>
-<div class="literalblock">
+<div class="listingblock">
 <div class="content">
-<pre>&lt;script type="text/javascript" 
src="/tracker/unomi-web-tracker.min.js"&gt;&lt;/script&gt;</pre>
+<pre class="highlight"><code class="language-javascript" 
data-lang="javascript">    &lt;script type="text/javascript" 
src="/tracker/unomi-web-tracker.min.js"&gt;&lt;/script&gt;</code></pre>
 </div>
 </div>
 <div class="paragraph">
 <p>or you can also use the non-minified version that is available here:</p>
 </div>
-<div class="literalblock">
+<div class="listingblock">
 <div class="content">
-<pre>&lt;script type="text/javascript" 
src="/tracker/unomi-web-tracker.js"&gt;&lt;/script&gt;</pre>
+<pre class="highlight"><code class="language-javascript" 
data-lang="javascript">    &lt;script type="text/javascript" 
src="/tracker/unomi-web-tracker.js"&gt;&lt;/script&gt;</code></pre>
 </div>
 </div>
 <div class="paragraph">
@@ -948,7 +969,7 @@ requests you can do once your server is
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code class="language-sh" data-lang="sh">curl 
--location --request POST 'http://localhost:8181/cxs/scopes' \
+<pre class="highlight"><code class="language-shell" data-lang="shell">curl 
--location --request POST 'http://localhost:8181/cxs/scopes' \
   --header 'Authorization: Basic a2FyYWY6a2FyYWY=' \
   --header 'Content-Type: application/json' \
   --data-raw '{
@@ -977,9 +998,9 @@ requests you can do once your server is
 <div class="paragraph">
 <p>Here&#8217;s an example on how to use it:</p>
 </div>
-<div class="literalblock">
+<div class="listingblock">
 <div class="content">
-<pre>yarn add apache-unomi-tracker</pre>
+<pre class="highlight"><code class="language-shell" data-lang="shell">    yarn 
add apache-unomi-tracker</code></pre>
 </div>
 </div>
 <div class="paragraph">
@@ -1047,7 +1068,7 @@ requests you can do once your server is
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code class="language-sh" data-lang="sh">curl 
--location --request POST 'http://localhost:8181/cxs/events/search' \
+<pre class="highlight"><code class="language-shell" data-lang="shell">curl 
--location --request POST 'http://localhost:8181/cxs/events/search' \
   --header 'Authorization: Basic a2FyYWY6a2FyYWY=' \
   --header 'Content-Type: application/json' \
   --data-raw '{
@@ -1061,9 +1082,9 @@ requests you can do once your server is
 <div class="paragraph">
 <p>Another (powerful) way to look at events is to use the SSH Console. You can 
connect to it with the following shell command:</p>
 </div>
-<div class="literalblock">
+<div class="listingblock">
 <div class="content">
-<pre>ssh -p 8102 karaf@localhost</pre>
+<pre class="highlight"><code class="language-shell" data-lang="shell">    ssh 
-p 8102 karaf@localhost</code></pre>
 </div>
 </div>
 <div class="paragraph">
@@ -1102,7 +1123,7 @@ Another interesting command is <code>pro
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code class="language-sh" data-lang="sh">curl 
--location --request GET 'http://localhost:8181/cxs/profiles/PROFILE_UUID' \
+<pre class="highlight"><code class="language-shell" data-lang="shell">curl 
--location --request GET 'http://localhost:8181/cxs/profiles/PROFILE_UUID' \
 --header 'Authorization: Basic a2FyYWY6a2FyYWY=' \</code></pre>
 </div>
 </div>
@@ -1117,7 +1138,7 @@ Another interesting command is <code>pro
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code class="language-sh" data-lang="sh">curl 
--location --request POST 'http://localhost:8181/cxs/rules' \
+<pre class="highlight"><code class="language-shell" data-lang="shell">curl 
--location --request POST 'http://localhost:8181/cxs/rules' \
 --header 'Authorization: Basic a2FyYWY6a2FyYWY=' \
 --header 'Content-Type: application/json' \
 --data-raw '{
@@ -1156,7 +1177,7 @@ Another interesting command is <code>pro
 <div class="sect3">
 <h4 id="_adding_personalization">2.4.7. Adding personalization</h4>
 <div class="paragraph">
-<p>The last step is to use the newly added property to the profile to perform 
some page personalization. In order to do that we will use the tracker&#8217;s 
API to register a personalization that will be</p>
+<p>The last step is to use the newly added property to the profile to perform 
some page personalization. In order to do that we will use the tracker&#8217;s 
API to register a personalization that will be using a condition that checks if 
the <code>pageViewCount</code> is higher than 5. If it has, 
<code>variant1</code> will be displayed, otherwise the fallback variant 
<code>variant2</code> will be used instead.</p>
 </div>
 <div class="listingblock">
 <div class="content">
@@ -1178,7 +1199,7 @@ Another interesting command is <code>pro
                         "condition": {
                             "type": "profilePropertyCondition",
                             "parameterValues": {
-                                "propertyName" : "properties.pageViewCount",
+                                "propertyName" : 
"properties.pageViewCount.&lt;scope&gt;",
                                 "comparisonOperator" : "greaterThan",
                                 "propertyValueInteger" : 5
                             }
@@ -1194,6 +1215,25 @@ Another interesting command is <code>pro
             });</code></pre>
 </div>
 </div>
+<div class="paragraph">
+<p>As you can see in the above code snippet, a <code>variants</code> array is 
created with two objects that associated personalization IDs with content IDs. 
Then we build the personalization object that contains the two IDs and their 
associated conditions (only a condition on <code>var1</code> is passed in this 
case) as well as an option to indicate which is the fallback variant in case no 
conditions are matched.</p>
+</div>
+<div class="paragraph">
+<p>The HTML part of this example looks like this:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-html" data-lang="html">    
&lt;div id="variant1" style="display: none"&gt;
+        You have already seen this page 5 times
+    &lt;/div&gt;
+    &lt;div id="variant2" style="display: none"&gt;
+        Welcome. Please reload this page 5 times until it triggers the 
personalization change
+    &lt;/div&gt;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>As you can see we hide the variants by default so that there is no 
"flashing" effect and then use the callback function to display to variant 
resolve by Unomi&#8217;s personalization engine.</p>
+</div>
 </div>
 <div class="sect3">
 <h4 id="_conclusion">2.4.8. Conclusion</h4>
@@ -1203,24 +1243,47 @@ Another interesting command is <code>pro
 <div class="ulist">
 <ul>
 <li>
-<p>Installed a tracker
--</p>
+<p>Installed a tracker in a web page</p>
+</li>
+<li>
+<p>Created a scope in which to collect the data</p>
+</li>
+<li>
+<p>Learned how to use the tracker as an NPM library</p>
+</li>
+<li>
+<p>How to view the collected events</p>
+</li>
+<li>
+<p>How to view the current visitor profile</p>
+</li>
+<li>
+<p>How to add a rule to update a profile property</p>
+</li>
+<li>
+<p>How to personalize a web page&#8217;s content based on the property updated 
by the rule</p>
 </li>
 </ul>
 </div>
+<div class="paragraph">
+<p>Of course this tutorial is just one example of what could be achieved, and 
hasn&#8217;t even yet introduced more advanced notions such as profile 
segmentation or Groovy action scripting. The system is capable of much more, 
for example by directly using its actions to integrate with third-party systems 
(CRM, social networks, etc..)</p>
+</div>
 </div>
 <div class="sect3">
 <h4 id="_next_steps">2.4.9. Next steps</h4>
 <div class="ulist">
 <ul>
 <li>
-<p>Learn more about the tracker, custom events, API, etc&#8230;&#8203;</p>
+<p>Learn more about the <a href="#_unomi_web_tracker_reference">web tracker, 
custom events, API, &#8230;&#8203;</a></p>
+</li>
+<li>
+<p>Learn more about <a href="#_segment">segmentation</a></p>
 </li>
 <li>
-<p>Learn more about segmentation,</p>
+<p>View some more <a href="#_integration_samples">samples</a></p>
 </li>
 <li>
-<p>Read Unomi&#8217;s user manual to see all that is possible with this 
technology</p>
+<p>Continue reading Unomi&#8217;s user manual to see all that is possible with 
this technology</p>
 </li>
 </ul>
 </div>
@@ -1817,6 +1880,139 @@ a single profile. Because of the merge,
 security issue since it could be a way to load data from other profiles by 
merging their data !</p>
 </div>
 </div>
+<div class="sect3">
+<h4 id="_what_profile_aliases_are_and_how_to_use_them">3.1.10. What profile 
aliases are and how to use them</h4>
+<div class="paragraph">
+<p>Profile aliases make it possible to reference profiles using multiple 
identifiers.
+The profile alias object basically contains a link between the alias ID and 
the profile ID. The <code>itemId</code> of a profile alias is the actual alias 
ID, which the <code>profileID</code> field contains the reference to the 
aliased profile.</p>
+</div>
+<div class="sect4">
+<h5 id="_what_they_are">What they are</h5>
+<div class="imageblock">
+<div class="content">
+<img src="images/profile-alias-overview.png" alt="Profile alias overview">
+</div>
+</div>
+<div class="paragraph">
+<p>Profile aliases:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Make it possible to lookup profiles by main (Unomi) ID or by any other 
alias ID</p>
+</li>
+<li>
+<p>Aliases are just IDs stored in a dedicated index</p>
+</li>
+<li>
+<p>A profile may have an unlimited number of aliases attached to it.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_how_to_use_them">How to use them</h5>
+<div class="imageblock">
+<div class="content">
+<img src="images/profile-alias-external-ids.png" alt="Profile with external 
IDs">
+</div>
+</div>
+<div class="paragraph">
+<p>Here are different use cases for profile aliases:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Connect different systems to Unomi such as a CRM, CMS and native mobile app 
that all have their own iD for a single customer</p>
+</li>
+<li>
+<p>Merging profiles when a visitor is identified</p>
+</li>
+<li>
+<p>Adding new IDs at a later time</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_example">Example</h5>
+<div class="paragraph">
+<p>Here is an example of multiple external aliases pointing to a single Unomi 
profile</p>
+</div>
+<div class="imageblock">
+<div class="content">
+<img src="images/profile-alias-example.png" alt="Profile alias example">
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_interactions_with_merging">Interactions with merging</h5>
+<div class="paragraph">
+<p>Profile merges have been modified to use aliases starting Unomi 2</p>
+</div>
+<div class="paragraph">
+<p>Upon merge:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Properties are copied to the master profile as before</p>
+</li>
+<li>
+<p>An alias is created for the "master" profile with the ID of the merged 
profile</p>
+</li>
+<li>
+<p>Merged profiles are now deleted</p>
+</li>
+<li>
+<p>"mergedWith" property is no longer used since we deleted the merged 
profiles</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_api">API</h5>
+<div class="paragraph">
+<p>/context.json and /eventcollector will now look up profiles by profile ID 
or aliases from the same cookie (<code>context-profile-id</code>) or body 
parameters (<code>profileId</code>)</p>
+</div>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 33.3333%;">
+<col style="width: 33.3334%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Verb</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Path</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">GET</p></td>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">/cxs/profiles/PROFILE_ID_OR_ALIAS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Retrieves 
a profile by ID or Alias ID (useful if an external system wants to get a 
profile)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">GET</p></td>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">/cxs/profiles/PROFILE_ID/aliases</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Get all 
the aliases for a profile</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">POST</p></td>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">/cxs/profiles/PROFILE_ID/aliases/ALIAS_ID</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Add an 
alias to a profile</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">DELETE</p></td>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">/cxs/profiles/PROFILE_ID/aliases/ALIAS_ID</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Remove an 
alias from a profile</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
 </div>
 <div class="sect2">
 <h3 id="_request_examples">3.2. Request examples</h3>
@@ -5440,7 +5636,7 @@ For example, when using scopes with a we
 </blockquote>
 </div>
 <div class="sect3">
-<h4 id="_example">13.5.1. Example</h4>
+<h4 id="_example_2">13.5.1. Example</h4>
 <div class="paragraph">
 <p>In the following example, the scope uses the unique identifier of a web 
site called “digitall”.</p>
 </div>
@@ -5597,7 +5793,7 @@ It is usually associated with an Item ob
 </table>
 </div>
 <div class="sect3">
-<h4 id="_example_2">13.7.2. Example</h4>
+<h4 id="_example_3">13.7.2. Example</h4>
 <div class="paragraph">
 <p>This example of a Metadata object structure was taken from a List 
associated object.
 See the MetadataItem to understand how the two fit together.</p>
@@ -5650,7 +5846,7 @@ See the MetadataItem to understand how t
 </table>
 </div>
 <div class="sect3">
-<h4 id="_example_3">13.8.2. Example</h4>
+<h4 id="_example_4">13.8.2. Example</h4>
 <div class="paragraph">
 <p>The following example is actually the definition of a <a 
href="#_list">List</a> object, which is simply a <a 
href="#_metadataitem">MetadataItem</a> sub-type with no additional fields.
 We can see here the “itemId” and “itemType” fields that come from the 
Item parent class and the “metadata” field that contains the object 
structure coming from the Metadata object type.</p>
@@ -5849,7 +6045,7 @@ action in a context where the user hadn�
 </table>
 </div>
 <div class="sect3">
-<h4 id="_example_4">13.10.2. Example</h4>
+<h4 id="_example_5">13.10.2. Example</h4>
 <div class="paragraph">
 <p>In the example below, a profile for a visitor called “Bill Galileo” is 
detailed.
 A lot of user properties (such as first name, last name, gender, job title and 
more) were copied over from the CMS upon initial login.
@@ -5960,14 +6156,74 @@ It has also been engaged in some goals (
 </div>
 </div>
 <div class="sect2">
-<h3 id="_persona">13.11. Persona</h3>
+<h3 id="_profile_aliases">13.11. Profile aliases</h3>
+<div class="paragraph">
+<p>Profile aliases make it possible to reference profiles using multiple 
identifiers.
+The profile alias object basically contains a link between the alias ID and 
the profile ID. The <code>itemId</code> of a profile alias is the actual alias 
ID, which the <code>profileID</code> field contains the reference to the 
aliased profile.</p>
+</div>
+<div class="sect3">
+<h4 id="_structure_definition_5">13.11.1. Structure definition</h4>
+<div class="paragraph">
+<p>Inherits all the fields from: <a href="#_item">Item</a></p>
+</div>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 33.3333%;">
+<col style="width: 33.3334%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Field name</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">profileID</p></td>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">String</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The 
identifier of the profile this aliases points to</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">creationTime</p></td>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">DateTime</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The date 
and time of creation of the alias</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">modifiedTime</p></td>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">DateTime</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The date 
and time of last modification of the alias</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_example_6">13.11.2. Example</h4>
+<div class="paragraph">
+<p>In the following example we show an alias ID <code>facebook_johndoe</code> 
for the profile with ID <code>f72242d2-3145-43b1-8be7-d1d47cf4ad0e</code></p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-json" data-lang="json">    {
+      "profileID": "f72242d2-3145-43b1-8be7-d1d47cf4ad0e",
+      "itemId" : "facebook_johndoe",
+      "creationTime" : "2022-09-16T19:23:51Z",
+      "modifiedTime" : "2022-09-16T19:23:51Z"
+    }</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_persona">13.12. Persona</h3>
 <div class="paragraph">
 <p>A persona is a specialized version of a <a href="#_profile">Profile</a> 
object. It basically represents a "typical" profile and can be used
 notably to simulate personalized for a type of profiles. Usually personas are 
created from Profile data and then edited
 to represent a specific marketing persona.</p>
 </div>
 <div class="sect3">
-<h4 id="_structure_definition_5">13.11.1. Structure definition</h4>
+<h4 id="_structure_definition_6">13.12.1. Structure definition</h4>
 <div class="paragraph">
 <p>Inherits all the fields from: <a href="#_profile">Profile</a></p>
 </div>
@@ -5976,7 +6232,7 @@ to represent a specific marketing person
 </div>
 </div>
 <div class="sect3">
-<h4 id="_example_5">13.11.2. Example</h4>
+<h4 id="_example_7">13.12.2. Example</h4>
 <div class="paragraph">
 <p>In the following example a Persona represents a visitor from Europe, that 
can be used to match by location.</p>
 </div>
@@ -6001,13 +6257,13 @@ to represent a specific marketing person
 </div>
 </div>
 <div class="sect2">
-<h3 id="_consent">13.12. Consent</h3>
+<h3 id="_consent">13.13. Consent</h3>
 <div class="paragraph">
 <p>A consent represents a single instance of a consent granted/refused or 
revoked by a profile.
 A profile will contain multiple instances of consent identified by unique 
identifiers.</p>
 </div>
 <div class="sect3">
-<h4 id="_structure_definition_6">13.12.1. Structure definition</h4>
+<h4 id="_structure_definition_7">13.13.1. Structure definition</h4>
 <div class="paragraph">
 <p>Inherits all the fields from: n/a</p>
 </div>
@@ -6054,7 +6310,7 @@ A profile will contain multiple instance
 </table>
 </div>
 <div class="sect3">
-<h4 id="_example_6">13.12.2. Example</h4>
+<h4 id="_example_8">13.13.2. Example</h4>
 <div class="paragraph">
 <p>In this example, the consent called “newsletter” was given on the 
“digitall” website.</p>
 </div>
@@ -6072,13 +6328,13 @@ A profile will contain multiple instance
 </div>
 </div>
 <div class="sect2">
-<h3 id="_session">13.13. Session</h3>
+<h3 id="_session">13.14. Session</h3>
 <div class="paragraph">
 <p>A session represents a period of time during which a visitor/profile has 
been active.
 It makes it possible to gather data and then use it for reporting and further 
analysis by regrouping all the events that occurred during the session.</p>
 </div>
 <div class="sect3">
-<h4 id="_structure_definition_7">13.13.1. Structure definition</h4>
+<h4 id="_structure_definition_8">13.14.1. Structure definition</h4>
 <div class="paragraph">
 <p>Inherits all the fields from: <a href="#_item">Item</a></p>
 </div>
@@ -6135,7 +6391,7 @@ It makes it possible to gather data and
 </table>
 </div>
 <div class="sect3">
-<h4 id="_example_7">13.13.2. Example</h4>
+<h4 id="_example_9">13.14.2. Example</h4>
 <div class="paragraph">
 <p>In this example the session contains a copy of the profile of the visitor.
 It is a visitor that has previously authentified in a CMS and who’se 
information was copied at the time of login from the CMS user account to the 
profile.
@@ -6243,7 +6499,7 @@ The visitor’s location is also reso
 </div>
 </div>
 <div class="sect2">
-<h3 id="_segment">13.14. Segment</h3>
+<h3 id="_segment">13.15. Segment</h3>
 <div class="paragraph">
 <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.</p>
@@ -6253,7 +6509,7 @@ if they are part of a segment or not.</p
 highly dynamic concept.</p>
 </div>
 <div class="sect3">
-<h4 id="_structure_definition_8">13.14.1. Structure definition</h4>
+<h4 id="_structure_definition_9">13.15.1. Structure definition</h4>
 <div class="paragraph">
 <p>Inherits all the fields from: <a href="#_metadataitem">MetadataItem</a></p>
 </div>
@@ -6280,7 +6536,7 @@ highly dynamic concept.</p>
 </table>
 </div>
 <div class="sect3">
-<h4 id="_example_8">13.14.2. Example</h4>
+<h4 id="_example_10">13.15.2. Example</h4>
 <div class="listingblock">
 <div class="content">
 <pre class="highlight"><code class="language-json" data-lang="json">{
@@ -6366,7 +6622,7 @@ EOF</code></pre>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_condition">13.15. Condition</h3>
+<h3 id="_condition">13.16. Condition</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>
@@ -6404,7 +6660,7 @@ Composition is an essential element of b
 <p>For a more complete list of available condition types, see the <a 
href="#_built_in_condition_types">Built-in condition types</a> reference 
section.</p>
 </div>
 <div class="sect3">
-<h4 id="_structure_definition_9">13.15.1. Structure definition</h4>
+<h4 id="_structure_definition_10">13.16.1. Structure definition</h4>
 <div class="paragraph">
 <p>Inherits all the fields from: n/a</p>
 </div>
@@ -6440,7 +6696,7 @@ that contains a list of conditions to ev
 </table>
 </div>
 <div class="sect3">
-<h4 id="_example_9">13.15.2. Example</h4>
+<h4 id="_example_11">13.16.2. Example</h4>
 <div class="paragraph">
 <p>Here is an example of a complex condition:</p>
 </div>
@@ -6477,7 +6733,7 @@ or <code>sessionReassigned</code>.</p>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_rule">13.16. Rule</h3>
+<h3 id="_rule">13.17. Rule</h3>
 <div class="imageblock">
 <div class="content">
 <img src="images/unomi-rule-engine.png" alt="Unomi Rule Engine">
@@ -6507,7 +6763,7 @@ You can imagine conditions checking inco
 <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="_structure_definition_10">13.16.1. Structure definition</h4>
+<h4 id="_structure_definition_11">13.17.1. Structure definition</h4>
 <div class="paragraph">
 <p>Inherits all the fields from: <a href="#_metadataitem">MetadataItem</a></p>
 </div>
@@ -6564,7 +6820,7 @@ You can imagine conditions checking inco
 </table>
 </div>
 <div class="sect3">
-<h4 id="_example_10">13.16.2. Example</h4>
+<h4 id="_example_12">13.17.2. Example</h4>
 <div class="paragraph">
 <p>In this example we can see the default <code>updateProperties</code> 
built-in rule that matches the <code>updateProperties</code> event and
 executes the built-in <code>updatePropertiesAction</code></p>
@@ -6606,7 +6862,7 @@ executes the built-in <code>updateProper
 </div>
 </div>
 <div class="sect2">
-<h3 id="_action">13.17. Action</h3>
+<h3 id="_action">13.18. Action</h3>
 <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
@@ -6622,7 +6878,7 @@ an IP address),  or even pulling and/or
 You may find the list of built-in action types in the <a 
href="#_built_in_action_types">Built-in action types</a> section.</p>
 </div>
 <div class="sect3">
-<h4 id="_structure_definition_11">13.17.1. Structure definition</h4>
+<h4 id="_structure_definition_12">13.18.1. Structure definition</h4>
 <div class="paragraph">
 <p>Inherits all the fields from: n/a</p>
 </div>
@@ -6654,7 +6910,7 @@ You may find the list of built-in action
 </table>
 </div>
 <div class="sect3">
-<h4 id="_example_11">13.17.2. Example</h4>
+<h4 id="_example_13">13.18.2. Example</h4>
 <div class="paragraph">
 <p>In this example of an action, taking from the 
<code>form-mapping-example.json</code> rule, the <code>setPropertyAction</code> 
action is used
 to set the <code>properties.firstName</code> profile property to a value read 
from the event properties called <code>properties.firstName</code>.
@@ -6676,7 +6932,7 @@ overridden or not.</p>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_list">13.18. List</h3>
+<h3 id="_list">13.19. List</h3>
 <div class="paragraph">
 <p>Lists are a “manual” way to organize profiles, whereas Segments are a 
dynamic way to regroup them.
 List objects actually only define the list in terms of name, description and 
other metadata but the list of members is actually not represented in the 
object.
@@ -6684,7 +6940,7 @@ The profiles contain references to the l
 This property is an array of list identifiers so in order to retrieve all the 
list names for a given profile, a lookup of List objects is required using the 
identifiers.</p>
 </div>
 <div class="sect3">
-<h4 id="_structure_definition_12">13.18.1. Structure definition</h4>
+<h4 id="_structure_definition_13">13.19.1. Structure definition</h4>
 <div class="paragraph">
 <p>Inherits all the fields from: <a href="#_metadataitem">MetadataItem</a></p>
 </div>
@@ -6708,7 +6964,7 @@ This property is an array of list identi
 </table>
 </div>
 <div class="sect3">
-<h4 id="_example_12">13.18.2. Example</h4>
+<h4 id="_example_14">13.19.2. Example</h4>
 <div class="paragraph">
 <p>Here’s an example of a list called “First list”, along with its 
description, its scope, tags, etc.. . As a List object is basically a 
MetadataItem sub-class it simply has all the fields defined in that parent 
class.
 Note that the List does not contain Profiles, it is Profiles that reference 
the Lists, not the reverse.</p>
@@ -6736,7 +6992,7 @@ Note that the List does not contain Prof
 </div>
 </div>
 <div class="sect2">
-<h3 id="_goal">13.19. Goal</h3>
+<h3 id="_goal">13.20. Goal</h3>
 <div class="paragraph">
 <p>A goal can be defined with two conditions: a start event condition and an 
target event condition.
 Basically the goal will be “active” when its start event condition is 
satisfied, and “reached” when the target event condition is true.
@@ -6744,7 +7000,7 @@ Goals may also (optionally) be associate
 Once a goal is “reached”, a “goal” event triggered and the profile 
that is currently interacting with the system will see its system properties 
updated to indicate which goal has been reached.</p>
 </div>
 <div class="sect3">
-<h4 id="_structure_definition_13">13.19.1. Structure definition</h4>
+<h4 id="_structure_definition_14">13.20.1. Structure definition</h4>
 <div class="paragraph">
 <p>Inherits all the fields from: <a href="#_metadataitem">MetadataItem</a></p>
 </div>
@@ -6781,7 +7037,7 @@ Once a goal is “reached”, a â
 </table>
 </div>
 <div class="sect3">
-<h4 id="_example_13">13.19.2. Example</h4>
+<h4 id="_example_15">13.20.2. Example</h4>
 <div class="paragraph">
 <p>In the following example, a goal called “downloadGoalExample” is 
started when a new session is created (we use the 
“sessionCreatedEventCondition” for that) and is reached when a profile 
downloads a file called “ACME_WP.pdf” (that’s what the 
“downloadEventCondition” means).</p>
 </div>
@@ -6821,12 +7077,12 @@ Once a goal is “reached”, a â
 </div>
 </div>
 <div class="sect2">
-<h3 id="_campaign">13.20. Campaign</h3>
+<h3 id="_campaign">13.21. Campaign</h3>
 <div class="paragraph">
 <p>A Campaign object represents a digital marketing campaign, along with 
conditions to enter the campaign and a specific duration, target and costs.</p>
 </div>
 <div class="sect3">
-<h4 id="_structure_definition_14">13.20.1. Structure definition</h4>
+<h4 id="_structure_definition_15">13.21.1. Structure definition</h4>
 <div class="paragraph">
 <p>Inherits all the fields from: <a href="#_metadataitem">MetadataItem</a></p>
 </div>
@@ -6883,7 +7139,7 @@ Once a goal is “reached”, a â
 </table>
 </div>
 <div class="sect3">
-<h4 id="_example_14">13.20.2. Example</h4>
+<h4 id="_example_16">13.21.2. Example</h4>
 <div class="paragraph">
 <p>In the following example a campaign that starts January 1st 31, 2020 at 
8:38am and finished on February 29th, 2020 at the same time has the following 
entry condition: the session duration must be less or equal to 3000 
milliseconds (3 seconds) and the profile has viewed the “about” page on the 
“digitall” website.
 The cost of the campaign is USD 1’000’000 and the timezone is 
Europe/Zurich.
@@ -6943,13 +7199,13 @@ The primary goal for the campaign is the
 </div>
 </div>
 <div class="sect2">
-<h3 id="_scoring_plan">13.21. Scoring plan</h3>
+<h3 id="_scoring_plan">13.22. Scoring plan</h3>
 <div class="paragraph">
 <p>Scoring plans make it possible to define scores that will be tracked for 
profiles and use conditions to increment a score when the conditions are met.
 This makes it possible to then use threshold conditions on profiles when they 
reach a certain score.</p>
 </div>
 <div class="sect3">
-<h4 id="_structure_definition_15">13.21.1. Structure definition</h4>
+<h4 id="_structure_definition_16">13.22.1. Structure definition</h4>
 <div class="paragraph">
 <p>Inherits all the fields from: <a href="#_metadataitem">MetadataItem</a></p>
 </div>
@@ -6976,7 +7232,7 @@ This makes it possible to then use thres
 </table>
 </div>
 <div class="sect3">
-<h4 id="_example_15">13.21.2. Example</h4>
+<h4 id="_example_17">13.22.2. Example</h4>
 <div class="paragraph">
 <p>In this example a scoring plan contains a single element that will 
increment a score with an increment one 1 once the profile has viewed at least 
3 pages (using the “hasSeenNPagesCondition” condition).</p>
 </div>
@@ -7018,12 +7274,12 @@ This makes it possible to then use thres
 </div>
 </div>
 <div class="sect2">
-<h3 id="_built_in_event_types">13.22. Built-in Event types</h3>
+<h3 id="_built_in_event_types">13.23. Built-in Event types</h3>
 <div class="paragraph">
 <p>Apache Unomi comes with built-in event types, which we describe below.</p>
 </div>
 <div class="sect3">
-<h4 id="_login_event_type">13.22.1. Login event type</h4>
+<h4 id="_login_event_type">13.23.1. Login event type</h4>
 <div class="paragraph">
 <p>The login event type is used to signal an authentication event has been 
triggered.
 This event should be “secured”, meaning that it should not be accepted 
from any location, and by default Apache Unomi will only accept this event from 
configured “third-party” servers (identified by their IP address and a 
Unomi application key).</p>
@@ -7074,7 +7330,7 @@ You can find an example of such a rule h
 </table>
 </div>
 <div class="sect4">
-<h5 id="_example_16">Example</h5>
+<h5 id="_example_18">Example</h5>
 <div class="paragraph">
 <p>In this case, a user has logged into a site called “digitall”, and his 
user information the following properties are associated with the active 
user..and perhaps show his visitor profile or user information.</p>
 </div>
@@ -7119,7 +7375,7 @@ You can find an example of such a rule h
 </div>
 </div>
 <div class="sect3">
-<h4 id="_view_event_type">13.22.2. View event type</h4>
+<h4 id="_view_event_type">13.23.2. View event type</h4>
 <div class="paragraph">
 <p>This event is triggered when a web page is viewed by a user.
 Some integrators might also want to trigger it when a single-page-application 
screen is displayed or when a mobile application screen is displayed.</p>
@@ -7161,7 +7417,7 @@ Some integrators might also want to trig
 </table>
 </div>
 <div class="sect4">
-<h5 id="_example_17">Example</h5>
+<h5 id="_example_19">Example</h5>
 <div class="paragraph">
 <p>In this case a use has visited the home page of the digitall site.
 As this is the first page upon login, the destination and referring URL are 
the same.</p>
@@ -7211,7 +7467,7 @@ As this is the first page upon login, th
 </div>
 </div>
 <div class="sect3">
-<h4 id="_form_event_type">13.22.3. Form event type</h4>
+<h4 id="_form_event_type">13.23.3. Form event type</h4>
 <div class="paragraph">
 <p>This event type is used to track form submissions.
 These could range from login to survey form data captured and processed in 
Apache Unomi using rules.</p>
@@ -7253,7 +7509,7 @@ These could range from login to survey f
 </table>
 </div>
 <div class="sect4">
-<h5 id="_example_18">Example</h5>
+<h5 id="_example_20">Example</h5>
 <div class="paragraph">
 <p>A form exists on the digitall site, and has been submitted by a visitor.
 In this case it was a search form that contains fields to adjust the search 
parameters.</p>
@@ -7320,7 +7576,7 @@ In this case it was a search form that c
 </div>
 </div>
 <div class="sect3">
-<h4 id="_update_properties_event_type">13.22.4. Update properties event 
type</h4>
+<h4 id="_update_properties_event_type">13.23.4. Update properties event 
type</h4>
 <div class="paragraph">
 <p>This event is usually used by user interfaces that make it possible to 
modify profile properties, for example a form where a user can edit his profile 
properties, or a management UI to modify.</p>
 </div>
@@ -7328,7 +7584,7 @@ In this case it was a search form that c
 <p>Note that this event type is a protected event type that is only accepted 
from configured third-party servers.</p>
 </div>
 <div class="sect4">
-<h5 id="_structure_definition_16">Structure definition</h5>
+<h5 id="_structure_definition_17">Structure definition</h5>
 <div class="paragraph">
 <p>Based on the structure of the following object: Event</p>
 </div>
@@ -7364,7 +7620,7 @@ In this case it was a search form that c
 </table>
 </div>
 <div class="sect4">
-<h5 id="_example_19">Example</h5>
+<h5 id="_example_21">Example</h5>
 <div class="paragraph">
 <p>In this example, this “updateProperties” event contains properties that 
must be added to the targetId profile.</p>
 </div>
@@ -7408,7 +7664,7 @@ In this case it was a search form that c
 </div>
 </div>
 <div class="sect3">
-<h4 id="_identify_event_type">13.22.5. Identify event type</h4>
+<h4 id="_identify_event_type">13.23.5. Identify event type</h4>
 <div class="paragraph">
 <p>This event type is used to add information learned about the current 
profile.
 This could be through a form that has asked the user to provide some 
information about himself, or it could be information sent by another system 
(CRM, SSO, DMP, LiveRamp or equivalent) to augment the data for the current 
profile.</p>
@@ -7492,7 +7748,7 @@ If you want to add/update/delete propert
 </table>
 </div>
 <div class="sect4">
-<h5 id="_example_20">Example</h5>
+<h5 id="_example_22">Example</h5>
 <div class="paragraph">
 <p>In this example, an event containing additional information about the user 
(his nickname, favorite compiler and industry) was sent to Apache Unomi.</p>
 </div>
@@ -7537,13 +7793,13 @@ If you want to add/update/delete propert
 </div>
 </div>
 <div class="sect3">
-<h4 id="_session_created_event_type">13.22.6. Session created event type</h4>
+<h4 id="_session_created_event_type">13.23.6. Session created event type</h4>
 <div class="paragraph">
 <p>The session created event is an internal event created by Apache Unomi when 
a new session is created.
 This indicates that a new visitor has interacted with a system that is using 
Apache Unomi to track their behavior.</p>
 </div>
 <div class="sect4">
-<h5 id="_structure_definition_17">Structure definition</h5>
+<h5 id="_structure_definition_18">Structure definition</h5>
 <div class="paragraph">
 <p>Based on the structure of the following object: Event</p>
 </div>
@@ -7579,7 +7835,7 @@ This indicates that a new visitor has in
 </table>
 </div>
 <div class="sect4">
-<h5 id="_example_21">Example</h5>
+<h5 id="_example_23">Example</h5>
 <div class="paragraph">
 <p>In this example, a new session was created for a visitor coming to the 
digitall website.
 The session contains the firstVisit property.
@@ -7627,12 +7883,12 @@ It may be augmented over time with more
 </div>
 </div>
 <div class="sect3">
-<h4 id="_goal_event_type">13.22.7. Goal event type</h4>
+<h4 id="_goal_event_type">13.23.7. Goal event type</h4>
 <div class="paragraph">
 <p>A goal event is triggered when the current profile (visitor) reaches a 
goal.</p>
 </div>
 <div class="sect4">
-<h5 id="_structure_definition_18">Structure definition</h5>
+<h5 id="_structure_definition_19">Structure definition</h5>
 <div class="paragraph">
 <p>Based on the structure of the following object: Event</p>
 </div>
@@ -7668,7 +7924,7 @@ It may be augmented over time with more
 </table>
 </div>
 <div class="sect4">
-<h5 id="_example_22">Example</h5>
+<h5 id="_example_24">Example</h5>
 <div class="paragraph">
 <p>In this example, a visitor has reached a goal by viewing a page called 
“sub-home” on the site “digitall” (event source).
 This goal event had the goal object as a target.
@@ -7752,14 +8008,14 @@ The goal object (see Goal object later i
 </div>
 </div>
 <div class="sect3">
-<h4 id="_modify_consent_event_type">13.22.8. Modify consent event type</h4>
+<h4 id="_modify_consent_event_type">13.23.8. Modify consent event type</h4>
 <div class="paragraph">
 <p>Consent type modification events are used to tell Unomi that consents were 
modified.
 A built-in rule will update the current profile with the consent modifications 
contained in the event.
 Consent events may be sent directly by a current profile to update their 
consents on the profile.</p>
 </div>
 <div class="sect4">
-<h5 id="_structure_definition_19">Structure definition</h5>
+<h5 id="_structure_definition_20">Structure definition</h5>
 <div class="paragraph">
 <p>Based on the structure of the following object: Event</p>
 </div>
@@ -7795,7 +8051,7 @@ Consent events may be sent directly by a
 </table>
 </div>
 <div class="sect4">
-<h5 id="_example_23">Example</h5>
+<h5 id="_example_25">Example</h5>
 <div class="paragraph">
 <p>In this example, a user-generated a consent modification when visiting the 
home page, possibly by interacting with a consent form that captured his 
preferences.
 Different consent types were present on the page and he decided to GRANT the 
“mailchimp” consent.</p>
@@ -7884,7 +8140,7 @@ Different consent types were present on
 </div>
 </div>
 <div class="sect2">
-<h3 id="_built_in_condition_types">13.23. Built-in condition types</h3>
+<h3 id="_built_in_condition_types">13.24. Built-in condition types</h3>
 <div class="paragraph">
 <p>Apache Unomi comes with an extensive collection of built-in condition 
types. Instead of detailing them one by one you will
 find here an overview of what a JSON condition descriptor looks like:</p>
@@ -7974,7 +8230,7 @@ type implementations. For more details o
 sections.</p>
 </div>
 <div class="sect3">
-<h4 id="_existing_condition_type_descriptors">13.23.1. Existing condition type 
descriptors</h4>
+<h4 id="_existing_condition_type_descriptors">13.24.1. Existing condition type 
descriptors</h4>
 <div class="paragraph">
 <p>Here is a non-exhaustive list of condition types 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>
@@ -7996,7 +8252,7 @@ type to make them more specific.</p>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_built_in_action_types">13.24. Built-in action types</h3>
+<h3 id="_built_in_action_types">13.25. Built-in action types</h3>
 <div class="paragraph">
 <p>Unomi comes with quite a lot of built-in action types. Instead of detailing 
them one by one you will find here an overview of
 what an action type descriptor looks like:</p>
@@ -8046,7 +8302,7 @@ Here&#8217;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_action_types_descriptors">13.24.1. Existing action types 
descriptors</h4>
+<h4 id="_existing_action_types_descriptors">13.25.1. Existing action types 
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>
@@ -8070,7 +8326,7 @@ discover more. But the list below should
 </div>
 </div>
 <div class="sect2">
-<h3 id="_updating_events_using_the_context_servlet">13.25. Updating Events 
Using the Context Servlet</h3>
+<h3 id="_updating_events_using_the_context_servlet">13.26. Updating Events 
Using the Context Servlet</h3>
 <div class="paragraph">
 <p>One of the use cases that needed to be supported by Unomi is the ability to 
build a user profile based on Internal System events or <a 
href="https://en.wikipedia.org/wiki/Change_data_capture";>Change Data 
Capture</a> which usally transported through internal messaging queues such as 
Kafka.</p>
 </div>
@@ -8082,7 +8338,7 @@ discover more. But the list below should
 we need to have a way to guarantee we wont have duplicate events in the 
system.</p>
 </div>
 <div class="sect3">
-<h4 id="_solution">13.25.1. Solution</h4>
+<h4 id="_solution">13.26.1. Solution</h4>
 <div class="paragraph">
 <p>One of the solutions to this scenario is to have the ability to control and 
pass in the <code>eventId</code> property from outside of Unomi,
 Using an authorized 3rd party. This way whenever an event with the same 
<code>itemId</code> will be processed once again he wont be appended to list of 
events, but will be updated.</p>
@@ -8115,7 +8371,7 @@ EOF</code></pre>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_defining_rules">13.25.2. Defining Rules</h4>
+<h4 id="_defining_rules">13.26.2. Defining Rules</h4>
 <div class="paragraph">
 <p>Another use case we support is the ability to define a rule on the above 
mentioned events.
 If we have a rule that increment a property on profile level, we would want 
the action to be executed only once per event id.
@@ -8156,37 +8412,249 @@ EOF</code></pre>
 </div>
 </div>
 <div class="sect2">
-<h3 id="_unomi_web_tracker_reference">13.26. Unomi Web Tracker reference</h3>
+<h3 id="_unomi_web_tracker_reference">13.27. Unomi Web Tracker reference</h3>
+<div class="paragraph">
+<p>In this section of the documentation, more details are provided about the 
web tracker provided by Unomi.</p>
+</div>
 <div class="sect3">
-<h4 id="_custom_events">13.26.1. Custom events</h4>
+<h4 id="_custom_events">13.27.1. Custom events</h4>
+<div class="paragraph">
+<p>In order to be able to use your own custom events with the web tracker, you 
must first declare them in Unomi so that they are properly recognized and 
validated by the <code>/context.json</code> or <code>/eventcollector</code> 
endpoints.</p>
+</div>
 <div class="sect4">
 <h5 id="_declaring_json_schema">Declaring JSON schema</h5>
-
+<div class="paragraph">
+<p>The first step is to declare a JSON schema for your custom event type. 
Here&#8217;s an example of such a declaration:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-json" data-lang="json">{
+  "$id": "https://unomi.apache.org/schemas/json/events/click/1-0-0";,
+  "$schema": "https://json-schema.org/draft/2019-09/schema";,
+  "self": {
+    "vendor": "org.apache.unomi",
+    "target": "events",
+    "name": "click",
+    "format": "jsonschema",
+    "version": "1-0-0"
+  },
+  "title": "ClickEvent",
+  "type": "object",
+  "allOf": [
+    {
+      "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0";
+    }
+  ],
+  "properties": {
+    "source": {
+      "$ref": "https://unomi.apache.org/schemas/json/items/page/1-0-0";
+    },
+    "target": {
+      "$ref": "https://unomi.apache.org/schemas/json/item/1-0-0";
+    }
+  },
+  "unevaluatedProperties": false
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above example comes from a built-in event type that is already declared 
in Unomi but that illustrates the structure of a JSON schema. It is not however 
the objective of this section of the documentation to go into the details of 
how to declare a JSON schema, instead, we recommend you go to the <a 
href="#_json_schemas_2">corresponding section</a> of the documentation.</p>
+</div>
 </div>
 <div class="sect4">
 <h5 id="_sending_event_from_tracker">Sending event from tracker</h5>
-
+<div class="paragraph">
+<p>In the Unomi web tracker, you can use the following function to send an 
event to Unomi:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-javascript" 
data-lang="javascript">        /**
+         * This function will send an event to Apache Unomi
+         * @param {object} event The event object to send, you can build it 
using wem.buildEvent(eventType, target, source)
+         * @param {function} successCallback optional, will be executed in 
case of success
+         * @param {function} errorCallback optional, will be executed in case 
of error
+         * @return {undefined}
+         */
+        collectEvent: function (event, successCallback = undefined, 
errorCallback = undefined)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>As you can see this function is quite straight forward to use. There are 
also helper functions to build events, such as :</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-javascript" 
data-lang="javascript">        /**
+         * This function return the basic structure for an event, it must be 
adapted to your need
+         *
+         * @param {string} eventType The name of your event
+         * @param {object} [target] The target object for your event can be 
build with wem.buildTarget(targetId, targetType, targetProperties)
+         * @param {object} [source] The source object for your event can be 
build with wem.buildSource(sourceId, sourceType, sourceProperties)
+         * @returns {object} the event
+         */
+        buildEvent: function (eventType, target, source)
+
+        /**
+         * This function return an event of type form
+         *
+         * @param {string} formName The HTML name of id of the form to use in 
the target of the event
+         * @param {HTMLFormElement} form optional HTML form element, if 
provided will be used to extract the form fields and populate the form event
+         * @returns {object} the form event
+         */
+        buildFormEvent: function (formName, form = undefined)
+
+        /**
+         * This function return the source object for a source of type page
+         *
+         * @returns {object} the target page
+         */
+        buildTargetPage: function ()
+
+        /**
+         * This function return the source object for a source of type page
+         *
+         * @returns {object} the source page
+         */
+        buildSourcePage: function ()
+
+        /**
+         * This function return the basic structure for the target of your 
event
+         *
+         * @param {string} targetId The ID of the target
+         * @param {string} targetType The type of the target
+         * @param {object} [targetProperties] The optional properties of the 
target
+         * @returns {object} the target
+         */
+        buildTarget: function (targetId, targetType, targetProperties = 
undefined)
+
+        /**
+         * This function return the basic structure for the source of your 
event
+         *
+         * @param {string} sourceId The ID of the source
+         * @param {string} sourceType The type of the source
+         * @param {object} [sourceProperties] The optional properties of the 
source
+         * @returns {object} the source
+         */
+        buildSource: function (sourceId, sourceType, sourceProperties = 
undefined)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Here&#8217;s an example of using these helper functions and the 
<code>collectEvent</code> function alltogether:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-javascript" 
data-lang="javascript">    var clickEvent = wem.buildEvent('click',
+        wem.buildTarget('buttonId', 'button'),
+        wem.buildSourcePage());
+
+    wem.collectEvent(clickEvent, function (xhr) {
+        console.info('Click event successfully collected.');
+    }, function (xhr) {
+        console.error('Could not send click event.');
+    });</code></pre>
+</div>
+</div>
 </div>
 <div class="sect4">
 <h5 id="_sending_multiple_events">Sending multiple events</h5>
-
+<div class="paragraph">
+<p>In some cases, especially when multiple events must be sent fast and the 
order of the events is critical for rules to be properly executed, it is better 
to use another function called <code>collectEvents</code> that will batch the 
sending of events to Unomi in a single HTTP request. Here&#8217;s the signature 
of this function:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-javascript" 
data-lang="javascript">        /**
+         * This function will send the events to Apache Unomi
+         *
+         * @param {object} events Javascript object { events: [event1, event2] 
}
+         * @param {function} successCallback optional, will be executed in 
case of success
+         * @param {function} errorCallback optional, will be executed in case 
of error
+         * @return {undefined}
+         */
+        collectEvents: function (events, successCallback = undefined, 
errorCallback = undefined)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This function is almost exactly the same as the <code>collectEvent</code> 
method except that it takes an events array instead of a single one. The events 
in the array may be of any mixture of types.</p>
+</div>
 </div>
 <div class="sect4">
 <h5 id="_extending_existing_events">Extending existing events</h5>
-
+<div class="paragraph">
+<p>An alternative to defining custom event types is to extend existing event 
types. This, for example, can be used to add new properties to the built-in 
<code>view</code> event type.</p>
+</div>
+<div class="paragraph">
+<p>For more information about event type extensions, please read the <a 
href="#_extend_an_existing_schema">JSON schema section</a> of this 
documentation.</p>
+</div>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_integrating_with_tag_managers">13.26.2. Integrating with tag 
managers</h4>
-
+<h4 id="_integrating_with_tag_managers">13.27.2. Integrating with tag 
managers</h4>
+<div class="paragraph">
+<p>Integrating with tag managers such as Google Tag Manager is an important 
part of the way trackers can be added to an existing site. Unomi&#8217;s web 
tracker should be pretty easy to integrate with such tools: you simply need to 
insert the script tag to load the script and then another tag to initialize it 
and map any tag manager variables you want.</p>
+</div>
+<div class="paragraph">
+<p>Personalization scripts should however be modified to check for the 
existence of the tracker object in the page because tag managers might 
deactivate scripts based on conditions such as GDPR approval, cookie 
preferences, &#8230;&#8203;</p>
+</div>
 </div>
 <div class="sect3">
-<h4 id="_cookiesession_handling">13.26.3. Cookie/session handling</h4>
-
+<h4 id="_cookiesession_handling">13.27.3. Cookie/session handling</h4>
+<div class="paragraph">
+<p>In order to track profiles, an identifier must be stored in the browser so 
that subsequent requests can keep a reference to the visitor&#8217;s profile. 
Also, a session identifier must be generated to group the current visitor 
interactions.</p>
+</div>
+<div class="paragraph">
+<p>Unomi&#8217;s web tracker uses 3 cookies in the tracker by default:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>server profile ID, called <code>context-profile-id</code> by default, that 
is sent from the Unomi server</p>
+</li>
+<li>
+<p>web tracker profile ID, called <code>web-profile-id</code> by default (this 
is a copy of the server profile ID that can be managed by the tracker 
directly)</p>
+</li>
+<li>
+<p>web tracker session ID, called <code>wem-session-id</code> by default</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>It is possible to change the name of these cookie by passing the following 
properties to the start&#8217;s initialization:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-javascript" 
data-lang="javascript">    "wemInitConfig": {
+        ...
+        "contextServerCookieName": "context-profile-id",
+        "trackerSessionIdCookieName": "unomi-tracker-test-session-id",
+        "trackerProfileIdCookieName": "unomi-tracker-test-profile-id"
+    }</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Please note however that the <code>contextServerCookieName</code> will also 
have to be changed in the server configuration in order for it to work. See the 
<a href="#_configuration">Configuration</a> section for details on how to do 
this.</p>
+</div>
+<div class="paragraph">
+<p>For session tracking, it is important to provide a value for the cookie 
otherwise the tracker will not initialize (a message is displayed in the 
console that explains that the session cookie is missing). Here is the code 
excerpt from the initialization code used in the tutorial that creates the 
initial cookie value.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-javascript" 
data-lang="javascript">    // generate a new session
+    if 
(unomiWebTracker.getCookie(unomiTrackerTestConf.wemInitConfig.trackerSessionIdCookieName)
 == null) {
+        
unomiWebTracker.setCookie(unomiTrackerTestConf.wemInitConfig.trackerSessionIdCookieName,
 unomiWebTracker.generateGuid(), 1);
+    }</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Note that this is just an example, you could very well customize this code 
to create session IDs another way.</p>
+</div>
 </div>
 <div class="sect3">
-<h4 id="_javascript_api">13.26.4. JavaScript API</h4>
-
+<h4 id="_javascript_api">13.27.4. JavaScript API</h4>
+<div class="paragraph">
+<p>The JavaScript API for the web tracker is directly provided in the source 
code of the web tracker. You can find it here: <a 
href="https://github.com/apache/unomi-tracker/blob/main/src/apache-unomi-tracker.js";
 
class="bare">https://github.com/apache/unomi-tracker/blob/main/src/apache-unomi-tracker.js</a></p>
+</div>
+<div class="paragraph">
+<p>Please note that only the functions that do NOT start with an underscore 
should be used. The ones that start with an underscore are not considered part 
of the public API and could change or even be removed at any point in the 
future.</p>
+</div>
 </div>
 </div>
 </div>
@@ -8389,7 +8857,7 @@ information about the context for the cu
 </div>
 </div>
 <div class="sect2">
-<h3 id="_example_24">14.4. Example</h3>
+<h3 id="_example_26">14.4. Example</h3>
 <div class="sect3">
 <h4 id="_html_page">14.4.1. HTML page</h4>
 <div class="paragraph">
@@ -10798,7 +11266,7 @@ They allow to modify an item, that would
 </div>
 <div id="footer">
 <div id="footer-text">
-Last updated 2022-09-30 10:36:29 +0200
+Last updated 2022-10-28 15:43:21 +0200
 </div>
 </div>
 </body>


Reply via email to