diff --git a/packages/docs/src/components/DocsSideNav.tsx b/packages/docs/src/components/DocsSideNav.tsx index d27f675a09..01369f0d5c 100644 --- a/packages/docs/src/components/DocsSideNav.tsx +++ b/packages/docs/src/components/DocsSideNav.tsx @@ -28,6 +28,12 @@ const DocsSideNav: React.FC = ({ isSideNavExpanded }) => ( + + API + + + Analytics Instrumentation + Chart data @@ -55,9 +61,6 @@ const DocsSideNav: React.FC = ({ isSideNavExpanded }) => ( Zoombar - - API - diff --git a/packages/docs/src/main.tsx b/packages/docs/src/main.tsx index 0baac40ab8..3e0d16e0ce 100644 --- a/packages/docs/src/main.tsx +++ b/packages/docs/src/main.tsx @@ -11,6 +11,7 @@ import { Data, Options, Api, + AnalyticsInstrumentation, Themes, Axes, Palettes, @@ -25,6 +26,7 @@ import { CirclePack, Combo, Donut, + EventListeners, Gauge, Heatmap, Histogram, @@ -48,7 +50,6 @@ import { } from './routes' import './index.scss' -import EventListeners from './routes/EventListeners' const App: React.FC = () => ( @@ -68,6 +69,7 @@ const App: React.FC = () => ( } /> } /> } /> + } /> } /> } /> } /> diff --git a/packages/docs/src/routes/AnalyticsInstrumentation.tsx b/packages/docs/src/routes/AnalyticsInstrumentation.tsx new file mode 100644 index 0000000000..9c057b0113 --- /dev/null +++ b/packages/docs/src/routes/AnalyticsInstrumentation.tsx @@ -0,0 +1,163 @@ +import { useEffect } from 'react' +import hljs from 'highlight.js/lib/core' +import javascript from 'highlight.js/lib/languages/javascript' +import { CodeSnippet } from '@carbon/react/es' +import PageHeader from '../components/PageHeader' + +export default function AnalyticsInstrumentation() { + const highlightCode = () => { + hljs.registerLanguage('javascript', javascript) + + const nodes = document.querySelectorAll('pre code') + nodes.forEach(el => { + hljs.highlightElement(el as HTMLElement) + }) + } + + useEffect(() => { + highlightCode() + }) + + return ( + <> + + +

+ Carbon Charts provides an events service that can be leveraged to track user interactions + and send telemetry data to analytics platforms like Amplitude. Below are examples of how to + instrument your charts to gather user behavior data. +

+ +

Basic Telemetry Setup

+ +

+ To track interactions with your chart, use a reference to the chart to add event listeners + for the dispatched events. The following example shows how to track legend clicks: +

+ + {`// Initialize Amplitude +amplitude.init("YOUR_AMPLITUDE_API_KEY") + +// Track legend interactions +chart.services.events.addEventListener("legend-item-onclick", ({ detail }) => { + amplitude.track("Chart_LegendClick", { + chartId: "sales-dashboard-main", + toggledSeries: detail.selection + }) +})`} + +

Common Events To Track

+ +

Here are examples of events that could provide valuable user interaction data:

+ + {`// Track bar clicks +chart.services.events.addEventListener("bar-click", ({ detail }) => { + amplitude.track("Chart_BarClick", { + group: detail.datum.group, + value: detail.datum.value + }) +}) + +// Track when charts finish rendering +chart.services.events.addEventListener("render-finished", ({ detail }) => { + amplitude.track("Chart_Rendered", { + renderTime: // number of seconds it took to render the chart + }) +}) + +// Track tooltip interactions +chart.services.events.addEventListener("show-tooltip", ({ detail }) => { + amplitude.track("Chart_TooltipView", { + data: detail.data + }) +})`} + +

Debouncing High-Frequency Events

+ +

+ For events that may fire frequently, such as tooltips or mouse movements, debouncing could + be used to prevent overwhelming your analytics platform: +

+ + {`import { debounce } from "lodash" + +// Create debounced tracking function +const debouncedTrack = debounce((eventName, eventData) => { + amplitude.track(eventName, eventData) +}, 300) + +// Apply to tooltip events +chart.services.events.addEventListener("show-tooltip", ({ detail }) => { + debouncedTrack("Chart_TooltipView", { + data: detail.data + }) +})`} + +

React Integration Pattern

+ +

+ When using Carbon Charts with React, you can set up event listeners using refs and + useEffect: +

+ + {`import { BarChart } from "@carbon/charts-react" +import { useRef, useEffect } from "react" +import amplitude from "amplitude-js" + +function InstrumentedChart({ data, options }) { + const chartRef = useRef(null) + + // Set up event tracking + useEffect(() => { + if (chartRef.current) { + const events = chartRef.current.chart.services.events + + // Track bar clicks + events.addEventListener("bar-click", ({ detail }) => { + amplitude.track("Chart_BarClick", { + group: detail.datum.group, + value: detail.datum.value + }) + }) + + // Track render completion + events.addEventListener("render-finished", ({ detail }) => { + amplitude.track("Chart_Rendered", { + renderTime: // number of seconds it took to render the chart + }) + }) + } + + // Clean up event listeners + return () => { + if (chartRef.current) { + const events = chartRef.current.chart.services.events + + events.removeEventListener("bar-click", handleBarClick) + events.removeEventListener("render-finished", handleRenderFinished) + } + } + }, [chartRef]) + + return ( + + ) +}`} + +

+ Event-based telemetry allows applications to gather valuable user behavior data without + disrupting the user experience. More information on available event listeners can be found{' '} + + here + + . +

+ + ) +} diff --git a/packages/docs/src/routes/Api.tsx b/packages/docs/src/routes/Api.tsx index 327a9c924f..2bd008193c 100644 --- a/packages/docs/src/routes/Api.tsx +++ b/packages/docs/src/routes/Api.tsx @@ -1,7 +1,7 @@ import { useEffect } from 'react' import hljs from 'highlight.js/lib/core' import javascript from 'highlight.js/lib/languages/javascript' -import { CodeSnippet } from '@carbon/react/es' +import { CodeSnippet, ListItem, UnorderedList } from '@carbon/react/es' import PageHeader from '../components/PageHeader' import styled from 'styled-components' @@ -74,6 +74,26 @@ console.log(myChart) .

+

Event Listener Code Examples

+ + + + vanilla + + + + + React + + + +

Full Documentation

diff --git a/packages/docs/src/routes/EventListeners.tsx b/packages/docs/src/routes/EventListeners.tsx index 566f330d48..27a5b70d54 100644 --- a/packages/docs/src/routes/EventListeners.tsx +++ b/packages/docs/src/routes/EventListeners.tsx @@ -1,7 +1,7 @@ import { useEffect } from 'react' import hljs from 'highlight.js/lib/core' import javascript from 'highlight.js/lib/languages/javascript' -import { CodeSnippet } from '@carbon/react/es' +import { CodeSnippet, ListItem, UnorderedList } from '@carbon/react/es' import PageHeader from '../components/PageHeader' export default function EventListeners() { @@ -44,6 +44,26 @@ export default function EventListeners() { .

+ +

Code Examples

+ + + + vanilla + + + + + React + + + ) } diff --git a/packages/docs/src/routes/index.ts b/packages/docs/src/routes/index.ts index 26d760b2f3..729da4f990 100644 --- a/packages/docs/src/routes/index.ts +++ b/packages/docs/src/routes/index.ts @@ -6,6 +6,7 @@ import Anatomy from './Anatomy.tsx' import Data from './Data.tsx' import Options from './Options.tsx' import Api from './Api.tsx' +import AnalyticsInstrumentation from './AnalyticsInstrumentation' import Themes from './Themes.tsx' import Axes from './Axes.tsx' import Palettes from './Palettes.tsx' @@ -20,6 +21,7 @@ import Choropleth from './Choropleth.tsx' import CirclePack from './CirclePack.tsx' import Combo from './Combo.tsx' import Donut from './Donut.tsx' +import EventListeners from './EventListeners' import Gauge from './Gauge.tsx' import Heatmap from './Heatmap.tsx' import Histogram from './Histogram.tsx' @@ -50,6 +52,7 @@ export { Data, Options, Api, + AnalyticsInstrumentation, Themes, Axes, Palettes, @@ -64,6 +67,7 @@ export { CirclePack, Combo, Donut, + EventListeners, Gauge, Heatmap, Histogram,