Custom events & goals

Custom events & goals

Pageviews are automatic. Add an event for each action you care about, like a signup, a download or a click on Buy. Every event name becomes a goal on the Goals page, with no setup.

Track from JavaScript#

The script exposes window.pulse.track(name, props). Properties are optional.

js
pulse.track('signup');
pulse.track('plan_selected', { plan: 'growth', seats: 3, annual: true });
LimitValue
Event nameUp to 100 characters (longer names are cut). Required.
PropertiesUp to 20 keys, each key up to 100 characters.
Property valuesStrings up to 200 characters, numbers, or booleans. Nested objects and arrays are rejected.

Track from HTML, no code#

Put data-pulse-event on any element. It fires when the element, or anything inside it, is clicked. Each data-pulse-event-<key> attribute becomes a property (up to 20).

html
<button data-pulse-event="signup_click" data-pulse-event-plan="growth" data-pulse-event-location="hero">
  Start free trial
</button>

HTML lowercases attribute names, so property keys are lowercase, and every value is a string.

Before the script has loaded#

Events fired before the script is ready would be lost. Declare a queue first and push [name, props] pairs onto it. The script sends them as soon as it starts, after the first pageview.

html
<script>
  window.pulse = window.pulse || { q: [] };
  window.pulse.q.push(['newsletter_open', { issue: 42 }]);
</script>
<script defer data-site="YOUR_SITE_ID" src="https://stats.shedi.app/script.js"></script>

Use pulse.q.push for this. The queue is a plain array, so pulse.track does not exist until the script has loaded.

Automatic events#

EventWhenProperties
downloadA visitor clicks a link whose path ends in .dmg, .zip, .pdf, .pkg or .exe.file: the file name
checkoutA visitor clicks a link to a Lemon Squeezy, Stripe Payment Link or Polar checkout (see revenue attribution).provider, and url without its query string
outboundA visitor clicks any other link to another hostname.url: the link without its query string

Turn all of them off with data-auto="false" on the script tag; checkout links are still tagged for revenue. Only http and https links count.

When a visit has a first source (a utm_source, a ?ref= or a referrer), the script can add it to every custom event as an ft property, but only when the tag has data-attribution (see revenue attribution); by default no ft is sent. It counts toward the 20 properties: when an event already has 20, ft is left out rather than failing the event.

Clicks that open a link in a new tab with the middle mouse button are tracked the same as normal clicks; a right-click only tags checkout links so a copied link carries the visitor id, and sends no event.

Event names Pulse understands#

Pulse never requires a name, but a few names light up parts of the dashboard.

NameWhat it powers
buyThe Buy clicks tile on Analytics (events named exactly buy; the automatic checkout event is not counted there, so put data-pulse-event="buy" on your buy button if you want the tile), and the last step of the preset funnel.
names containing buy, checkout or purchaseMark a live visitor as “Clicked buy” in Likely to buy. The automatic checkout event qualifies.
anything elseA row on the Goals page: count, events per 100 visitors, change versus the period before. Usable as a funnel step.

Unknown names are shown as words: film-play reads “Film play”.

Reading your goals#

Open Goals. Each event name is a goal with its count in the selected range, how many were fired per 100 visitors (one visitor can fire an event many times, so this is not a conversion rate), and the change versus the period before. Events from an imported Umami app show too, marked as app events.

Switching from DataFast#

The Pulse script understands DataFast’s tag, goals and checkout metadata, so a switch is mostly swapping the script. Keep data-website-id and data-domain, put your Pulse site id in data-website-id, and point src at Pulse:

html
<script defer data-website-id="YOUR_PULSE_SITE_ID" data-domain="yoursite.com" data-datafast-cookie
  src="https://YOUR_PULSE/script.js"></script>
DataFastIn Pulse
window.datafast('goal', params)An event named goal with the params as properties. Calls queued by DataFast’s datafast.q stub are sent after the first pageview. identify calls are ignored.
data-fast-goalA click event; each data-fast-goal-<key> becomes a property, kebab-case turned into snake_case like DataFast does (product-id → product_id).
datafast_visitor_id in checkout metadataRead by every payment connection as the visitor id. Pulse is cookieless, so this cookie only exists when the tag has data-datafast-cookie; it holds the Pulse visitor id, on data-domain when set. It is a cookie, so keep the consent you had for DataFast.
Payment linksNothing to do: Lemon Squeezy, Stripe and Polar links are tagged automatically (see revenue attribution).

The Buy clicks tile counts events named exactly buy. DataFast’s usual initiate_checkout still marks a visitor as “Clicked buy” and still feeds revenue attribution.

Common issues#

My event does not show up
Open the Network tab, trigger it, and look for a POST /api/collect carrying "type":"event". A 400 name means the name was empty; 400 props means a value was an object or array, or you sent more than 20 keys.
pulse is not defined
The script has not loaded yet (it is deferred). Use the queue above, or call pulse.track from an event handler that runs after load.
Events fire twice
Check that the script is installed once and that you do not use both data-pulse-event and a pulse.track call for the same click.
Do events count toward my plan?
Yes, a custom event counts like a pageview. See plans & limits.