diff --git a/_search-plugins/ubi/client_datastructures.md b/_search-plugins/ubi/client_datastructures.md index 6028aa1538..a5ed403b83 100644 --- a/_search-plugins/ubi/client_datastructures.md +++ b/_search-plugins/ubi/client_datastructures.md @@ -1,3 +1,11 @@ +--- +layout: default +title: Client Data structures old +parent: User behavior insights +has_children: false +nav_order: 7 +--- + The datastructures that we use for indexing events adhere to the following nested structure that aligns with the Ubi schemas. See the [schemas](.././schemas.md) for descriptions and examples of the following fields. `struct UbiEvent {` diff --git a/_search-plugins/ubi/data-structures.md b/_search-plugins/ubi/data-structures.md index 0df4fdae86..e77cd02ba9 100644 --- a/_search-plugins/ubi/data-structures.md +++ b/_search-plugins/ubi/data-structures.md @@ -1,3 +1,10 @@ +--- +layout: default +title: Client data structures +parent: User behavior insights +has_children: false +nav_order: 7 +--- # Sample data structures The data structures below can be used to create events that follow the [UBI event schema](schemas.md). diff --git a/_search-plugins/ubi/documentation.md b/_search-plugins/ubi/documentation.md index ad7467289b..80fef4bb84 100644 --- a/_search-plugins/ubi/documentation.md +++ b/_search-plugins/ubi/documentation.md @@ -1,38 +1,52 @@ +--- +layout: default +title: Ubi plugin management +parent: User behavior insights +has_children: false +nav_order: 2 +--- + + # OpenSearch User Behavior Insights -This repository contains the OpenSearch plugin for the User Behavior Insights (UBI) capability. This plugin +This *repository* contains the OpenSearch plugin for the User Behavior Insights (UBI) capability. This plugin facilitates persisting client-side events (e.g. item clicks, scroll depth) and OpenSearch queries for the purpose of analyzing the data to improve search relevance and user experience. ## Quick Start Build the plugin. Note that you will have to match up the JDK 11 on your system to java home in the `gradle.properties` file: - -`./gradlew build` +```bash +./gradlew build +``` +{% include copy.html %} Build the OpenSearch docker image and add the plugin, then start the containers: -``` +```bash docker compose build docker compose up ``` +{% include copy.html %} Or to start a three-node OpenSearch cluster: -``` +```bash docker compose build docker compose -f docker-compose-cluster.yaml up ``` +{% include copy.html %} Initialize the `awesome` UBI store: -``` +```bash curl -X PUT "http://localhost:9200/_plugins/ubi/awesome?index=ecommerce&object_id=id" ``` +{% include copy-curl.html %} Send an event to the `awesome` store: -``` +```bash curl -X POST http://localhost:9200/_plugins/ubi/mystore -H "Content-Type: application/json" -d ' { "action_name": "search", @@ -40,30 +54,35 @@ curl -X POST http://localhost:9200/_plugins/ubi/mystore -H "Content-Type: applic "timestamp": 1705596607509 }' ``` +{% include copy-curl.html %} Get events: -``` +```bash curl -s http://localhost:9200/.awesome_events/_search | jq ``` +{% include copy-curl.html %} Do a search of the `ecommerce` index: -``` +```bash curl -s http://localhost:9200/ecommerce/_search -H "X-ubi-store: awesome" | jq ``` +{% include copy-curl.html %} Get queries: -``` +```bash curl -s http://localhost:9200/.awesome_queries/_search | jq ``` +{% include copy-curl.html %} Delete the store: -``` +```bash curl -X DELETE http://localhost:9200/_plugins/ubi/awesome ``` +{% include copy-curl.html %} ## UBI Store @@ -95,14 +114,16 @@ To create a UBI store to contain events and queries, send a `PUT` request: ``` curl -X PUT http://localhost:9200/_plugins/ubi/mystore?index=ecommerce ``` +{% include copy-curl.html %} ### Deleting a UBI Store To delete a store, send a `DELETE` request: -``` +```bash curl -X DELETE http://localhost:9200/_plugins/ubi/mystore ``` +{% include copy-curl.html %} This will delete the UBI store and all contained events and queries. Please use this with caution. @@ -110,15 +131,16 @@ This will delete the UBI store and all contained events and queries. Please use To get a list of stores, send a `GET` request: -``` +```bash curl -X GET http://localhost:9200/_plugins/ubi ``` +{% include copy-curl.html %} ### Persist a Client-Side Event into a UBI Store To persist a client-side event into a store, send a `POST` request where the body of the request is the event: -``` +```bash curl -X POST http://localhost:9200/_plugins/ubi/mystore -H "Content-Type: application/json" -d ' { "action_name": "search", @@ -126,6 +148,7 @@ curl -X POST http://localhost:9200/_plugins/ubi/mystore -H "Content-Type: applic "timestamp": 1705596607509 }' ``` +{% include copy-curl.html %} ## Capturing Queries with UBI @@ -149,9 +172,10 @@ To make this association, queries need to have a header value that indicates the The following query tells the plugin that the query being run should be persisted to the store `mystore` and be associated with user ID `john`: -``` +```bash curl http://localhost:9200/ecommerce/_search -H "X-ubi-store: mystore" -H "X-ubi-user-id: 12345" ``` +{% include copy-curl.html %} With this query, when the plugin sees a query, the plugin will be able to associate the query with an individual user and know to persist the query in the UBI store `mystore`. diff --git a/_search-plugins/ubi/index.md b/_search-plugins/ubi/index.md index 4dd2be854c..36c7c25b4c 100644 --- a/_search-plugins/ubi/index.md +++ b/_search-plugins/ubi/index.md @@ -3,75 +3,34 @@ layout: default title: User behavior insights parent: Search relevance has_children: false -nav_order: 220 +nav_order: 1 redirect_from: - /search-plugins/ubi/ --- +# Overview +User Behavior Insights, or UBI, is a community plugin for capturing client-side events and queries for the purposes of improving search relevance and user experience. +It is a causal system, linking a user's query to all subsequent user interactions with your application until they perform another search. -# User behavior insights - -User Behavior Insights, or UBI, is a community plugin for capturing client-side events and queries for the purposes of improving search relevance and user experience. UBI consists of three components: * An OpenSearch [plugin](https://github.com/o19s/opensearch-ubi) that facilitates the storage of client-side events and queries. * A client-side JavaScript library reference implementation that shows how to capture events and send those events to the OpenSearch UBI plugin. -* An OpenSearch Dashboards plugin that provides access to the collected events and queries for analysis. This component is still largely in the design phase. - -UBI is currently only supported in OpenSearch 2.12.0. -{: .warning } - -## Installing the plugin - -The User Behavior Insights plugin is available for OpenSearch 2.12.0. To install the plugin, run the following command: - -```bash -./bin/opensearch-plugin install \ - "https://github.com/o19s/opensearch-ubi/releases/download/0.0.8/opensearch-ubi-0.0.8-os2.12.0.zip" -``` -{% include copy.html %} - -For plugin APIs and examples, see [OpenSearch User Behavior Insights documentation](https://github.com/o19s/opensearch-ubi/blob/main/documentation.md). - -The following steps outline how to get started with the UBI plugin. - -## Initializing a UBI store - -A _store_ contains the client-side events and the queries. After installing the plugin we need to initialize a store. In the following request we are creating a store called `mystore`. - -```json -PUT _plugins/ubi/mystore -``` -{% include copy.html %} - -A store consists of two OpenSearch indexes whose names are based on the name of the store being created. For the `mystore` store, the names of the indexes are: - -* `.mystore_events` - This index contains the client-side events sent to the plugin by the JavaScript library. -* `.mystore_queries` - This index contains the queries that the plugin passively stores. - -## Sending events to the store - -With the store initialized, you can now send client-side events to our `mystore` store: - -```json -POST /_plugins/ubi/mystore -{ - "type": "instant-search", - "keywords": "laptop", - "url": "my_url.html", - "lang": "en-US", - "session": "npckcy4", - "channel": "demo-channel" -} -``` -{% include copy-curl.html %} +TODO: link a client implementation +{: .warn } -## Capturing queries +| Explanation & Reference | Description +| :--------- | :------- | +| [Ubi Plugin Admin]({{site.url}}{{site.baseurl}}/search-plugins/ubi/documentation) | How to install and use the UBI Plugin | +| [Ubi Request/Response Specification](https://github.com/o19s/ubi) | Schema standard for making Ubi requests and responses | +| [Ubi OpenSearch Schema Documentation]({{site.url}}{{site.baseurl}}/search-plugins/ubi/schemas) | Documentation on the individual Query and Event stores for OpenSearch | +| [`query_id` Data Flow]({{site.url}}{{site.baseurl}}/search-plugins/ubi/query_id) | How the `query_id` ties the search to results and user events | -The UBI plugin passively stores queries. To test it, you can run a query against an example index of products called `ecommerce`: -```bash -GET /ecommerce/_search -H "X-ubi-store: mystore" -``` -{% include copy.html %} +| Tutorials & How-to Guides | Description +| :--------- | :------- | +| [ javascript client structures ]({{site.url}}{{site.baseurl}}/search-plugins/ubi/data_structures) | Sample javascript structures for populating the Event store | +| [Ubi Sql queries ]({{site.url}}{{site.baseurl}}/search-plugins/ubi/sql_queries) | How to write analytic queries for Ubi data | +| [Ubi Dashboard]({{site.url}}{{site.baseurl}}/search-plugins/ubi/ubi_dashboard_tutorial) | Teaches you how to build an OpenSearch dashboard with UBI data | +| ... | teaches how to do something | -Note that this request includes a header called `X-ubi-store`. This header allows the UBI plugin to associate this query with a UBI store. +Documentation adapted using concepts from (Diátaxis)[https://diataxis.fr/] \ No newline at end of file diff --git a/_search-plugins/ubi/query_id.md b/_search-plugins/ubi/query_id.md index f885ffd389..acb8a69f3d 100644 --- a/_search-plugins/ubi/query_id.md +++ b/_search-plugins/ubi/query_id.md @@ -1,3 +1,10 @@ +--- +layout: default +title: Ubi data flow +parent: User behavior insights +has_children: false +nav_order: 7 +--- # Basic Ubi flow **Executive Summary**: Once a user performs search, that search is tied to a `query_id`. Then any following user events until the next search are logged and indexed by the search's `query_id`. If the user finds something of interest, that something's identifier (`object_id` or `key_value`) is logged in the event store with the `query_id`. diff --git a/_search-plugins/ubi/schemas.md b/_search-plugins/ubi/schemas.md index 234e013df6..9f7748ed95 100644 --- a/_search-plugins/ubi/schemas.md +++ b/_search-plugins/ubi/schemas.md @@ -1,3 +1,10 @@ +--- +layout: default +title: Ubi index schemas +parent: User behavior insights +has_children: false +nav_order: 7 +--- # Key User Behavior Insights concepts **User Behavior Insights** (Ubi) **Logging** is really just a matter of linking and indexing queries, results and events within OpenSearch. diff --git a/_search-plugins/ubi/sql_queries.md b/_search-plugins/ubi/sql_queries.md index 68096c821f..958686653e 100644 --- a/_search-plugins/ubi/sql_queries.md +++ b/_search-plugins/ubi/sql_queries.md @@ -1,3 +1,11 @@ +--- +layout: default +title: Ubi queries with sql +parent: User behavior insights +has_children: false +nav_order: 7 +--- + # Sample UBI SQL queries These can be performed on the OpenSearch Dashboards/Query Workbench: http(s):\//`{server}`:5601/app/opensearch-query-workbench diff --git a/_search-plugins/ubi/004_build_a_basic_dashboard.md b/_search-plugins/ubi/ubi_dashboard_tutorial.md similarity index 69% rename from _search-plugins/ubi/004_build_a_basic_dashboard.md rename to _search-plugins/ubi/ubi_dashboard_tutorial.md index 9835ed7569..b24ba1f79f 100644 --- a/_search-plugins/ubi/004_build_a_basic_dashboard.md +++ b/_search-plugins/ubi/ubi_dashboard_tutorial.md @@ -1,23 +1,31 @@ -# Kata 4: Build an analytic dashboard! -Whether you've been collecting user events and queries for a while, or [you uploaded some sample events](003_import_preexisting_event_data.md), now you're ready to visualize them in the dashboard! +--- +layout: default +title: UBI Dashboard Tutorial +parent: User behavior insights +has_children: false +nav_order: 7 +--- + +# Build an analytic dashboard for UBI! +Whether you've been collecting user events and queries for a while, or [you uploaded some sample events](https://github.com/o19s/chorus-opensearch-edition/blob/main/katas/003_import_preexisting_event_data.md), now you're ready to visualize them in the dashboard! ## 1) Fire up the OpenSearch dashboards Depending on your configuration: http://localhost:5601/app/home#/ -![Dashboard Home](images/home.png "Dashboards") +![Dashboard Home]({{site.url}}{{site.baseurl}}/images/ubi/home.png "Dashboards") ## 2) Create an index pattern http://localhost:5601/app/management/opensearch-dashboards/indexPatterns -![Index Patterns](images/index_pattern1.png "Index Patterns") +![Index Patterns]({{site.url}}{{site.baseurl}}/images/ubi/index_pattern1.png "Index Patterns") Index patterns are how OpenSearch dashboards access your indices. In this case, we want to access the *hidden* indices that UBI creates, so that we can visualize your users' online, search behaviors. After you click on "Create index pattern" you'll see a list of indices in your OpenSearch instance. The UBI stores are hidden by default; so, be sure to click on "Include system and hidden indices". -![Index Patterns](images/index_pattern2.png "Index Patterns") +![Index Patterns]({{site.url}}{{site.baseurl}}/images/ubi/index_pattern2.png "Index Patterns") With wildcards you can group indices into the same data source for your dashboard. Assuming the name of your UBI is `chorus`, we'll lump both the query and event stores together as `ubi_chorus*`. It will prompt you to filter on any `date` field in your schema, so that you can look at things like trending queries over the last 15 minutes, etc. However, for your first dashboard, do not filter on any date field. -Index Patterns +Index Patterns Click on "Create index pattern", and you're ready to start building your dashboard pointing to your UBI store! @@ -25,44 +33,44 @@ It will prompt you to filter on any `date` field in your schema, so that you can ## 3) Create a new dasboard http://localhost:5601/app/opensearch_dashboards_overview#/ -![First Dashboard](images/first_dashboard.png "First Dashboard") +![First Dashboard]({{site.url}}{{site.baseurl}}/images/ubi/first_dashboard.png "First Dashboard") The screen will bring up an empty dashboard, ready for you to add some analytic widgets. We'll start with a pie chart. Click on "Create new" and select a pie chart visualization. Then select the index patter you made in Step 2. |Create new|Visualizations| |---|---| -|![New Chart](images/new_widget.png "New Chart")|Pie Chart| +|![New Chart]({{site.url}}{{site.baseurl}}/images/ubi/new_widget.png "New Chart")|Pie Chart| Most of the visualization require some sort of aggregate function on an bucket/facet/aggregatable field (i.e. numeric or keyword). We'll add a `Terms` aggregation on the field `action_name` so that we can see the distribution across event names. Change the size to the number of slices you want to display. -![Pie Chart](images/pie.png "Pie Chart") +![Pie Chart]({{site.url}}{{site.baseurl}}/images/ubi/pie.png "Pie Chart") Save that visualization and it will be added to your new dashboard. Now that you have a visualization on your dashboard, you can save your dashboard. ## 4) Add a "Tag Cloud" vizualization to your dashboard Let's add a word cloud for trending searches. Choose the Tag Cloud visualization of the terms in the `message` field where the javascript client logs the raw text that the user searches on. (Note: the true query, as processed by OpenSearch with filters, boosting, etc. will be in the `.{store}_queries` index, but what we are looking at is the `message` field of the `.{store}_events` index, where the javascript client captures what the user actually typed. ) -![Word Cloud](images/tag_cloud1.png "Word Cloud") +![Word Cloud]({{site.url}}{{site.baseurl}}/images/ubi/tag_cloud1.png "Word Cloud") **But there's a problem!** The `message` field is on *every* event --not just query/search events-- and can be used in anyway the client developer decides to use it; so, it can contain error messages, debug messages, click information, etc. We need to add a filter to only see search terms on query events. Since the developer gave a `message_type` of `QUERY` for each search event, we will filter on that message type to isolate just the users' searches. -![Word Cloud](images/tag_cloud2.png "Word Cloud") +![Word Cloud]({{site.url}}{{site.baseurl}}/images/ubi/tag_cloud2.png "Word Cloud") You should now have two visualizations on your dashboard. -![UBI Dashboard](images/dashboard2.png "UBI Dashboard") +![UBI Dashboard]({{site.url}}{{site.baseurl}}/images/ubi/dashboard2.png "UBI Dashboard") ## 5) Add one more visualization of a histogram of item clicks To add a histogram, first, add a vertical bar chart. -Vertical Bar Chart +Vertical Bar Chart The data field we want to examine is `event_attributes.position.ordinal`, meaning the user clicked on the *n*th item in a list. The y-axis will be the number of times that *n*th was clicked. The x-axis will be the ordinal number itself that was clicked, using the `Histogram` aggregation. -![Vertical Bar Chart](images/histogram.png "Vertical Bar Chart") +![Vertical Bar Chart]({{site.url}}{{site.baseurl}}/images/ubi/histogram.png "Vertical Bar Chart") ## 6) Have fun slicing and dicing! For example, let's see how the click position changes when there is a purchase, by adding this filter `action_name:product_purchase`. -![Product Purchase](images/product_purchase.png "Product Purchase") +![Product Purchase]({{site.url}}{{site.baseurl}}/images/ubi/product_purchase.png "Product Purchase") Or let's see what event messages include "\*UBI\*" somewhere between the wildcards. -![UBI](images/ubi.png "UBI") +![UBI]({{site.url}}{{site.baseurl}}/images/ubi/ubi.png "UBI") You now have a basic dashboard that lets you look at the data. In the next Katas we'll focus on some typical ecommerce driven scenarios.