Skip to main content

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:

📡 Telemetry Sandboxno events yet — click anything
event stream — what the tracker would send to Azure

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:

  1. data-track attribute — you named it explicitly. Best.
  2. aria-label — the accessible name doubles as the analytics name.
  3. 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.