Anatomy of a Click
An operator taps "Acknowledge" on an alert. A few seconds later, an event lands in Azure that says — precisely — which button, in which panel, for which camera, at which second of the session. Nobody wrote tracking code for that button.
Let's dissect how one click becomes that event, because once you see the pipeline, you'll know exactly how to make your features show up well in the data — and that part does take a little deliberate effort.
See it from the data's side first — click around this sandbox and watch what each control would send. One of these buttons produces garbage; find it, then fix it:
Step 1 — catching the click at all
useClickTracking attaches a single listener for the entire app:
document.addEventListener('click', handleClick, { capture: true });
The capture: true is the load-bearing detail. Events in the capture phase travel down the
tree before components see them — so the tracker hears every click even when a component calls
stopPropagation(), and even if the clicked element is removed from the DOM by its own handler
a millisecond later.
Step 2 — finding what was really clicked
The literal event target is usually junk — the <svg> inside the icon inside the button. So
findClickableElement walks up the DOM from the target until it finds something genuinely
clickable: a BUTTON/A/INPUT tag, a role="button"/role="link", or an element carrying
onclick or data-track. No clickable ancestor within ~10 levels → the click is discarded as
noise.
Step 3 — naming the action
Every event needs a human-readable actionName, resolved by priority:
data-trackattribute — you named it explicitly. Best.aria-label— the accessible name doubles as the analytics name.- Visible text —
"button:Create Alert". Fine, until someone rewords the button and your six-month query breaks.
Notice the alignment: the same aria-label that serves screen-reader users serves analytics.
Accessible components produce good telemetry for free.
Step 4 — gathering context
Around that name, the tracker packs: element type/id/classes (with CSS-in-JS noise like css-*
and MuiBox-* filtered out), all data-* attributes flattened into the event, a
parentContext built by walking up the DOM collecting data-component/data-section markers
and semantic landmarks (<nav>, <dialog>, role="navigation"…), a simplified XPath, and
session metadata (userFlowSequence — this click's position in the session — plus seconds since
session start and the URL).
That parentContext is what turns "a Delete button was clicked" into "the Delete button in
AlertManagement > AlertList was clicked" — same label, completely different meaning.
Writing components that produce good telemetry
This is the part you'll actually use. Three habits, in increasing order of payoff:
Name your actions. One attribute makes an event unambiguous and rename-proof:
<Button data-track="CreateNewAlert">Create Alert</Button>
Mark your regions. Wrap feature areas so every click inside them carries hierarchy:
<div data-component="AlertManagement">
<div data-section="AlertList">
<Button data-track="ViewAlert">View</Button>
</div>
</div>
// → parentContext: "AlertManagement > AlertList"
Attach your domain ids. Any data-* on the clicked element or its clickable ancestor rides
along automatically:
<CameraCard data-camera-id={camera.id} data-camera-status={camera.status}>
<Button data-track="ControlCamera">Control</Button>
</CameraCard>
// → event includes data_cameraId, data_cameraStatus
With those three in place, the question "which cameras do operators try to control while offline?" is a one-line query instead of a data-archaeology project.
Checking your work
In development, every tracked click is logged to the console (Click tracked: <actionName> plus
the payload). To watch events leave the building, filter the DevTools Network tab for
dc.services.visualstudio.com — and remember events are batched (every 15 s, 100 events, or
page unload), so don't panic when a click doesn't produce an instant request.
Wrapping up
One capture-phase listener, a walk up the DOM, a three-tier naming rule, and a context bundle —
that's the entire click pipeline. Your part is three attributes: data-track to name actions,
data-component/data-section to mark regions, data-* to attach domain ids.
Now that the data exists, learn to interrogate it: Asking Questions of the Data.