Docs·Usage

Track events

Pageviews arrive on their own once the tracking script is on your site. Everything else you care about, such as a signup, an upgrade or a download, is a custom event: a name you choose, plus optional properties that describe that one occurrence. You can send one from your own code, or tag an element in your HTML and let the script send it when someone clicks.

The script adds one global object to your pages, Spreelytics, and every call on this page goes through it.

The Events page, with the event volume chart on top and the table of recent events below it

Send an event

One call, with the event name:

Spreelytics.track("signup_completed");

Add properties when the details matter:

Spreelytics.track("plan_purchased", {
  plan: "growth",
  billing: "annual",
  seats: 5,
});

Spreelytics.track() takes up to three arguments:

ArgumentRequiredWhat it is
nameYesThe event name, as a string. It is recorded exactly as you send it.
propertiesNoAn object with details about this occurrence, such as the plan or the price.
attributesNoFields to save on the person who sent the event. Only used once the visitor is identified. See Update the person with the third argument.

A few things to know before you rely on it:

  • Call it after Spreelytics.init(). A call made before init() is dropped. A call made after init() but before the script has finished loading is queued and sent as soon as it is ready.
  • It never throws and returns nothing. If a request fails, nothing tells you, unless you add debug: true to Spreelytics.init(). Then the script logs what it does to the browser console.
  • Each event goes out in its own request, at the moment you call it. A small request is allowed to finish after the page is gone, so an event sent right before a redirect still arrives.
  • Automated browsers send nothing. In a browser driven by Selenium, Puppeteer or Playwright the script does not track at all (see Filter traffic), so test in a normal browser.

What properties can hold

Properties are stored as pairs of a key and a value, and the type of each value decides how you can use it later. A number can be compared with is greater than in a goal or a report filter, while text cannot. So send numbers as numbers: seats: 5, not seats: "5".

You sendIt is stored as
A numberA number.
true or falseTrue or false.
A stringText, with three exceptions. The strings "true" and "false" are stored as true or false. A string written as an ISO date, such as "2026-10-01" or "2026-10-01T09:30:00Z", is stored as a date. A number inside quotes, such as "42", stays text.
A JavaScript DateIt is sent as an ISO date string, so it is stored as a date.
A nested objectFlattened into dotted keys: { coupon: { code: "AUTUMN" } } becomes coupon.code.
An array of plain valuesOne value per item, all under the same key.
An array of objectsEach object's fields, under key[].field.
null or undefinedDropped. The key is not stored at all.

Here is one event that uses all three shapes:

Spreelytics.track("order_placed", {
  coupon: { code: "AUTUMN", percent: 20 },
  tags: ["gift", "express"],
  items: [
    { sku: "TSHIRT-M", price: 25 },
    { sku: "MUG", price: 12 },
  ],
});

And the properties it stores:

PropertyValues
coupon.codeAUTUMN
coupon.percent20
tagsgift, express
items[].skuTSHIRT-M, MUG
items[].price25, 12

Each request, properties included, can be up to 250 KB once it is encoded for sending. A bigger one is refused and the event is lost. The encoded form is larger than the data you pass in, so treat that as a ceiling you never get near: send ids and short labels, not whole documents.

Reserved property names

These names carry the details of payments, and Spreelytics reads them in a special way:

revenue.amount, revenue.currency, revenueReportingAmount, reportingCurrency, transactionId, refunded, renewal, isFreeTrial, customerName, customerId

Do not use them for your own properties. Sending them from the browser does not record a payment, and they are left out of the Properties tab on the Overview. Note that an object called revenue with an amount inside flattens to revenue.amount, so it falls under this rule too. Revenue only comes from a connected payment provider or from your server, as described in Revenue.

Naming your events

There is no list of events to set up first. An event exists the moment it is first sent, which makes these habits worth keeping from day one:

  • Name what happened, in the past tense. signup_completed, plan_purchased, invoice_downloaded.
  • Pick one style and keep it. Names are case sensitive, so plan_purchased and Plan Purchased are two different events, and a goal on one does not count the other.
  • Name the action, not the element. checkout_started still makes sense after a redesign. blue_button_clicked does not.
  • Put the details in properties, not in the name. Send plan_purchased with { plan: "growth" } rather than growth_plan_purchased. You get one goal for every purchase, and you can still split it by plan.

On the Events page, underscores are shown as spaces, so signup_completed reads as "signup completed". The name stored and matched is still the one you sent.

Update the person with the third argument

track() can also save fields on the person who sent the event, in the same call:

Spreelytics.track("plan_upgraded", { plan: "growth" }, { company: "Example Ltd" });

The third argument takes the same keys as Spreelytics.identify(), such as first_name, company or country, and follows the same rules.

It only works for a visitor you have already identified. On an anonymous visitor the attributes are dropped, because there is no person yet to save them on. The event itself is recorded either way.

Track clicks without code

Add data-spree-track to any element and a click on it sends a custom event with that name. Add data-spree-prop- attributes to give the event properties:

<button
  data-spree-track="trial_started"
  data-spree-prop-plan="growth"
  data-spree-prop-position="hero"
>
  Start free trial
</button>

A click on that button sends the same event as this call:

Spreelytics.track("trial_started", { plan: "growth", position: "hero" });

How it behaves:

  • It is on by default. To turn it off, add track_data_attributes: false to Spreelytics.init().
  • The closest tagged element wins. A click on the icon inside a tagged button counts for the button. When tagged elements sit inside each other, only the innermost one sends an event.
  • Elements added later work too. The script listens on the whole page, so content rendered after the page loaded needs nothing extra.
  • Every value arrives as text. data-spree-prop-seats="5" sends the text "5", not a number. The string rules above still apply, so "true" and "false" become true or false. When you need a real number, use Spreelytics.track() instead.
  • Attribute names are lowercased by the browser. HTML does not keep capital letters in attribute names, so data-spree-prop-planName arrives as planname. Use lowercase names with underscores, such as data-spree-prop-plan_name.
  • An empty name sends nothing. data-spree-track="" is ignored.

These clicks are ordinary custom events, so they count toward your monthly events like any track() call.

Link clicks are not recorded until you turn them on in the snippet:

Spreelytics.init({
  client_key: "YOUR_CLIENT_KEY",
  track_links: "outbound",
});
track_linksWhat it records
false (the default)No link clicks.
"outbound"Clicks on links that point at a different hostname.
trueEvery link click, links to your own pages included.

Prefer "outbound". Clicks between your own pages already show up as pageviews, so true mostly adds a second copy of your own navigation.

What counts as outbound

The script compares the link's hostname with the page's hostname, exactly. That gives some results people do not expect:

  • Your own subdomains count as outbound. A link from www.example.com to app.example.com is recorded, because the two hostnames differ.
  • www and the bare domain are different hostnames. A link from example.com to www.example.com is recorded.
  • Links with no hostname count as outbound, such as mailto: and tel: links.
  • Links to the same hostname are skipped, including jumps to an #anchor on the page.

Every recorded click is one event with the fixed name Link Click. You cannot rename it. It carries these properties:

PropertyValue
hrefThe full destination, with a trailing slash removed.
textThe link's visible text, trimmed.
idThe link's id attribute, only when it has one.

Link clicks do not count toward your monthly events. A link click does count as interaction, so a visitor who lands on one page and clicks a recorded link is not counted as a bounce.

You can find link clicks on the Events page, in session timelines and in the report builder. Goals, the Event filter and segment rules do not offer them.

To record clicks on one element, with your own properties, whether or not track_links is on:

Spreelytics.push(["trackLink", document.querySelector("#pricing-cta"), { position: "hero" }]);

Use the push form shown here. Spreelytics.trackLink() only exists once the full script has loaded, so calling it earlier throws an error, while Spreelytics.push() works before and after.

It sends the same Link Click event, with your properties merged over href, text and id, so a property of yours with one of those names replaces the collected value. Each element is set up once: a second call on the same element is ignored.

Which events count toward your monthly events

Your plan includes a number of events each month (see Billing). Here is what counts toward it:

CountedNot counted
PageviewsThe scroll event the script sends once per page view (see Autocapture)
Custom events from track()Link Click events
Clicks on data-spree-track elementsThe session end the script sends when a visitor leaves or switches tabs
Payment events from a payment provider or your serverRefunds
Payments from before you connected a provider, added with an import (see Import past payments)

Identifying a visitor is not an event, so it is never counted. Events that are not counted are still stored and still appear in your reports. The list above only decides what you pay for.

Where events show up

Once events arrive, they appear across the app:

  • The Events page lists everything the audience recorded, newest first, including pageviews and the events the script sends on its own. The Event volume chart above it draws one line per event name. Click a row to open the event in a side panel with its Context, its Properties and the Session it belongs to. See Events.
  • The Events card on the Overview, among the breakdowns, ranks your custom events by how many times each was sent in the date range. The automatic scroll event appears there as scroll. Click a row to filter the whole page to that event.
  • The Properties tab on the Overview, in the panel below the breakdowns, lists every property your custom events carried in the date range. Pick one to see its values with Visitors, Events and a share of the total.
  • Goals count the people who sent a custom event, optionally only when its properties match. See Goals.
  • Segments can group people by what they sent: for example, everyone who sent plan_purchased at least once in the last 30 days. See Segments.
  • Filter → Content → Event narrows a page to the visits that included a given event.
  • The report builder charts any event, split or filtered by its properties. See Dashboards and reports.
The side panel for one event, showing its context, its properties as JSON and the session it happened in

What is not tracked for you

The script records pageviews, scroll depth and, when you turn them on, link clicks. Form submissions, JavaScript errors, video plays and file downloads (other than as link clicks) are not recorded unless you send them with Spreelytics.track(). Spreelytics does not draw heatmaps. On the Growth plan, session replay shows each visit's clicks beside its events, without any tracking code.

  • Identify users: put a name to the people who send your events.
  • Goals: count the people who sent an event, and the revenue it carried.
  • Autocapture: what the script records without any code from you.
  • JavaScript SDK: every option and method on the Spreelytics object.

See your own numbers today.

Free up to 100k events a month · no credit card

Contact

Tell us what you need.

A real person reads these. We usually reply within one working day.

Or email us directly at contact@spreelytics.com.