@wavetrace/client
Version:
Lightweight web analytics client with TypeScript support
442 lines (344 loc) • 11.2 kB
Markdown
# WaveTrace Client
A lightweight, TypeScript-first web analytics client for tracking user behavior, page views, clicks, and custom events. The primary goal for this client is to provide analytics on a specific user by tracking his/her activity on a DApp. Some tracking are automated while some could be manually tracked.
So, it provides:
- Both automated and manual tracking for users
- Connect annoymous/signed out user tracking linked to existing/future wallet/user login
## Features
- **Lightweight**: Only 4.8KB minified
- **TypeScript Support**: Full type definitions included
- **Zero Dependencies**: No external dependencies
- **DApp Ready**: Built-in wallet tracking for Web3 applications
- **Auto-Detect Wallets**: Automatically detect and track MetaMask, Coinbase, and other wallet connections
- **Transaction Tracking**: Complete lifecycle tracking for blockchain transactions (initiated → pending → executed/failed)
- **Offline Queue**: localStorage persistence - events are saved and sent when back online
- **Retry Logic**: Exponential backoff for failed requests with configurable retries
- **Smart Click Tracking**: Intelligent filtering - track only buttons, links, and important interactions
- **Automatic Tracking**: Auto-track page views and clicks with configurable modes
- **Event Batching**: Efficient event batching with configurable batch size and timeout
- **User Identification**: Track user ID, username, wallet addresses, and custom properties
- **Anonymous-to-Wallet Linking**: Seamlessly connect anonymous activity to wallet addresses
- **Session Management**: Automatic session tracking with 30-minute timeout
- **Privacy-Conscious**: Configurable data collection
- **Multiple Formats**: ESM, CommonJS, and browser IIFE builds
## Installation
```bash
npm install @wavetrace/client
```
## Usage
### Basic Setup (Browser)
```html
<script src="https://unpkg.com/@wavetrace/client/dist/wavetrace.min.js"></script>
<script>
const tracker = new WaveTrace.WaveTracker({
endpoint: "https://your-api.com/track",
autoTrackPageViews: true,
autoTrackClicks: true,
});
</script>
```
### ES Modules
```typescript
import { WaveTracker } from "@wavetrace/client";
const tracker = new WaveTracker({
endpoint: "https://your-api.com/track",
autoTrackPageViews: true,
autoTrackClicks: true,
batchSize: 10,
batchTimeout: 5000,
debug: false,
});
```
### DApp Wallet Tracking
For Web3/DApp applications, track wallet connections with automatic detection or manual tracking:
#### Automatic Wallet Detection (Recommended)
```typescript
const tracker = new WaveTracker({
endpoint: "https://your-api.com/track",
autoDetectWallet: true, // Automatically detect wallet connections
autoTrackPageViews: true,
});
// That's it! Wallet connections are automatically tracked
// No need to manually call connectWallet() or disconnectWallet()
```
The tracker automatically:
- Detects when users connect wallets (MetaMask, Coinbase, etc.)
- Tracks `wallet_connected` event with wallet address and chain ID
- Links anonymous activity to wallet address
- Detects account switches
- Detects disconnections
- Handles network changes
#### Manual Wallet Tracking
```typescript
// When user connects wallet (if not using auto-detection)
await tracker.connectWallet("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", {
properties: {
chainId: 1,
walletType: "metamask",
},
});
// Track DApp events
tracker.track("swap_executed", {
fromToken: "ETH",
toToken: "USDC",
amount: "1.5",
txHash: "0x...",
});
// When user disconnects
await tracker.disconnectWallet();
```
**How it works:**
1. User browses your DApp anonymously → tracked with anonymous ID
2. User connects wallet → automatically linked to wallet address
3. All future events include wallet address
4. Backend receives `wallet_connected` event with `previousAnonymousId` for user merging
See [DAPP-INTEGRATION.md](./DAPP-INTEGRATION.md) for complete DApp integration guide.
### Smart Click Tracking
WaveTrace includes intelligent click filtering to reduce noise and focus on meaningful interactions.
**Default behavior** (tracks only important elements):
```typescript
const tracker = new WaveTracker({
endpoint: "...",
autoTrackClicks: true, // Uses 'important' mode - tracks buttons, links, data-track elements
});
```
**Track specific elements with data-track:**
```html
<button data-track="connect-wallet">Connect Wallet</button>
<button data-track="execute-swap">Swap</button>
<div data-track="feature-card">
<!-- Entire card is trackable -->
</div>
```
**Advanced configuration:**
```typescript
const tracker = new WaveTracker({
endpoint: "...",
autoTrackClicks: {
mode: "important", // 'all' | 'important' | 'data-attribute' | 'custom'
ignoreSelectors: ["[data-track-ignore]", ".no-track"],
customSelectors: [".my-button", "[data-action]"], // For 'custom' mode
},
});
```
**Tracking modes:**
- `important` (default): Buttons, links, and `data-track` elements
- `all`: Every click on the page
- `data-attribute`: Only elements with `data-track`
- `custom`: Use your own CSS selectors
See [CLICK-TRACKING.md](./CLICK-TRACKING.md) for complete guide and examples.
### User Identification
Track user information with your events:
```typescript
tracker.identify({
userId: "12345",
username: "john_doe",
wallet: "0x1234567890abcdef",
email: "john@example.com",
properties: {
plan: "premium",
signupDate: "2024-01-01",
},
});
```
### Transaction Tracking (DApps)
Automatically track the complete lifecycle of blockchain transactions:
```typescript
// Track a swap transaction with automatic lifecycle tracking
const tx = await tracker.trackTransaction(
"swap",
async () => {
// Your transaction logic
return await contract.swap(fromToken, toToken, amount);
},
{
fromToken: "ETH",
toToken: "USDC",
amount: "1.5",
}
);
// Automatically tracks:
// 1. swap_initiated - When transaction starts
// 2. swap_pending - Transaction submitted with txHash
// 3. swap_executed - Transaction confirmed with gasUsed, blockNumber
// 4. swap_failed - If transaction fails (with error details)
```
The transaction helper captures:
- Transaction hash
- Gas used
- Block number
- Confirmation time
- Error messages (if failed)
This eliminates the need to manually track each transaction state.
### Track Custom Events
```typescript
// Simple event
tracker.track("button_click");
// Event with properties
tracker.track("purchase", {
productId: "prod_123",
amount: 99.99,
currency: "USD",
});
```
### Manual Page View Tracking
```typescript
// Track page view with custom properties
tracker.trackPageView({
campaign: "summer_sale",
source: "email",
});
```
### Configuration Options
```typescript
interface TrackerConfig {
// Required: Your tracking endpoint URL
endpoint: string;
// Auto-detect wallet connections (MetaMask, Coinbase, etc.)
// Automatically tracks wallet_connected events and links anonymous activity
// (default: false)
autoDetectWallet?: boolean;
// Enable offline queue with localStorage persistence
// Events are saved locally and sent when back online
// (default: true)
offlineQueue?: boolean;
// Maximum number of events to store offline
// (default: 100)
maxOfflineEvents?: number;
// Retry configuration for failed requests
retry?: {
enabled?: boolean; // Enable retry logic (default: true)
maxRetries?: number; // Max retry attempts (default: 3)
initialDelay?: number; // Initial delay in ms (default: 1000)
backoffMultiplier?: number; // Exponential backoff multiplier (default: 2)
};
// Auto-track page views (default: true)
autoTrackPageViews?: boolean;
// Auto-track link clicks (default: true)
autoTrackClicks?: boolean;
// Batch size for sending events (0 = send immediately, default: 10)
batchSize?: number;
// Max time in ms to wait before sending batch (default: 5000)
batchTimeout?: number;
// Include referrer information (default: true)
includeReferrer?: boolean;
// Include user agent (default: true)
includeUserAgent?: boolean;
// Custom headers for tracking requests
customHeaders?: Record<string, string>;
// Enable debug logging (default: false)
debug?: boolean;
}
```
## Event Structure
All events sent to your endpoint follow this structure:
```typescript
{
events: [
{
type: "pageview" | "click" | "custom_event_name",
timestamp: "2024-01-15T10:30:00.000Z",
url: "https://example.com/page",
title: "Page Title",
referrer: "https://google.com",
userAgent: "Mozilla/5.0...",
screen: { width: 1920, height: 1080 },
viewport: { width: 1200, height: 800 },
sessionId: "1234567890-abcdef",
user: {
userId: "12345",
username: "john_doe",
wallet: "0x1234...",
properties: {
/* custom user properties */
},
},
properties: {
/* event-specific properties */
},
},
];
}
```
### Click Events
Click events include additional properties:
```typescript
{
type: 'click',
properties: {
tagName: 'button',
id: 'submit-btn',
className: 'btn btn-primary',
href: 'https://example.com/link', // for anchor tags
text: 'Click Me',
x: 450, // click coordinates
y: 200
}
}
```
## Advanced Usage
### Manual Event Flushing
```typescript
// Flush all queued events immediately
await tracker.flush();
```
### Disable Click Tracking
```typescript
tracker.disableClickTracking();
```
### Cleanup
```typescript
// Clean up resources and flush remaining events
tracker.destroy();
```
## Server-Side Endpoint
Your tracking endpoint should accept POST requests with JSON payloads. Here's a simple example using Express:
```typescript
app.post("/track", express.json(), (req, res) => {
const { events } = req.body;
// Store events in your database
events.forEach((event) => {
// Add IP address from request
event.ip = req.ip;
// Save to database
db.events.insert(event);
});
res.json({ success: true });
});
```
## Building from Source
```bash
# Install dependencies
npm install
# Build all formats
npm run build
# Build and watch for changes
npm run dev
```
## Browser Support
- Modern browsers (Chrome, Firefox, Safari, Edge)
- ES2020+ features required
- LocalStorage required for session management
## Privacy Considerations
- IP addresses are captured server-side (from request headers)
- User agent strings are optional (configurable)
- No cookies are used
- Session data stored in localStorage only
- All tracking is explicit and configurable
## License
MIT
## Roadmap
### Completed ✅
- ✅ Auto-detect wallet connections (MetaMask, Coinbase, etc.)
- ✅ Offline queue persistence with localStorage
- ✅ Retry logic with exponential backoff
- ✅ Transaction lifecycle tracking helper
### Planned
- React integration with hooks
- Next.js plugin
- Vue integration
- Server-side tracking
- Custom storage adapters
- Event validation and schemas
- Performance monitoring
- Multi-wallet management
- GDPR compliance helpers