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.
pulse.track('signup');
pulse.track('plan_selected', { plan: 'growth', seats: 3, annual: true });| Limit | Value |
|---|---|
| Event name | Up to 100 characters (longer names are cut). Required. |
| Properties | Up to 20 keys, each key up to 100 characters. |
| Property values | Strings 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).
<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.
<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#
| Event | When | Properties |
|---|---|---|
download | A visitor clicks a link whose path ends in .dmg, .zip, .pdf, .pkg or .exe. | file: the file name |
checkout | A visitor clicks a link to a Lemon Squeezy, Stripe Payment Link or Polar checkout (see revenue attribution). | provider, and url without its query string |
outbound | A 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.
| Name | What it powers |
|---|---|
buy | The 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 purchase | Mark a live visitor as “Clicked buy” in Likely to buy. The automatic checkout event qualifies. |
| anything else | A 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:
<script defer data-website-id="YOUR_PULSE_SITE_ID" data-domain="yoursite.com" data-datafast-cookie
src="https://YOUR_PULSE/script.js"></script>| DataFast | In 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-goal | A 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 metadata | Read 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 links | Nothing 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/collectcarrying"type":"event". A400 namemeans the name was empty;400 propsmeans 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.trackfrom 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-eventand apulse.trackcall for the same click. - Do events count toward my plan?
- Yes, a custom event counts like a pageview. See plans & limits.