forked from opensearch-project/documentation-website
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from o19s/ubi-docs-consolidation
UBI docs consolidation
- Loading branch information
Showing
29 changed files
with
1,119 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
--- | ||
layout: default | ||
title: UBI client data structures | ||
parent: User behavior insights | ||
has_children: false | ||
nav_order: 7 | ||
--- | ||
|
||
# Sample client data structures | ||
The client data structures can be used to create events that follow the [UBI event schema specification](https://github.com/o19s/opensearch-ubi), | ||
which is described in further detail [here]({{site.url}}{{site.baseurl}}/search-plugins/ubi/schemas/). | ||
|
||
The developer provides an implementation for the following functions: | ||
- `getClientId()` | ||
- `getQueryId()` | ||
|
||
_Optionally_: | ||
- `getSessionId()` | ||
- `getPageId()` | ||
|
||
<!-- Not needed with this page: Other sample implementations can be found [here](#TODO-clients-link). --> | ||
|
||
```js | ||
/********************************************************************************************* | ||
* Ubi Event data structures | ||
* The following structures help ensure adherence to the UBI event schema | ||
*********************************************************************************************/ | ||
|
||
|
||
|
||
export class UbiEventData { | ||
constructor(object_type, id=null, description=null, details=null) { | ||
this.object_id_field = object_type; | ||
this.object_id = id; | ||
this.description = description; | ||
this.object_detail = details; | ||
} | ||
} | ||
export class UbiPosition{ | ||
constructor({ordinal=null, x=null, y=null, trail=null}={}) { | ||
this.ordinal = ordinal; | ||
this.x = x; | ||
this.y = y; | ||
if(trail) | ||
this.trail = trail; | ||
else { | ||
const trail = getTrail(); | ||
if(trail && trail.length > 0) | ||
this.trail = trail; | ||
} | ||
} | ||
} | ||
|
||
|
||
export class UbiEventAttributes { | ||
/** | ||
* Tries to prepopulate common event attributes | ||
* The developer can add an `object` that the user interacted with and | ||
* the site `position` information relevant to the event | ||
* | ||
* Attributes, other than `object` or `position` can be added in the form: | ||
* attributes['item1'] = 1 | ||
* attributes['item2'] = '2' | ||
* | ||
* @param {*} attributes: object with general event attributes | ||
* @param {*} object: the data object the user interacted with | ||
* @param {*} position: the site position information | ||
*/ | ||
constructor({attributes={}, object=null, position=null}={}) { | ||
if(attributes != null){ | ||
Object.assign(this, attributes); | ||
} | ||
if(object != null && Object.keys(object).length > 0){ | ||
this.object = object; | ||
} | ||
if(position != null && Object.keys(position).length > 0){ | ||
this.position = position; | ||
} | ||
this.setDefaultValues(); | ||
} | ||
|
||
setDefaultValues(){ | ||
try{ | ||
if(!this.hasOwnProperty('dwell_time') && typeof TimeMe !== 'undefined'){ | ||
this.dwell_time = TimeMe.getTimeOnPageInSeconds(window.location.pathname); | ||
} | ||
|
||
if(!this.hasOwnProperty('browser')){ | ||
this.browser = window.navigator.userAgent; | ||
} | ||
|
||
if(!this.hasOwnProperty('page_id')){ | ||
this.page_id = window.location.pathname; | ||
} | ||
if(!this.hasOwnProperty('session_id')){ | ||
this.session_id = getSessionId(); | ||
} | ||
|
||
if(!this.hasOwnProperty('page_id')){ | ||
this.page_id = getPageId(); | ||
} | ||
|
||
if(!this.hasOwnProperty('position') || this.position == null){ | ||
const trail = getTrail(); | ||
if(trail.length > 0){ | ||
this.position = new UbiPosition({trail:trail}); | ||
} | ||
} | ||
// ToDo: set IP | ||
} | ||
catch(error){ | ||
console.log(error); | ||
} | ||
} | ||
} | ||
|
||
|
||
|
||
export class UbiEvent { | ||
constructor(action_name, {message_type='INFO', message=null, event_attributes={}, data_object={}}={}) { | ||
this.action_name = action_name; | ||
this.client_id = getClientId(); | ||
this.query_id = getQueryId(); | ||
this.timestamp = Date.now(); | ||
|
||
this.message_type = message_type; | ||
if( message ) | ||
this.message = message; | ||
|
||
this.event_attributes = new UbiEventAttributes({attributes:event_attributes, object:data_object}); | ||
} | ||
|
||
/** | ||
* Use to suppress null objects in the json output | ||
* @param key | ||
* @param value | ||
* @returns | ||
*/ | ||
static replacer(key, value){ | ||
if(value == null || | ||
(value.constructor == Object && Object.keys(value).length === 0)) { | ||
return undefined; | ||
} | ||
return value; | ||
} | ||
|
||
/** | ||
* | ||
* @returns json string | ||
*/ | ||
toJson() { | ||
return JSON.stringify(this, UbiEvent.replacer); | ||
} | ||
} | ||
``` | ||
{% include copy.html %} | ||
|
||
# Sample usage | ||
|
||
```js | ||
export async function logUbiMessage(event_type, message_type, message){ | ||
let e = new UbiEvent(event_type, { | ||
message_type:message_type, | ||
message:message | ||
}); | ||
logEvent(e); | ||
} | ||
|
||
export async function logDwellTime(action_name, page, seconds){ | ||
console.log(`${page} => ${seconds}`); | ||
let e = new UbiEvent(action_name, { | ||
message:`On page ${page} for ${seconds} seconds`, | ||
event_attributes:{dwell_seconds:seconds}, | ||
data_object:TimeMe | ||
}); | ||
logEvent(e); | ||
} | ||
``` | ||
{% include copy.html %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
--- | ||
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 | ||
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. | ||
|
||
[Link to repo plugin's documentation](https://github.com/o19s/opensearch-ubi) | ||
|
||
## Quick start | ||
|
||
We need a Quick Start!!! | ||
|
||
## UBI store | ||
|
||
The plugin has a concept of a "store", which is a logical collection of the events and queries. A store consists of two indexes. | ||
One index is used to store events, and the other index is for storing queries. | ||
|
||
### OpenSearch data mappings | ||
UBI has 2 primary indexes: | ||
- **UBI Queries** stores all queries and results. | ||
- **UBI Events** store that the UBI client writes events to. | ||
*Follow the [schema deep dive]({{site.url}}{{site.baseurl}}/search-plugins/ubi/schemas/) to understand how these two indexes make UBI into a causal framework for search.* | ||
|
||
## Plugin API | ||
|
||
|
||
### Associating a query with client-side events | ||
|
||
The plugin passively listens to query requests passing through OpenSearch. Without any extra information, | ||
the plugin cannot associate a query with the client-side events associated with the query. (What user clicked on what to make this query?) | ||
|
||
To make this association, queries need to have a header value that indicates the user ID. | ||
|
||
|
||
### Example queries | ||
|
||
[Sample SQL queries]({{site.url}}{{site.baseurl}}/search-plugins/ubi/sql-queries/) | ||
|
||
[Sample OpenSearch queries]({{site.url}}{{site.baseurl}}/search-plugins/ubi/dsl-queries/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
--- | ||
layout: default | ||
title: UBI queries using OpenSearch | ||
parent: User behavior insights | ||
has_children: false | ||
nav_order: 8 | ||
--- | ||
|
||
# Sample UBI using OpenSearch DSL queries | ||
|
||
|
||
|
||
```json | ||
GET .ubi_log_events/_search | ||
{ | ||
"size":0, | ||
"aggs":{ | ||
"event_types":{ | ||
"terms": { | ||
"field":"action_name", | ||
"size":10 | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
{% include copy.html %} | ||
|
||
returns | ||
```json | ||
{ | ||
"took": 1, | ||
"timed_out": false, | ||
"_shards": { | ||
"total": 1, | ||
"successful": 1, | ||
"skipped": 0, | ||
"failed": 0 | ||
}, | ||
"hits": { | ||
"total": { | ||
"value": 10000, | ||
"relation": "gte" | ||
}, | ||
"max_score": null, | ||
"hits": [] | ||
}, | ||
"aggregations": { | ||
"event_types": { | ||
"doc_count_error_upper_bound": 0, | ||
"sum_other_doc_count": 0, | ||
"buckets": [ | ||
{ | ||
"key": "brand_filter", | ||
"doc_count": 3084 | ||
}, | ||
{ | ||
"key": "product_hover", | ||
"doc_count": 3068 | ||
}, | ||
{ | ||
"key": "button_click", | ||
"doc_count": 3054 | ||
}, | ||
{ | ||
"key": "product_sort", | ||
"doc_count": 3012 | ||
}, | ||
{ | ||
"key": "on_search", | ||
"doc_count": 3010 | ||
}, | ||
{ | ||
"key": "type_filter", | ||
"doc_count": 2925 | ||
}, | ||
{ | ||
"key": "login", | ||
"doc_count": 2433 | ||
}, | ||
{ | ||
"key": "logout", | ||
"doc_count": 1447 | ||
}, | ||
{ | ||
"key": "new_user_entry", | ||
"doc_count": 207 | ||
} | ||
] | ||
} | ||
} | ||
} | ||
``` | ||
{% include copy.html %} | ||
|
||
These can be performed on the OpenSearch Dashboards/Query Workbench: | ||
[http://chorus-opensearch-edition.dev.o19s.com:5601/app/opensearch-query-workbench](http://chorus-opensearch-edition.dev.o19s.com:5601/app/opensearch-query-workbench) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
--- | ||
layout: default | ||
title: User behavior insights | ||
has_children: true | ||
nav_order: 90 | ||
redirect_from: | ||
- /search-plugins/ubi/ | ||
--- | ||
# Overview | ||
|
||
**Introduced 2.15** | ||
{: .label .label-purple } | ||
|
||
**References UBI Draft Specification X.Y.Z** | ||
{: .label .label-purple } | ||
|
||
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. | ||
|
||
|
||
* An machine readable [schema](https://github.com/o19s/ubi) that faciliates interoperablity of the UBI specification. | ||
* An OpenSearch [plugin](https://github.com/o19s/opensearch-ubi) that facilitates the storage of client-side events and queries. | ||
* A client-side JavaScript [ example ]({{site.url}}{{site.baseurl}}/search-plugins/ubi/data-structures/) reference implementation that shows how to capture events and send those events to the OpenSearch UBI plugin. | ||
|
||
<!-- vale off --> | ||
|
||
| Explanation & Reference | Description | ||
| :--------- | :------- | | ||
| [UBI Request/Response Specification](https://github.com/o19s/ubi/) <br/> **References UBI Draft Specification X.Y.Z** | 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/) --> | To remove? | | ||
|
||
|
||
| Tutorials & How-to Guides | Description | ||
| :--------- | :------- | | ||
| [UBI Plugin Admin]({{site.url}}{{site.baseurl}}/search-plugins/ubi/documentation/) | How to install and use the UBI Plugin | | ||
| [ 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 in SQL | | ||
| [UBI Dashboard Tutorial]({{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 | | ||
|
||
<!-- vale on --> | ||
Documentation adapted using concepts from [Diátaxis](https://diataxis.fr/) | ||
{: .tip } | ||
|
Oops, something went wrong.