hardal
v3.6.9
Published
Connect your first-party data from any source to any destination for websites and mobile apps with server-side.
Readme
Hardal
An official plugin to add the Hardal tracking to your web project with automatic pageview tracking, click tracking, and privacy-first analytics.
What is Hardal?
Hardal is a privacy-first, server-side analytics platform that helps you:
- Track user behavior without compromising privacy
- Automatic PII redaction from URLs and data
- First-party data collection - you own your data
- Event tracking with custom properties
- Automatic pageview tracking for SPAs and Next.js
- Works everywhere - Vanilla JS, React, Next.js, Vue, etc.
Installation
npm install hardal
# or
bun add hardal
# or
yarn add hardalQuick Start
For React/Next.js Apps (Recommended)
// app/providers.tsx
'use client';
import { HardalProvider } from 'hardal/react';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<HardalProvider
config={{
website: // Your Hardal Signal ID,
hostUrl: // Your Hardal Signal Domain,
}}
autoPageTracking={true} // ✅ Tracks all route changes
>
{children}
</HardalProvider>
);
}For Vanilla JavaScript / HTML
<script
defer
src="<YOUR_SIGNAL_ENDPOINT>/hardal"
data-website-id="<YOUR_SIGNAL_ID>"
data-host-url="<YOUR_SIGNAL_ENDPOINT>"
data-auto-track="true"
></script>Usage
Example
'use client';
import { useHardal } from 'hardal/react';
export function ContactForm() {
const { track, distinct } = useHardal();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const email = formData.get('email') as string;
// Track the submission
await track('form_submitted', {
formType: 'contact',
source: 'landing_page',
});
// Identify the user
await distinct({
email,
source: 'contact_form',
});
};
return <form onSubmit={handleSubmit}>{/* form fields */}</form>;
}Configuration Options
HardalProvider (React/Next.js)
<HardalProvider
config={{
website: 'your-website-id', // Required: Your Hardal website ID
hostUrl: 'https://your-host.com', // Required: Your Hardal server URL
}}
autoPageTracking={true} // Optional: Auto-track route changes (default: false)
disabled={process.env.NODE_ENV === 'development'} // Optional: Disable tracking
>
{children}
</HardalProvider>Vanilla JS
const hardal = new Hardal({
website: 'your-website-id',
hostUrl: 'https://your-hardal-server.com',
autoTrack: true, // Auto-track pageviews and history changes
});Identify Users
// Identify a user with custom properties
hardal?.distinct({
userId: 'user-123',
email: '[email protected]',
plan: 'premium',
});Manual Pageview Tracking
// Track a pageview manually
hardal?.trackPageview();
API Reference
new Hardal(config)
Creates a new Hardal instance.
Config Options:
website(required): Your Hardal website IDhostUrl(optional): Custom host URL for your Hardal serverautoTrack(optional): Auto-track pageviews (default:true)
track(eventName, data?)
Track a custom event.
hardal.track('event_name', { custom: 'data' });distinct(data)
Identify a user with custom properties.
hardal.distinct({ userId: '123', email: '[email protected]' });trackPageview()
Manually track a pageview.
hardal.trackPageview();Common Patterns
Track A/B Test Variants
const { track, distinct } = useHardal();
// Track which variant user sees
track('experiment_viewed', {
experimentId: 'pricing_test_v1',
variant: 'B',
});
// Associate user with variant
distinct({
experiments: {
pricing_test_v1: 'B',
},
});Track Error Events
const { track } = useHardal();
try {
await riskyOperation();
} catch (error) {
track('error_occurred', {
errorType: error.name,
errorMessage: error.message,
page: window.location.pathname,
});
}Track Time on Page
'use client';
import { useEffect } from 'react';
import { useHardal } from 'hardal/react';
export function TimeTracker() {
const { track } = useHardal();
useEffect(() => {
const startTime = Date.now();
return () => {
const timeSpent = Math.round((Date.now() - startTime) / 1000);
track('time_on_page', {
seconds: timeSpent,
page: window.location.pathname,
});
};
}, [track]);
return null;
}Conditional Tracking (Development vs Production)
<HardalProvider
config={{
website: // Your Hardal Signal ID,
hostUrl: // Your Hardal Signal Domain,
}}
disabled={process.env.NODE_ENV === 'development'} // Don't track in dev
autoPageTracking={true}
>
{children}
</HardalProvider>Best Practices
✅ DO:
- Track meaningful user actions (clicks, form submissions, purchases)
- Use descriptive event names (
checkout_completed, notevent1) - Include relevant context in event properties
- Identify users after authentication
- Test tracking in production-like environment
❌ DON'T:
- Track PII (emails, phone numbers) directly - use
distinct()for user identification - Send sensitive data in properties
- Track too many events (focus on business-critical actions)
- Use autoTrack in React apps - use
autoPageTrackinginstead - Create multiple Hardal instances
Privacy & Security
Hardal automatically:
- 🔒 Redacts PII from URLs (emails, phone numbers, credit cards)
- 🛡️ Respects Do Not Track when configured
- 🔐 Server-side processing - no third-party trackers
- 📊 First-party cookies - you own your data
- ✅ GDPR & CCPA friendly
Performance
- 📦 Lightweight: ~18KB minified
- ⚡ Non-blocking: Events sent asynchronously
- 🚀 Queue system: No lost events during initialization
- ⏱️ 5-second timeout: Requests abort if server is slow
- 🧹 Memory safe: Proper cleanup on unmount
Examples
Check the examples/ directory for complete examples:
- Next.js App Router -
examples/nextjs-app-router.tsx - Next.js Pages Router -
examples/nextjs-pages-router.tsx - React SPA -
examples/react-spa.tsx - HTML Data Attributes -
examples/data-attributes.html
Troubleshooting
"Browser freezes" or "Infinite loop"
- ❌ Don't use
autoTrack: truein the config for React apps - ✅ Use
autoPageTracking={true}inHardalProviderinstead
"No valid hostUrl configured"
- Make sure you've set
hostUrlin your config - Verify it starts with
http://orhttps://
"Events not showing up"
- Check browser console for errors
- Verify
hostUrlandwebsiteID are correct - Make sure your Hardal server is running
- Check network tab for failed requests
TypeScript errors with hardal/react
- Run
npm installto ensure dependencies are installed - Restart TypeScript server in your IDE
- See TYPESCRIPT_SETUP.md
Migration from v2.x
// ❌ Old way (v2.x)
const hardal = new Hardal({
endpoint: 'https://server.com',
autoPageview: true,
});
// ✅ New way (v3.x)
<HardalProvider
config={{
website: 'your-id',
hostUrl: 'https://server.com',
}}
autoPageTracking={true}
>Breaking changes:
endpoint→hostUrlautoPageview→ removed (useautoPageTrackingprop instead)fetchFromGA4,fetchFromFBPixel,fetchFromRTB,fetchFromDataLayer→ removed- React: Must use
HardalProviderwrapper
License
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
Support
- Documentation: https://usehardal.com/docs
- Email: [email protected]
