@atlaskit/analytics-next 11.1.4 → 11.2.1
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/AnalyticsReactContext/package.json +15 -0
- package/CHANGELOG.md +21 -0
- package/afm-cc/tsconfig.json +0 -2
- package/afm-products/tsconfig.json +0 -2
- package/cleanProps/package.json +15 -0
- package/dist/cjs/components/AnalyticsReactContext.js +13 -0
- package/dist/cjs/events/UIAnalyticsEvent.js +11 -1
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/utils/isModernContextEnabledEnv.js +2 -1
- package/dist/es2019/components/AnalyticsReactContext.js +1 -0
- package/dist/es2019/events/UIAnalyticsEvent.js +13 -1
- package/dist/es2019/index.js +1 -1
- package/dist/es2019/utils/isModernContextEnabledEnv.js +2 -1
- package/dist/esm/components/AnalyticsReactContext.js +1 -0
- package/dist/esm/events/UIAnalyticsEvent.js +11 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/utils/isModernContextEnabledEnv.js +2 -1
- package/dist/types/components/AnalyticsContext/index.d.ts +1 -1
- package/dist/types/components/AnalyticsContext/types.d.ts +1 -1
- package/dist/types/components/AnalyticsListener/LegacyAnalyticsListener.d.ts +1 -1
- package/dist/types/components/AnalyticsListener/index.d.ts +1 -1
- package/dist/types/components/AnalyticsListener/types.d.ts +1 -1
- package/dist/types/components/AnalyticsReactContext.d.ts +2 -0
- package/dist/types/hocs/withAnalyticsEvents.d.ts +1 -1
- package/dist/types/hooks/useAnalyticsEvents.d.ts +1 -1
- package/dist/types/hooks/usePatchedProps.d.ts +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/types.d.ts +1 -1
- package/dist/types/utils/createAndFireEvent.d.ts +2 -2
- package/dist/types/utils/isModernContextEnabledEnv.d.ts +2 -2
- package/dist/types-ts4.5/components/AnalyticsContext/index.d.ts +1 -1
- package/dist/types-ts4.5/components/AnalyticsContext/types.d.ts +1 -1
- package/dist/types-ts4.5/components/AnalyticsListener/LegacyAnalyticsListener.d.ts +1 -1
- package/dist/types-ts4.5/components/AnalyticsListener/index.d.ts +1 -1
- package/dist/types-ts4.5/components/AnalyticsListener/types.d.ts +1 -1
- package/dist/types-ts4.5/components/AnalyticsReactContext.d.ts +2 -0
- package/dist/types-ts4.5/hocs/withAnalyticsEvents.d.ts +1 -1
- package/dist/types-ts4.5/hooks/useAnalyticsEvents.d.ts +1 -1
- package/dist/types-ts4.5/hooks/usePatchedProps.d.ts +1 -1
- package/dist/types-ts4.5/index.d.ts +2 -2
- package/dist/types-ts4.5/types.d.ts +1 -1
- package/dist/types-ts4.5/utils/createAndFireEvent.d.ts +2 -2
- package/dist/types-ts4.5/utils/isModernContextEnabledEnv.d.ts +2 -2
- package/docs/0-intro.tsx +68 -37
- package/docs/10-concepts.tsx +138 -112
- package/docs/20-usage-with-presentational-components.tsx +177 -198
- package/docs/30-usage-for-container-components.tsx +69 -53
- package/docs/40-listeners.tsx +17 -14
- package/docs/50-error-boundary.tsx +28 -22
- package/docs/60-events.tsx +27 -19
- package/docs/70-advanced-usage.tsx +182 -179
- package/docs/80-upgrade-guide.tsx +182 -100
- package/docs/DocBlocks.tsx +106 -0
- package/package.json +2 -2
- package/tsconfig.json +1 -2
- package/usePlatformLeafSyntheticEventHandler/package.json +15 -0
- package/afm-jira/tsconfig.json +0 -33
|
@@ -1,19 +1,9 @@
|
|
|
1
|
+
/* eslint-disable @atlaskit/design-system/use-primitives-text, @atlaskit/design-system/use-heading -- Legacy analytics-next docs intentionally use plain HTML prose instead of ADS docs primitives. */
|
|
1
2
|
import React from 'react';
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
+
import { CodeBlock, PropsBlock } from './DocBlocks';
|
|
4
5
|
|
|
5
|
-
const
|
|
6
|
-
${code`import { AnalyticsErrorBoundary } from '@atlaskit/analytics-next';`}
|
|
7
|
-
|
|
8
|
-
Wrap part of your tree in \`AnalyticsErrorBoundary\` to provide error boundary track to any events created beneath it.
|
|
9
|
-
|
|
10
|
-
When a component is created verifies all of the components above it in the tree and any error will be catched and tracked automatically.
|
|
11
|
-
|
|
12
|
-
It's up to the developer pass this information when you're adding the component.
|
|
13
|
-
|
|
14
|
-
Usage:
|
|
15
|
-
|
|
16
|
-
${code`
|
|
6
|
+
const usageCode = `
|
|
17
7
|
import {
|
|
18
8
|
AnalyticsListener,
|
|
19
9
|
AnalyticsErrorBoundary
|
|
@@ -43,13 +33,29 @@ class ButtonWithAnalyticsErrorBoundary extends React.Component {
|
|
|
43
33
|
)
|
|
44
34
|
}
|
|
45
35
|
}
|
|
46
|
-
`}
|
|
47
|
-
|
|
48
|
-
${(
|
|
49
|
-
<Props
|
|
50
|
-
heading="AnalyticsErrorBoundary Props"
|
|
51
|
-
props={require('!!extract-react-types-loader!../src/components/AnalyticsErrorBoundary')}
|
|
52
|
-
/>
|
|
53
|
-
)}
|
|
54
36
|
`;
|
|
55
|
-
|
|
37
|
+
|
|
38
|
+
export default function ErrorBoundaryDocs(): React.JSX.Element {
|
|
39
|
+
return (
|
|
40
|
+
<div>
|
|
41
|
+
<CodeBlock code={`import { AnalyticsErrorBoundary } from '@atlaskit/analytics-next';`} />
|
|
42
|
+
<p>
|
|
43
|
+
Wrap part of your tree in <code>AnalyticsErrorBoundary</code> to provide error boundary
|
|
44
|
+
track to any events created beneath it.
|
|
45
|
+
</p>
|
|
46
|
+
<p>
|
|
47
|
+
When a component is created verifies all of the components above it in the tree and any
|
|
48
|
+
error will be catched and tracked automatically.
|
|
49
|
+
</p>
|
|
50
|
+
<p>
|
|
51
|
+
It's up to the developer pass this information when you're adding the component.
|
|
52
|
+
</p>
|
|
53
|
+
<h4>Usage</h4>
|
|
54
|
+
<CodeBlock code={usageCode} />
|
|
55
|
+
<PropsBlock
|
|
56
|
+
heading="AnalyticsErrorBoundary Props"
|
|
57
|
+
props={require('!!extract-react-types-loader!../src/components/AnalyticsErrorBoundary')}
|
|
58
|
+
/>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
}
|
package/docs/60-events.tsx
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable @atlaskit/design-system/use-primitives-text, @atlaskit/design-system/use-heading -- Legacy analytics-next docs intentionally use plain HTML prose instead of ADS docs primitives. */
|
|
2
|
+
import React from 'react';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
<a name="UIAnalyticsEvent"></a>
|
|
5
|
-
### UIAnalyticsEvent
|
|
4
|
+
import { CodeBlock } from './DocBlocks';
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
${code`
|
|
6
|
+
const uiAnalyticsEventCode = `
|
|
10
7
|
/** An array of objects containing data provided by any AnalyticsContext
|
|
11
8
|
* components in the tree above where this event was created. */
|
|
12
9
|
context: Array<{}>;
|
|
@@ -40,16 +37,27 @@ update(
|
|
|
40
37
|
[string]: any,
|
|
41
38
|
}),
|
|
42
39
|
) => UIAnalyticsEvent;
|
|
43
|
-
`}
|
|
44
|
-
|
|
45
|
-
<a name="AnalyticsEvent"></a>
|
|
46
|
-
### AnalyticsEvent
|
|
47
|
-
|
|
48
|
-
${code`import { AnalyticsEvent } from '@atlaskit/analytics-next';`}
|
|
49
|
-
|
|
50
|
-
A more generic type of event which only contains a payload and an update method.
|
|
51
|
-
If you want to create an event outside of the UI you can create an instance of this class directly.
|
|
52
|
-
|
|
53
|
-
Please see [UIAnalyticsEvent](#UIAnalyticsEvent) for more information.
|
|
54
40
|
`;
|
|
55
|
-
|
|
41
|
+
|
|
42
|
+
export default function EventsDocs(): React.JSX.Element {
|
|
43
|
+
return (
|
|
44
|
+
<div>
|
|
45
|
+
<h3 id="UIAnalyticsEvent">UIAnalyticsEvent</h3>
|
|
46
|
+
<p>
|
|
47
|
+
The class can be used to represent an analytics event triggered by a user interaction. It
|
|
48
|
+
has the following interface:
|
|
49
|
+
</p>
|
|
50
|
+
<CodeBlock code={uiAnalyticsEventCode} />
|
|
51
|
+
<h3 id="AnalyticsEvent">AnalyticsEvent</h3>
|
|
52
|
+
<CodeBlock code={`import { AnalyticsEvent } from '@atlaskit/analytics-next';`} />
|
|
53
|
+
<p>
|
|
54
|
+
A more generic type of event which only contains a payload and an update method. If you want
|
|
55
|
+
to create an event outside of the UI you can create an instance of this class directly.
|
|
56
|
+
</p>
|
|
57
|
+
<p>
|
|
58
|
+
{/* eslint-disable-next-line @atlaskit/design-system/no-html-anchor -- This legacy docs page keeps plain hash links for local section navigation. */}
|
|
59
|
+
Please see <a href="#UIAnalyticsEvent">UIAnalyticsEvent</a> for more information.
|
|
60
|
+
</p>
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
@@ -1,38 +1,14 @@
|
|
|
1
|
+
/* eslint-disable @atlaskit/design-system/use-primitives-text, @atlaskit/design-system/use-heading, @atlaskit/design-system/no-html-anchor -- Legacy analytics-next docs intentionally use plain HTML prose and hash links instead of ADS docs primitives. */
|
|
1
2
|
import React from 'react';
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
+
import { CodeBlock, ExampleBlock } from './DocBlocks';
|
|
4
5
|
|
|
5
|
-
const
|
|
6
|
-
### Contents
|
|
7
|
-
|
|
8
|
-
* [Adding more information to an event](#adding-more-information-to-an-event)
|
|
9
|
-
* [Using a channel](#using-a-channel)
|
|
10
|
-
* [Passing an event to your consumers](#passing-an-event-to-your-consumers)
|
|
11
|
-
* [Cloning an event](#cloning-an-event)
|
|
12
|
-
* [Tracking events outside the UI](#tracking-events-outside-the-ui)
|
|
13
|
-
|
|
14
|
-
<a name="adding-more-information-to-an-event"></a>
|
|
15
|
-
## Adding more information to an event
|
|
16
|
-
|
|
17
|
-
This package provides two methods for adding extra information to analytics events.
|
|
18
|
-
The first method is by adding data to the analytics events payload. The second method
|
|
19
|
-
is to provide contextual information to any event.
|
|
20
|
-
|
|
21
|
-
<a name="adding-data-to-an-events-payload"></a>
|
|
22
|
-
### Adding data to an event's payload
|
|
23
|
-
|
|
24
|
-
Before firing an analytics event, you can add data the payload by using the \`update\` method.
|
|
25
|
-
Here's an example of how that looks:
|
|
26
|
-
|
|
27
|
-
##### SaveButton.js
|
|
28
|
-
|
|
29
|
-
${code`
|
|
6
|
+
const saveButtonCode = `
|
|
30
7
|
import Button from '@atlaskit/button';
|
|
31
8
|
|
|
32
9
|
const SaveButton = ({ onClick }) => (
|
|
33
10
|
<Button
|
|
34
11
|
onClick={(e, analytic) => {
|
|
35
|
-
// update will merge the value into the existing payload
|
|
36
12
|
analytic
|
|
37
13
|
.update({ timestamp: Date.now() })
|
|
38
14
|
.fire();
|
|
@@ -44,52 +20,20 @@ const SaveButton = ({ onClick }) => (
|
|
|
44
20
|
Save
|
|
45
21
|
</Button>
|
|
46
22
|
);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
In addition to accepting an object, the \`update\` method accepts a function which is called
|
|
50
|
-
with the event's current payload and is expected to return a new payload.
|
|
51
|
-
|
|
52
|
-
Below is a fleshed out example demonstrating how to add extra information to the event's payload.
|
|
53
|
-
|
|
54
|
-
${(
|
|
55
|
-
<Example
|
|
56
|
-
packageName="@atlaskit/analytics-next"
|
|
57
|
-
Component={require('../examples/40-updating-an-event').default}
|
|
58
|
-
title="Updating an event's payload"
|
|
59
|
-
source={require('!!raw-loader!../examples/40-updating-an-event')}
|
|
60
|
-
/>
|
|
61
|
-
)}
|
|
62
|
-
|
|
63
|
-
<a name="using-a-channel"></a>
|
|
64
|
-
## Using a channel
|
|
65
|
-
|
|
66
|
-
The feature is likey more useful for component authors.
|
|
67
|
-
|
|
68
|
-
When calling \`fire\` on an analytics event, you can optionally specify a channel
|
|
69
|
-
to fire the event on. Only listeners on that channel will recieve the event.
|
|
70
|
-
|
|
71
|
-
##### Button.js (handleClick method)
|
|
23
|
+
`;
|
|
72
24
|
|
|
73
|
-
|
|
25
|
+
const usingChannelCode = `
|
|
74
26
|
handleClick = e => {
|
|
75
|
-
// Create our analytics event
|
|
76
27
|
const analyticsEvent = this.props.createAnalyticsEvent({ action: 'click' });
|
|
77
|
-
|
|
78
|
-
// Fire our analytics event on the 'atlaskit' channel
|
|
79
28
|
analyticsEvent.fire('atlaskit');
|
|
80
29
|
|
|
81
30
|
if (this.props.onClick) {
|
|
82
31
|
this.props.onClick(e);
|
|
83
32
|
}
|
|
84
33
|
};
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
In the above example, we fire events on the \`'atlaskit'\` channel. To listen
|
|
88
|
-
on this channel we would set up our App like:
|
|
89
|
-
|
|
90
|
-
##### App.js (render method)
|
|
34
|
+
`;
|
|
91
35
|
|
|
92
|
-
|
|
36
|
+
const appRenderCode = `
|
|
93
37
|
render() {
|
|
94
38
|
return (
|
|
95
39
|
<AnalyticsListener channel="atlaskit" onEvent={this.handleEvent}>
|
|
@@ -97,147 +41,53 @@ render() {
|
|
|
97
41
|
</AnalyticsListener>
|
|
98
42
|
);
|
|
99
43
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
The \`AnalyticsListener\` component accepts \`channel\` and \`onEvent\` props. When an event is fired on this Listener's channel its onEvent function will be called.
|
|
103
|
-
|
|
104
|
-
<a name="passing-an-event-to-your-consumers"></a>
|
|
105
|
-
## Passing an event to your consumers
|
|
106
|
-
|
|
107
|
-
The features described in this section are likey to be more useful to component
|
|
108
|
-
authors.
|
|
109
|
-
|
|
110
|
-
If you are building components, you might not want to fire an event as
|
|
111
|
-
soon as it's created - instead it is better to provide the event to the consumer
|
|
112
|
-
of your component. The consumer then has a chance to add more information and fire
|
|
113
|
-
the event when they're ready.
|
|
114
|
-
|
|
115
|
-
This is exactly the approach we took to instrument our own Atlaskit components.
|
|
116
|
-
This section will show you how we did it and how to use the same approach in
|
|
117
|
-
your components.
|
|
118
|
-
|
|
119
|
-
The most straight forward way is to pass the event as an extra argument to the
|
|
120
|
-
corresponding callback prop. Here's our updated Button component:
|
|
121
|
-
|
|
122
|
-
##### Button.js (handleClick method)
|
|
44
|
+
`;
|
|
123
45
|
|
|
124
|
-
|
|
46
|
+
const passingEventCode = `
|
|
125
47
|
handleClick = e => {
|
|
126
|
-
// Create our analytics event
|
|
127
48
|
const analyticsEvent = this.props.createAnalyticsEvent({ action: 'click' });
|
|
128
49
|
|
|
129
50
|
if (this.props.onClick) {
|
|
130
|
-
// Pass the event through the corresponding callback prop
|
|
131
51
|
this.props.onClick(e, analyticsEvent);
|
|
132
52
|
}
|
|
133
53
|
};
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
This is a pretty common pattern for component authors, so \`withAnalyticsEvents\`
|
|
137
|
-
provides a shortcut:
|
|
138
|
-
|
|
139
|
-
##### Button.js
|
|
54
|
+
`;
|
|
140
55
|
|
|
141
|
-
|
|
56
|
+
const shortcutCode = `
|
|
142
57
|
const ButtonWithAnalytics = withAnalyticsEvents({
|
|
143
|
-
// simply provide a payload we'll automatically create an event for you
|
|
144
58
|
onClick: { action: 'click' }
|
|
145
59
|
})(Button);
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
\`withAnalyticsEvents\` accepts an optional object mapping callback prop names to payloads.
|
|
149
|
-
This event will be automatically added as a final argument to the callback prop.
|
|
150
|
-
If the analytics event payload needs to include some information from the components
|
|
151
|
-
props, \`withAnalyticsEvents\` also accepts a function.
|
|
152
|
-
|
|
153
|
-
##### Button.js
|
|
60
|
+
`;
|
|
154
61
|
|
|
155
|
-
|
|
62
|
+
const propsFunctionCode = `
|
|
156
63
|
const ButtonWithAnalytics = withAnalyticsEvents({
|
|
157
|
-
// this function should return an analytics event
|
|
158
64
|
onClick: (createEvent, props) => {
|
|
159
65
|
return createEvent({ action: 'click', appearance: props.appearance });
|
|
160
66
|
},
|
|
161
67
|
})(Button);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
${(
|
|
165
|
-
<Example
|
|
166
|
-
packageName="@atlaskit/analytics-next"
|
|
167
|
-
Component={require('../examples/30-passing-events-to-a-callback').default}
|
|
168
|
-
title="Passing events through callbacks"
|
|
169
|
-
source={require('!!raw-loader!../examples/30-passing-events-to-a-callback')}
|
|
170
|
-
/>
|
|
171
|
-
)}
|
|
172
|
-
|
|
173
|
-
<a name="cloning-an-event"></a>
|
|
174
|
-
## Cloning an event
|
|
175
|
-
|
|
176
|
-
The features described in this section are likey to be more useful to component
|
|
177
|
-
authors.
|
|
178
|
-
|
|
179
|
-
Once an event has been fired it cannot be updated or fired again. This poses a
|
|
180
|
-
problem for library component authors who want to record their own analytics
|
|
181
|
-
events, while also exposing analytics events to their consumers.
|
|
182
|
-
|
|
183
|
-
That's where \`.clone\` comes in.
|
|
184
|
-
|
|
185
|
-
Let's imagine a Form component. If it accepted an \`onSubmit\` callback prop we could do something like this:
|
|
186
|
-
|
|
187
|
-
##### Form.js (onSubmit method):
|
|
68
|
+
`;
|
|
188
69
|
|
|
189
|
-
|
|
70
|
+
const cloningCode = `
|
|
190
71
|
onSubmit = analyticsEvent => {
|
|
191
72
|
const { value } = this.state;
|
|
192
|
-
|
|
193
|
-
// Clone the analytics event
|
|
194
73
|
const publicEvent = analyticsEvent.clone();
|
|
195
|
-
|
|
196
|
-
// Add whatever data we want to know about to our event and fire it
|
|
197
74
|
analyticsEvent.update({ value }).fire('atlaskit');
|
|
198
75
|
|
|
199
76
|
if (this.props.onSubmit) {
|
|
200
|
-
// Pass the cloned event to the callback prop for consumers to use
|
|
201
77
|
this.props.onSubmit(value, publicEvent);
|
|
202
78
|
}
|
|
203
79
|
};
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
This is a common enough usecase that we have built a helper to make this
|
|
207
|
-
easier to do.
|
|
208
|
-
|
|
209
|
-
##### Form.js (onSubmit method):
|
|
80
|
+
`;
|
|
210
81
|
|
|
211
|
-
|
|
82
|
+
const cloningShortcutCode = `
|
|
212
83
|
import { withAnalyticsEvents, createAndFireEvent } from '@atlaskit/analytics-next';
|
|
213
84
|
|
|
214
85
|
const FormWithAnalytics = withAnalyticsEvents({
|
|
215
86
|
onSubmit: createAndFireEvent('atlaskit')({ action: 'submit' })
|
|
216
87
|
})(Form);
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
This will create the event with the payload, fire it on the specified channel
|
|
220
|
-
and return a clone of the event.
|
|
221
|
-
|
|
222
|
-
${(
|
|
223
|
-
<Example
|
|
224
|
-
packageName="@atlaskit/analytics-next"
|
|
225
|
-
Component={require('../examples/50-cloning-an-event').default}
|
|
226
|
-
title="Cloning an event"
|
|
227
|
-
source={require('!!raw-loader!../examples/50-cloning-an-event')}
|
|
228
|
-
/>
|
|
229
|
-
)}
|
|
230
|
-
|
|
231
|
-
<a name="tracking-events-outside-the-ui"></a>
|
|
232
|
-
## Tracking events outside the UI
|
|
233
|
-
|
|
234
|
-
This library provides tools for tracking interactions with UI components, and makes it really easy to capture the UI context and state when these events occur. But what if the event you're tracking doesn't care about the UI? Can you still use this library to track it?
|
|
235
|
-
|
|
236
|
-
Well, sure - but you might not need to. An event has to be created by a UI component to get \`context\` and a \`.fire\` method. Without these properties an analytics event is basically a payload! It might be simpler to just create an object and pass it directly to the function that handles your events.
|
|
237
|
-
|
|
238
|
-
In case it is useful for you to have a consistent interface for your events, even if they're not coming from the UI, we do export the base \`AnalyticsEvent\` class. Here's an example of how you might use it:
|
|
88
|
+
`;
|
|
239
89
|
|
|
240
|
-
|
|
90
|
+
const outsideUiCode = `
|
|
241
91
|
import { AnalyticsEvent } from '@atlaskit/analytics-next';
|
|
242
92
|
import sendAnalyticsEventToBackend from './sendAnalyticsEventToBackend';
|
|
243
93
|
|
|
@@ -250,22 +100,175 @@ const fetchBacon = async () => {
|
|
|
250
100
|
|
|
251
101
|
const responseTime = performance.now() - startTime;
|
|
252
102
|
|
|
253
|
-
/** This event records server response time. This function doesn't live inside
|
|
254
|
-
* a component and we don't care what state the UI is in when it runs. It
|
|
255
|
-
* would be annoying if we had to create the event inside a component, then
|
|
256
|
-
* pass it to this function. We can create a generic AnalyticsEvent and handle
|
|
257
|
-
* it all inside this function instead. */
|
|
258
103
|
const analyticsEvent = new AnalyticsEvent({
|
|
259
104
|
payload: { action: 'server-request', data, responseTime },
|
|
260
105
|
});
|
|
261
106
|
|
|
262
|
-
/** Because we're not in the UI this event doesn't have any
|
|
263
|
-
* AnalyticsListeners, which means it doesn't have a .fire method. We need to
|
|
264
|
-
* explicitly pass it to the function that will handle it. */
|
|
265
107
|
sendAnalyticsEventToBackend(analyticsEvent);
|
|
266
108
|
|
|
267
109
|
return data;
|
|
268
110
|
};
|
|
269
|
-
`}
|
|
270
111
|
`;
|
|
271
|
-
|
|
112
|
+
|
|
113
|
+
export default function AdvancedUsage(): React.JSX.Element {
|
|
114
|
+
return (
|
|
115
|
+
<div>
|
|
116
|
+
<h3>Contents</h3>
|
|
117
|
+
<ul>
|
|
118
|
+
<li>
|
|
119
|
+
<a href="#adding-more-information-to-an-event">Adding more information to an event</a>
|
|
120
|
+
</li>
|
|
121
|
+
<li>
|
|
122
|
+
<a href="#using-a-channel">Using a channel</a>
|
|
123
|
+
</li>
|
|
124
|
+
<li>
|
|
125
|
+
<a href="#passing-an-event-to-your-consumers">Passing an event to your consumers</a>
|
|
126
|
+
</li>
|
|
127
|
+
<li>
|
|
128
|
+
<a href="#cloning-an-event">Cloning an event</a>
|
|
129
|
+
</li>
|
|
130
|
+
<li>
|
|
131
|
+
<a href="#tracking-events-outside-the-ui">Tracking events outside the UI</a>
|
|
132
|
+
</li>
|
|
133
|
+
</ul>
|
|
134
|
+
|
|
135
|
+
<h2 id="adding-more-information-to-an-event">Adding more information to an event</h2>
|
|
136
|
+
<p>
|
|
137
|
+
This package provides two methods for adding extra information to analytics events. The
|
|
138
|
+
first method is by adding data to the analytics events payload. The second method is to
|
|
139
|
+
provide contextual information to any event.
|
|
140
|
+
</p>
|
|
141
|
+
<h3>Adding data to an event's payload</h3>
|
|
142
|
+
<p>
|
|
143
|
+
Before firing an analytics event, you can add data the payload by using the{' '}
|
|
144
|
+
<code>update</code> method. Here's an example of how that looks:
|
|
145
|
+
</p>
|
|
146
|
+
<h5>SaveButton.js</h5>
|
|
147
|
+
<CodeBlock code={saveButtonCode} />
|
|
148
|
+
<p>
|
|
149
|
+
In addition to accepting an object, the <code>update</code> method accepts a function which
|
|
150
|
+
is called with the event's current payload and is expected to return a new payload.
|
|
151
|
+
</p>
|
|
152
|
+
<p>
|
|
153
|
+
Below is a fleshed out example demonstrating how to add extra information to the
|
|
154
|
+
event's payload.
|
|
155
|
+
</p>
|
|
156
|
+
<ExampleBlock
|
|
157
|
+
Component={require('../examples/40-updating-an-event').default}
|
|
158
|
+
title="Updating an event's payload"
|
|
159
|
+
source={require('!!raw-loader!../examples/40-updating-an-event')}
|
|
160
|
+
/>
|
|
161
|
+
|
|
162
|
+
<h2 id="using-a-channel">Using a channel</h2>
|
|
163
|
+
<p>The feature is likey more useful for component authors.</p>
|
|
164
|
+
<p>
|
|
165
|
+
When calling <code>fire</code> on an analytics event, you can optionally specify a channel
|
|
166
|
+
to fire the event on. Only listeners on that channel will recieve the event.
|
|
167
|
+
</p>
|
|
168
|
+
<h5>Button.js (handleClick method)</h5>
|
|
169
|
+
<CodeBlock code={usingChannelCode} />
|
|
170
|
+
<p>
|
|
171
|
+
In the above example, we fire events on the <code>'atlaskit'</code> channel. To
|
|
172
|
+
listen on this channel we would set up our App like:
|
|
173
|
+
</p>
|
|
174
|
+
<h5>App.js (render method)</h5>
|
|
175
|
+
<CodeBlock code={appRenderCode} />
|
|
176
|
+
<p>
|
|
177
|
+
The <code>AnalyticsListener</code> component accepts <code>channel</code> and{' '}
|
|
178
|
+
<code>onEvent</code> props. When an event is fired on this Listener's channel its
|
|
179
|
+
onEvent function will be called.
|
|
180
|
+
</p>
|
|
181
|
+
|
|
182
|
+
<h2 id="passing-an-event-to-your-consumers">Passing an event to your consumers</h2>
|
|
183
|
+
<p>
|
|
184
|
+
The features described in this section are likey to be more useful to component authors.
|
|
185
|
+
</p>
|
|
186
|
+
<p>
|
|
187
|
+
If you are building components, you might not want to fire an event as soon as it's
|
|
188
|
+
created - instead it is better to provide the event to the consumer of your component. The
|
|
189
|
+
consumer then has a chance to add more information and fire the event when they're
|
|
190
|
+
ready.
|
|
191
|
+
</p>
|
|
192
|
+
<p>
|
|
193
|
+
This is exactly the approach we took to instrument our own Atlaskit components. This section
|
|
194
|
+
will show you how we did it and how to use the same approach in your components.
|
|
195
|
+
</p>
|
|
196
|
+
<p>
|
|
197
|
+
The most straight forward way is to pass the event as an extra argument to the corresponding
|
|
198
|
+
callback prop. Here's our updated Button component:
|
|
199
|
+
</p>
|
|
200
|
+
<h5>Button.js (handleClick method)</h5>
|
|
201
|
+
<CodeBlock code={passingEventCode} />
|
|
202
|
+
<p>
|
|
203
|
+
This is a pretty common pattern for component authors, so <code>withAnalyticsEvents</code>{' '}
|
|
204
|
+
provides a shortcut:
|
|
205
|
+
</p>
|
|
206
|
+
<h5>Button.js</h5>
|
|
207
|
+
<CodeBlock code={shortcutCode} />
|
|
208
|
+
<p>
|
|
209
|
+
<code>withAnalyticsEvents</code> accepts an optional object mapping callback prop names to
|
|
210
|
+
payloads. This event will be automatically added as a final argument to the callback prop.
|
|
211
|
+
If the analytics event payload needs to include some information from the components props,{' '}
|
|
212
|
+
<code>withAnalyticsEvents</code> also accepts a function.
|
|
213
|
+
</p>
|
|
214
|
+
<h5>Button.js</h5>
|
|
215
|
+
<CodeBlock code={propsFunctionCode} />
|
|
216
|
+
<ExampleBlock
|
|
217
|
+
Component={require('../examples/30-passing-events-to-a-callback').default}
|
|
218
|
+
title="Passing events through callbacks"
|
|
219
|
+
source={require('!!raw-loader!../examples/30-passing-events-to-a-callback')}
|
|
220
|
+
/>
|
|
221
|
+
|
|
222
|
+
<h2 id="cloning-an-event">Cloning an event</h2>
|
|
223
|
+
<p>
|
|
224
|
+
The features described in this section are likey to be more useful to component authors.
|
|
225
|
+
</p>
|
|
226
|
+
<p>
|
|
227
|
+
Once an event has been fired it cannot be updated or fired again. This poses a problem for
|
|
228
|
+
library component authors who want to record their own analytics events, while also exposing
|
|
229
|
+
analytics events to their consumers.
|
|
230
|
+
</p>
|
|
231
|
+
<p>
|
|
232
|
+
That's where <code>.clone</code> comes in.
|
|
233
|
+
</p>
|
|
234
|
+
<p>
|
|
235
|
+
Let's imagine a Form component. If it accepted an <code>onSubmit</code> callback prop
|
|
236
|
+
we could do something like this:
|
|
237
|
+
</p>
|
|
238
|
+
<h5>Form.js (onSubmit method):</h5>
|
|
239
|
+
<CodeBlock code={cloningCode} />
|
|
240
|
+
<p>This is a common enough usecase that we have built a helper to make this easier to do.</p>
|
|
241
|
+
<h5>Form.js (onSubmit method):</h5>
|
|
242
|
+
<CodeBlock code={cloningShortcutCode} />
|
|
243
|
+
<p>
|
|
244
|
+
This will create the event with the payload, fire it on the specified channel and return a
|
|
245
|
+
clone of the event.
|
|
246
|
+
</p>
|
|
247
|
+
<ExampleBlock
|
|
248
|
+
Component={require('../examples/50-cloning-an-event').default}
|
|
249
|
+
title="Cloning an event"
|
|
250
|
+
source={require('!!raw-loader!../examples/50-cloning-an-event')}
|
|
251
|
+
/>
|
|
252
|
+
|
|
253
|
+
<h2 id="tracking-events-outside-the-ui">Tracking events outside the UI</h2>
|
|
254
|
+
<p>
|
|
255
|
+
This library provides tools for tracking interactions with UI components, and makes it
|
|
256
|
+
really easy to capture the UI context and state when these events occur. But what if the
|
|
257
|
+
event you're tracking doesn't care about the UI? Can you still use this library to
|
|
258
|
+
track it?
|
|
259
|
+
</p>
|
|
260
|
+
<p>
|
|
261
|
+
Well, sure - but you might not need to. An event has to be created by a UI component to get{' '}
|
|
262
|
+
<code>context</code> and a <code>.fire</code> method. Without these properties an analytics
|
|
263
|
+
event is basically a payload! It might be simpler to just create an object and pass it
|
|
264
|
+
directly to the function that handles your events.
|
|
265
|
+
</p>
|
|
266
|
+
<p>
|
|
267
|
+
In case it is useful for you to have a consistent interface for your events, even if
|
|
268
|
+
they're not coming from the UI, we do export the base <code>AnalyticsEvent</code>{' '}
|
|
269
|
+
class. Here's an example of how you might use it:
|
|
270
|
+
</p>
|
|
271
|
+
<CodeBlock code={outsideUiCode} />
|
|
272
|
+
</div>
|
|
273
|
+
);
|
|
274
|
+
}
|