UserPath is a privacy-focused analytics tool that serves as an alternative to Google Analytics. It's built with a focus on reliability, performance, and data privacy. The platform offers first-party integration capabilities, allowing you to collect and analyze user data directly from your own servers without external dependencies, resulting in more accurate and comprehensive insights.
npm install userpath-js
UserPath can be used both in the browser and server in different contexts.
In a browser environment, you can import the UserPath
class and initialize it with your app ID and base URL. The library will automatically start tracking events and send them to the server as soon as you initialize it.
// file: src/userpath.ts
import { UserPath } from 'userpath-js';
const up = new UserPath({
appId: 'my-app-id',
serverUrl: 'https://my-userpath-domain.com/events', // Optional
version: 1,
flushIntervalMs: 5000, // Optional: Time in milliseconds between event batch sends (default: 5000)
});
export { up };
// file: src/pricing.ts
import { up } from './userpath';
// Tracking is already initialized and running
// You can track custom events like this:
up.track('purchase', {
price: 42,
amount: 10,
currency: 'USD',
properties: {
product_id: '123',
product_name: 'Product 1',
},
});
Alternatively, you can include the UserPath Pixel using a script tag in your HTML file. This will automatically initialize the client and start tracking events. You can also track custom events using the exposed userpath
object in the global scope.
<!-- index.html -->
<script
src="https://my-userpath-domain.com/events/v1/px.js"
data-app="my-app-id"
></script>
// index.js
const up = window.userpath;
up.track('purchase', {
price: 42,
amount: 10,
currency: 'USD',
});
In order to avoid privacy-first browsers and ad blockers, you can use the UserPath server integration to provide a first-party analytics solution. This will proxy all requests to the main UserPath server, so you can continue to use the client in the browser as usual without worrying about being blocked.
// file: src/index.ts
import { userpath } from 'userpath-js/server';
// Using Node.js
http
.createServer(function (req, res) {
return userpath.fetch(req);
})
.listen(3000);
// Using Bun
Bun.serve({
fetch(req) {
return userpath.fetch(req);
},
});
// Using Elysia
const app = new Elysia({ name: 'my-userpath' });
app.get('/', () => 'Hello World from Elysia');
app.mount('/events', userpath.fetch); // Mount the UserPath server
app.listen(3000);
UserPath also provides easy and native integrations for the most popular server frameworks:
When using the client in the browser, UserPath automatically tracks various user interactions without any additional configuration. Here's what gets tracked automatically, but you can also track custom events.
Tracks when users submit forms:
{
name: 'form_submit',
url: 'https://example.com/signup',
referrer: 'https://example.com/home',
properties: {
form_name: 'signup-form', // Form name, id, or aria-label
time_to_complete: 15000, // Time in milliseconds from first interaction to submission
}
}
Tracks when users complete filling in text-based input fields. Events are only fired when:
- The input value has actually changed
- The new value is not empty
- The user has finished editing (on blur)
{
name: 'input_fill',
url: 'https://example.com/signup',
referrer: 'https://example.com/home',
properties: {
input_type: 'text', // text, email, number, etc.
label: 'Full Name', // Input label or identifier
form_name: 'signup-form', // If available
}
}
Tracks when users select an option from dropdowns:
{
name: 'input_select',
url: 'https://example.com/checkout',
referrer: 'https://example.com/cart',
properties: {
input_type: 'select',
label: 'Country',
option_label: 'United States',
form_name: 'shipping-form',
}
}
Tracks radio button selections:
{
name: 'input_radio',
url: 'https://example.com/profile',
referrer: 'https://example.com/settings',
properties: {
input_type: 'radio',
group: 'gender',
label: 'Male',
form_name: 'profile-form',
}
}
Tracks checkbox interactions:
{
name: 'input_checkbox',
url: 'https://example.com/preferences',
referrer: 'https://example.com/signup',
properties: {
input_type: 'checkbox',
label: 'Subscribe to newsletter',
checked: true,
form_name: 'preferences-form',
}
}
Tracks range slider changes:
{
name: 'input_range',
url: 'https://example.com/settings',
referrer: 'https://example.com/profile',
properties: {
input_type: 'range',
label: 'Volume',
form_name: 'settings-form',
}
}
Automatically tracks meaningful clicks on:
- Buttons
- Links
- Interactive elements with labels
{
name: 'click',
url: 'https://example.com/form',
referrer: 'https://example.com/home',
properties: {
label: 'Submit',
element: 'button',
id: 'submit-btn',
}
}
Tracks meaningful scroll depth on pages:
{
name: 'scroll',
url: 'https://example.com/blog/post',
title: 'Blog Post Title',
referrer: 'https://example.com'
}
Automatically tracks video interactions for HTML5 video elements:
Tracks when a video starts playing:
{
name: 'video_play',
url: 'https://example.com/page',
referrer: 'https://example.com',
title: 'Introduction Video', // Video title if available
properties: {
duration: 180, // Total video duration in seconds
current_time: 0, // Current playback position in seconds
src: 'https://example.com/video.mp4',
video_id: 'intro-video', // Video element ID if available
}
}
Tracks when a video is paused:
{
name: 'video_pause',
url: 'https://example.com/page',
referrer: 'https://example.com',
title: 'Introduction Video',
properties: {
duration: 180,
current_time: 45,
watch_time: 45, // Time watched in this session in seconds
src: 'https://example.com/video.mp4',
video_id: 'intro-video',
}
}
Tracks when a video playback completes:
{
name: 'video_complete',
url: 'https://example.com/page',
referrer: 'https://example.com',
title: 'Introduction Video',
properties: {
duration: 180,
current_time: 180,
watch_time: 180, // Total time watched in this session in seconds
src: 'https://example.com/video.mp4',
video_id: 'intro-video',
}
}
Automatically tracks how long users spend on pages, including active (visible) time:
Automatically tracks user activity and inactivity periods:
Tracks when a user becomes inactive (no mouse movement, keyboard input, or other interactions for 60 seconds):
{
name: 'user_inactive',
url: 'https://example.com/page',
title: 'Page Title'
}
Tracks when a user becomes active again after being inactive:
{
name: 'user_active',
properties: {
inactive_duration: 75, // How long the user was inactive in seconds
url: 'https://example.com/page',
title: 'Page Title'
}
}
Tracks when a page is initially loaded:
{
name: 'page_view',
url: 'https://example.com/page',
title: 'Page Title',
referrer: 'https://example.com'
}
Tracks when users switch tabs or minimize the browser:
{
name: 'page_visibility',
url: 'https://example.com/page',
title: 'Page Title',
referrer: 'https://example.com',
properties: {
visible: true, // or false
total_time: 120, // Total time since page load in seconds
visible_time: 85 // Time the page was actually visible in seconds
}
}
Tracks timing information when users leave the page:
{
name: 'page_exit',
url: 'https://example.com/page',
title: 'Page Title',
referrer: 'https://example.com',
properties: {
total_time: 300, // Total time spent on page in seconds
visible_time: 240 // Time the page was actually visible in seconds
}
}
- Password fields are never tracked
- Only interaction events are tracked, not actual input values
- Form submissions are tracked without capturing sensitive data
- All tracking respects user privacy settings and GDPR compliance
UserPath automatically captures uncaught errors and unhandled promise rejections in your application, providing valuable insights about JavaScript errors that users encounter.
When enabled (on by default), the SDK will automatically capture:
- Uncaught exceptions via the global
error
event - Unhandled promise rejections via the
unhandledrejection
event
{
name: 'error',
message: 'Cannot read property of undefined',
stack: 'Error: Cannot read property of undefined\n at button.onClick (app.js:42)',
source: 'window.onerror',
filename: 'app.js',
lineno: 42,
colno: 24
}
You can also manually track errors in try/catch blocks:
try {
// Some code that might throw an error
processUserPurchase();
} catch (error) {
// Log the error to UserPath
up.trackError(error, {
context: 'purchase_flow',
product_id: '123',
});
// Handle the error appropriately
showErrorMessage();
}
UserPath automatically tracks various user interactions, but you can customize which features are enabled:
// All tracking options are enabled by default
const up = new UserPath({
appId: 'my-app-id',
autoTrack: {
errors: true, // Track JavaScript errors
clicks: true, // Track clicks on buttons, links, etc.
scrolling: true, // Track scroll depth
forms: true, // Track form interactions and submissions
videos: true, // Track video play/pause/end events
pageVisibility: true, // Track page visibility and time spent
inactivity: true, // Track user activity/inactivity
},
});
You can disable any specific tracking feature individually:
const up = new UserPath({
appId: 'my-app-id',
autoTrack: {
forms: false, // Disable form tracking
videos: false, // Disable video tracking
},
});
You can also disable error tracking after initialization:
up.uninstallErrorHandler();
And re-enable it later if needed:
up.installErrorHandler();
There are several ways to identify users in UserPath:
You can add a data-user
attribute to your script tag to identify users immediately:
<script
src="https://api.userpath.co/v1/px.js"
data-app="your-app-id"
data-user="user123"
></script>
You can also identify users programmatically using the SDK:
// On initialization
const up = new UserPath({
appId: 'your-app-id',
userId: 'user123',
});
// Set user ID programmatically
up.setUserId('user123');
// Or with additional user information
up.identify({
id: 'user123',
email: 'user@example.com',
name: 'John Doe',
properties: {
plan: 'premium',
signupDate: '2023-01-15',
},
});
You can get the current user ID:
const currentUserId = userpath.getUserId();
Got questions? We're here to help!
Email us at support@userpath.co
When initializing the UserPath SDK, you can provide several configuration options:
Option | Type | Default | Description |
---|---|---|---|
appId |
string | (required) | Your UserPath application ID |
serverUrl |
string | "https://api.userpath.co" | The base URL for the UserPath API |
version |
number | 1 | API version to use |
userId |
string | undefined | Optional user ID to associate with all events |
flushIntervalMs |
number | 5000 | Time in milliseconds between event batch sends. Events are batched and sent in groups rather than individually to reduce server load. |
autoTrack |
object | see below | Configuration for automatic event tracking |
// All tracking options are enabled by default
const up = new UserPath({
appId: 'my-app-id',
autoTrack: {
errors: true, // Track JavaScript errors
clicks: true, // Track clicks on buttons, links, etc.
scrolling: true, // Track scroll depth
forms: true, // Track form interactions and submissions
videos: true, // Track video play/pause/end events
pageVisibility: true, // Track page visibility and time spent
inactivity: true, // Track user activity/inactivity
},
});
You can disable any specific tracking feature individually:
const up = new UserPath({
appId: 'my-app-id',
autoTrack: {
forms: false, // Disable form tracking
videos: false, // Disable video tracking
},
});
You can also disable error tracking after initialization:
up.uninstallErrorHandler();
And re-enable it later if needed:
up.installErrorHandler();
Connect your domain with CloudFlare, and then enable the managed transform for location headers:
Rules > Settings > Add visitor location headers Adds HTTP request headers with location information for the visitor's IP address, including city, country, continent, longitude, and latitude.
UserPath will use this information when saving events.