# Track events with HTML attributes

> Track clicks and form submissions as custom events without writing JavaScript, using data-privatus-event and data-privatus-prop HTML attributes on any element.

Add `data-privatus-event` to any element to send an event when it's
clicked:

```html
<a href="/pricing" data-privatus-event="Pricing CTA">See pricing</a>
<button data-privatus-event="Play video" data-privatus-prop-video="intro">Play</button>
```

## Properties

Every `data-privatus-prop-<key>` attribute becomes a property. Dashes in the
key become underscores:

```html
<a href="/signup" data-privatus-event="Signup CTA"
   data-privatus-prop-plan="pro"
   data-privatus-prop-button-location="hero">Start free</a>
```

sends `Signup CTA` with `{ plan: 'pro', button_location: 'hero' }`.
Attribute values are always strings.

## Forms

On a `<form>`, the event fires when the form is **submitted** (clicks
inside the form don't trigger it):

```html
<form action="/contact" method="post" data-privatus-event="Contact form" data-privatus-prop-topic="sales">
  …
</form>
```

Form fields are never read or sent. Only the attributes you write become
properties.

## How it works

The tracker listens for clicks and submits on the whole document (in the
capture phase), finds the nearest ancestor with `data-privatus-event`, and
sends the event. It works for elements added later, too.

- Clicking a child element (an icon inside a button) counts for the
  element with the attribute.
- Elements with `data-privatus-event` are ignored by the
  [`auto` module](/docs/tracker/modules#auto-automatic-events), so a
  tracked outbound link isn't counted twice.
- Links navigate as usual. The request uses `keepalive` so it survives the
  navigation.

## Click maps

For aggregate click maps, the `clicks` module also recognizes
`data-privatus-click` as a named click target. See
[Modules](/docs/tracker/modules#clicks-click-maps).
