@miso.ai/client-sdk-core 1.13.0-beta.5 → 1.13.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/plugin/analytics.js +66 -4
- package/dist/cjs/version.js +1 -1
- package/package.json +2 -2
- package/src/plugin/analytics.js +68 -6
- package/src/version.js +1 -1
|
@@ -15,6 +15,7 @@ class AnalyticsPlugin extends _commons.Component {
|
|
|
15
15
|
super('analytics');
|
|
16
16
|
this._members = [];
|
|
17
17
|
this._engagement = undefined;
|
|
18
|
+
this._activity = undefined;
|
|
18
19
|
}
|
|
19
20
|
config(options = {}) {
|
|
20
21
|
this._options = options;
|
|
@@ -27,34 +28,94 @@ class AnalyticsPlugin extends _commons.Component {
|
|
|
27
28
|
install(MisoClient, context) {
|
|
28
29
|
context.addSubtree(this);
|
|
29
30
|
this._engagement = new _commons.UserEngagementObserver(this._handleEngagement.bind(this));
|
|
31
|
+
this._activity = new _commons.UserActivityObserver(this._handleActivity.bind(this));
|
|
30
32
|
// TODO: should we provide a way to stop the observer?
|
|
31
33
|
window.addEventListener('beforeunload', this._handlePageExit.bind(this));
|
|
34
|
+
window.addEventListener('click', this._handleClick.bind(this, MisoClient));
|
|
32
35
|
MisoClient.on('create', this._injectClient.bind(this));
|
|
33
36
|
}
|
|
34
37
|
_injectClient(client) {
|
|
35
38
|
client.on('workflow', this._injectWorkflow.bind(this));
|
|
36
39
|
}
|
|
37
40
|
_injectWorkflow(workflow) {
|
|
38
|
-
if (!
|
|
41
|
+
if (!shallApplyAnalytics(workflow)) {
|
|
39
42
|
return;
|
|
40
43
|
}
|
|
41
44
|
workflow.analytics = new Analytics(this, workflow);
|
|
42
45
|
}
|
|
43
|
-
_shallInjectWorkflow(workflow) {
|
|
44
|
-
return workflow._name === 'ask' && !workflow.previous || workflow._name === 'hybrid-search';
|
|
45
|
-
}
|
|
46
46
|
_handleEngagement() {
|
|
47
47
|
for (const member of this._members) {
|
|
48
48
|
member._syncEngagementState();
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
+
_handleActivity(event) {
|
|
52
|
+
for (const member of this._members) {
|
|
53
|
+
member._sendHeartbeat();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
51
56
|
_handlePageExit() {
|
|
52
57
|
for (const member of this._members) {
|
|
53
58
|
member._sendHeartbeat();
|
|
54
59
|
}
|
|
55
60
|
}
|
|
61
|
+
_handleClick(MisoClient, event) {
|
|
62
|
+
// get the first client instance
|
|
63
|
+
const client = MisoClient.instances[0];
|
|
64
|
+
if (!client) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const workflow = getGenericClickWorkflow(this, event);
|
|
68
|
+
if (!workflow || !isDataReady(workflow)) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const href = getGenericClickHref(event);
|
|
72
|
+
if (!href) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
workflow.trackers.container.genericClick({
|
|
76
|
+
href
|
|
77
|
+
});
|
|
78
|
+
}
|
|
56
79
|
}
|
|
57
80
|
exports.default = AnalyticsPlugin;
|
|
81
|
+
function shallApplyAnalytics(workflow) {
|
|
82
|
+
return workflow._name === 'ask' && !workflow.previous || workflow._name === 'hybrid-search';
|
|
83
|
+
}
|
|
84
|
+
function getGenericClickWorkflow(plugin, event) {
|
|
85
|
+
// find the closet container
|
|
86
|
+
for (let element = event.target; element; element = element.parentElement) {
|
|
87
|
+
const {
|
|
88
|
+
role,
|
|
89
|
+
workflow
|
|
90
|
+
} = element;
|
|
91
|
+
if (role && !workflow) {
|
|
92
|
+
return undefined; // inside component, not a generic click
|
|
93
|
+
}
|
|
94
|
+
// if inside a container, we should use the container's workflow
|
|
95
|
+
if (workflow) {
|
|
96
|
+
return shallApplyAnalytics(workflow) ? workflow : undefined;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// fallback to default workflow
|
|
101
|
+
for (const member of plugin._members) {
|
|
102
|
+
const workflow = member._workflow;
|
|
103
|
+
if (shallApplyAnalytics(workflow)) {
|
|
104
|
+
return workflow;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
function getGenericClickHref(event) {
|
|
110
|
+
const element = event.target.closest('[href]');
|
|
111
|
+
return element ? element.getAttribute('href') : undefined;
|
|
112
|
+
}
|
|
113
|
+
function isDataReady(workflow) {
|
|
114
|
+
const {
|
|
115
|
+
data = {}
|
|
116
|
+
} = workflow.states;
|
|
117
|
+
return data.status === 'ready';
|
|
118
|
+
}
|
|
58
119
|
function normalizeOptions(_ref = {}) {
|
|
59
120
|
let options = Object.assign({}, (_objectDestructuringEmpty(_ref), _ref));
|
|
60
121
|
return Object.assign({}, options);
|
|
@@ -169,5 +230,6 @@ class Analytics {
|
|
|
169
230
|
} else {
|
|
170
231
|
this._timer.stop();
|
|
171
232
|
}
|
|
233
|
+
this._sendHeartbeat();
|
|
172
234
|
}
|
|
173
235
|
}
|
package/dist/cjs/version.js
CHANGED
package/package.json
CHANGED
package/src/plugin/analytics.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, UserEngagementObserver, Stopwatch, trimObj, mergeInteractions } from '@miso.ai/commons';
|
|
1
|
+
import { Component, UserEngagementObserver, UserActivityObserver, Stopwatch, trimObj, mergeInteractions } from '@miso.ai/commons';
|
|
2
2
|
|
|
3
3
|
const PLUGIN_ID = 'std:analytics';
|
|
4
4
|
|
|
@@ -12,6 +12,7 @@ export default class AnalyticsPlugin extends Component {
|
|
|
12
12
|
super('analytics');
|
|
13
13
|
this._members = [];
|
|
14
14
|
this._engagement = undefined;
|
|
15
|
+
this._activity = undefined;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
config(options = {}) {
|
|
@@ -26,8 +27,10 @@ export default class AnalyticsPlugin extends Component {
|
|
|
26
27
|
install(MisoClient, context) {
|
|
27
28
|
context.addSubtree(this);
|
|
28
29
|
this._engagement = new UserEngagementObserver(this._handleEngagement.bind(this));
|
|
30
|
+
this._activity = new UserActivityObserver(this._handleActivity.bind(this));
|
|
29
31
|
// TODO: should we provide a way to stop the observer?
|
|
30
32
|
window.addEventListener('beforeunload', this._handlePageExit.bind(this));
|
|
33
|
+
window.addEventListener('click', this._handleClick.bind(this, MisoClient));
|
|
31
34
|
MisoClient.on('create', this._injectClient.bind(this));
|
|
32
35
|
}
|
|
33
36
|
|
|
@@ -36,28 +39,85 @@ export default class AnalyticsPlugin extends Component {
|
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
_injectWorkflow(workflow) {
|
|
39
|
-
if (!
|
|
42
|
+
if (!shallApplyAnalytics(workflow)) {
|
|
40
43
|
return;
|
|
41
44
|
}
|
|
42
45
|
workflow.analytics = new Analytics(this, workflow);
|
|
43
46
|
}
|
|
44
47
|
|
|
45
|
-
_shallInjectWorkflow(workflow) {
|
|
46
|
-
return (workflow._name === 'ask' && !workflow.previous) || workflow._name === 'hybrid-search';
|
|
47
|
-
}
|
|
48
|
-
|
|
49
48
|
_handleEngagement() {
|
|
50
49
|
for (const member of this._members) {
|
|
51
50
|
member._syncEngagementState();
|
|
52
51
|
}
|
|
53
52
|
}
|
|
54
53
|
|
|
54
|
+
_handleActivity(event) {
|
|
55
|
+
for (const member of this._members) {
|
|
56
|
+
member._sendHeartbeat();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
55
60
|
_handlePageExit() {
|
|
56
61
|
for (const member of this._members) {
|
|
57
62
|
member._sendHeartbeat();
|
|
58
63
|
}
|
|
59
64
|
}
|
|
60
65
|
|
|
66
|
+
_handleClick(MisoClient, event) {
|
|
67
|
+
// get the first client instance
|
|
68
|
+
const client = MisoClient.instances[0];
|
|
69
|
+
if (!client) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const workflow = getGenericClickWorkflow(this, event);
|
|
73
|
+
if (!workflow || !isDataReady(workflow)) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const href = getGenericClickHref(event);
|
|
77
|
+
if (!href) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
workflow.trackers.container.genericClick({ href });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function shallApplyAnalytics(workflow) {
|
|
86
|
+
return (workflow._name === 'ask' && !workflow.previous) || workflow._name === 'hybrid-search';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function getGenericClickWorkflow(plugin, event) {
|
|
90
|
+
// find the closet container
|
|
91
|
+
for (let element = event.target; element; element = element.parentElement) {
|
|
92
|
+
const { role, workflow } = element;
|
|
93
|
+
if (role && !workflow) {
|
|
94
|
+
return undefined; // inside component, not a generic click
|
|
95
|
+
}
|
|
96
|
+
// if inside a container, we should use the container's workflow
|
|
97
|
+
if (workflow) {
|
|
98
|
+
return shallApplyAnalytics(workflow) ? workflow : undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// fallback to default workflow
|
|
103
|
+
for (const member of plugin._members) {
|
|
104
|
+
const workflow = member._workflow;
|
|
105
|
+
if (shallApplyAnalytics(workflow)) {
|
|
106
|
+
return workflow;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function getGenericClickHref(event) {
|
|
114
|
+
const element = event.target.closest('[href]');
|
|
115
|
+
return element ? element.getAttribute('href') : undefined;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function isDataReady(workflow) {
|
|
119
|
+
const { data = {} } = workflow.states;
|
|
120
|
+
return data.status === 'ready';
|
|
61
121
|
}
|
|
62
122
|
|
|
63
123
|
function normalizeOptions({ ...options } = {}) {
|
|
@@ -194,6 +254,8 @@ class Analytics {
|
|
|
194
254
|
} else {
|
|
195
255
|
this._timer.stop();
|
|
196
256
|
}
|
|
257
|
+
|
|
258
|
+
this._sendHeartbeat();
|
|
197
259
|
}
|
|
198
260
|
|
|
199
261
|
}
|
package/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '1.13.0-beta.
|
|
1
|
+
export default '1.13.0-beta.6';
|