JavaScript Tracking

Overview

Add event tracking to your website or product without Segment or a CDP. The TrailSpark tracking script is a lightweight JavaScript library that sends signals directly to your webhook endpoint. It supports track, identify, and page calls with automatic anonymous identity resolution.

Quick Start

Add the script tag to your site with your API key:

html
1<script src="https://app.trailspark.ai/t.js" data-key="YOUR_API_KEY"></script>
2<script>
3  trailspark.page();
4</script>

Create an API key at Settings > API Keys with endpoint type Signal Staging. Enable the Enable client-side tracking toggle and optionally configure allowed domains. See Managing API Keys.

For browser-based tracking, create your API key without a secret. Secrets are visible in client-side JavaScript and offer no security benefit in this context. The API key is write-only — it can only send signals, not read any data.

Installation

The simplest option. The data-key attribute auto-initializes the library:

html
1<script src="https://app.trailspark.ai/t.js" data-key="YOUR_API_KEY"></script>

Async Loading

Load the script without blocking page rendering. Commands called before the script loads are queued and replayed automatically:

html
1<script>
2  !function(){var t=window.trailspark={_q:[],
3  init:function(){t._q.push(["init"].concat([].slice.call(arguments)))},
4  track:function(){t._q.push(["track"].concat([].slice.call(arguments)))},
5  identify:function(){t._q.push(["identify"].concat([].slice.call(arguments)))},
6  page:function(){t._q.push(["page"].concat([].slice.call(arguments)))},
7  reset:function(){t._q.push(["reset"].concat([].slice.call(arguments)))},
8  getAnonymousId:function(){return null}};
9  var s=document.createElement("script");
10  s.async=true;s.src="https://app.trailspark.ai/t.js";
11  s.setAttribute("data-key","YOUR_API_KEY");
12  document.head.appendChild(s)}();
13</script>

Manual Initialization

If you need to set a custom host or delay initialization:

html
1<script src="https://app.trailspark.ai/t.js"></script>
2<script>
3  trailspark.init('YOUR_API_KEY', {
4    host: 'https://app.trailspark.ai'
5  });
6</script>

The host option defaults to the origin of the script URL. You only need to set it if your TrailSpark instance runs at a different address than where the script is served.

API Reference

track(event, properties)

Record a user action.

ParameterTypeDescription
eventstringEvent name (e.g., "Form Submitted", "Feature Activated")
propertiesobjectOptional event data
javascript
1trailspark.track('Demo Requested', {
2  form_id: 'hero-demo-form',
3  plan_interest: 'enterprise'
4});

identify(traits)

Link the current anonymous visitor to a known identity. Call this at login, signup, or any point where you know the user's email.

ParameterTypeDescription
traitsobjectUser attributes. Include email for identity resolution
javascript
1trailspark.identify({
2  email: 'user@company.com',
3  name: 'Jane Smith',
4  company: 'Acme Corp',
5  title: 'VP Engineering'
6});

After an identify call, TrailSpark links all prior anonymous signals from this visitor to the newly identified lead. See Identity Resolution.

page(name, properties)

Record a page view. Automatically captures url, path, referrer, title, and search.

ParameterTypeDescription
namestringOptional page name
propertiesobjectOptional additional properties (merged with auto-captured values)
javascript
1trailspark.page();
2
3trailspark.page('Pricing', { plan_shown: 'enterprise' });

reset()

Clear the current identity. Call on logout to prevent the next user's activity from being attributed to the previous user. Generates a new anonymous ID.

javascript
1trailspark.reset();

getAnonymousId()

Returns the current anonymous ID (persisted in localStorage).

javascript
1var anonId = trailspark.getAnonymousId();

Implementation Patterns

Page View Tracking

Track views on every page load:

html
1<script src="https://app.trailspark.ai/t.js" data-key="YOUR_API_KEY"></script>
2<script>
3  trailspark.page();
4</script>

For single-page applications, call trailspark.page() on route changes:

javascript
1// React Router example
2useEffect(() => {
3  trailspark.page();
4}, [location.pathname]);
Not every page view adds signal value. Consider tracking only high-intent pages like pricing, case studies, and documentation rather than every route.

Form Submissions

Track form submissions that indicate buying intent:

javascript
1document.getElementById('demo-form').addEventListener('submit', function (e) {
2  trailspark.track('Demo Requested', {
3    form_id: 'demo-form',
4    company: document.getElementById('company').value,
5    company_size: document.getElementById('size').value
6  });
7});

Login and Signup

Identify users at authentication to link their anonymous browsing history:

javascript
1// After successful login or signup
2function onAuthSuccess(user) {
3  trailspark.identify({
4    email: user.email,
5    name: user.name,
6    company: user.company,
7    userId: user.id
8  });
9}

Product Events

Track feature usage and milestones inside your product:

javascript
1trailspark.track('Project Created', {
2  project_type: 'team',
3  template: 'kanban'
4});
5
6trailspark.track('Team Member Invited', {
7  invite_count: 3,
8  role: 'editor'
9});
10
11trailspark.track('Integration Connected', {
12  integration: 'slack'
13});

Logout

Reset identity when users log out:

javascript
1function onLogout() {
2  trailspark.reset();
3}

How It Works

  1. When the script loads, it generates a unique anonymousId and stores it in localStorage
  2. All track and page calls include this anonymousId in the payload
  3. Signals from anonymous visitors are stored in cold storage
  4. When identify is called with an email, TrailSpark links the anonymousId to the identified lead
  5. All prior anonymous signals are rehydrated and associated with that lead

This means you can start tracking immediately — even before you know who the visitor is. Their full activity history becomes available once they identify themselves.

For more details, see Identity Resolution.

Domain Restrictions

Each API key can be restricted to specific domains. When allowed domains are configured, only requests from those origins will be accepted — requests from any other website will be rejected with a 403 error.

To configure allowed domains, go to Settings > API Keys:

  • New keys: Enable the Enable client-side tracking toggle when creating a key. Enter the full origins (e.g., https://example.com, https://app.example.com) as a comma-separated list. Leave the field empty to allow all origins.
  • Existing keys: Click the pencil icon next to "Allowed domains" on any active key card, or click + Add allowed domains if none are configured yet.
For browser-based tracking, create your API key without a secret. Secrets are visible in client-side JavaScript and offer no security benefit in this context. Use allowed domains instead to restrict which sites can send signals.
Domain restrictions only apply to browser-based requests that include an Origin header. Server-to-server webhook calls (which do not send an Origin header) are unaffected and always allowed.

First-Party Domain (CNAME)

Ad blockers and privacy tools may block requests to third-party tracking domains. To avoid this, you can serve the tracking script and send signals from your own domain using a CNAME record.

Setup

  1. Create a DNS CNAME record pointing a subdomain to your TrailSpark subdomain:
tracking.yoursite.com → acme.trailspark.ai
  1. Configure SSL/TLS for the custom subdomain through your CDN or hosting provider (e.g., Cloudflare, AWS CloudFront)

  2. Update your tracking script to use the first-party domain:

html
1<script src="https://tracking.yoursite.com/t.js" data-key="YOUR_API_KEY"></script>

The script auto-detects its host from the src attribute, so all signal requests will be sent through tracking.yoursite.com — appearing as first-party traffic to the browser.

Troubleshooting

Signals not appearing in Signal Queue -- Open the browser's Network tab and look for POST requests to /api/signal-staging/webhook/. Check for HTTP error responses. Verify the API key is active and not expired at Settings > API Keys.

Identity not resolving -- The identify call must include an email field in traits. Without email, TrailSpark cannot create a lead record. Confirm identify is being called after login or signup.

Console errors about sendBeacon -- The script automatically falls back to fetch if sendBeacon is unavailable. If both fail, check that the TrailSpark endpoint is reachable from the user's browser.

HTTP 429 responses -- Your plan's signal limit has been reached. Reduce tracking volume by filtering to high-intent events only, or upgrade your plan.

Next Steps