Skip to content

Tracking Tags

Assign human-friendly identifiers to interactive elements so the HUD shows meaningful labels. You can use data-rpm-id / data-rpm-group explicitly, or rely on automatic resolution from common attributes and content.

Automatic Resolution (No Attributes Required)

The tracker resolves interaction IDs from many sources without requiring data-rpm-id:

SourceExample
Button/link text<button>Load users</button>"Load users"
id<input id="search-filter" />"search-filter"
aria-label<button aria-label="Close">×</button>"Close"
placeholder<input placeholder="Search..." />"Search..."
data-testid<button data-testid="submit-btn">Submit</button>"submit-btn"
name (form controls)<input name="email" />"email"

Labels are truncated to 30 characters. If none match, the element tagName is used (button, input, etc.).

data-rpm-id

Use data-rpm-id on the element that the user interacts with (or a parent). The value becomes the Last Interaction label in the HUD.

tsx
<button data-rpm-id="load-users">Load users</button>
<input data-rpm-id="search-query" placeholder="Search" />
<form data-rpm-id="submit-form" onSubmit={handleSubmit}>
  <button type="submit">Submit</button>
</form>

data-rpm-group

Use data-rpm-group to tag a container. When the user interacts with any descendant, the group value is used as the interaction ID.

tsx
<div data-rpm-group="auth-flow">
  <input type="email" />
  <input type="password" />
  <button>Sign in</button>
</div>

Resolution Order

When an interaction occurs, the tracker resolves the ID in this order:

  1. Closest [data-rpm-id] – Nearest ancestor (or self) with data-rpm-id
  2. Closest [data-rpm-group] – Nearest ancestor (or self) with data-rpm-group
  3. Element id – The interacted element’s id attribute
  4. aria-label – Accessible label
  5. placeholder – For input / textarea
  6. data-testid – Common test identifier
  7. name – For input, select, textarea
  8. Button/link text – For button, a, [role="button"], etc.
  9. Tag name – Fallback to button, input, form, etc.

Capture Phase

Listeners use the capture phase (addEventListener(..., { capture: true })), so the interaction is attributed even when events bubble through nested components or portals.

Portals

Interactions inside React portals (e.g. modals) are still captured. The portal’s DOM is part of the same document, so data-rpm-id and data-rpm-group work as usual:

tsx
// Inside a portal
<div data-rpm-group="modal-actions">
  <button data-rpm-id="modal-submit">Submit</button>
  <button data-rpm-id="modal-cancel">Cancel</button>
</div>

Best Practices

  • Prefer automatic resolution – Use id, aria-label, placeholder, or button text when possible; no extra attributes needed
  • Use data-rpm-id when you need an explicit label that differs from the visible text
  • Use data-rpm-group for section-level grouping when individual control labels don't matter
  • Use short, descriptive values; avoid dynamic or random values for easier debugging