Package Exports
- @grainql/analytics-web
Readme
@grainql/analytics-web
A lightweight, dependency-free TypeScript SDK for sending analytics events to Grain's REST API with automatic batching, retry logic, and reliable event delivery.
Features
- 🚀 Zero dependencies - Tiny bundle size
- 📦 Automatic batching - Efficient event queueing and bulk sending
- 🔄 Retry logic - Exponential backoff for failed requests
- 📡 Beacon API - Reliable event delivery on page exit
- 🔐 Multiple auth strategies - NONE, server-side, and JWT support
- 📱 Cross-platform - Works in browsers, Node.js, and React Native
- 🎯 TypeScript first - Full type safety out of the box
- 👤 Global user tracking - Set user ID once, used for all events
- 📊 Template events - Pre-built event tracking for common scenarios
Installation
npm install @grainql/analytics-webQuick Start
Basic Usage (No Authentication)
import { createGrainAnalytics } from '@grainql/analytics-web';
const grain = createGrainAnalytics({
tenantId: 'your-tenant-id',
authStrategy: 'NONE'
});
// Track an event
grain.track('page_view', {
page: '/home',
referrer: document.referrer
});
// Track with user ID
grain.track('button_click', {
button: 'signup',
userId: 'user123'
});Global User ID
Set a user ID once and it will be used for all subsequent events:
// Set global user ID in config
const grain = createGrainAnalytics({
tenantId: 'your-tenant-id',
userId: 'user123' // Global user ID for all events
});
// Or set it after initialization
grain.setUserId('user123');
// All events will now use this user ID
grain.track('page_view', { page: '/dashboard' });User Properties
Set user properties that can be used for analytics and segmentation:
// Set properties for the current user
await grain.setProperty({
plan: 'premium',
status: 'active',
signupDate: '2024-01-15',
source: 'web'
});
// Set properties for a specific user
await grain.setProperty({
plan: 'free',
lastLogin: new Date().toISOString()
}, { userId: 'user123' });
// Properties are automatically serialized to strings
await grain.setProperty({
isActive: true, // Becomes "true"
count: 42, // Becomes "42"
metadata: { // Becomes JSON string
source: 'api',
version: '2.0'
}
});Note: You can set up to 4 properties per request, and all values are automatically converted to strings.
Server-Side Authentication
const grain = createGrainAnalytics({
tenantId: 'your-tenant-id',
authStrategy: 'SERVER_SIDE',
secretKey: 'your-secret-key'
});JWT Authentication
const grain = createGrainAnalytics({
tenantId: 'your-tenant-id',
authStrategy: 'JWT',
authProvider: {
async getToken() {
// Return your JWT token from Auth0, next-auth, etc.
return await getAccessToken();
}
}
});Template Events
The SDK provides pre-built event tracking methods for common scenarios:
User Authentication
// Track login
await grain.trackLogin({
method: 'email',
success: true,
rememberMe: true
});
// Track signup
await grain.trackSignup({
method: 'google',
source: 'landing_page',
plan: 'pro',
success: true
});E-commerce
// Track checkout
await grain.trackCheckout({
orderId: 'order_123',
total: 99.99,
currency: 'USD',
items: [
{ id: 'prod_1', name: 'Product 1', price: 49.99, quantity: 1 },
{ id: 'prod_2', name: 'Product 2', price: 50.00, quantity: 1 }
],
paymentMethod: 'credit_card',
success: true
});
// Track purchase
await grain.trackPurchase({
orderId: 'order_123',
total: 99.99,
currency: 'USD',
paymentMethod: 'credit_card',
shipping: 5.99,
tax: 8.50
});
// Track cart interactions
await grain.trackAddToCart({
itemId: 'prod_1',
itemName: 'Product 1',
price: 49.99,
quantity: 1,
currency: 'USD'
});
await grain.trackRemoveFromCart({
itemId: 'prod_2',
itemName: 'Product 2',
price: 50.00,
quantity: 1
});Page Views and Search
// Track page view
await grain.trackPageView({
page: '/products',
title: 'Product Catalog',
referrer: 'https://google.com',
url: 'https://yoursite.com/products'
});
// Track search
await grain.trackSearch({
query: 'blue shoes',
results: 24,
filters: { category: 'footwear', color: 'blue' },
sortBy: 'price_asc'
});API Reference
Configuration Options
interface GrainConfig {
tenantId: string; // Required: Your Grain tenant ID
apiUrl?: string; // API base URL (default: 'https://api.grainql.com')
authStrategy?: AuthStrategy; // 'NONE' | 'SERVER_SIDE' | 'JWT' (default: 'NONE')
secretKey?: string; // Required for SERVER_SIDE auth
authProvider?: AuthProvider; // Required for JWT auth
userId?: string; // Global user ID for all events
batchSize?: number; // Events per batch (default: 50)
flushInterval?: number; // Auto-flush interval in ms (default: 5000)
retryAttempts?: number; // Retry attempts for failed requests (default: 3)
retryDelay?: number; // Base retry delay in ms (default: 1000)
debug?: boolean; // Enable debug logging (default: false)
}Core Methods
track(eventName, properties?, options?)
Track a single event:
grain.track('purchase', {
product_id: 'abc123',
price: 29.99,
currency: 'USD'
});track(event, options?)
Track with a full event object:
grain.track({
eventName: 'purchase',
userId: 'user123',
properties: {
product_id: 'abc123',
price: 29.99
},
timestamp: new Date()
});setUserId(userId)
Set global user ID for all subsequent events:
grain.setUserId('user123');getUserId()
Get current global user ID:
const userId = grain.getUserId(); // Returns 'user123' or nullidentify(userId)
Alias for setUserId() - sets user ID for subsequent events:
grain.identify('user123');setProperty(properties, options?)
Set user properties for analytics and segmentation:
// Set properties for current user
await grain.setProperty({
plan: 'premium',
status: 'active',
signupDate: '2024-01-15'
});
// Set properties for specific user
await grain.setProperty({
plan: 'free'
}, { userId: 'user123' });Parameters:
properties: Object with up to 4 key-value pairsoptions.userId: Optional user ID override
flush()
Manually flush all queued events:
await grain.flush();destroy()
Clean up resources and send remaining events:
grain.destroy();Template Event Methods
Authentication Events
trackLogin(properties?, options?)- Track user logintrackSignup(properties?, options?)- Track user signup
E-commerce Events
trackCheckout(properties?, options?)- Track checkout processtrackPurchase(properties?, options?)- Track completed purchasetrackAddToCart(properties?, options?)- Track item added to carttrackRemoveFromCart(properties?, options?)- Track item removed from cart
Navigation Events
trackPageView(properties?, options?)- Track page viewstrackSearch(properties?, options?)- Track search queries
Template Event Properties
All template events support their own typed properties:
// Login event properties
interface LoginEventProperties {
method?: string; // 'email', 'google', 'facebook', etc.
success?: boolean; // Whether login was successful
errorMessage?: string; // Error message if login failed
loginAttempt?: number; // Attempt number
rememberMe?: boolean; // Whether "remember me" was checked
twoFactorEnabled?: boolean; // Whether 2FA was used
}
// Checkout event properties
interface CheckoutEventProperties {
orderId?: string; // Unique order identifier
total?: number; // Total amount
currency?: string; // Currency code
items?: Array<{ // Array of items
id: string;
name: string;
price: number;
quantity: number;
}>;
paymentMethod?: string; // 'credit_card', 'paypal', 'stripe', etc.
success?: boolean; // Whether checkout was successful
errorMessage?: string; // Error message if checkout failed
couponCode?: string; // Applied coupon code
discount?: number; // Discount amount
}Authentication Strategies
NONE
No authentication required. Events are sent directly to the API.
SERVER_SIDE
Use a secret key for server-side authentication:
- Obtain your secret key from the Grain dashboard
- Include it in your configuration
- Events are sent with
Authorization: Chase {SECRET}header
JWT
Use JWT tokens for client-side authentication:
- Configure JWT settings in your Grain tenant
- Provide an auth provider that returns valid tokens
- Supports Auth0, next-auth, and other JWT providers
Build Outputs
The package provides multiple build formats:
- ESM:
dist/index.mjs- Modern ES modules - CommonJS:
dist/index.js- Node.js compatible - IIFE:
dist/index.global.js- Browser global (window.Grain) - Types:
dist/index.d.ts- TypeScript definitions
Browser Usage (Script Tag)
<script src="https://unpkg.com/@grainql/analytics-web/dist/index.global.js"></script>
<script>
const grain = Grain.createGrainAnalytics({
tenantId: 'your-tenant-id',
userId: 'user123'
});
grain.trackPageView({ page: '/home' });
grain.trackLogin({ method: 'email', success: true });
</script>Advanced Usage
Custom Auth Provider
class Auth0Provider {
constructor(private auth0Client) {}
async getToken() {
return await this.auth0Client.getTokenSilently();
}
}
const grain = createGrainAnalytics({
tenantId: 'your-tenant-id',
authStrategy: 'JWT',
authProvider: new Auth0Provider(auth0Client)
});Error Handling
try {
await grain.track('event', { data: 'value' }, { flush: true });
} catch (error) {
console.error('Failed to send event:', error);
}Debug Mode
const grain = createGrainAnalytics({
tenantId: 'your-tenant-id',
debug: true // Enables console logging
});User Session Management
// Set user ID when user logs in
grain.setUserId('user123');
// Track user-specific events
await grain.trackLogin({ method: 'email', success: true });
await grain.trackPageView({ page: '/dashboard' });
// Clear user ID when user logs out
grain.setUserId(null);Changelog
[1.4.0] - 2024-12-19
Added
- User Properties API: New
setProperty()method for setting user properties- Set up to 4 properties per request
- Automatic string serialization for all values
- Support for user-specific property overrides
- Full authentication support (NONE, SERVER_SIDE, JWT)
- Updated API Endpoints:
- Events now use
/v1/events/{tenant}/multiendpoint - Properties use
/v1/events/{tenant}/propertiesendpoint
- Events now use
Changed
- Updated all event sending to use the new
/multiendpoint - Enhanced error handling and retry logic for properties API
Technical
- Added comprehensive test coverage for properties functionality
- Updated all existing tests to use new endpoint structure
- Improved TypeScript interfaces for better type safety
[1.3.0] - Previous Release
- Template events for common analytics scenarios
- Enhanced user ID management
- Improved error handling and retry logic
- Cross-platform compatibility improvements
License
MIT
Support
For questions and support, please visit grainql.com or contact our support team.