This is an automated email from the ASF dual-hosted git repository.

shuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/unomi.git


The following commit(s) were added to refs/heads/master by this push:
     new 5b36b14ec UNOMI-657 New tracker tutorial & reference, profile aliases 
and more (#521)
5b36b14ec is described below

commit 5b36b14ec468536ed77ec5032e47b4a2ae81c5ff
Author: Serge Huber <shu...@jahia.com>
AuthorDate: Fri Oct 7 14:35:31 2022 +0200

    UNOMI-657 New tracker tutorial & reference, profile aliases and more (#521)
    
    - Added profile aliases to what's new section (detailed documentation will 
be added later in UNOMI-686
    - Add new web tracking tutorial that explains how to use the tracker in 
progressive steps
    - Add new tracker reference sections with custom events definition, cookie 
and session handling and more
    - Fix section titles and levels
    - Update tracker HTML to align with the new tutorial
---
 .../web-tracker/wab/src/main/webapp/index.html     |  57 +++-
 manual/src/main/asciidoc/configuration.adoc        |   2 -
 manual/src/main/asciidoc/graphql.adoc              |   8 +-
 manual/src/main/asciidoc/index.adoc                |  18 +-
 .../src/main/asciidoc/jsonSchema/json-schema.adoc  |   3 -
 .../src/main/asciidoc/migrations/migrations.adoc   |   1 -
 manual/src/main/asciidoc/tutorial.adoc             | 343 +++++++++++++++++++++
 manual/src/main/asciidoc/web-tracker.adoc          | 220 +++++++++++++
 manual/src/main/asciidoc/whats-new.adoc            |  16 +-
 9 files changed, 638 insertions(+), 30 deletions(-)

diff --git a/extensions/web-tracker/wab/src/main/webapp/index.html 
b/extensions/web-tracker/wab/src/main/webapp/index.html
index 7f7a12a8d..4e5fa453b 100644
--- a/extensions/web-tracker/wab/src/main/webapp/index.html
+++ b/extensions/web-tracker/wab/src/main/webapp/index.html
@@ -69,6 +69,39 @@
                 console.log("Unomi tracker test successfully loaded context", 
unomiWebTracker.getLoadedContext());
             }, 'Unomi tracker test callback example');
 
+            variants = {
+                "var1" : {
+                    content : "variant1",
+                },
+                "var2" : {
+                    content : "variant2",
+                }
+            }
+            unomiWebTracker.registerPersonalizationObject({
+                "id": "testPersonalization",
+                "strategy": "matching-first",
+                "strategyOptions": {"fallback": "var2"},
+                "contents": [{
+                    "id": "var1",
+                    "filters": [{
+                        "condition": {
+                            "type": "profilePropertyCondition",
+                            "parameterValues": {
+                                "propertyName" : "properties.pageViewCount",
+                                "comparisonOperator" : "greaterThan",
+                                "propertyValueInteger" : 5
+                            }
+                        }
+                    }]
+                }, {
+                    "id": "var2"
+                }]
+            }, variants, false, function (successfulFilters, selectedFilter) {
+                if (selectedFilter) {
+                    
document.getElementById(selectedFilter.content).style.display = '';
+                }
+            });
+
             // start the tracker
             unomiWebTracker.startTracker();
         })();
@@ -79,18 +112,20 @@
 
 <p>
     The current page is sending a page view event using the <strong>Unomi web 
tracker</strong>.<br/><br/>
-    <strong>(Prerequisite: create scope "unomi-tracker-test" for the event to 
be accepted by the backend)</strong>
+
+    <strong>See the <a 
href="https://unomi.apache.org/manual/latest/index.html#_unomi_web_tracking_tutorial";>Unomi
 tutorial</a> for details on how to use
+        and setup the prerequisites for this code to work properly.</strong>
 </p>
-<pre>
-        POST /cxs/scopes
 
-        {
-          "itemId" : "unomi-tracker-test",
-          "metadata" : {
-            "id" : "unomi-tracker-test",
-            "name" : "Unomi tracker test"
-          }
-        }
-</pre>
+<p>The line below this one will be personalized depending on whether you have 
been on this page before.
+    Try reload the page to see the changes.</p>
+
+    <div id="variant1" style="display: none">
+        You have already seen this page 5 times
+    </div>
+    <div id="variant2" style="display: none">
+        Welcome. Please reload this page 5 times until it triggers the 
personalization change
+    </div>
+
 </body>
 </html>
diff --git a/manual/src/main/asciidoc/configuration.adoc 
b/manual/src/main/asciidoc/configuration.adoc
index 328c9866d..6594f5954 100644
--- a/manual/src/main/asciidoc/configuration.adoc
+++ b/manual/src/main/asciidoc/configuration.adoc
@@ -11,8 +11,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-== Configuration
-
 === Centralized configuration
 
 Apache Unomi uses a centralized configuration file that contains both system 
properties and configuration properties.
diff --git a/manual/src/main/asciidoc/graphql.adoc 
b/manual/src/main/asciidoc/graphql.adoc
index 418a5fd05..ed3ec9af6 100644
--- a/manual/src/main/asciidoc/graphql.adoc
+++ b/manual/src/main/asciidoc/graphql.adoc
@@ -11,7 +11,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-=== GraphQL API
+=== Introduction
 
 First introduced in Apache Unomi 2.0, a GraphQL API is available as an 
alternative to REST for interacting with the platform. 
 Disabled by default, the GraphQL API is currently considered a beta feature.
@@ -19,7 +19,7 @@ Disabled by default, the GraphQL API is currently considered 
a beta feature.
 We look forward for this new GraphQL API to be used, feel free to open 
discussion on 
 https://the-asf.slack.com/messages/CBP2Z98Q7/[Unomi Slack channel] or 
https://issues.apache.org/jira/projects/UNOMI/issues[create tickets on Jira]
 
-==== Enabling/ the API
+=== Enabling the API
 
 The GraphQL API must be enabled using a system property (or environment 
variable):
 
@@ -35,13 +35,13 @@ 
org.apache.unomi.graphql.feature.activated=${env:UNOMI_GRAPHQL_FEATURE_ACTIVATED
 You can either modify the `org.apache.unomi.graphql.feature.activated` 
property or specify the `UNOMI_GRAPHQL_FEATURE_ACTIVATED` 
 environment variable (if using Docker for example).
 
-==== Endpoints
+=== Endpoints
 
 Two endpoints were introduced for Apache Unomi 2 GraphQL API:
 * `/graphql` is the primary endpoint for interacting programatically with the 
API and aims at receiving POST requests.
 * `/graphql-ui` provides access to the GraphQL Playground UI and aims at being 
accessed by a Web Browser.
 
-==== GraphQL Schema
+=== GraphQL Schema
 
 Thanks to GraphQL introspection, there is no dedicated documentation per-se as 
the Schema itself serves as documentation. 
 
diff --git a/manual/src/main/asciidoc/index.adoc 
b/manual/src/main/asciidoc/index.adoc
index dcebaf79c..f8bdab770 100644
--- a/manual/src/main/asciidoc/index.adoc
+++ b/manual/src/main/asciidoc/index.adoc
@@ -28,24 +28,34 @@ image::asf_logo_url.png[pdfwidth=35%,align=center]
 
 include::whats-new.adoc[]
 
-== Quick start
+== Discover Unomi
 
 include::5-min-quickstart.adoc[]
 
-== First steps with Apache Unomi
-
 include::getting-started.adoc[]
 
+include::tutorial.adoc[]
+
+== Apache Unomi Recipes and requests
+
 include::recipes.adoc[]
 
 include::request-examples.adoc[]
 
+== Configuration
+
 include::configuration.adoc[]
 
+== JSON schemas
+
 include::jsonSchema/json-schema.adoc[]
 
+== GraphQL API
+
 include::graphql.adoc[]
 
+== Migrations
+
 include::migrations/migrations.adoc[]
 
 == Queries and aggregations
@@ -86,6 +96,8 @@ include::builtin-action-types.adoc[]
 
 include::updating-events.adoc[]
 
+include::web-tracker.adoc[]
+
 == Integration samples
 
 include::samples/samples.adoc[]
diff --git a/manual/src/main/asciidoc/jsonSchema/json-schema.adoc 
b/manual/src/main/asciidoc/jsonSchema/json-schema.adoc
index a4586a6ae..352c27ebe 100644
--- a/manual/src/main/asciidoc/jsonSchema/json-schema.adoc
+++ b/manual/src/main/asciidoc/jsonSchema/json-schema.adoc
@@ -11,9 +11,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-
-== JSON schemas
-
 include::introduction.adoc[]
 
 include::json-schema-api.adoc[]
diff --git a/manual/src/main/asciidoc/migrations/migrations.adoc 
b/manual/src/main/asciidoc/migrations/migrations.adoc
index 5f1f3bd26..7507e2514 100644
--- a/manual/src/main/asciidoc/migrations/migrations.adoc
+++ b/manual/src/main/asciidoc/migrations/migrations.adoc
@@ -11,7 +11,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-== Migrations
 
 This section contains information and steps to migrate between major Unomi 
versions.
 
diff --git a/manual/src/main/asciidoc/tutorial.adoc 
b/manual/src/main/asciidoc/tutorial.adoc
new file mode 100644
index 000000000..ab7c36f63
--- /dev/null
+++ b/manual/src/main/asciidoc/tutorial.adoc
@@ -0,0 +1,343 @@
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+=== Unomi web tracking tutorial
+
+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.
+
+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: 
https://github.com/apache/unomi/blob/master/extensions/web-tracker/wab/src/main/webapp/index.html
 . However you will still need to use the REST API calls to create the scope 
and rule to make it all work.
+
+==== Installing the web tracker in a web page
+
+Using the built-in tracker is pretty simple, simply add the following code to 
your HTML page :
+
+[source,javascript]
+----
+    <script type="text/javascript" 
src="/tracker/unomi-web-tracker.min.js"></script>
+----
+
+or you can also use the non-minified version that is available here:
+
+[source,javascript]
+----
+    <script type="text/javascript" 
src="/tracker/unomi-web-tracker.js"></script>
+----
+
+This will only load the tracker. To initialize it use a snipper like the 
following code:
+
+[source,javascript]
+----
+    <script type="text/javascript">
+        (function () {
+            const unomiTrackerTestConf = {
+                "scope": "unomi-tracker-test",
+                "site": {
+                    "siteInfo": {
+                        "siteID": "unomi-tracker-test"
+                    }
+                },
+                "page": {
+                    "pageInfo": {
+                        "pageID": "unomi-tracker-test-page",
+                        "pageName": document.title,
+                        "pagePath": document.location.pathname,
+                        "destinationURL": document.location.origin + 
document.location.pathname,
+                        "language": "en",
+                        "categories": [],
+                        "tags": []
+                    },
+                    "attributes": {},
+                    "consentTypes": []
+                },
+                "events:": [],
+                "wemInitConfig": {
+                    "contextServerUrl": document.location.origin,
+                    "timeoutInMilliseconds": "1500",
+                    "contextServerCookieName": "context-profile-id",
+                    "activateWem": true,
+                    "trackerSessionIdCookieName": 
"unomi-tracker-test-session-id",
+                    "trackerProfileIdCookieName": 
"unomi-tracker-test-profile-id"
+                }
+            }
+
+            // generate a new session
+            if 
(unomiWebTracker.getCookie(unomiTrackerTestConf.wemInitConfig.trackerSessionIdCookieName)
 == null) {
+                
unomiWebTracker.setCookie(unomiTrackerTestConf.wemInitConfig.trackerSessionIdCookieName,
 unomiWebTracker.generateGuid(), 1);
+            }
+
+            // init tracker with our conf
+            unomiWebTracker.initTracker(unomiTrackerTestConf);
+
+            unomiWebTracker._registerCallback(() => {
+                console.log("Unomi tracker test successfully loaded context", 
unomiWebTracker.getLoadedContext());
+            }, 'Unomi tracker test callback example');
+
+            // start the tracker
+            unomiWebTracker.startTracker();
+        })();
+    </script>
+----
+
+==== Creating a scope to collect the data
+
+You might notice the `scope` used in the snippet. All events sent to Unomi 
must be associated with a scope, that must have been created before events are 
accepted. So in order to make sure the events are collected with the above 
Javascript code, we must create a scope with the following request.
+
+[source,shell]
+----
+curl --location --request POST 'http://localhost:8181/cxs/scopes' \
+  --header 'Authorization: Basic a2FyYWY6a2FyYWY=' \
+  --header 'Content-Type: application/json' \
+  --data-raw '{
+    "itemId": "unomi-tracker-test",
+    "metadata": {
+      "id": "unomi-tracker-test",
+      "name": "Unomi tracker Test Scope"
+    }
+  }'
+----
+
+The authorization is the default username/password for the REST API, which is 
`karaf:karaf` and you that should definitely be changed as soon as possible by 
modifying the `etc/users.properties` file.
+
+==== Using tracker in your own JavaScript projects
+
+The tracker also exists as an NPM library that you can integrate with your own 
Javascript projects. You can find the library here:
+
+    https://www.npmjs.com/package/apache-unomi-tracker
+
+Here's an example on how to use it:
+
+[source,shell]
+----
+    yarn add apache-unomi-tracker
+----
+
+You can then simply use it in your JS code using something like this:
+
+[source,javascript]
+----
+import {useTracker} from "apache-unomi-tracker";
+
+(function () {
+    const unomiWebTracker = useTracker();
+    const unomiTrackerTestConf = {
+        "scope": "unomi-tracker-test",
+        "site": {
+            "siteInfo": {
+                "siteID": "unomi-tracker-test"
+            }
+        },
+        "page": {
+            "pageInfo": {
+                "pageID": "unomi-tracker-test-page",
+                "pageName": document.title,
+                "pagePath": document.location.pathname,
+                "destinationURL": document.location.origin + 
document.location.pathname,
+                "language": "en",
+                "categories": [],
+                "tags": []
+            },
+            "attributes": {},
+            "consentTypes": []
+        },
+        "events:": [],
+        "wemInitConfig": {
+            "contextServerUrl": document.location.origin,
+            "timeoutInMilliseconds": "1500",
+            "contextServerCookieName": "context-profile-id",
+            "activateWem": true,
+            "trackerSessionIdCookieName": "unomi-tracker-test-session-id",
+            "trackerProfileIdCookieName": "unomi-tracker-test-profile-id"
+        }
+    }
+
+    // generate a new session
+    if 
(unomiWebTracker.getCookie(unomiTrackerTestConf.wemInitConfig.trackerSessionIdCookieName)
 == null) {
+        
unomiWebTracker.setCookie(unomiTrackerTestConf.wemInitConfig.trackerSessionIdCookieName,
 unomiWebTracker.generateGuid(), 1);
+    }
+
+    // init tracker with our conf
+    unomiWebTracker.initTracker(unomiTrackerTestConf);
+
+    unomiWebTracker._registerCallback(() => {
+        console.log("Unomi tracker test successfully loaded context", 
unomiWebTracker.getLoadedContext());
+    }, 'Unomi tracker test callback example');
+
+    // start the tracker
+    unomiWebTracker.startTracker();
+})();
+----
+
+==== Viewing collected events
+
+There are multiple ways to view the events that were received. For example, 
you could use the following cURL request:
+
+[source,shell]
+----
+curl --location --request POST 'http://localhost:8181/cxs/events/search' \
+  --header 'Authorization: Basic a2FyYWY6a2FyYWY=' \
+  --header 'Content-Type: application/json' \
+  --data-raw '{
+    "sortby" : "timeStamp:desc",
+    "condition" : {
+      "type" : "matchAllCondition"
+    }
+  }'
+----
+
+Another (powerful) way to look at events is to use the SSH Console. You can 
connect to it with the following shell command:
+
+[source,shell]
+----
+    ssh -p 8102 karaf@localhost
+----
+
+Using the same username password (karaf:karaf) and then you can use command 
such as :
+
+- `event-tail` to view in realtime the events as they come in (CTRL+C to stop)
+- `event-list` to view the latest events
+- `event-view EVENT_ID` to view the details of a specific event
+
+==== Viewing the current profile
+
+By default, Unomi uses a cookie called context-profile-id to keep track of the 
current profile. You can use this the value of this cookie which contains a 
UUID to lookup the details of the profile. For example with the SSH console you 
can simply to:
+
+    profile-view PROFILE_UUID
+
+Which will print out the details of the profile with the associated ID.
+Another interesting command is `profile-list` to list all the recently 
modified profiles
+
+You could also retrieve the profile details using the REST API by using a 
request such as this one:
+
+[source,shell]
+----
+curl --location --request GET 
'http://localhost:8181/cxs/profiles/PROFILE_UUID' \
+--header 'Authorization: Basic a2FyYWY6a2FyYWY=' \
+----
+
+==== Adding a rule
+
+Rules are a powerful ways to react in real-time to incoming events. For 
example a rule could update a profile when a certain event comes in, either 
copying values from the event or performing some kind of computation when the 
event occurs, including accessing remote systems such as a Salesforce CRM (see 
the Salesforce connector sample).
+
+In this example we will simply setup a basic rule that will react to the 
`view` event and set a property in the current profile.
+
+[source,shell]
+----
+curl --location --request POST 'http://localhost:8181/cxs/rules' \
+--header 'Authorization: Basic a2FyYWY6a2FyYWY=' \
+--header 'Content-Type: application/json' \
+--data-raw '{
+    "metadata": {
+        "id": "viewEventRule",
+        "name": "View event rule",
+        "description": "Increments a property on a profile to indicate that 
this rule executed successfully when a view event occurs"
+    },
+    "condition": {
+        "type": "eventTypeCondition",
+        "parameterValues": {
+            "eventTypeId": "view"
+        }
+    },
+    "actions": [
+        {
+            "type": "incrementPropertyAction",
+            "parameterValues": {
+                "propertyName": "pageViewCount"
+            }
+        }
+    ]
+}'
+----
+
+The above rule will execute when a view event is received (which is 
automatically sent by the tracker when a page is loaded) and increments a 
property called `pageViewCount` on the user's profile.
+
+You can then reload then page and check with the `profile-view PROFILE_UUID` 
SSH command that the profile was updated with the new property and that it is 
incremented on each page reload.
+
+You can also use the `rule-list` command to display all the rules in the 
system and the `rule-tail` to watch in real-time which rules are executed. The 
`rule-view RULE_ID` command will let you view the contents of a rule.
+
+==== Adding personalization
+
+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's API to 
register a personalization that will be using a condition that checks if the 
`pageViewCount` is higher than 5. If it has, `variant1` will be displayed, 
otherwise the fallback variant `variant2` will be used instead.
+
+[source,javascript]
+----
+            variants = {
+                "var1" : {
+                    content : "variant1",
+                },
+                "var2" : {
+                    content : "variant2",
+                }
+            }
+            unomiWebTracker.registerPersonalizationObject({
+                "id": "testPersonalization",
+                "strategy": "matching-first",
+                "strategyOptions": {"fallback": "var2"},
+                "contents": [{
+                    "id": "var1",
+                    "filters": [{
+                        "condition": {
+                            "type": "profilePropertyCondition",
+                            "parameterValues": {
+                                "propertyName" : "properties.pageViewCount",
+                                "comparisonOperator" : "greaterThan",
+                                "propertyValueInteger" : 5
+                            }
+                        }
+                    }]
+                }, {
+                    "id": "var2"
+                }]
+            }, variants, false, function (successfulFilters, selectedFilter) {
+                if (selectedFilter) {
+                    
document.getElementById(selectedFilter.content).style.display = '';
+                }
+            });
+
+----
+
+As you can see in the above code snippet, a `variants` 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 `var1` is passed in this case) as well as an 
option to indicate which is the fallback variant in case no conditions are 
matched.
+
+The HTML part of this example looks like this:
+
+[source,html]
+----
+    <div id="variant1" style="display: none">
+        You have already seen this page 5 times
+    </div>
+    <div id="variant2" style="display: none">
+        Welcome. Please reload this page 5 times until it triggers the 
personalization change
+    </div>
+----
+
+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's personalization engine.
+
+==== Conclusion
+
+What have we achieved so far ?
+
+- Installed a tracker in a web page
+- Created a scope in which to collect the data
+- Learned how to use the tracker as an NPM library
+- How to view the collected events
+- How to view the current visitor profile
+- How to add a rule to update a profile property
+- How to personalize a web page's content based on the property updated by the 
rule
+
+Of course this tutorial is just one example of what could be achieved, and 
hasn'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..)
+
+==== Next steps
+
+- Learn more about the <<_unomi_web_tracker_reference,web tracker, custom 
events, API, ...>>
+- Learn more about <<_segment,segmentation>>
+- View some more <<_integration_samples,samples>>
+- Continue reading Unomi's user manual to see all that is possible with this 
technology
\ No newline at end of file
diff --git a/manual/src/main/asciidoc/web-tracker.adoc 
b/manual/src/main/asciidoc/web-tracker.adoc
new file mode 100644
index 000000000..e88718c7d
--- /dev/null
+++ b/manual/src/main/asciidoc/web-tracker.adoc
@@ -0,0 +1,220 @@
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+=== Unomi Web Tracker reference
+
+In this section of the documentation, more details are provided about the web 
tracker provided by Unomi.
+
+==== Custom events
+
+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 `/context.json` or `/eventcollector` endpoints.
+
+===== Declaring JSON schema
+
+The first step is to declare a JSON schema for your custom event type. Here's 
an example of such a declaration:
+
+[source,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
+}
+----
+
+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 
<<_json_schemas_2,corresponding section>> of the documentation.
+
+===== Sending event from tracker
+
+In the Unomi web tracker, you can use the following function to send an event 
to Unomi:
+
+[source,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)
+----
+
+As you can see this function is quite straight forward to use. There are also 
helper functions to build events, such as :
+
+[source,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)
+
+----
+
+Here's an example of using these helper functions and the `collectEvent` 
function alltogether:
+
+[source,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.');
+    });
+----
+
+===== Sending multiple events
+
+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 `collectEvents` that will batch the sending of 
events to Unomi in a single HTTP request. Here's the signature of this function:
+
+[source,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)
+----
+
+This function is almost exactly the same as the `collectEvent` 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.
+
+===== Extending existing events
+
+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 
`view` event type.
+
+For more information about event type extensions, please read the 
<<_extend_an_existing_schema,JSON schema section>> of this documentation.
+
+==== Integrating with tag managers
+
+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'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.
+
+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, ...
+
+==== Cookie/session handling
+
+In order to track profiles, an identifier must be stored in the browser so 
that subsequent requests can keep a reference to the visitor's profile. Also, a 
session identifier must be generated to group the current visitor interactions.
+
+Unomi's web tracker uses 3 cookies in the tracker by default:
+
+- server profile ID, called `context-profile-id` by default, that is sent from 
the Unomi server
+- web tracker profile ID, called `web-profile-id` by default (this is a copy 
of the server profile ID that can be managed by the tracker directly)
+- web tracker session ID, called `wem-session-id` by default
+
+It is possible to change the name of these cookie by passing the following 
properties to the start's initialization:
+
+[source,javascript]
+----
+    "wemInitConfig": {
+        ...
+        "contextServerCookieName": "context-profile-id",
+        "trackerSessionIdCookieName": "unomi-tracker-test-session-id",
+        "trackerProfileIdCookieName": "unomi-tracker-test-profile-id"
+    }
+----
+
+Please note however that the `contextServerCookieName` will also have to be 
changed in the server configuration in order for it to work. See the 
<<_configuration,Configuration>> section for details on how to do this.
+
+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.
+
+[source,javascript]
+----
+    // generate a new session
+    if 
(unomiWebTracker.getCookie(unomiTrackerTestConf.wemInitConfig.trackerSessionIdCookieName)
 == null) {
+        
unomiWebTracker.setCookie(unomiTrackerTestConf.wemInitConfig.trackerSessionIdCookieName,
 unomiWebTracker.generateGuid(), 1);
+    }
+----
+
+Note that this is just an example, you could very well customize this code to 
create session IDs another way.
+
+==== JavaScript API
+
+The JavaScript API for the web tracker is directly provided in the source code 
of the web tracker. You can find it here: 
https://github.com/apache/unomi-tracker/blob/main/src/apache-unomi-tracker.js
+
+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.
\ No newline at end of file
diff --git a/manual/src/main/asciidoc/whats-new.adoc 
b/manual/src/main/asciidoc/whats-new.adoc
index 97e5a1661..764309d59 100644
--- a/manual/src/main/asciidoc/whats-new.adoc
+++ b/manual/src/main/asciidoc/whats-new.adoc
@@ -14,10 +14,15 @@
 === What's new in Apache Unomi 2.0
 
 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.
 
 This new release also introduces a first (beta) version of the Unomi GraphQL 
API.
 
+==== Introducing profiles aliases
+
+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.
+
 ==== Scopes declarations are now required
 
 Scopes declarations are now required in Unomi 2. When submitting an event and 
specifying a scope,
@@ -133,15 +138,14 @@ Is replaced by the following in Apache Unomi 2.x:
 ----
 
 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.
 
-==== Removal of the Web Tracker
+If you are using custom events/objects, please refer to the detailed 
<<_migration_overview,migration guide>> for more details.
+
+==== New Web Tracker
 
-[TODO: Add more details about the web tracker]
+Apache Unomi 2.0 Web Tracker, located in `extensions/web-tracker/` 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.
 
-Apache Unomi 2.0 Web Tracker, previously located in `extensions/web-tracker/` 
has been removed.
-We considered it as outdated and instead recommend implementing your own 
tracker logic based on your project
-use case.
+You can find more information about the <<_unomi_web_tracking_tutorial,new web 
tracker here>>.
 
 ==== GraphQL API - beta
 


Reply via email to