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:
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
Script Tag (recommended)
The simplest option. The data-key attribute auto-initializes the library:
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:
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:
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.
| Parameter | Type | Description |
|---|---|---|
| event | string | Event name (e.g., "Form Submitted", "Feature Activated") |
| properties | object | Optional event data |
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.
| Parameter | Type | Description |
|---|---|---|
| traits | object | User attributes. Include email for identity resolution |
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.
| Parameter | Type | Description |
|---|---|---|
| name | string | Optional page name |
| properties | object | Optional additional properties (merged with auto-captured values) |
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.
1trailspark.reset();getAnonymousId()
Returns the current anonymous ID (persisted in localStorage).
1var anonId = trailspark.getAnonymousId();Implementation Patterns
Page View Tracking
Track views on every page load:
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:
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:
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:
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:
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:
1function onLogout() {
2 trailspark.reset();
3}How It Works
- When the script loads, it generates a unique
anonymousIdand stores it in localStorage - All
trackandpagecalls include thisanonymousIdin the payload - Signals from anonymous visitors are stored in cold storage
- When
identifyis called with an email, TrailSpark links theanonymousIdto the identified lead - 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
- Create a DNS CNAME record pointing a subdomain to your TrailSpark subdomain:
tracking.yoursite.com → acme.trailspark.ai
-
Configure SSL/TLS for the custom subdomain through your CDN or hosting provider (e.g., Cloudflare, AWS CloudFront)
-
Update your tracking script to use the first-party domain:
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
- API Keys -- manage keys for the tracking endpoint
- Webhook Payload Format -- full field reference for signal payloads
- Creating Signal Mapping -- set up rules to score incoming signals
- Identity Resolution -- how anonymous tracking connects to leads
