feat(ui): add analytics event tracking to BUI navigation components (#33150)
* feat(ui): add analytics types Signed-off-by: Johan Persson <johanopersson@gmail.com> * feat(ui): add useAnalytics hook with dev-mode swap guard Signed-off-by: Johan Persson <johanopersson@gmail.com> * feat(ui): add AnalyticsProvider, getNodeText, and analytics barrel exports Signed-off-by: Johan Persson <johanopersson@gmail.com> * feat(ui): integrate analytics into defineComponent and useDefinition Signed-off-by: Johan Persson <johanopersson@gmail.com> * feat(ui): add analytics tracking to Link component Signed-off-by: Johan Persson <johanopersson@gmail.com> * feat(ui): add analytics tracking to ButtonLink component Signed-off-by: Johan Persson <johanopersson@gmail.com> * feat(ui): add analytics tracking to Tab component Signed-off-by: Johan Persson <johanopersson@gmail.com> * feat(ui): add analytics tracking to MenuItem component Signed-off-by: Johan Persson <johanopersson@gmail.com> * feat(ui): add analytics tracking to Tag component Signed-off-by: Johan Persson <johanopersson@gmail.com> * feat(ui): add analytics tracking to Table Row component Signed-off-by: Johan Persson <johanopersson@gmail.com> * feat(ui): widen getNodeText to accept render functions Signed-off-by: Johan Persson <johanopersson@gmail.com> * chore(ui): update API reports Signed-off-by: Johan Persson <johanopersson@gmail.com> * chore: add changeset for BUI analytics Signed-off-by: Johan Persson <johanopersson@gmail.com> * fix(ui): chain MenuItem onAction with user-provided handler instead of overwriting Signed-off-by: Johan Persson <johanopersson@gmail.com> * chore(ui): address review feedback — changeset wording and types docs Signed-off-by: Johan Persson <johanopersson@gmail.com> * feat(core-app-api): wire AnalyticsProvider from @backstage/ui into app shell Signed-off-by: Johan Persson <johanopersson@gmail.com> * feat(plugin-app): add AnalyticsProvider wrapper extension for BUI components Signed-off-by: Johan Persson <johanopersson@gmail.com> * chore: update API reports Signed-off-by: Johan Persson <johanopersson@gmail.com> * chore: update API reports for core-components and scaffolder Signed-off-by: Johan Persson <johanopersson@gmail.com> * docs(ui): add analytics documentation and noTrack prop to component docs Signed-off-by: Johan Persson <johanopersson@gmail.com> * chore: update yarn.lock Signed-off-by: Johan Persson <johanopersson@gmail.com> * feat(plugin-app): move AnalyticsProvider into AppRoot directly Signed-off-by: Johan Persson <johanopersson@gmail.com> * chore: format installation docs Signed-off-by: Johan Persson <johanopersson@gmail.com> * fix(ui): call user onPress before analytics in Tag component Signed-off-by: Johan Persson <johanopersson@gmail.com> * refactor(ui): replace AnalyticsProvider with generic BUIProvider Signed-off-by: Johan Persson <johanopersson@gmail.com> * chore: replace remaining AnalyticsProvider references with BUIProvider Signed-off-by: Johan Persson <johanopersson@gmail.com> * fix(plugin-app): import useAnalytics from frontend-plugin-api Signed-off-by: Johan Persson <johanopersson@gmail.com> * docs(ui): improve noTrack prop description Signed-off-by: Johan Persson <johanopersson@gmail.com> --------- Signed-off-by: Johan Persson <johanopersson@gmail.com>
This commit is contained in:
@@ -62,6 +62,11 @@ export const buttonLinkPropDefs: Record<string, PropDef> = {
|
||||
</>
|
||||
),
|
||||
},
|
||||
noTrack: {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Suppresses the automatic analytics click event, e.g. if you already have custom tracking.',
|
||||
},
|
||||
onSurface: {
|
||||
type: 'enum',
|
||||
values: ['0', '1', '2', '3', 'danger', 'warning', 'success', 'auto'],
|
||||
|
||||
@@ -68,6 +68,11 @@ export const linkPropDefs: Record<string, PropDef> = {
|
||||
'Truncates text with ellipsis when it overflows its container.',
|
||||
default: 'false',
|
||||
},
|
||||
noTrack: {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Suppresses the automatic analytics click event, e.g. if you already have custom tracking.',
|
||||
},
|
||||
standalone: {
|
||||
type: 'boolean',
|
||||
description: 'Removes underline by default. Underline appears on hover.',
|
||||
|
||||
@@ -309,6 +309,11 @@ export const menuItemPropDefs: Record<string, PropDef> = {
|
||||
type: 'boolean',
|
||||
description: 'Whether the item is disabled.',
|
||||
},
|
||||
noTrack: {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Suppresses the automatic analytics click event, e.g. if you already have custom tracking.',
|
||||
},
|
||||
textValue: {
|
||||
type: 'string',
|
||||
description: 'Text used for typeahead and accessibility.',
|
||||
|
||||
@@ -456,6 +456,11 @@ export const rowPropDefs: Record<string, PropDef> = {
|
||||
description:
|
||||
'Row content. Can be a render function receiving column config.',
|
||||
},
|
||||
noTrack: {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Suppresses the automatic analytics click event, e.g. if you already have custom tracking.',
|
||||
},
|
||||
...classNamePropDefs,
|
||||
...stylePropDefs,
|
||||
};
|
||||
|
||||
@@ -68,6 +68,11 @@ export const tabPropDefs: Record<string, PropDef> = {
|
||||
default: 'false',
|
||||
description: 'Disables this tab. Use for temporarily unavailable options.',
|
||||
},
|
||||
noTrack: {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Suppresses the automatic analytics click event, e.g. if you already have custom tracking.',
|
||||
},
|
||||
...childrenPropDefs,
|
||||
...classNamePropDefs,
|
||||
};
|
||||
|
||||
@@ -84,6 +84,11 @@ export const tagPropDefs: Record<string, PropDef> = {
|
||||
type: 'boolean',
|
||||
description: 'Whether the tag is disabled.',
|
||||
},
|
||||
noTrack: {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Suppresses the automatic analytics click event, e.g. if you already have custom tracking.',
|
||||
},
|
||||
...childrenPropDefs,
|
||||
...classNamePropDefs,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { CodeBlock } from '@/components/CodeBlock';
|
||||
import { Banner } from '@/components/Banner';
|
||||
import { snippet } from './snippets';
|
||||
import {
|
||||
snippet,
|
||||
analyticsSetupSnippet,
|
||||
analyticsNoTrackSnippet,
|
||||
} from './snippets';
|
||||
|
||||
# Installation
|
||||
|
||||
@@ -44,3 +48,25 @@ your plugin and import the components you need.
|
||||
/>
|
||||
|
||||
<CodeBlock lang="tsx" title="Let's get started 🚀" code={snippet} />
|
||||
|
||||
## Analytics
|
||||
|
||||
BUI components with navigation behavior — Link, ButtonLink, Tab, MenuItem, Tag, and Row — can fire analytics events when clicked. To enable this, you need to connect BUI's analytics layer to Backstage's analytics system.
|
||||
|
||||
### Setup
|
||||
|
||||
If you're using the **new frontend system**, analytics is wired automatically via `@backstage/plugin-app` — no setup required.
|
||||
|
||||
For the **old frontend system**, the `BUIProvider` is included in the app shell from `@backstage/core-app-api` and works out of the box.
|
||||
|
||||
If you need to set up the provider manually (e.g. in a custom app shell), wrap your app content with the `BUIProvider` and pass in Backstage's `useAnalytics` hook:
|
||||
|
||||
<CodeBlock lang="tsx" code={analyticsSetupSnippet} />
|
||||
|
||||
### How it works
|
||||
|
||||
Once configured, BUI components fire a `click` event through Backstage's analytics system when a user navigates. Events include the link text as the subject and the destination URL in the attributes, along with any `AnalyticsContext` metadata (such as `pluginId`) from the component's position in the tree.
|
||||
|
||||
To suppress tracking on an individual component, use the `noTrack` prop:
|
||||
|
||||
<CodeBlock lang="tsx" code={analyticsNoTrackSnippet} />
|
||||
|
||||
@@ -4,3 +4,16 @@ export const snippet = `import { Flex, Button, Text } from '@backstage/ui';
|
||||
<Text>Hello World</Text>
|
||||
<Button>Click me</Button>
|
||||
</Flex>;`;
|
||||
|
||||
export const analyticsSetupSnippet = `import { BUIProvider } from '@backstage/ui';
|
||||
import { useAnalytics } from '@backstage/core-plugin-api';
|
||||
|
||||
// Wrap your app content with the provider
|
||||
<BUIProvider useAnalytics={useAnalytics}>
|
||||
<AppContent />
|
||||
</BUIProvider>`;
|
||||
|
||||
export const analyticsNoTrackSnippet = `// Suppress analytics for a specific link
|
||||
<Link href="/internal" noTrack>
|
||||
Skip tracking
|
||||
</Link>`;
|
||||
|
||||
Reference in New Issue
Block a user