# Custom events

An event counts something a visitor did on a page, such as signing up. Every event is a goal on the dashboard.

As a goal, each event shows how many visits did it, what share of all visits that was, and where those visits came from. From a button or a link, sending one takes an attribute and no script. From anything else, such as a form your own code accepts, it takes one line of JavaScript.

## Sending an event

Send one from your own script, or from anything clicked with no script at all.

### From a script

Once the script has loaded, `tally()` sends an event:

```
tally('Signup', { plan: 'pro' });
```

It takes the event’s name, then, optionally, its data and a function to call once it’s on its way: `tally(name, data, callback)`.

### Without a script

Give anything that can be clicked a `data-tally` attribute, and it sends that event when it’s clicked. Its `data-tally-` attributes are the event’s data:

```
<button data-tally="Signup" data-tally-plan="pro">Start</button>
```

A click anywhere inside the element counts, on its text or an icon in it. A middle click counts on a link, where it opens a new tab, and nowhere else. Elements inside a web component count too, unless its shadow root is closed.

### Before the script has loaded

The script is `async`, so your own scripts can run before `tally()` exists. Make a queue instead, and push each call onto it as a list of the arguments `tally()` would take. They’re sent in order once the script loads:

```
window.tally = window.tally || [];
tally.push(['Signup', { plan: 'pro' }]);
```

`tally.push()` keeps working after the script has loaded, so you can use it throughout.

### The callback

The function given third is called once the browser has the event to send, or straight away when nothing is sent, such as on your own computer, so it’s always called. Events are sent in a way that survives the page closing, so a link followed or a form sent straight after `tally()` loses nothing. The callback is for anything that has to wait all the same.

## Names

- A name is kept as sent, capitals and all, so `Signup` and `signup` are two events. Spaces at its ends are trimmed, and each run of spaces inside it becomes one.
- Up to 64 characters are kept.
- A name can’t start with `/`, which is how [page goals](https://fiveb.ar/docs/goals.md#page-goals) are named.
- `pageview`, `timing`, `engagement`, `outbound` and `download` are the script’s own. It sends nothing for them, and only calls the callback.
- A site can send 100 different event names a day. Past that, new names aren’t counted until the next day.

## Data

An event’s data is an object of names and values sent with it. Filtered by the event, the dashboard shows each value under its name, narrowed by any other filter but an entry or exit page.

- Up to 8 names, each up to 32 lower case letters, digits, `-` and `_`. Capitals are lowercased.
- A value is text, a number, or true or false, up to 255 characters. Anything else, such as an object or a list, is dropped.
- A value with an email address in it is dropped. The rest are kept exactly as sent, so send nothing about a person.

Data describes one event. To label everything a page sends, use a [custom property](https://fiveb.ar/docs/properties.md).

## What is counted

Each event is a goal under its name, with its conversions and conversion rate: see [Goals](https://fiveb.ar/docs/goals.md#what-is-counted). A visit that sends an event is never a bounce.
