Skip to content

Custom events

Send your own events with statsy.goal(): naming, properties, what never to include, common patterns and how to debug what is sent.

Anything the automatic events miss is one call. A custom event is a goal with a name you choose and optional properties, and it shows up in the same places: the Goals page, funnels, filters, alerts and the API.

js
statsy.goal('signup', { plan: 'pro', trial: true });

Naming

  • Lowercase with underscores: signup, add_to_cart, invite_sent. Names are case sensitive and cut at 120 characters.
  • Name the action, not the place. pricing_cta ages badly; start_trial does not.
  • Keep to a few dozen names. Put variation in properties (plan: 'pro'), not in names (signup_pro).
  • Avoid the automatic names (download, form_submit, site_search…) unless you mean to add to them.

Properties

Values are strings, numbers or booleans; anything else is dropped. Keep them short: a whole event is limited to 64 KB, and server-side events cap keys at 64 characters and values at 500. Split any event by a property from its detail sheet on the Goals page, or through GET /api/v1/sites/:site/events/breakdown?name=&prop=.

Never send personal data in an event. No emails, names, addresses, card numbers or free text a person typed. Properties are stored in plain form and appear in exports. The place for who a visitor is, is statsy.identify(), which is stored separately and never leaves your workspace.

Patterns

Signup, with the plan

js
statsy.goal('signup', { plan, source: 'pricing_page' });
statsy.identify(user.id, { email: user.email, plan });

A step inside your own checkout

js
statsy.goal('checkout_step', { step: 2, items: cart.length });

Search in a single-page app

js
statsy.search(query, results.length); // records site_search with results

Anything without JavaScript

html
<a href="/demo" data-statsy-goal="book_demo" data-statsy-prop-plan="team">Book a demo</a>

Before the script loads

js
window.statsyq = window.statsyq || [];
statsyq.push(['goal', 'signup', { plan: 'pro' }]);

From your server

Anything that happens after the browser is gone, an invoice paid, a trial converted, a job finished, can be sent as a server-side event with the same name and properties, and the same visitor id when you have it. See the REST API for POST /api/v1/sites/:site/events.

Seeing what is sent

Turn on debug logging in the console and every beacon prints its type, name and properties as it leaves.

js
statsy.debug();          // start logging
statsy.goal('test_event');
// [statsy] goal test_event {…}
statsy.debug(false);     // stop

Then open Live: a goal reaches the dashboard within a few seconds. If it does not, see Troubleshooting.

Frequently asked questions

Can I attach a value to a custom event?

A goal created on the Goals page can carry a default value, and that value is counted as goal value, separately from real revenue. Amounts sent from the browser are ignored on purpose because they can be forged; revenue comes from your payment provider webhooks.

Does an event need a goal to be created first?

No. Any name you send is stored and can be filtered or split at once. Creating a goal with that name adds it to the Goals table with a conversion rate and lets you give it a value.

Last updated · Markdown version